How to pass data to custom mailer in rails? - ruby-on-rails

I am using custom mailer to send confirmation email to user but I need to pass some data to the mailer. I have tried using session and application helper but no success.
Application helper is not able to access session data.
mailer is also not able to access session data.
This is my code
class CustomMailer < Devise::Mailer
helper :application # gives access to all helpers defined within `application_helper`.
include Devise::Controllers::UrlHelpers # Optional. eg. `confirmation_url`
#include ApplicationHelper
default template_path: 'devise/mailer' # to make sure that you mailer uses the devise views
def confirmation_instructions(record, token, opts={})
opts[:subject] = "Email Confirmation"
opts[:from] = 'no-reply#test.com'
end
end
I dont want to call custommailer from controller. I just want to pass data.
Is this possible?

Related

Pass variable from Devise controller to custom mailer?

I use Devise for authentication in my Rails app.
In my registrations_controller I have a variable like this:
class RegistrationsController < Devise::RegistrationsController
def create
foo = "bar"
super
end
end
In my customized mailer I then try to access the foo variable. The opts argument seems to be the one to look at:
class CustomMailer < Devise::Mailer
helper :application
include Devise::Controllers::UrlHelpers
def confirmation_instructions(record, token, opts={})
Rails.logger.error opts[:foo].inspect
super
end
end
But how do I pass on the foo variable on, without overwriting a lot of methods?
First, read about Devise custom mailer to familiarize yourself with the process.
Briefly this is how you'd go about doing it:
in config/initializers/devise.rb:
config.mailer = "DeviseMailer"
Now you can just use DeviseMailer like you'd do for any other mailer in your project:
class DeviseMailer < 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["Custom-header"] = "Bar"
opts[:from] = 'my_custom_from#domain.com'
opts[:reply_to] = 'my_custom_from#domain.com'
super
end
...
end
You can now call the confirmation_instructions in your project and pass whatever variable you want to be able to access in your template.
i.e:
Calling the confirmation_instructions method:
DeviseMailer.confirmation_instructions(User.first, "faketoken", {})
confirmation_instructions.html.erb
<p> And then override the template according to you. <p>
Hope this will help you :)

Failed Resque Job for Devise Invitable - undefined method `invitation_instructions' for #<User:0x

Ruby on Rails Project, I'm running Resque to process emails (in particular Devise and Devise Invitable). Devise emails are sending fine (out via API through postmark gem) but devise_invitable emails are failing in Resque with undefined method invitation_instructions for #User:0x0xxxxxx Did you mean? invitations_count.
When sending through the default devise mailer it all works fine, but fails with my custom mailer. I am wanting to add an inline attachment, hence the need for a custom mailer.
Custom Devise Mailer:
class DeviseMailer < Devise::Mailer
helper :application
include Devise::Controllers::UrlHelpers
include Devise::Mailers::Helpers
include DeviseInvitable::Mailer
default template_path: 'devise/mailer'
default from: sender#example.com
layout 'mailer_devise'
before_action :add_inline_attachment!
def reset_password_instructions(record, token, opts={})
super
end
def invitation_instructions(record, token, opts={})
#token = token
devise_mail(record)#, record.invitation_instructions || :invitation_instructions, opts)
end
private
def add_inline_attachment!
attachments.inline['logo.png'] = File.read(Rails.root.join('app/assets/images/logo.png'))
end
end
Summary:
def reset_password_instructions - working fine
def invitation_instructions - failing with undefined method error
I ended up migrating to Sidekiq for other reasons. Below is my updated Devise Mailer Class, which is working well. There was no need to define the invitation_instructions method as the before_action callback was attaching the inline image, what was what i was after in the beginning.
class DeviseMailer < Devise::Mailer
helper :application
include Devise::Controllers::UrlHelpers
include Devise::Mailers::Helpers
include DeviseInvitable::Mailer
default template_path: 'devise/mailer'
default from: ENV['EMAIL_NAME']
layout 'mailer_devise'
before_action :add_inline_attachment!
private
def add_inline_attachment!
attachments.inline['logo.png'] = File.read(Rails.root.join('app/assets/images/logo.png'))
end
end

Devise doesn't override email views

I have my scope views reset_password_instructions.html
and in my devise.rb
config.scoped_views = true
It works fine in development and sends the custom email. However, in production, when user receives email, device sent a default template.
How can I fix this in production?
when I use devise I this is what I do to send my own emails
class MyMailer < 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
end
now, in your config/initializers/devise.rb, you can set config.mailer to "MyMailer".
You may now use your MyMailer in the same way as any other mailer. In case you want to override specific mails to add extra headers, you can do so by simply overriding the method and calling super at the end of your custom method, to trigger Devise's default behavior.
You can also override any of the basic headers (from, reply_to, etc) by manually setting the options hash:
def confirmation_instructions(record, token, opts={})
headers["Custom-header"] = "Bar"
opts[:from] = 'my_custom_from#example.com'
opts[:reply_to] = 'my_custom_from#example.com'
super
end
In order to get preview (if User is your devise model name):
# test/mailers/previews/my_mailer_preview.rb
# Preview all emails at http://localhost:3000/rails/mailers/my_mailer
class MyMailerPreview < ActionMailer::Preview
def confirmation_instructions
MyMailer.confirmation_instructions(User.first, "faketoken", {})
end
def reset_password_instructions
MyMailer.reset_password_instructions(User.first, "faketoken", {})
end
def unlock_instructions
MyMailer.unlock_instructions(User.first, "faketoken", {})
end
end
I hope that this was useful :)

Devise mailer custom domain from option

Given that request object is not working in ActionMailer, is there a way to detect current URL and set from option for custom devise mailer controller?
So this is what I have so far in application_controller.rb:
before_filter :images, :hide_sidebar, :global_vars, :set_mailer_host
before_action :sidebar_menu
def set_mailer_host
ActionMailer::Base.default_url_options[:host] = request.host_with_port
#host = request.env['HTTP_HOST'] unless request.env['HTTP_HOST'].include? 'localhost'
end
Devise Mailer custom class:
class DeviseMailer < Devise::Mailer
helper :application # gives access to all helpers defined within `application_helper`.
include Devise::Controllers::UrlHelpers # Optional. eg. `confirmation_url`
def confirmation_instructions(record, token, opts={})
if record.events.present?
name = record.events.last.name
#event = name
else
name = "#{record.first_name},"
end
opts[:from] = "noreply##{#host}" if #host
opts[:subject] ="#{name} Registration - Confirmation Required"
super
end
end
Also in Devise.rb I've set below:
config.mailer = 'DeviseMailer'
I don't know why I'm still getting default domain instead of the current URL.
Since I have multiple urls pointing to the same application, is there a way to detect this and configure for Devise Mailers?
Why won't you pass the host as argument to your mailer?
def confirmation_instructions(record, token, opts={}, host)
...
end
DeviseMailer.confirmation_instructions(..., #host).deliver

How do I set a custom email subject in a custom Devise email?

I am using Devise in a Rails 3 application to create accounts. I have different types of users, so I want to send out custom password recovery emails based on the type of user.
I am able to send the custom email, I haven't found a way to set custom headers on that email. I am particularly interested in setting the subject of the email.
I have done the following:
Created a custom Devise mailer with a custom method inside. This method calls devise_mail with parameters. In this case, the custom mailer is called "reset_partner_instructions". I am able to call this mailer and successfully send an email from my User model.
Created a custom email view template which is successfully being called from devise_mail.
My custom mailer looks like this:
class AccountMailer < Devise::Mailer
helper :application # gives access to all helpers defined within application_helper.
def reset_partner_instructions(record, opts={})
devise_mail(record, :reset_partner_instructions, opts)
end
end
The problem is that the subject of the email is always "Reset partner instructions". I believe Devise is generating this title from the name of the mail template.
In this tutorial https://github.com/plataformatec/devise/wiki/How-To:-Use-custom-mailer, they call the following code:
def confirmation_instructions(record, opts={})
headers["Custom-header"] = "Bar"
super
end
Since I'm calling "devise_mail" directly, I'm not seeing how to pass the headers intoto the mailer. Is there a simple setting or method I can use to set the email subject?
See devise helper
class AccountMailer < Devise::Mailer
def confirmation_instructions(record, opts={})
headers = {
:subject => "Subject Here"
}
super
end
end
Or you can change it in devise.en.yml file in intilizer directory
And set your own subject
mailer:
confirmation_instructions:
subject: 'Confirmation instructions'
It is very old question, it may be helpful still for you are others,
for custom subject:
create a file config/locales/devise.en.yml
add the content like this as shown below, make sure you do the indentation properly with 2 spaces as you do in database.yml file.
en:
devise:
mailer:
confirmation_instructions:
subject: 'Verification subject here'
reset_password_instructions:
subject: 'Reset password subject here'
This is an old question but still comes up at the top of search and I was able to solve this by setting opts[:subject] instead of setting the header:
# https://github.com/plataformatec/devise/wiki/How-To:-Use-custom-mailer
class DeviseMailer < Devise::Mailer
helper :application
include Devise::Controllers::UrlHelpers
default template_path: 'devise/mailer'
def confirmation_instructions(record, token, opts={})
opts[:subject] = ...
opts[:from] = ...
opts[:reply_to] = ...
super
end
end
And in devise.rb:
config.mailer = 'DeviseMailer'
I realized I should just use ActionMailer for this task. Devise wasn't giving me extra functionality, and since I was trying to generate a custom mailer, i could do that outside of Devise.
There's no need to set up a custom mailer or override Devise's confirmation_instructions method.
Devise let's you pass in optional parameters to the confirmation_instructions method that will get merged with Devise's default options (the opts hash gets passed through to Devise's headers_for helper).
So you could use the following code to send confirmation instructions with a custom subject:
Devise::Mailer.confirmation_instructions(user, {subject: "Custom Subject"}).deliver

Resources