Since the first post on this topic, I have migrated my app from Rails 2.3.11 to Rails 3.0.6. See the first post if you still need the solution for Rails 2.

I had a need at work to send email out of our Rails application which met the following criteria:

  • It has both a plain text and HTML part.
  • It may have embedded images in the HTML part.
  • It may have attachments.

Below is the code, which you can put in your app/models directory.

class EmbeddedMailer < ActionMailer::Base

  def embedded_mail(to, from, subject, html_message, text_message, files = {}, embeds = {})
    mail(:to => to, :from => from, :subject => subject) do |format|
      format.text { render :text => text_message }
      format.html { render :text => html_message }
    end

    # Embeds
    embeds.each do |key, embed|
      attachments.inline[key] = {
        :content => File.read(embed[:path]),
        :content_id => "<#{key}>"
      }
    end

    # Attachments
    files.each do |key, embed|
      attachments[key] = File.read(embed[:path])
    end
  end

end

A Quick Explanation

Rails 3 has made this a lot easier. The only real hack is handling dynamic inline Content-ID’s. ActionMailer will dynamically generate a Content-ID for each inline attachment. We override that with the :content_id => "<#{key}>" line. The brackets are required.

The format of the files and embeds hashes is as follows. The key is the file name of the attached file. The value is another hash with content_type set to the content type of the attachment and path is the full path to the file. For example:

{ 'image.png' =>
    'content_type' => 'image/png',
    'path' => '/tmp/image.png'
}
Soeren on said:

Hi

Great post! I am trying this, but a little different though. It seems to work, I do get a attachment in my sent email, but how do I know if it is inline? I am trying to refer to my attachment from the email HTML body like this:

img src=/tmp/MyJpg.jpg alt=MyJpg (plus the HTML lesser/greater and double quotes and all, but I could not post that)

I have also tried without the /tmp/ but I can not get it to work. How do I refer to the inline attachment from my HTML message?

Thank you Soeren

James Coleman on said:

Using your code in Rails 3 doesn't give the same MIME hierarchy as your post on Rails 2 does. This causes it not to display attachments in devices like the iPhone. I've released a gem to make this super easy: https://github.com/jcoleman/mail_alternatives_with_attachments (which is also on RubyGems as 'mail_alternatives_with_attachments'.)

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*
You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>