AnApprentice
AnApprentice

Reputation: 110940

ActionMailer - How to Add an attachment?

Seems simple enough but I haven't been able to get it to work. The files work fine from S3 on the web app, but when I email them out via the code below, the files are corrupt.

App Stack: rails 3, heroku, paperclip + s3

Here's the code:

class UserMailer < ActionMailer::Base
# Add Attachments if any
if @comment.attachments.count > 0
  @comment.attachments.each do |a|
    require 'open-uri'
    open("#{Rails.root.to_s}/tmp/#{a.attachment_file_name}", "wb") do |file|
      file << open(a.authenticated_url()).read
      attachments[a.attachment_file_name] = File.read("#{Rails.root.to_s}/tmp/#{a.attachment_file_name}")
    end
  end
end

mail( :to => "#{XXXX}", 
      :reply_to => "XXXXX>", 
      :subject => "XXXXXX"
      )

a.authenticated_url() just gives me a URL to s3 to get the file (of any type), I checked this, works fine. Something to do with the way I'm saving the tempfile must be breaking the ActionMailer Attachment.

Any ideas?

Upvotes: 5

Views: 3385

Answers (1)

Seamus Abshere
Seamus Abshere

Reputation: 8516

This might work better because it doesn't touch the filesystem (which is often problematic on Heroku):

require 'net/http'
require 'net/https' # You can remove this if you don't need HTTPS
require 'uri'

class UserMailer < ActionMailer::Base
  # Add Attachments if any
  if @comment.attachments.count > 0
    @comment.attachments.each do |a|
      # Parse the S3 URL into its constituent parts
      uri = URI.parse a.authenticated_url
      # Use Ruby's built-in Net::HTTP to read the attachment into memory
      response = Net::HTTP.start(uri.host, uri.port) { |http| http.get uri.path }
      # Attach it to your outgoing ActionMailer email
      attachments[a.attachment_file_name] = response.body
    end
  end
end

I don't think this will cause any extra memory issues because in any case you have to load the file's data into memory on the attachments[a.attachment_file_name] line.

Upvotes: 8

Related Questions