Sending mail, getting ActionView::MissingTemplate <path> with 'mailer' - ruby-on-rails

When trying to send emails with Sidekiq, I am getting this error
ActionView::MissingTemplate: Missing template campaign_mailer/hugh_email with "mailer". Searched in: * "campaign_mailer"
In the controller
CampaignMailer.hugh_email(email, user).deliver_later
In campaign_mailer.rb
layout 'mailer'
def hugh_email(email, user)
mail(to: #user.email, subject: email.subject)
end
app/views/campaign_mailer/hugh_email.html.slim has the html, and I have a template in layouts/mailer
Note: I have tried everything I can find, even re-generated mailers. It seems to work with a new mailer when I send with deliver_now, but as soon as I try deliver_later the error returns (even when going back to trying a deliver_now).
UPDATE:
My solution to this probably won't help many people, but I'll add it here just in case.
I now save the emails on my system, and pass the html into the mailer with CampaignMailer.hugh_email(email.subject, html).deliver_later. In the campaign_mailer.rb I run
mail(to: to_address, subject: email_subject) do |format|
format.text { render(text: "") }
format.html { html }
end
Again, unfortunately this probably won't help most people having this issue. But I essentially solved the problem by specifying the html instead of using the mailer view.

hugh_email.html.slim must be at
/app/views/campaign_mailer/hugh_email.html.slim
mailer.html.slim at
/app/views/layouts/mailer.html.slim
mailer.text.erb at
/app/views/layouts/mailer.text.erb

Related

setting erb template in Rails with mailgun-ruby

I would like to use the mailgun-ruby MessageBuilder API to build and send application emails in my production environment. The documentation suggests that I do something like this:
def confirmation_instructions(record, token, opts={})
mg_client = Mailgun::Client.new ENV['MAILGUN_API_KEY']
mb_obj = Mailgun::MessageBuilder.new
mb_obj.from("from#site.com", {"first" => "First", "last" => "Last"})
mb_obj.add_recipient(:to, record.email)
mb_obj.subject("Please confirm your account")
mb_obj.body_html("<p>how would i pass the default confirmation_instructions erb template as an argument to this method?</p>")
mg_client.send_message("mail.site.com", mb_obj)
end
The problem is, once I started using Mailgun, I also stopped using ActionMailer's default mail() syntax. This seems to prevent Rails from manually selecting the template that matches the method name.
My first thought is I need to select it manually. An answer here says that I can change the template like this:
mail(to: user.email, subject: "New Projects") do |format|
format.html { render layout: layout_name }
format.text { render layout: layout_name }
end
But this syntax conflicts with what is expected by mailgun-ruby. I can't leave the body/text setting methods out, and if I do, it throws an error: Mailgun::CommunicationError (400 Bad Request: Need at least one of 'text' or 'html' parameters specified).
In the first example above, how would I pass the proper layout to body_html? That is, without directly writing the html in as an argument?
Update: my rake routes for confirmations
new_user_confirmation GET /users/confirmation/new(.:format) users/confirmations#new
user_confirmation GET /users/confirmation(.:format) users/confirmations#show
POST /users/confirmation(.:format) users/confirmations#create
update_user_confirmation PATCH /users/confirmation(.:format) users/confirmations#update
Looking at the gem's issues, it looks like it is not supported.
The way to go is to use your preferred template engine and give the output to the body_html.
You're not telling it, but looking at the method name, I guess you're using the Devise gem, and you'd like to send its content.
Here is how to make it working (didn't try it):
def confirmation_instructions(record, token, opts={})
email_html_body = ERB.new(File.read('devise/mailer/confirmation_instructions.html.erb'))
.result_with_hash(
email: current_user.email,
resource: resource,
token: #token
)
# ...
mb_obj.body_html(email_html_body)
# ...
end
Wow, so...Rails default mail() syntax does still work with Mailgun. I don't know why it was not at first attempt, but I think it had something to do with the fact that I had not set the production.rb config to config.action_mailer.delivery_method = :mailgun.

Preview emails in rails with text and html

In our Rails 3.2 app we have the following set up to preview emails:
examples_controller
def registration
mail = EventMailer.registration(registration: EventRegistration.last, cache_email: false)
return render_mail(mail)
end
event_mailer.rb
def registration(options = {})
#registration = options[:registration]
#event = Event.find(#registration.event_id)
#subject = options[:subject] || 'Your Learn Registration'
return_email = mail(to: #registration.email, subject: #subject)
# the email if we got it
return_email
end
We just added a text version of the emails, so now in app/views/event_mailer we have registration.html.erb and registration.text.erb. Before adding the text version of the email users could browse to /webmail/examples/registration and view the html version of the email. After adding the text email, that is broken.
Ideas on how to fix this? I tried setting multipart to false in the examples controller, but that did not work.
Also, here is the render_mail method...
def render_mail(mail)
# send it through the inline style processing
inlined_content = InlineStyle.process(mail.body.to_s,ignore_linked_stylesheets: true)
render(:text => inlined_content, :layout => false)
end
I think it's not easy to debug all this code with just seeing some parts, so I'm going to suggest a different solution.
Some time ago I wrote a gem to preview emails (attachments and multiparts as well) in the browser: https://github.com/markets/maily
Main features:
Visual preview via browser (multiparts and attachments)
Template edition (development)
Email delivery
Flexible authorization system
Easy way to hook sample-data for emails
It's a Rails mountable (by default under /maily) engine, so you just need to install it, configure it and you'll be able to preview your email templates in your browser.
You can try to integrate Maily and you'll get a lot of things done, ping me if you have any doubt or suggestion.

Rails mailer and mailer views in subfolder not working

I have a mailer that I can see in my log is getting sent, but the email body does not contain anything from the mailer view.
It's due to the fact that I've put things in subfolders and i've tried using :template_path in my mail function but to no avail.
app/mailers/marketing/marketing_mailer.rb
class Marketing::MarketingMailer < ActionMailer::Base
require 'mail'
address = Mail::Address.new "test#example.com" # ex: "john#example.com"
address.display_name = "Text" # ex: "John Doe"
# Set the From or Reply-To header to the following:
address.format # returns "John Doe <john#example.com>"
default from: address
# Sends an email when someone fills out the contact form
def contact(name, email, message)
#name = name
#email = email
#message = message
mail(:subject => "Test", :to => 'test#example.com', :reply_to => #email) # <== I've tried using :template_path => 'marketing', 'marketing/marketing_mailer', etc, but none worked.
end
end
/app/views/marketing/marketing_mailer/contact.html.erb
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
</head>
<body>
<p>Name: <%= #name %></p>
<p>Email: <%= #email %></p>
<p>Message: <%= #message %></p>
</body>
</html>
I noticed that devise has mailer views inside /views/devise/mailers/... so I know it's possible, but i'm not sure how.
Have you tried mail with {:template_path => 'marketing/marketing_mailer, :template_name =>'contact'} ?
The template name probably expects the namespace in the filename somehow
Does it work without the template Rendering
class Marketing::MarketingMailer < ActionMailer::Base
def welcome_email(user, email_body)
mail(to: user.email,
body: email_body,
content_type: "text/html",
subject: "Already rendered!")
end
end
I came back to this project today and it seems to be finding the template today no problem without having to specify the template_path.
As sad as this is, apparently all I needed to do was stop and restart my server for my mailer views to get picked up. Since other views get picked up without stopping and starting my server, i'm very surprised by this.
Since your file is in the format of .html.erb, you may have to specify that you want to use this format. Like so:
mail(:subject => "Test", :to => 'test#example.com', :reply_to => #email) do
format.html
end
Usually, your template should just be picked up automatically, since the names match up, but there's probably a second file by the same name ending in .text.erb or some other thing that gets in the way of template look-up.
EDIT1 (wild guess)
Aside from template lookup issues, the only other source of problems I can imagine, would be your instance variables. Maybe #message is supposed to be something else and you're interfering with internals, so renaming it might help. According to the code on apidock, mail is using #variables at certain places. This is far fetched though, I admit.
EDIT2 (explanation of the problem faced here)
The behavior behind the actual problem - not finding a new template until server restart - works like this:
A template gets looked up but at that time, it's not present yet. The server doesn't find it, but remembers the fact that it's not there. Then won't look for it again until the next restart, even though you added it.
So, restarting will fix this.
Have you tried turning it off and on again?

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.

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