简体   繁体   English

带有 ical 附件的多部分 email 显示不正确

[英]Multipart email with ical attachment displays incorrectly

I'm not sure if this is an issue with my code, ActionMailer , Mail , or maybe even the icalendar gem?我不确定这是否是我的代码、 ActionMailerMail或什至是icalendar gem 的问题?

A user registers for an event and they get an email with an ical attachment:用户注册一个事件,他们会得到一个带有 ical 附件的 email:

# app/mailers/registration_mailer.rb

class RegistrationMailer < ApplicationMailer
  helper MailerHelper

  def created(registration)
    ...

    cal = Icalendar::Calendar.new
    cal.event do |e|
      e.dtstart = @event.start_time
      e.dtend = @event.end_time
      e.organizer = 'mailto:filterbuilds@20liters.org'
      e.attendee = @recipient
      e.location = @location.addr_one_liner
      e.summary = @summary
      e.description = @description
    end
    cal.append_custom_property('METHOD', 'REQUEST')
    mail.attachments[@attachment_title] = { mime_type: 'text/calendar', content: cal.to_ical }

    mail(to: @recipient.email, subject: "[20 Liters] You registered for a filter build on #{@event.mailer_time}")
  end

  ...
end

I have text and HTML views:我有文字和 HTML 次浏览:

  • app/views/registration_mailer/created.text.erb
  • app/views/registration_mailer/created.html.erb

When I omit the attachment, the email is structured like this:当我省略附件时,email 的结构如下:

Header stuff...
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary="--==_mimepart_63358693571_1146901122e"; charset=UTF-8
Content-Transfer-Encoding: 7bit

----==_mimepart_63358693571_1146901122e
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit

[the text version of the email here]

----==_mimepart_63358693571_1146901122e
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 7bit

[the HTML version of the email here]
----==_mimepart_63358693571_1146901122e--

When the attachment is present, the email is structured like this:当存在附件时,email 的结构如下:

Header stuff...
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="--==_mimepart_6335c3388b140_114924286ed"; charset=UTF-8
Content-Transfer-Encoding: 7bit

----==_mimepart_6335c3388b140_114924286ed
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit

[the text version of the email here]

----==_mimepart_6335c3388b140_114924286ed
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 7bit

[the HTML version of the email here]

----==_mimepart_6335c3388b140_114924286ed
Content-Type: multipart/alternative; boundary="--==_mimepart_6335c3389bc30_114924287a3"; charset=UTF-8
Content-Transfer-Encoding: 7bit

----==_mimepart_6335c3389bc30_114924287a3
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit

[the text version of the email AGAIN]

----==_mimepart_6335c3389bc30_114924287a3
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 7bit

[the HTML version of the email AGAIN]

----==_mimepart_6335c3389bc30_114924287a3--
----==_mimepart_6335c3388b140_114924286ed
Content-Type: text/calendar; charset=UTF-8
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=20Liters_filterbuild_20221011T0900.ical
Content-ID: <6335c3389e99c_1149242894f@railway.mail>

[numbers and letters]
----==_mimepart_6335c3388b140_114924286ed--

It's a weird tree suddenly:突然是一棵奇怪的树:

1. Content-Type: multipart/mixed
    A. Content-Type: text/plain
    B. Content-Type: text/html
    C. Content-Type: multipart/alternative
        i. Content-Type: text/plain
        ii. Content-Type: text/html
    D. Content-Type: text/calendar

Rails' mailer preview doesn't reproduce this issue, nor does using Litmus' email client previews (because it seems to remove the text part and attachments), but I'm assuming with the deformed structure of content-types this isn't just a client-specific rendering issue. Rails 的邮件预览不会重现这个问题,使用 Litmus 的 email 客户端预览也不会(因为它似乎删除了文本部分和附件),但我假设内容类型的变形结构不仅仅是特定于客户端的渲染问题。

I'm thinking this is coming from the Mail gem underneath ActionMailer structuring the content-types oddly, but I'm a bit out of my depth here.我认为这是来自 ActionMailer 下的 Mail gem,奇怪地构造了内容类型,但我在这里有点超出了我的理解范围。 It could be ActionMailer, I really don't know how to tell.可能是ActionMailer,我真的不知道怎么说。

I'm not very well versed in this, but I think I want this structure:我不是很精通这个,但我想我想要这个结构:

1. Content-Type: multipart/mixed
    A. Content-Type: multipart/alternative
        i. Content-Type: text/plain
        ii. Content-Type: text/html
    B. Content-Type: text/calendar

So, two questions:那么,两个问题:

1. If it's my code, what am I doing wrong? 1.如果是我的代码,我做错了什么?

2. If it's not my code, can I force the structure I want? 2. 如果不是我的代码,我可以强制使用我想要的结构吗?

I've been combing through ActionMailer and Mail code bases, but haven't found a way to manually form my email to this level.我一直在梳理 ActionMailer 和 Mail 代码库,但还没有找到一种方法来手动将我的 email 构建到这个级别。

After more digging, I'm blaming ActionMailer , though I'm still not sure why text and html parts are getting added twice.经过更多挖掘,我责怪ActionMailer ,尽管我仍然不确定为什么文本和 html 部分被添加了两次。

A monkey patch for my specific use was to let ActionMailer and Mail build the mail object and then just manually remove the unwanted parts:我的特定用途的猴子补丁是让 ActionMailer 和 Mail 构建mail object,然后手动删除不需要的部分:

# app/mailers/registration_mailer.rb

...

mail.attachments[@attachment_title] = { mime_type: 'text/calendar', content: cal.to_ical }

mail(to: @recipient.email, subject: "[20 Liters] You registered for a filter build on #{@event.mailer_time}")

# PATCH: text and html parts are getting inserted in multipart/mixed (top level) as well as multipart/alternative (2nd level)
mail.parts.reject! { |part| !part.attachment? && !part.multipart? }

This only works for my specific case.这仅适用于我的特定情况。 If the nesting that mail creates for you is different, your reject!如果mail为您创建的嵌套不同,您reject! statement will need to be different.声明将需要不同。

In my case, mail builds this structure:在我的例子中, mail构建了这个结构:

1. Content-Type: multipart/mixed
    A. Content-Type: text/plain
    B. Content-Type: text/html
    C. Content-Type: multipart/alternative
        i. Content-Type: text/plain
        ii. Content-Type: text/html
    D. Content-Type: text/calendar

So I step into the first level (A. - D.) and reject any parts that are not multipart and not an attachment:所以我进入第一级 (A. - D.) 并拒绝任何不是多部分且不是附件的部分:

1. Content-Type: multipart/mixed
    A. Content-Type: text/plain <-- not multipart, not attachment = rejected
    B. Content-Type: text/html <-- not multipart, not attachment = rejected
    C. Content-Type: multipart/alternative  <-- is multipart, not attachment = kept
        i. Content-Type: text/plain
        ii. Content-Type: text/html
    D. Content-Type: text/calendar  <-- not multipart, is attachment = kept

If you are facing this issue, I recommend you use a debugger to inspect your mail object, specifically focusing on the parts .如果您遇到这个问题,我建议您使用调试器检查您的mail object,特别关注parts Keep in mind that parts can be deeply nested.请记住, parts可以嵌套很深。

Mail::Part inherits from Mail::Message which has some helpful methods you can use to determine the "shape" of your message: Mail::Part继承自Mail::Message ,它有一些有用的方法可用于确定消息的“形状”:

  • multipart?
  • attachment?
  • attachments
  • has_attachments?
  • boundary
  • parts
  • all_parts

And good luck.还有祝你好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM