I am using the Mandrill API to handle my transactional email for a variety of reasons. One issue I am encountering is generating the confirmation_url, edit_password_url and unlock_url in the new mailer. I am including Devise's URL helpers in the new mailer. Everything else in the email is being generated properly.
I am getting the following error:
NoMethodError (undefined method `main_app' for #<DeviseMailer:0x007f812b6abe78>):
app/mailers/devise_mailer.rb:15:in `confirmation_instructions'
app/controllers/lenders/registrations_controller.rb:9:in `create'
devise_mailer.rb
class DeviseMailer < MandrillMailer::TemplateMailer
helper :application
include Devise::Controllers::UrlHelpers
default from: 'no-reply#test.com'
def confirmation_instructions(record, token)
mandrill_mail template: 'Confirmation Instructions',
subject: 'Confirm Email',
from_name: 'Test',
to: { email: record.email },
vars: {
'FNAME' => record.first_name,
'LIST_COMPANY' => "Apples",
'HTML_LIST_ADDRESS_HTML' => "1 Infinite Loop",
'CONFIRMATION_LINK' => confirmation_url(record, :confirmation_token => token)
}
end
end
Thank you for the help
For anyone hitting this issue - I had the same method missing issue when using mandrill_mailer to replace devise's customer mailer.
Using the above example above I fixed it like so
class DeviseMailer < MandrillMailer::TemplateMaile
# ..... mailer code in here here .....
private
def main_app
Rails.application.routes.default_url_options[:host] = Rails.application.routes.default_url_options[:host]
Rails.application.routes.url_helpers
end
end
Related
I am trying to send an email while using noticed gem version 1.4.1
This is my notification class
class Freelancer::UpdatePayoutSetting < Noticed::Base
# Add your delivery methods
deliver_by :database
deliver_by :email, mailer: "FreelancerMailer", method: 'updated_settings'
# deliver_by :slack
# deliver_by :custom, class: "MyDeliveryMethod"
# Add required params
param :user
# Define helper methods to make rendering easier.
def message
t("notifications.client.update_payout_setting.message", name: "#{params[:user]&.first_name} #{params[:user]&.last_name}")
end
def url
freelancer_profile_path
end
end
And this is my Mailer code
class FreelancerMailer < ApplicationMailer
def updated_settings
#user = params[:user]
mail(to: #user.email, subject: "#{#user.name} Your Business Info Update successfully.")
end
end
`
And this is my updated_settings.html.erb code for mailer action
<p>Hi <%= #user.name %>,</p>
<p>Your Payout Setting Update Successfully.</p>
<p>Regards,</p>
<p>Team Loovit</p>
I am calling this by running below command
Freelancer::UpdatePayoutSetting.with(user: current_user).deliver_later(current_user)
And its working fine on my local machine but it produces this Error on my production server
NoMethodError: undefined method `updated_settings' for #ActionMailer::Parameterized::Mailer:0x00005635bdaaa9d0
I have added the devise_invitable gem and a custom mailer. It works and normal devise emails (eg. confirmation_instructions) are reading the i18n file correctly, but invitation_instructions is not.
Here is the devise.en.yml:
en:
devise:
mailer:
confirmation_instructions:
subject: "Hi %{first_name}, please confirm your email to activate your account"
invitation_instructions:
subject: "%{first_name} has invited you to join their team!"
hello: "Oi"
someone_invited_you: "Pig"
The custom mailer class:
class CustomDeviseMailer < Devise::Mailer
def confirmation_instructions(record, token, opts={})
custom_options(record, opts, :confirmation_instructions)
super
end
def invitation_instructions(record, token, opts={})
custom_options(record, opts, :invitation_instructions)
super
end
private
def custom_options(record, opts, key)
opts[:subject] = I18n.t('subject', scope: [:devise, :mailer, key], first_name: record.first_name)
end
end
If I change the invitation_instructions method to this:
def invitation_instructions(record, token, opts={})
custom_options(record, opts, :invitation_instructions)
opts[:subject] = "TEST"
super
end
then the invitation email subject correctly changes to 'TEST'.
So why is it not reading the i18n file?
NOTE
I also generated the default invitation view and that is also not reading the i18n file. For example the first line of the default view is:
\app\views\devise\mailer\invitation_instructions.html.erb
<p>
<%= t("devise.mailer.invitation_instructions.hello", email: #resource.email) %>
</p>
Which should render 'Oi' from the i18n file, but it renders the default 'Hello' instead.
It turns out that the devise_invitable gem does not read devise.en.yml because it creates its OWN locale file:
devise_invitable.en.yml
and so that is where I need to make the text customisations.
I want to send devise confirmation mails using sendgrid templates, so I have a template on sendgrid which I will use and this code in rails
class CustomMailer < Devise::Mailer
helper :application # gives access to all helpers defined within `application_helper`.
include Devise::Controllers::UrlHelpers # Optional. eg. `confirmation_url`
default template_path: 'devise/mailer' # to make sure that your mailer uses the devise views
def confirmation_instructions(record, token, opts={})
headers["X-SMTPAPI"] => {
"sub": {
"%record%" => [record],
"%token%" => [token],
},
"filters": {
"templates": {
"settings": {
"enable": 1,
"template_id": 'id here'
}
}
}
}.to_json
mail(
subject: "subject"
)
end
the problem is I have this error when it tries to send the mail:
An ActionView::Template::Error occurred in registrations#create:
undefined method `url' for nil:NilClass
app/views/devise/mailer/confirmation_instructions.html.erb:5:in `_app_views_devise_mailer_confirmation_instructions_html_erb___3785479096466683301_70149801011060'
so it seems like rails trying to send email the default way and no sengrid flow was triggered
I'm trying to figure out how to setup my Rails 4 app so that the devise mailer sends through Postmark, using Postmark Templates.
I have postmark-rails gem in my gem file.
I have everything working, except I can't figure out how to give the confirmation token to postmark.
In Postmark I have this template:
To get started, please confirm your account below:
action_url_Value
I can't figure out how to put the following line into the template instead of action url value:
<%= link_to 'Confirm my account', confirmation_url(#resource, confirmation_token: #token) %></div>
I have added the following to my initializer/devise.rb:
config.mailer = 'PostmarkDeviseMailer'
In postmark_devise_mailer.rb, I have:
class PostmarkDeviseMailer < ActionMailer::Base
include Devise::Mailers::Helpers
def message
mail(
:subject => 'Hello from Postmark',
:to => 'sender#address.com',
:from => 'sender#address.comm',
:html_body => '<strong>Hello</strong> dear Postmark user.',
:track_opens => 'true')
end
end
default from: "sender#address.com"
def confirmation_instructions(record)
devise_mail(record, :confirmation_instructions)
end
def reset_password_instructions(record)
devise_mail(record, :reset_password_instructions)
end
def unlock_instructions(record)
devise_mail(record, :unlock_instructions)
end
The next steps are less clear to me. Has anyone figured out how to use Postmark Templates as the mailer for devise transaction emails?
The first thing you need to do is create a custom mailer in app/mailers in this example it is user_mailer.rb If you are reading this answer, I am assuming you both have a postmark account if not grab one here: Postmark Registration and I am assuming you have a template and layout selected.
One important item to remember is to make sure you assign an alias to your template. This can be found in a small link found above the template title in small gray text.
The items within self.template_model are 100% customizable and are shown in your layout / template editors as so: {{product_name}}.
class UserMailer < Devise::Mailer
include PostmarkRails::TemplatedMailerMixin
helper :application
include Rails.application.routes.url_helpers
include Devise::Controllers::UrlHelpers
default from: 'from_you#something.com'
default reply_to: 'support#hammer-lane-industries.com' # Optional
def confirmation_instructions(record, token, opts={})
#admin = record
#token = token
# this will pass the data via the postmark-api to your template / layout these fields are 100% customizable and can be cahnged in your template / layout
self.template_model = { product_name: 'your product',
username: #user.username,
email: #user.email,
confirmation_url: user_confirmation_url(#resource, confirmation_token: #token, subdomain: 'add subdomain here if needed'),
login_url: login_root_url(subdomain: 'add subdomain here if needed'),
trial_length: '14-days',
sender_name: 'What ever you want',
action_url: user_confirmation_url(#resource, confirmation_token: #token, subdomain: 'add subdomain here if needed'),
parent_company_name: 'Your company name',
company_address: 'Your address'}
mail to: #admin.email, postmark_template_alias: 'devise_user_confirmation'
end
end
Rinse and repeat with unlocks and password mailers, all you will need to know is the urls that you'll be sending the tokens to.
To finish it all off:
You will need to add a small block to your devise resource model, in this example I've used user.rb
class User < ApplicationRecord
devise :database_authenticatable, :confirmable,
:recoverable, :rememberable, :validatable,
:timeoutable, :trackable
def devise_mailer
UserMailer # Must match your mailer class
end
end
Once this is done, restart your rails server, and give it a go!
I hope this helps you with hooking Postmark Templates (API) into Devise mailers
Response from Postmark help desk is:
Unfortunately, Postmark templates don’t fit nicely into the traditional Rails ecosystem. See my reply here for more details:
https://github.com/wildbit/postmark-rails/issues/53
To sum it up, by using the Postmark API with Postmark templates you could potentially replace ActionMailer, but mixing them together presents a significant challenge. Unfortunately, we’ve never tried the "ActionMailer-free" approach with Devise, so I can’t help you here. Unless you have a good reason not to, I’d suggest going with ActionMailer templates and using the postmark-rails gem as a delivery adapter. This approach is known to work well with Devise. Please let me know if you have any questions.
I'm trying to make an app in Rails 4.
For the past 3 years, I've been struggling to figure out devise/omniauth (I am still trying to get it to work).
Stepping aside from the main problems while I try and find the will to live through this, I've tried to setup emails with Mandrill.
I found this tutorial, which I am trying to follow along: https://nvisium.com/blog/2014/10/08/mandrill-devise-and-mailchimp-templates/
I have a mailer called mandrill_devise_mailer.rb
class MandrillDeviseMailer < Devise::Mailer
def confirmation_instructions(record, token, opts={})
# code to be added here later
end
def reset_password_instructions(record, token, opts={})
options = {
:subject => "Reset your password",
:email => record.email,
:global_merge_vars => [
{
name: "password_reset_link",
# content: "http://www.example.com/users/password/edit?reset_password_token=#{token}"
content: "http://www.cr.com/users/password/edit?reset_password_token=#{token}"
},
{
name: "PASSWORD_RESET_REQUEST_FROM",
content: record.full_name
}
],
:template => "Forgot Password"
}
mandrill_send options
end
def unlock_instructions(record, token, opts={})
# code to be added here later
end
def mandrill_send(opts={})
message = {
:subject=> "#{opts[:subject]}",
:from_name=> "Reset Instructions",
# :from_email=>"example#somecorp.com",
:from_email=>["PROD_WELCOME"],
:to=>
[{"name"=>"#{opts[:full_name]}",
"email"=>"#{opts[:email]}",
"type"=>"to"}],
:global_merge_vars => opts[:global_merge_vars]
}
sending = MANDRILL.messages.send_template opts[:template], [], message
rescue Mandrill::Error => e
Rails.logger.debug("#{e.class}: #{e.message}")
raise
end
end
The differences between the above and what they have done in the tutorial are:
In my mail chimp mandrill template, I have:
Change my password
When I receive the email to reset the instructions, I get an underlined link to the change password form, which says 'change my password next to it. I want 'change my password to be the label which conceals the link text'.
Can anyone see what I've done wrong?
Here is how I created custom DeviseMailer
class MyDeviseMailer < Devise::Mailer
default template_path: 'devise/mailer' # to make sure that your mailer uses the devise views
def reset_password_instructions(record, token, opts={})
opts['from_email'] = "donotreply#mywebsite.com"
opts['from_name'] = "Password Reset"
#Rails.logger.mail.info "reset_password_instructions #{record.to_json} \n #{token.to_json} \n #{opts.to_json}"
super
end
end
https://github.com/plataformatec/devise/wiki/How-To:-Use-custom-mailer and
Add dynamic value in devise email subject