With RoR ActionMailer, send plain-textmessage without using a view file - ruby-on-rails

For rendering a text (not html) message with ActionMailer in Rails 3, I see many threads instructing the programmer to make a .text.erb file and run the following code:
mail do |format|
format.html
format.text
end
...but I wish to render a very short message, without using a mailer view at all. I have success doing this in html format but not in plain text.
I use the following code:
mail do |format|
format.html{ render( text: 'my text' ) }
format.text{ render( text: 'my text' ) }
end
...but it sends an html email every time. What can I do to send a plain-text email and specify its content without a mailer view file?

From doc:
Action Mailer will automatically send multipart emails if you have
different templates for the same action. So, for our UserMailer
example, if you have welcome_email.text.erb and welcome_email.html.erb
in app/views/user_mailer, Action Mailer will automatically send a
multipart email with the HTML and text versions setup as different
parts.
Just do:
mail do |format|
format.text{ render( text: 'my text' ) }
end
If you only want a text email.

Related

Encoding error using wicked_pdf and rails ActiveJob

I am using wicked-pdf to simplify generating pdf invoices in my Rails 5 application. I have two actions making use of the pdf functionality of wicked-pdf. The first action generates the pdf and renders it in a new browser window. The second method attaches the pdf to an email.
Both of these actions work just fine. The issue comes in when I set my pdf mailer action to 'deliver_later' using ActiveJob/Sidekiq. When I add 'deliver_later' I am presented with a error stating:
"\xFE" from ASCII-8BIT to UTF-8
This error does not happen if I use the "deliver_now" command. Using "deliver_now" send the email and attaches the PDF correctly.
Here is some of my code for the mailing action, mailer and job:
invoices_controller.rb
...
def create
respond_to do |format|
format.html do
pdf = render_to_string( pdf: #order.ruling_invoice,
template: "orders/invoices/show.pdf.haml",
encoding: "utf8",
locals: { order: #order.decorate}
)
SendInvoiceMailJob.new.perform( #order, pdf, #order.token )
redirect_to order_url(id: #order.id, subdomain: current_company.slug), notice: "This invoice has been emailed."
end
end
end
...
send_invoice_mail_job.rb
...
def perform( order, pdf, order_token )
InvoiceMailer.send_invoice(order, pdf, order_token).deliver_later
end
...
invoice_mailer.rb
...
def send_invoice( order, pdf_invoice , invoice_token)
#order = order
attachments["#{invoice_token}.pdf"] = pdf_invoice
mail(
to: #order.email,
from: #order.seller_email
)
end
...
Why would this code work using "deliver_now" in send_invoice_mail_job.rb but it doesn't work using "deliver_later" ?
You can't just throw binary data (the PDF) into job arguments.
https://github.com/mperham/sidekiq/wiki/Best-Practices#1-make-your-job-parameters-small-and-simple
You need to move the PDF compiling from outside of your mailer job to inside it. So in your controller, you can do:
SendInvoiceMailJob.new.perform(#order, #order.token)
Then in your mailer job you can do:
def send_invoice(order, invoice_token)
#order = order
pdf = render_to_string(
pdf: #order.ruling_invoice,
template: "orders/invoices/show.pdf.haml",
locals: { order: #order.decorate }
) )
attachments["#{invoice_token}.pdf"] = pdf_invoice
mail(
to: #order.email,
from: #order.seller_email
)
end
That way you're not passing the PDF binary into the jobs queue.

Rails grab template file as string variable in controller

I'm creating a custom ActionMailer which will also send Direct Messages on Twitter, and Text Message through Twilio. I need each to receive a parameter of the body of the message. I need to use the current template as a string variable.
For example:
# calling send_invite's mail method will load the send_invite template
def send_invite(to)
mail(to: to) # body parameter is automatically rendered from template
end
Now if I modify it to send through other services:
def send_invite(to, option)
if option == :email
mail(to: to) # body parameter is automatically rendered from template
elsif option == :twitter
twitter.create_direct_message(to, NEED_TEMPLATE_AS_STRING_HERE)
elsif option == :sms
twilio.sms(to, NEED_TEMPLATE_AS_STRING_HERE)
end
end
How might I grab the template for each of these service calls? Would there be something like:
message(to, render layout: false)
# or
message(to, IO.read template_path_helper("template") )
# or
message(to, template_helper.to_s)
How might I get the template as a string for my message body in these other methods? What's the Rails Way to do it? The templates are erb files and need to be able to render the appropriate variable as they would from a render.
I need to do it this way for translations of templates to be available.
I think you can create the template string from the controller, and send it to your mailer, like this:
#parsed_template = render_to_string(:partial => 'my_partial', :layout => false, :locals => {:my_object => my_value})
SomeMailer.send_invite(to, option, #parsed_template).deliver

Sending multipart emails with Rails: how to favor the HTML version over the plain text one?

I setup a standard rails mailer with multipart view following the official guide, like this:
mail(to: user.email, subject: "Welcome") do |format|
format.html { render layout: 'my_layout' }
format.text
end
With the clear and common intent to give priority to the html version of the message, only to find that, as this article points out, calling format.html before the format.text makes a lot of mail clients to show only the text version of the message. In my case I verified (and struggled with) that with both Gmail and Mozilla Thunderbird.
Is there a reliable solution to give precedence to the html version?
The only solution I found so far is to switch format.html with format.text so that the text format is called before the html one. Which is exactly the opposite of what one would expect.

PDF attachment in email is called 'Noname'

When I send an email with a attached pdf file the email only shows a file called 'Noname'. The file itself is the multipart section of the email with the base64 attached pdf. How can I send the PDF so it comes up as an attachment and doesn't corrupt the email?
Here is my code:
attachments['126539_statistics.pdf'] = File.read("app/assets/pdfs/126539_statistics.pdf")
mail(:to => email, :subject => subject, :body => message, :content_type => 'application/pdf')
I had face same problem. I have corrected it by following way
1) As per ActionMailer Guide, You need to make view file into app/views/[action_mailer_model_name]/[method_name]
Here is reference of guide: http://api.rubyonrails.org/classes/ActionMailer/Base.html
2) Action Mailer is smart enough that it identify content-type automatically while reading file. So there is no need to pass explicitly 'application/pdf' in your mail function.
Hope, this information helps to solve your problem
Also experienced the same problem
solution is :
set Attachments before sending mail function.
code is attached below:
attachments["invoice_#{invoice.bill_date.strftime('%B-%Y')}.pdf"] = WickedPdf.new.pdf_from_string(
render_to_string pdf: 'project_report.pdf',
template: 'users/_invoice.html.erb'
)
mail(to: email , from: from, subject: subject) do |format|
format.html
end

Why do I have to specify text format to render template with ActionMailer?

I'm using ActionMailer 3.0.7
According to the docs plain text emails are the default. So if I have an EnquiryNotifier mailer with a notify method then I expect that app/views/enquiry_notifier/notify.text.plain.erb will be rendered.
If I simply use mail(someparams) within the notify method then the body of the email is empty.
I read that ActionMailer is meant to scan the view directory to look for all types of templates.
However, if I specify the format within a block and do
mail(:to => 'somebody', :subject => 'something') do |format|
format.text
end
then my template notify.text.plain.erb does get rendered.
Maybe unrelated: If I don't specify the format but rename the template to notify.erb then it works but the email is sent as text/html.
Here's what seems to work for me in rails 3.0.6:
I don't specify a format at all in my mailer class, I just let it find the view automatically.
I name my view "notify.text.erb"

Resources