outlook - 如何通过 SendGrid 发送 .ics 日历邀请,以便在电子邮件客户端中呈现?

标签 outlook gmail sendgrid icalendar sendgrid-api-v3

我正在尝试发送 .ics通过 SendGrid(来自 Node 服务器)日历邀请,以便它在 Outlook 或 Gmail 等客户端中呈现为实际邀请(带有接受/拒绝按钮),而不仅仅是作为附件文件。
我花了几天的时间研究这个(几十个 Stackoverflow 问题,RFC-5545RFC-2446iCalendar Specification Excerpts,Sendgrid 的 GitHub 问题线程:12,7Sendgrid 等 6 个来源)。
然而,这似乎没有答案(或者我错过了什么?)。

到目前为止我发现的是 Content-Type因为附件在这里很重要,特别是,method=REQUEST部分。甚至 3 .
尽管这里有很多关于 SO 的问题,但由于某种原因,大多数问题仍未得到解答。

这是我如何设置我的 attachment目的:

const SendGrid = require("@sendgrid/mail");

  const attachment = {
    filename: 'invite.ics',
    name: 'invite.ics',
    content: Buffer.from(data).toString('base64'),
    disposition: 'attachment',
    contentId: uuid(),
    type: 'application/ics'
  };

SendGrid.send({
      attachments: [attachment],
      templateId,
      from: {
        email: config.emailSender,
        name: config.emailName,
      },
      to: user.email,
      dynamicTemplateData: {
        ...rest,
        user,
      },
      headers: {
        'List-Unsubscribe': `<mailto:unsubscribe.link`,
      },
    });

至于type属性,我尝试了以下变体:
1. type: 'text/calendar; method=REQUEST'
2. type: 'application/ics'
3. type: 'text/calendar;method=REQUEST;name=\"invite.ics\"'
4. type: 'text/calendar; method=REQUEST; charset=UTF-8; component=vevent'
5. type: 'text/calendar'
但是,除了 'text/calendar' 之外,什么都不起作用。和 'application/ics' (而且它们之间似乎没有任何区别)。Content-Type是根据 SendGrid 文档的保留 header ,因此无法通过 headers 以某种方式设置它属性(property)disposition: 'inline'选项也根本不起作用(仅 disposition: 'attachment' )。

这是 .ics我生成的文件看起来像:
BEGIN:VCALENDAR
PRODID:-//Organization//Organization App//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
DTSTART:20210426T160000Z
DTEND:20210426T170000Z
DTSTAMP:20210418T134622Z
ORGANIZER;CN=John Smith:MAILTO:john.smith+test1@gmail.com
UID:dcfd5905-be85-4c8f-8a27-475b0ec67d8b
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=John Smith;X-NUM-GUESTS=0:MAILTO:john.smith+test1@gmail.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=John Test;X-NUM-GUESTS=0:MAILTO:john.smith+test2@gmail.com
CREATED:20210418T134622Z
DESCRIPTION:my description
LAST-MODIFIED:20210418T134622Z
LOCATION:https://location.url
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:my summary
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

该文件完全有效并且可以在 iCalendar 中无缝打开。
但是为什么这不会在 Outlook 或 Gmail 中呈现?
目前,将事件添加到日历的唯一方法是单击附件 invite.ics 上的“下载”。 ,然后打开它,只有在此之后日历应用程序才会打开,您可以确认邀请。

PS:我的意思是rendering .ics邀请是 Outlook 或 Gmail 自动识别时 .ics附件并如下图所示显示(对不起红线):
the order of properties in the file makes difference
enter image description here

如果它有任何区别,我正在使用 @sendgrid/mail v6.3.1
你能帮我以某种方式解决我的问题吗?
我究竟做错了什么?
如何让电子邮件客户端识别我的 .ics文件并允许用户在电子邮件客户端本身中接受/拒绝这些邀请,而无需手动下载文件并打开它?

