William Shallum

ActionMailer embedding images in HTML email

Posted May 7 2011, 04:21 by William Shallum [updated May 7 2011, 04:41]

By default this is a bit tricky to do. Other mail libraries allow you to specify the Content-ID header for the images so they can be referenced using cid:someimage.png in the HTML. TMail aims to be compliant and enforces the formatting of the Content-ID header. To handle this, we can either relax TMail’s restrictions or live with it. I choose to live with it and generate compliant Content-IDs.

There are other ways of solving this that relax the restriction in TMail instead:

Now for the way I did it:

class Foo < ActionMailer::Base

def bar

  # ... set other attributes here...
  image_cid = TMail::new_message_id(nil) # or pass fqdn in there

  part "text/html" do | p |
    # Content-IDs are referred to using the cid: URL-scheme, without the angle brackets
    p.body = render_message("...", {:image_cid => image_cid.gsub(/^<|>$/, '')})
  end

  attachment :content_type => 'image/png', :disposition => 'inline', :headers => { 'content-id' => image_cid } do | a |
    a.body = generate_an_image
  end

end

end

See the Wikipedia article on MIME to learn about the usual format of a Content-ID. It turns out that Content-IDs must obey the same restrictions as Message-IDs i.e. be globally unique. Thus those who use cid:someimage.png are technically in violation of the spec. Who knew?