发送到 Outlook 的 ics 文件未被识别为事件

问题描述 投票:0回答:2

我需要开发一个应用程序来将事件发送到 Gmail / Outlook 日历。使用Java邮件1.5.5。我用 1.6.2 版本做了一些测试,但没有成功 选择的解决方案是生成 ics 文件,并通过电子邮件将其发送到目标日历地址。

在 Gmail 上,该电子邮件被很好地识别为活动电子邮件(该电子邮件包含活动的描述、更改答案的可能性,并且该活动会自动添加到日历中)

在 Outlook 上,附件不会被识别为事件(电子邮件仅包含 ics 文件作为附件,没有描述或响应请求,并且事件不会自动添加到日历中)。然后,您必须单击附件,然后单击“添加到日历”,以便在日历中创建该活动

我在网上找到了很多类似的主题,但没有任何可以帮助我解决问题

问题可能来自 ics 文件或邮件标头。 ics 文件对我来说看起来不错:如果在 gmail 上创建一条新消息,将我的 ics 添加为附件,然后将其发送到我的 Outlook 地址,则该电子邮件会被很好地识别为一个事件

这是ics文件的内容

BEGIN:VCALENDAR
PRODID:<MYPRODID>
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
DTSTAMP:20220629T121224Z
SUMMARY:Test Event
DTSTART:20220630T110000Z
DTEND:20220630T130000Z
UID:<MYUID>
SEQUENCE:1656460800
DESCRIPTION:Event body
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=FALSE;CN=<MYCN>:mailto:<MYEMAIL>
ORGANIZER;CN=<MYORGNAME>:mailto:<MYORGEMAIL>
END:VEVENT
END:VCALENDAR

我对标题/邮件结构有一些疑问。我在互联网上找到了很多不同的东西,但我尝试的所有内容都会导致相同的结果(需要在 Outlook 中打开我的电子邮件,手动导入附件)

这是我上次测试时的java代码:

Properties prop = new Properties();

prop.put("mail.mime.charset", "UTF-8");
prop.put("mail.smtp.host", "<MYHOST>");
prop.put("mail.smtp.port", "<MYPORT>");
prop.put("mail.smtp.auth", Boolean.TRUE.toString());
prop.put("mail.smtp.user", "<MYUSER>");
prop.put("password", "<MYPASS>");

String from = "<MYORGEMAIL>";
String to = "<MYEMAIL>";

Session session = Session.getInstance(prop, new SMTPAuthenticator(prop));
// Define message
MimeMessage message = new MimeMessage(session);
message.addHeader("method", "REQUEST");
message.addHeader("charset", "UTF-8");
message.addHeader("component", "VEVENT");

message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject("Outlook Meeting Request Using JavaMail");

File invitation = new File("<MYFILEPATH>\\vCalendar_5067936453064913847.ics");

MimeMultipart mixed = new MimeMultipart("mixed");

// Create the message part
MimeMultipart alternative = new MimeMultipart("alternative");
MimeBodyPart alternativePart = new MimeBodyPart();
alternativePart.setContent(alternative);
mixed.addBodyPart(alternativePart);
MimeBodyPart plain = new MimeBodyPart();
plain.setText("body", "UTF-8", "plain");
MimeBodyPart html = new MimeBodyPart();
html.setText("<div dir=\"ltr\">body</div>", "UTF-8", "html");
alternative.addBodyPart(plain);
alternative.addBodyPart(html);

// Create the attachment part
BodyPart icsBodyPart = new MimeBodyPart();
icsBodyPart.addHeader("method", "REQUEST");
icsBodyPart.addHeader("Content-Class", "urn:content-classes:calendarmessage");
icsBodyPart.addHeader("Content-ID", "calendar_message");
icsBodyPart.addHeader("component", "VEVENT");
FileInputStream inputStream = new FileInputStream(invitation.getAbsolutePath());
final DataSource source =
    new ByteArrayDataSource(inputStream,
        "text/calendar; charset=\"UTF-8\"; name=\"vCalendar_5067936453064913847.ics\"");
icsBodyPart.setDataHandler(new DataHandler(source));
icsBodyPart.setFileName(invitation.getName());
mixed.addBodyPart(icsBodyPart);

// Put parts in message
message.setContent(mixed);

// send message
Transport.send(message);

为了了解如何构建我的 mime 部分,我查看了 gmail 发送箱(由 Outlook 识别的发送箱)中的消息结构:

MIME-Version: 1.0
Date: Tue, 12 Jul 2022 14:44:10 +0200
Message-ID: <[email protected]>
Subject: Mail title test
From: XXXXXXXXXXX <[email protected]>
To: XXXXXXXXXXX <[email protected]>
Content-Type: multipart/mixed; boundary="00000000000072927505e39b0616"

--00000000000072927505e39b0616
Content-Type: multipart/alternative; boundary="00000000000072927005e39b0614"

