A project I am working on right now requires reports sent via email with embedded images. Most email programs optionally prevent linked images in html emails from being displayed. To make them display properly, I need to send the image file with email and link to the embedded image in the html portion of the email.
Information on how this can work can be found here.
Creating a multi-part mime email in Rails is not hard, but as I looked around, it seems there is not support for inline attachments.
Another person was trying to get an answer to how to do this on the mailing list.
I am sure he has moved on as that unanswered question was posted in Nov of 2006. But maybe sharing how I found a solution will help someone here.
After googling about i found that there is a patch to rails that is supposed to allow ActionMailer to send inline attachments.
It seems the ticket is closed, and until someone writes some tests and creates a diff, it won’t be accepted into the core.
Ok, I have to get my job done.. monkey patch rails with this persons patch? No, I should really learn how to make a plugin out of it. I have been putting that off for too long.
Well it happens that Ryan Bates has just created a screen cast on how to make a plugin.
After watching it and realizing how easy this stuff is, I set to work making it happen in my app.
script/generate plugin inline_attachment
I opened up this file:
vendor/plugins/inline_attachment/lib/inline_attachment.rb
and pasted in the patch from rails ticket 2179.
I created a second file in the lib directory called:
vendor/plugins/inline_attachment/lib/tmail_content_id.rb
and pasted in the second file of the patch from the same ticket.
Now I opened up:
vendor/plugins/inline_attachment/init.rb
and put in this bit of code:
require "inline_attachment" require "tmail_content_id"
Is that really it? After restarting my mongrel server, I add this to my Mailer:
@cid = Time.now.to_f.to_s + "lightbulb.png@domain.com" inline_attachment :content_type => "image/png", :body => File.read("#{RAILS_ROOT}/public/images/lightbulb.png"), :filename => "lightbulb.png", :cid => "<#{@cid}>"
That instance variable @cid is supposed to be globally unique, and ends up being the id to get the image to show up in the html part of the email, so I pass it on to my email template. In my email template I have something like this:
<img src="cid:#{@cid}" />
July 24th, 2007 at 8:26 am
Thanks for posting this example.
One thing that gave me trouble was the line
File.read()
as it didn’t read the binary gif or png file. With the following code it worked:
image_path = “#{RAILS_ROOT}/public/images/lightbulb.png”
f=File.open(image_path,’rb’)
inline_attachment :content_type => “image/png”,
:body => f.read,
:filename => “lightbulb.png”,
:cid => “”
November 9th, 2007 at 3:06 am
Thanks for your post, we took what you’d done and crammed it into a gem, then we got excited and improved the gem so it automatically does the embedding for you in an ActionMailer template.
It’s available on RubyForge, here’s our post about it:
http://flow.handle.it/past/2007/11/5/inline_attachment_now_official_rocks/
December 4th, 2007 at 12:24 pm
require “inline_attachments” should be require”inline_attachment” (without the ’s’)
Cheers
December 7th, 2007 at 10:22 pm
Thanks Michel, that is now corrected
October 1st, 2008 at 2:17 am
I was amazed how simple you made this. Even with my usual thick-headedness, it only took a few hours to get this working. (The gem didn’t work for me at all, and I didn’t see how it was better, so I followed just what you have on this page.)
My only problem: the images ARE displayed inline. That rocks. Apple’s Mail.app also show them at the bottom of the page. Is there an HTML trick or something to make them vanish down there?
Thanks.
October 1st, 2008 at 4:32 pm
Odd, I don’t see my comment from yesterday. But after some research on the web I have discovered that some mail clients show the inline attachments twice, both inline and as attachments (at the bottom).
October 2nd, 2008 at 12:58 am
Nice Colin, glad it helped.
November 5th, 2008 at 12:27 pm
< img src=”cid:#{@cid}” /> didn’t work for me. Other than that, it was perfect (coupled with opening the file in ‘rb’ mode). I used
<img src=”cid:” />
instead. Thanks a lot for greak work.
Asang Dani
Nagpur, India
June 10th, 2009 at 7:07 am
Thanks for this detailed post Nathan, it helped a lot !
Just a note though that I had to add :
content_type ‘multipart/related’
to my mailer function. The default ‘multipart/alternatives’ was causing problems when displaying with my mua.
Also, I’m trying to send a regular attachment with the html mail. When I create a mail with an embedded png and an attached pdf in my client I get the following content-type hierarchy :
multipart/mixed
|- multipart/related
| |- multipart/alternative
| | |- text/plain
| | |- text/html
| |
| |- image/png
|
|- application/pdf
Any idea how that could be done with ActionMailer ? The only way I can see right now is to revert back to plain TMail…
June 23rd, 2009 at 10:24 am
Thanks a lot..it helped us solve our problem