Spam filters often require that an HTML email also have a text alternative that is generally the same as the HTML message. This means you need to send an email with a MIME type of multipart/alternative
containing text/html
and text/plain
parts. ActionMailer 3 supports this scenario, but it falls apart when you need to add (inline) attachments to that mix. The proper MIME hierarchy for an email like this is:
multipart/mixed
multipart/alternative
multipart/related
text/html
image/png
(e.g. for an inline attachment; pdf would be another good example)
text/plain
application/zip
(e.g for an attachment--not inline)
If this seems more complicated then it should be, that's because it is. Thankfully, this gem allows you to create this entire hierarchy without all the hard work.
Either include
gem "mail_alternatives_with_attachments"
in your Gemfile (if using Bundler) or run
gem install mail_alternatives_with_attachments
Including the mail_alternatives_with_attachments
gem in your project will patch ActionMailer with the following two methods:
ActionMailer::Base#prepare_message(headers={})
: This method does exactly whatActionMailer::Base#mail(headers={})
does; however it doesn't automatically render templates. This allows us to add our own custom message parts.Mail::Message#alternative_content_types_with_attachment(options, &block)
: This method allows you to conveniently add all of the different parts of a complex email with alternatives and attachments.
Typically when using ActionMailer 3, you would create a message with the following code:
class MyEmailerClass < ActionMailer::Base
def my_email_method(address)
mail :to => address,
:from => "noreply@myemail.com",
:subject => "My Subject"
end
end
To create an email with both alternatives and attachments you would use the following code:
class MyEmailerClass < ActionMailer::Base
def my_email_method(address, attachment, logo)
message = prepare_message to: address, subject: "My Subject", :content_type => "multipart/mixed"
message.alternative_content_types_with_attachment(
:text => render_to_string(:template => "my_template.text"),
:html => render_to_string(:template => "my_template.html")
) do |inline_attachments|
inline_attachments.inline['logo.png'] = logo
end
attachments['attachment.pdf'] = attachment
message
end
end