We have been working on a mailing service for a while now and we really like what we can do with html emails. Unfortunately, with the plethora of smart phones these days, HTML support is inconsistent. We figured that a good stop-gap solution was to offer both HTML and text versions of an email. Preferably in one package.
And that’s where multipart emails come in.
Suprisingly (or not), this was rather easy to implement in Rails 2.3.
There are two ways of doing this. Implicit and explicit multipart emails. I decided to go with the former.
All I had to do was to make sure the content type is set correctly:
content_type “multipart/alternative”
Then, I just had to make sure my template file ends with the right signature “foo.text.plain.erb” and “foo.text.html.erb” for plain text and html emails respectively.
See the multipart email section in the official doc here: http://api.rubyonrails.org/classes/ActionMailer/Base.html
I used a controller to trigger the email and it all worked just like a charm. I had my email with both text and html components. I checked in the code, fired up my mailer service which runs in backgroundrb and called it a day.
That’s when I saw this error popping up:
can’t convert nil into String
/usr/lib/ruby/gems/1.8/gems/actionmailer-2.3.2/lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb:551:in `quote’
/usr/lib/ruby/gems/1.8/gems/actionmailer-2.3.2/lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb:551:in `read_multipart’
/usr/lib/ruby/gems/1.8/gems/actionmailer-2.3.2/lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb:540:in `parse_body_0′
/usr/lib/ruby/gems/1.8/gems/actionmailer-2.3.2/lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb:522:in `parse_body’
/usr/lib/ruby/gems/1.8/gems/actionmailer-2.3.2/lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb:476:in `body=’
/usr/lib/ruby/gems/1.8/gems/actionmailer-2.3.2/lib/action_mailer/base.rb:650:in `create_mail’
…
After some investigation, I figure that this is one of those things where backgroundrb is incompatible with a certain feature of rails. I considered fudging around with the tmail code but gave up on that endeavor quickly. Instead, I decided to work around with an explicit version of the multipart email. To my delight, that worked perfectly.
content_type “multipart/alternative”
part :content_type => “text/plain”,:body => render_message(”foo.text.plain”, :variable1=>variable1, :variable2 => variable2)part :content_type => “text/html”,:body => render_message(”foo.text.html”, :variable1=>variable1, :variable2 => variable2)
Be sure to declare text/plain and text/html in that order. Email clients like Gmail may not offer the text alternative or show the HTML version automatically if you change that order.
The template files work as-is without any modifications. Well, crisis averted. Back to making some barcodes. :)
December 30th, 2009 on 3:09 pm
Thanks! I’m using the Workling + Starling background tasks system, but this fixed my similar issue.
December 31st, 2009 on 2:22 pm
Thank you! This was a very annoying problem, thanks for posting the solution.
January 29th, 2010 on 11:51 am
I’m working on a project that uses Delayed Job for mail delivery, and we were getting this same error. One of my co-workers was also getting this error when running tests.
This workaround seems to have resolved both. I’m really glad to have a workaround, but I’m uneasy that I don’t understand what the difference in run-time environment might be that triggers this.
Thank you!