如何通过Icalendar gem获取RSVP按钮

时间:2014-12-16 21:48:28

标签: ruby-on-rails ruby icalendar

所以我在我的ruby项目中获得了Icalendar宝石。我试图在邀请中获得Yes / No / Maybe的RSVP按钮,但无论何时发送,我只会得到一个"添加到日历"。

想知道我还需要什么:

def make_ical_appointment(start_time, end_time, uid, email_one, email_two)
  ical = Icalendar::Calendar.new
  ical.timezone.tzid = "UTC"

  e = Icalendar::Event.new
  e.dtstart = start_time
  e.dtend = end_time
  e.organizer = %W(mailto:#{email_one} mailto#{email_two})
  e.uid = uid

  ical.add_event(e)
  ical.publish

  mail.attachments['appointment.ics'] = { mime_type: 'application/ics', content: ical.to_ical }
end

我读过人们需要将其设置为METHOD:REQUEST,但我不知道该去哪里做。我还读到您需要设置与会者,但是如果您有闹钟,似乎只能设置与会者?

只是想让它看起来像常规邀请。

1 个答案:

答案 0 :(得分:8)

解决问题需要做两件事:

  1. Read RFC-2445,定义了iCal格式。看起来像讨论ATTENDEE属性的4.8.4.1节以及讨论RSVP参数的4.2.17将是特别感兴趣的。

  2. 查看您收到的可在各种电子邮件客户端中正确显示的电子邮件和.ics文件。

  3. 上面评论中的page I linked to有三个提示。

    第一个提示

      

    我尝试添加此属性:
    calendar.custom_property("METHOD", "REQUEST") [1]

    从我认为应该是append_custom_property的文档开始。

    打开邀请某人通过Google日历发送给我的邀请,我发现了这一行:

    METHOD:REQUEST
    

    所以这似乎是合法的。

    第二个提示

      

    我猜您需要添加ATTENDEE属性RSVP=TRUE,并将电子邮件设置为Outlook或Yahoo链接到其用户的同一封邮件。 [2] < / SUP>

    在同一个邀请中我发现了这个:

    ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=
     TRUE;CN=Firstname Lastname;X-NUM-GUESTS=0:mailto:jordan@example.com
    

    我没有阅读整个RFC,但我认为它会像这样崩溃:

    • ATTENDEE属性名称
    • 第一个;和第一个:之间的所有内容都是参数。它们中的每一个都记录在RFC中,我不知道是否所有这些都是必需的,但我们可以在那里看到RSVP=TRUE参数。
    • 第一个:之后的所有内容,即mailto:jordan@example.com

    查看append_custom_property的来源,我们看到它会检查value是否为Icalendar::Value个对象,如果不是,则会创建一个Icalendar::Values::Text.new(value)。由于除了值之外我们还有参数,让我们看看构造函数here。我们看到它可以采用第二个参数,即params Hash。

    现在,我还没有对它进行测试,但这表明你可以使用类似以下之类的代码构建一条如上所述的行:

    attendee_params = { "CUTYPE"   => "INDIVIDUAL",
                        "ROLE"     => "REQ-PARTICIPANT",
                        "PARTSTAT" => "NEEDS-ACTION",
                        "RSVP"     => "TRUE",
                        "CN"       => "Firstname Lastname",
                        "X-NUM-GUESTS" => "0" }
    
    attendee_value = Icalendar::Values::Text.new("MAILTO:jordan@example.com", attendee_params)
    ical.append_custom_property("ATTENDEE", attendee_value)
    

    编辑:在Icalendar 2.x中,您似乎也可以这样做:

    attendee_value = Icalendar::Values::CalAddress.new("MAILTO:jordan@example.com", attendee_params)
    ical.append_attendee(attendee_value)
    

    CalAddress类是Uri的子类,它只通过URI.parse运行给定值,而append_attendee似乎是append_custom_property("ATTENDEE", ...)的快捷方式

    我不确定是否所有这些参数都是实际需要的,但您可以通过阅读RFC了解每个参数。

    第三个提示

      

    要使其在所有邮件客户端中运行,我必须做的是将其作为多部分/替代消息发送,使用ical作为替代视图而不是作为附件。 [3]

    果然,在Gmail中进行“显示原创”我看到我收到的邀请电子邮件是一封多部分电子邮件,其中包含text/calendar部分:

    --047d7b0721581f7baa050a6c3dc0
    Content-Type: text/calendar; charset=UTF-8; method=REQUEST
    Content-Transfer-Encoding: 7bit
    
    BEGIN:VCALENDAR
    PRODID:-//Google Inc//Google Calendar 70.9054//EN
    ...
    

    ...和application/ics附件部分:

    --047d7b0721581f7bae050a6c3dc2
    Content-Type: application/ics; name="invite.ics"
    Content-Disposition: attachment; filename="invite.ics"
    Content-Transfer-Encoding: base64
    
    QkVHSU46VkNBTEVOREFSDQpQUk9ESUQ6LS8vR29vZ2xlIEluYy8vR29vZ2xlIENhbGVuZGFyIDcw
    ...
    

    你已经得到的第二部分,感谢mail.attachments。对于第一部分,您只需要使用正确的Mail::Part创建一个新的content_type,然后将其添加到mail.parts,这将看起来像这样的 :< / p>

    ical_part = Mail::Part.new do
      content_type "text/calendar; charset=UTF-8; method=REQUEST"
      body ical.to_ical
    end
    mail.add_part(ical_part)
    

    这就是我所拥有的一切。我再次测试过这个,我不确定它会解决你的问题,但希望它会给你一些想法。

    我认为最重要的是查看电子邮件的来源(如果您使用Gmail,“显示原始”位于“回复”按钮旁边的下拉菜单中)并邀请并查看它们的来源重新构建,同样查看.ics附件,看看它们是否与您正在生成的内容相匹配。

    祝你好运!


    根据the way Icalendar transforms the params hash into iCal parameters判断,我认为您也可以使用符号键,如下所示:

    attendee_params = { cutype:   "INDIVIDUAL",
                        role:     "REQ-PARTICIPANT",
                        partstat: "NEEDS-ACTION",
                        rsvp:     "TRUE",
                        cn:       "Firstname Lastname",
                        x_num_guests: "0" }