I am using the following code to send an email with a pdf attachment:
class StudyMailer < ActionMailer::Base
def notify_office(study, sent_at = Time.now)
subject "Email Subject Goes Here"
recipients 'user#domain.come'
from "#{study.sender.full_name} <#{study.sender.email}>"
sent_on sent_at
body :study => study
for document in study.documents
attachment :content_type => "application/pdf", :body => File.read(document.document.path) #absolute path to .pdf document
end
end
end
When the email is sent, the attachment seems to render inline as binary code rather than as a .pdf attachment.
How do I render the .pdf as a typical attachment, rather than inline?
attachment :content_type => "application/pdf",
:content_disposition => "attachment",
:filename => File.basename(fattach),
:body => File.new(fattach,'rb').read()
Notice the content-disposition line.
I believe you have to indicate the multipart nature of the email, so add this line under the from line:
content_type "multipart/alternative"
Does your email have a template? If the email does not have a template, the attachment shows up inline even if everything else is set up correctly. Create an attachment email template.
views/notifier/attachment.html.erb
<p> Please see attachment </p>
Then in Notifier, specify to use this template.
notifier.rb
def my_email_method
...
mail(:template_name => 'attachment', :from => from_address, ...)
end
Related
Here after called the controller.rb, one file(chart.png) will save in my rails app folder, so how to take this and will attach with mail?
controller.rb
def mail
#imageURL = "https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=5&choe=UTF-8"
open(#imageURL) do |chart|
File.open('chart.png', 'wb') {|f| f.write chart.read }
end
UserMailer.welcome_email(#imageURL, #mailID).deliver
end
how can i pass that image into welcome_email method for attaching with the mail? need some help to solve this?
user_mailer.rb
def welcome_email(imageURL, mailID)
mail(:to => mailID,
:subject => "code",
:body => "Code for the branch "+imageURL+"")
end
end
If you want to attach it to the email, you'd have to download the image, and then attach it from the file-system.
Creating attachment is easy :
attachments["filename"] = File.read("/path/to/file")
If I were you, I'd just add the image in an image_tag in the body of the email
Edit : I didn't see you were already writing the file.
So here is the complete solution :
def mail
#imageURL = "https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=5&choe=UTF-8"
path_image = "/tmp/chart-#{#imageUrl.hash}.png" #Avoid filename collision
open(#imageURL) do |chart|
File.open(path_image, 'wb') {|f| f.write chart.read }
end
UserMailer.welcome_email(#imageURL,#mailID, path_image).deliver
File.delete(path_image)
end
def welcome_email(imageURL,mailID, path_image)
attachments["charts.png"] = File.read(path_image)
mail(:to => mailID,
:subject => "code",
:body => "Code for the branch "+imageURL+"")
end
How to render prawn pdf as attachment in ActionMailer? I use delayed_job and don't understand, how could I render pdf-file in action mailer (not in controller). What format should I use?
You just need to tell Prawn to render the PDF to a string, and then add that as an attachment to the email. See the ActionMailer docs for details on attachments.
Here's an example:
class ReportPdf
def initialize(report)
#report = report
end
def render
doc = Prawn::Document.new
# Draw some stuff...
doc.draw_text #report.title, :at => [100, 100], :size => 32
# Return the PDF, rendered to a string
doc.render
end
end
class MyPdfMailer < ActionMailer::Base
def report(report_id, recipient_email)
report = Report.find(report_id)
report_pdf_view = ReportPdf.new(report)
report_pdf_content = report_pdf_view.render()
attachments['report.pdf'] = {
mime_type: 'application/pdf',
content: report_pdf_content
}
mail(:to => recipient_email, :subject => "Your report is attached")
end
end
I followed the RailsCasts for PRAWN. Taken what has already been said and what I was trying to similarly accomplish, I set the attachment name and then created the PDF.
InvoiceMailer:
def invoice_email(invoice)
#invoice = invoice
#user = #invoice.user
attachments["#{#invoice.id}.pdf"] = InvoicePdf.new(#invoice, view_context).render
mail(:to => #invoice.user.email,
:subject => "Invoice # #{#invoice.id}")
end
My solution:
render_to_string('invoices/show.pdf', :type => :prawn)
PDF was corrupted because I didn't write block for mail function and multi-part email was incorrect.
I am using Rails 2.3.11. I created a UserMailer with following methods:
def rsvp_created(user, rsvp, pdf_file)
setup_email(user)
content_type "multipart/mixed"
#subject << "Your RSVP for #{rsvp.ticket.holiday.title}"
#body[:rsvp] = rsvp
attachment :content_type => 'application/pdf',
:body => File.read(pdf_file),
:filename => "#{rsvp.confirmation_number}.pdf"
end
def rsvp_cancelled(user, rsvp)
setup_email(user)
content_type "text/html"
#subject << "Cancelled RSVP for #{rsvp.ticket.holiday.title}"
#body[:rsvp] = rsvp
#body[:holiday_url] = APP_CONFIG['site_url'] + holiday_path(rsvp.ticket.holiday)
end
protected
def setup_email(user)
#recipients = "#{user.email}"
#from = APP_CONFIG['admin_email']
#subject = "[#{APP_CONFIG['site_name']}] "
#sent_on = Time.now
#body[:user] = user
end
The rsvp_cancelled works fine and sends email properly. But the rsvp_created email, which has an attachment, doesn't work properly. It sends the email with the attached file but doesn't render any text. Any one faced this issue before or know how I can resolve it?
Thanks
With Rails 2.x, for some reason or the other you need to define all the parts for the HTML to appear.
def rsvp_created(user, rsvp, pdf_file)
setup_email(user)
content_type "multipart/mixed"
#subject << "Your RSVP for #{rsvp.ticket.holiday.title}"
part :content_type => 'multipart/alternative' do |copy|
copy.part :content_type => 'text/html' do |html|
html.body = render( :file => "rsvp_created.text.html.erb",
:body => { :rsvp => rsvp } )
end
end
attachment :content_type => 'application/pdf',
:body => File.read(pdf_file),
:filename => "#{rsvp.confirmation_number}.pdf"
end
Thankfully it appears this is not the case in Rails 3.x.
I was trying to do the same sort of thing, but following Douglas' answer above, kept getting corrupted pdf attachments. I was finally able to resolve the issue by reading the pdf file in binary mode:
attachment :content_type => 'application/pdf',
:body => File.open(pdf_file, 'rb') {|f| f.read}
:filename => "#{rsvp.confirmation_number}.pdf"
I was able to get mine working with Douglas' answer but was also able to get it working in one line. I was using a template but this also works by substituting "rsvp" for the render_message method.
part :content_type => "text/html",
:body => render_message("template_name", { :symbol => value } )
My application creates a .pdf file when it is rendered by passing it to the URL (for example, domain.com/letter/2.pdf)
It doesn't get saved anywhere.
How can I make that actual pdf an attachment in an outbound email.
Here is my mailer:
def campaign_email(contact,email)
subject email.subject
recipients contact.email
from 'Me <me#me.com>'
sent_on Date.today
attachment = File.read("http://localhost:3000/contact_letters/#{attachment.id}.pdf")
attachment "application/pdf" do |a|
a.body = attachment
a.filename = "Othersheet.pdf"
end
end
This is the controller that creates/renders the PDF:
def create
#contact_letter = ContactLetter.new(params[:contact_letter])
#contact = Contact.find_by_id(#contact_letter.contact_id)
#letter = Letter.find_by_id(#contact_letter.letter_id)
if #contact_letter.save
flash[:notice] = "Successfully created contact letter."
#redirect_to contact_path(#contact_letter.contact_id)
redirect_to contact_letter_path(#contact_letter, :format => 'pdf')
else
render :action => 'new'
end
end
NOTE: I hardcoded localhost:3000/ how can I substitute that with a variable so that on dev it is localhost:3000 and on production is it the correct domain? Is there a way to include routing in this?)
ERROR: I get an
Invalid argument -
http://localhost:3000/contact_letters/9.pdf
Here's an example for rails 2
class ApplicationMailer < ActionMailer::Base
# attachments
def signup_notification(recipient, letter)
recipients recipient.email_address_with_name
subject "New account information"
from "system#example.com"
attachment :content_type => "image/jpeg",
:body => File.read("an-image.jpg")
attachment "application/pdf" do |a|
a.body = letter
end
end
end
in your view or wherever your calling your method:
ApplicationMailer.deliver_signup_notification(letter)
one quick an easy solution would be fetch the url content using net/http and open-uri, to get the attachment
attachments['free_book.pdf'] = open("http://#{request.host}/letter/#{id}.pdf")
eg:
def campaign_email(contact,email)
subject email.subject
recipients contact.email
attachments['free_book.pdf'] = open("http://#{request.host}/letter/#{id}.pdf")
from 'Me <me#me.com>'
sent_on Date.today
body :email => email
end
or, call the PDF generation inside your mailer controller action
I got it to work by passing the pdf object directly into the campaign_email method and then assigning an attachment.
How do I reuse the same action mailer template for multiple mailer "actions"?
In ActionController, you can do
...
render :action => 'another_action'
I'd imagine the same thing can be done in ActionMailer, but I couldn't seem to find the right method. If it's relevant, I'm on Rails 2.3.2.
Thanks!
You're looking for render_message, there is a good example in the API Docs Multipart Message section - pasted below.
class ApplicationMailer < ActionMailer::Base
def signup_notification(recipient)
recipients recipient.email_address_with_name
subject "New account information"
from "system#example.com"
content_type "multipart/alternative"
part :content_type => "text/html",
:body => render_message("signup-as-html", :account => recipient)
part "text/plain" do |p|
p.body = render_message("signup-as-plain", :account => recipient)
p.transfer_encoding = "base64"
end
end
end