Adding multiple email attachments with Ruby on Rails

JUN

20

2007

I was building some forms for a client that required the user be able to upload supporting documents along with the application. I had implemented emailable forms before with single attachments, but never multiple. Turns out, it was just as simple to do, I just needed to call the attach function for each file I wanted to attach.

Here is the method in my controller that calls the ActionMailer class to send the email, where params[:file1], params[:file2], and params[:file3] are the file_field_tag's from the form:

UPDATE: I've re-factored this after Shawn suggested that it could be simplified into an array and iterated over.

def submit_application
  @uploaded_files = []
  @uploaded_files << params[:file1]
  @uploaded_files << params[:file2]
  @uploaded_files << params[:file3]
  ContactMailer.deliver_email_with_attachments(params[:application], @uploaded_files)
  flash[:notice] = 'Your application has been submitted.  Thank you!'
  redirect_to application_home_url
rescue Exception => ex
  logger.warn(ex.message)
  flash[:notice] = 'Uh oh!  There was an error sending your application.'
  redirect_to :back
end

And here is the ActionMailer method that attaches the files. I just need to iterate over the files, calling attach for each one.

def email_with_attachments(application_fields={},files=[])
  @headers = {}
  @sent_on = Time.now
  @recipients = 'client@domain.com'
  @from = 'info@domain.com'

  @subject = 'Here are some file attachments'
  application_fields.keys.each {|k| @body[k] = application_fields[k]}

  # attach files
  files.each do |file|
    attachment "application/octet-stream" do |a|
      a.body = file.read
      a.filename = file.original_filename
    end unless file.blank?
  end
end

The "application/octet-stream" is the generic MIME type for attaching unknown file types.

Pretty simple!

Tagged: tutorial, rails, email attachment, actionmailer


Shawn Veader said on June 25, 2007:

Nice... You could also compact it some by collecting the attachments together in an array and just iterate over them adding each as an attachment. The #compact method on an array would squash out any nils too.

Christie said on August 7, 2008:

Do you have an example of what the form would look like

Travis said on August 13, 2008:

@Christie Take a look at this: http://pastie.org/252548

Christie said on August 13, 2008:

Thanks Travis! I am very new to this and I am having a very hard time with the learning curve for this but slowly I am starting to get it.

Beakid said on February 11, 2010:

I suppose the "fields[k]" should be "application_fields[k]" here, right? *trying it out*

Travis said on March 19, 2010:

@Breakid Good catch. I've updated the post.

tj said on May 26, 2010:

or just use the .each method for hashes. then u wouldnt have that problem at all

tj said on May 27, 2010:

on second thought: why not just set @body = application_fields or at least @body.merge!(application_fields)

paul said on June 7, 2010:

Hi trevis thanks for the post it was pretty nice , it helped me alot as am tryin out emails with attachment for the first time.

Leave a comment:




© 2010 Travis Roberts. All rights reserved.