最佳答案

好的,经过大量的反复试验,我终于得到了这个工作。我希望代码对其他人有帮助。
所以,首先,我所做的是从 iCalendar 发送一个实际的事件邀请并收到这个 .ics邀请(实际上在 Outlook 和 Gmail 中都呈现了)。我查看了这个文件与我生成的文件有何不同,并发现了一件奇怪的事情:
让这个工作的关键是......
魔术弦
是的,完全随机的,奇怪的魔法弦。
下面我发布了 .ics对我有用的文件内容。TOTTALLY-RANDOM-MAGIC-STRING - 是一个完全随机的字符串的占位符,比如 uuids 或者你的组织电子邮件或其他任何东西。
关键是:在 Outlook 和 Gmail 文件中使用这些字符串正确呈现邀请,没有它们 - 不要。奇怪,但工作。
我无法在文档或 RFC 中找到任何有意义的内容,所以我想现在调用这些魔术字符串是安全的。
第一个魔法字符串是 TOTTALLY-RANDOM-MAGIC-STRING@imip.me.com .
第二个魔法字符串是 /TOTTALLY-RANDOM-MAGIC-STRING/principal/ .

BEGIN:VCALENDAR
PRODID:-//Organisation//Organisation App//EN
METHOD:REQUEST
VERSION:2.0
BEGIN:VEVENT
DTEND:20210427T160000Z
ORGANIZER;CN=Organization Name;EMAIL=admin@organisation.com:mailto:TOTTALLY-RANDOM-MAGIC-STRING@imip.me.com
UID:D670DA52-3E7F-4F61-97E2-CB8878954504
DTSTAMP:20210419T181455Z
LOCATION:virtual.event.location.com
DESCRIPTION:description
URL;VALUE=URI:http://organization.com/invite
SEQUENCE:0
SUMMARY:my summary
LAST-MODIFIED:20210419T181455Z
DTSTART:20210427T150000Z
CREATED:20210419T181455Z
ATTENDEE;CUTYPE=INDIVIDUAL;EMAIL=my.email1@gmail.com:mailto:my.email1@gmail.com
ATTENDEE;CUTYPE=INDIVIDUAL;EMAIL=my.email2@gmail.com:mailto:my.email2@gmail.com
ATTENDEE;CN=Organisation Name;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED;ROLE=CHAIR;EMAIL=admin@organisation.com:/TOTTALLY-RANDOM-MAGIC-STRING/principal/
END:VEVENT
END:VCALENDAR
和代码:
  const SendGrid = require("@sendgrid/mail");

  const attachment = {
    filename: 'invite.ics',
    name: 'invite.ics',
    content: Buffer.from(data).toString('base64'),
    disposition: 'attachment',
    contentId: uuid(),
    type: 'text/calendar; method=REQUEST',
  };

    await SendGrid.send({
      attachments: [attachment],
      templateId,
      from: {
        email: config.emailSender,
        name: config.emailName,
      },
      to: user.email,
      dynamicTemplateData: templateData
   });
我希望这会为试图获得此内容的人们节省一些时间 .ics东西工作。

关于outlook - 如何通过 SendGrid 发送 .ics 日历邀请,以便在电子邮件客户端中呈现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67149571/

相关文章:

security - 展望安全

email - 使用Google Apps设置无回复的电子邮件地址

node.js - 如何从 firestore 数据库发送循环遍历数组的电子邮件

android - 在 Android < 2.0 中获取主 gmail 帐户用户名

django - SMTPServerDisconnected : Connection unexpectedly closed: timed out

php - 覆盖 Laravel Mailer 的 setGlobalTo

html - 如何删除 Outlook 中的链接下划线?

vba - 如何使用 vba 读取粘贴在 Outlook 邮件正文中的表格?

c# - (Outlook 2010) 在 C# 中获取邮件 header

javascript - 我应该如何包含和引用我的 JavaScript 文件