--00000000000072927005e39b0614
Content-Type: text/plain; charset="UTF-8"

Mail content test

--00000000000072927005e39b0614
Content-Type: text/html; charset="UTF-8"

<div dir="ltr">Mail content test<br></div>

--00000000000072927005e39b0614--
--00000000000072927505e39b0616
Content-Type: text/calendar; charset="UTF-8"; name="vCalendar_5067936453064913847.ics"
Content-Disposition: attachment; filename="vCalendar_5067936453064913847.ics"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_l4i5zybk0
Content-ID: <f_l4i5zybk0>

QkVHSU46VkNBTEVOREFSClBST0RJRDpTeWxvYiBudWxsClZFUlNJT046Mi4wCkNBTFNDQUxFOkdS
RUdPUklBTgpXXXXXXXXXXXVRVUVTVApCRUdJTjpWRVZFTlQKRFRTVEFNUDoyMDIyMDYyOVQxMjEy
MjRaClNVTU1BUlk6NSAtIMOJdsOpbmVtZW50IGR1IDI4MDYgw6AgU3lsb2IgZGUgZMOpbW8gCkRU
U1RBUlQ6MjAyMjA2MzBUMTEwMDAwWgpEVEVORDoyMDIyMDYzMFQxMzAwMDBaClVJRDp0ZXN0VWlk
MTY1OTc1QHN5bG9iLmNvbQpTRVFVRU5DRToxNjU2NDYwODAwCkRFU0NSSVBUSU9OOlRlc3QgZGUg
Y29ycCBkZSB0ZXh0ZVxuc3VyIHBsdXNpZXVycyBsaWduZXNcLCBhY2NlbnRzIMOgIHRlc3RlcgpB
VFRFTkRFRTtST0xFPVJFUSXXXXXXXXXXXXXOVDtQQVJUU1RBVD1BQ0NFUFRFRDtSU1ZQPUZBTFNF
O0NOPUFsZXhhbmRyZSBORURORUQ6bWFpbHRvOmFsZXgubmVkamFyaUBnbWFpbC5jb20KT1JHQU5J
WkVSO0NOPSJPcmfDom5pc2F0ZXVyIjptYWlsdG86ZGF0YUBzeWxvYi5jb20KRU5EOlZFVkVOVApF
TkQ6VkNBTEVOREFSCgo=
--00000000000072927505e39b0616--

如果我知道如何在outlook上查看相同的信息,我可以比较从gmail收到的邮件和从java收到的邮件,但我不确定这是否可能(我找到了“显示/消息详细信息”选项,但是这个选项仅显示有关顶级 mime 部分的信息,而不是完整的 mime 结构)

有人知道如何解决这个问题吗?

谢谢,

java email icalendar
2个回答
0
投票

我遇到了类似的问题,并找到了重写

Content-Type
标头的解决方案。我已将
method=REQUEST
添加到此标头,之后 Outlook 开始将我的电子邮件识别为事件。

Content-Type: text/calendar; charset="utf-8"; method=REQUEST

Python 代码示例:

msg = MIMEMultipart()
msg['Subject'] = 'Your event'
msg['From'] = '[email protected]'
msg['To'] = '[email protected]'

with open('example.ics') as f:
    event = MIMEText(f.read(), _subtype='calendar', _charset='utf-8')
    event.replace_header('Content-Type', 'text/calendar; charset="utf-8"; method=REQUEST')
    msg.attach(event)


s.send_message(msg)
s.quit()

0
投票

对于 eml 文件中的 ics 部分,需要添加

request
语句。

对于您的 eml 文件,它可能如下所示:

...
--00000000000072927505e39b0616
Content-Type: text/calendar; method=REQUEST; charset="UTF-8"; 
Content-Transfer-Encoding: quoted-printable

BEGIN:VCALENDAR
PRODID:<MYPRODID>
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
DTSTAMP:20220629T121224Z
SUMMARY:Test Event
DTSTART:20220630T110000Z
DTEND:20220630T130000Z
UID:<MYUID>
SEQUENCE:1656460800
DESCRIPTION:Event body
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=FALSE;CN=<MYCN>:mailto:<MYEMAIL>
ORGANIZER;CN=<MYORGNAME>:mailto:<MYORGEMAIL>
END:VEVENT
END:VCALENDAR

--00000000000072927505e39b0616

request
可以是
PUBLISH
REQUEST
REPLY
ADD
CANCEL
REFRESH
COUNTER

对于您的 Java 代码,请更改

final DataSource source =
    new ByteArrayDataSource(inputStream,
        "text/calendar; charset=\"UTF-8\"; name=\"vCalendar_5067936453064913847.ics\"");

final DataSource source =
    new ByteArrayDataSource(inputStream,
        "text/calendar; method=REQUEST; charset=\"UTF-8\"; name=\"vCalendar_5067936453064913847.ics\"");
© www.soinside.com 2019 - 2024. All rights reserved.