Reputation: 1622
I've taken a look at similar posts that mostly deal with sending an attachment by creating a view and controller, such as:
PDF attachment in email is called 'Noname'
but I've got a process that generates files in the background dynamically and need to attach it to a recipient list using ActionMailer::Base.mail. Below is the code:
def send_email(connection)
email = ActionMailer::Base.mail(to: connection['to'], from: connection['from'], subject: 'Sample File', body: "<p>Hello,</p><p>Your data is ready</p>", content_type: 'multipart/mixed')
email.cc = connection['cc'] if connection['cc'].present?
email.bcc = connection['bcc'] if connection['bcc'].present?
@files.each do |file|
report_file_name = "#{@start_time.strftime('%Y%M%dT%I%m%s')}_#{file[0]}.xlsx"
file_location = "#{Rails.root}/tmp/#{report_file_name}"
email.attachments[report_file_name] = File.open(file_location, 'rb'){|f| f.read}
end
email.deliver if email
end
I can see in the logs that it's sending with the content but assume it's sending as Noname because it can't find the view. Any way to get this to work successfully?
Below is the sample output:
Sent mail to [email protected] (383.9ms) Date: Thu, 13 Oct 2016 08:47:30 -0400 From: Sample To: Recipient Message-ID: <[email protected]> Subject: Sample File Mime-Version: 1.0 Content-Type: multipart/mixed; charset=UTF-8 Content-Transfer-Encoding: 7bit
-- Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; filename=20161012T08101476259208_Data.xlsx Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=20161012T08101476259208_Data.xlsx Content-ID: <[email protected]>
UEsDBBQAAAAIAO.. ... ...ADUFQAAAAA=
Update - I noticed if I use email.content_type = 'text/plain' - the attachment comes through successfully. For me, this works, though I'd appreciate later being able to style my emails with HTML
I presume this works because it prevents Rails from its usual gleaning/autointerpreting process. I'd certainly like to see a multipart/mixed or html compatible version work here though.
Update 2 This only fixed the issue artificially in the rails_email_preview
gem, which renders the emails to a new tab in development. In production, this simply and understandably prints the details and the presumably base64-encoded file, so question remains open.
Upvotes: 3
Views: 1179
Reputation: 321
You might don't have mailer.text.erb file along with mailer.html.erb file. Add it and your mail will be multipart.
Upvotes: 0
Reputation: 436
This has been driving me insane. Make sure you have a well formed .html template and a .text template if you are using mailer views.
Minimal errors in either of them will render the entire email as a noname attachment.
Upvotes: 0
Reputation: 4312
I have meet this problem too, after some investigation, it seems in Rails 4, you can't call attachments method after calling mail method, otherwise the content_type of the mail message object won't have boundary information so that the attachments part can't be parsed correctly in the received email.
I think digging into the actionmailer source code and you should be able to find a solution, either by override the default mail method or set the correct boundary info manually.
But for quick resolving this problem, I thought out a not elegant work around by using meta programming: define a delegation class which inherits ActionMailer::Base.
class AnyMailer < ActionMailer::Base
# a delegation mailer class used to eval dynamic mail action
end
Then eval this class with defining an arbitrary method to perform the email sending.
def send_email(connection, files)
AnyMailer.class_eval do
def any_mailer(connection, files)
files.each do |file|
report_file_name = :foo
file_location = :bar
attachments[report_file_name] = File.open(file_location, 'rb'){|f| f.read}
end
mail(to: connection['to'], from: connection['from'], subject: 'Sample File', body: "<p>Hello,</p><p>Your data is ready</p>")
end
end
AnyMailer.any_mailer(connection, files).deliver_now
end
Attention, you don't need to specify the content_type as 'multipart/mixed', ActionMailer will handle it correctly. I tried to specify it explicitly but get messed up email content instead.
Upvotes: 0