How to change "Devise: password reset instruction email's subject" - ruby-on-rails

I'm just unable to change "password reset instruction" email's subject. I have changed notifer.rb in Mailer to overwrite Devise default email subject. But it's not working.
Here in my application there is default Email subject inside Devise .yml file. But I want to make it dynamic to change it by pulling data from DB.

you can change it in devise.en.yml file in intilizer directory
And set your own subject for any mailer
mailer:
confirmation_instructions:
subject: 'Confirmation instructions'
reset_password_instructions:
subject: 'Reset password instructions'
unlock_instructions:
subject: 'Unlock Instructions'

I got this to work by creating my own sub-class of Devise::Mailer.
class DeviseMailer < Devise::Mailer
def reset_password_instructions(record, token, opts={})
mail = super
# your custom logic
mail.subject = "[SOME DB DATA]"
mail
end
end
And then modifying the devise.rb initializer to use my mailer.
# Configure the class responsible to send e-mails.
config.mailer = 'DeviseMailer'

Change option :subject:
class DeviseMailer < Devise::Mailer
def reset_password_instructions(record, token, opts={})
opts[:subject] = 'SOME DB DATA'
super
end
end

You can write your own method inside your controller and call the respective mailer template. This will help you.. Else devise views, there will be a view page to send reset instruction. Change the content there..

For default foreign language (example Japanese)
STEP 1 Create a 'ja.yml' in config/locales/ (or whatever filename)
ja:
devise:
mailer:
confirmation_instructions:
subject: '仮会員登録完了のお知らせ'
reset_password_instructions:
subject: 'パスワード再設定手順のお知らせ'
STEP 2 On config/environments/development.rb
config.i18n.default_locale = :ja
STEP 3 Restart server

If you're willing to translate your Devise messages, which was my case, a better practice would be creating a new yml file in config/locale and changing your application's locale at config/application.rb
To illustrate, I had to create devise.pt-BR.yml inside config/locale.
Then I copied its translations from internet, on this link.
Finally, I set my application's new locale at config/application.rb as follows:
config.i18n.default_locale = :'pt-BR'
Hope it helps some of you guys having the same problem as mine.

Related

How to use Sorcery Gem with Sidekiq

I am using Sorcery Gem to Authenticate user in my Rails application. Everything is working fine. When user register then I am able to send user activation email. However sending email is taking long time so I was thinking to delay the email or send email in backgroud using Sidekiq. I read Sorcery documentation but couldn't find the way to delay the email using Sidekiq.
Please guide me how to delay the email send by Sorcery gem using Sidekiq.
There could be two approach to this:
Call Sidekiq worker inside Mailer
what I understand from the docs is that you can configure it to call any
Mailer. What you could do inside the method is call
MailerJob.perform_late(*arg) instead of calling mail(*args) right away
Assuming you have a code something like this (ref: https://github.com/Sorcery/sorcery/wiki/User-Activation)
# app/mailers/user_mailer.rb
def activation_needed_email(user)
#user = user
#url = activate_user_url(#user.activation_token)
mail(to: user.email, subject: 'Welcome to My Awesome Site')
end
You can change the code to this
# app/mailers/user_mailer.rb
def activation_needed_email(user)
#user = user
#url = activate_user_url(#user.activation_token)
# mail(to: user.email, subject: 'Welcome to My Awesome Site')
MyMailerWorker.perfor_later(to: user.email, subject: 'Welcome to My Awesome Site')
end
Your worker would be defined as per the sidekiq docs(ref: https://github.com/mperham/sidekiq/wiki/Getting-Started)
class MyMailerWorker
include Sidekiq::Worker
def perform(to: nil, subject: nil)
MailerIWantToCall.send_activation_email(to, subject)
end
end
P.S: Option 1 is not a clean approach but works if you are stuck with Sorcery legacy configs
Don't set mail settings for srcoery(A cleaner approach)
Do not setup mail through sorcery at all.You can revert the changes
mentioned for UserMailer on this page
(github.com/Sorcery/sorcery/wiki/User-Activation) and add a callback on User
model based on when do you want to trigger an email and that way you have
control over what to call and with sidekiq or not.
I found the solution. It's quite easy. We just need to add following line in sorcery.rb file and all sorcery mail will be handled by ActiveJob
user.email_delivery_method = :deliver_later

Override mail function in rails ActionMailer

I use this class for Action Mailer:
class UserMailer < ActionMailer::Base
default from: "something#example.com",
reply_to: 'whatever#example.com'
def mail_method
mail(to: 'email#example.com', subject: "SUBJECT")
end
end
So like this I got many classes and methods which send emails like this from smtp delivery method.
But now I want to perform_deliveries , i.e. send emails only on production environment not in development or test environment.
So for that I want to use my email only, which is why I need to override mail method.
Things I have tried.
-> Making a function to return email, where function name is get_right_email
class UserMailer < ActionMailer::Base
default from: "something#example.com",
reply_to: 'whatever#example.com'
def mail_method
mail(to: get_right_email('email#example.com'), subject: "SUBJECT")
end
end
And definition of get_right_email is as follows:
def get_right_email(email)
if(Rails.env=='production')
return email
else
return 'myPersonalEmail#example.com'
end
end
It would need some refactoring but it is still manageable. Will take a few hours and I can do, but is there a quicker way where I can just override mail function.
In your config > enviroments folder you should have a file for production, development and test. Here you can specify your settings for each one.
Settings in these folders overide those in config > application.rb
For example when testing I don't usually actually send the emails but I do want to be able to test the emails so I use
config.action_mailer.delivery_method = :test
This makes the emails accessible by calling ActionMailer::Base.deliveries
You can set the default from email address in these files as well using:
config.action_mailer.default_options = {
:from => "foo#bar.com"
}
Theres a gem called letter_opener managed by the fantastic Ryan Bates which instead of sending an email in development opens the email in a new tab. This makes testing out emails in development a breeze.
Letter Opener
UPDATE BELOW ------
Apologies, I didn't quite follow what you were looking for.
Rails has webhooks you can use to intercept emails and redirect them. You'll want to use an environment different than production.
The test environment is typically used for automated testing, to keep things clear you might want to consider setting up a new environment (eg: staging).
To create a new environment just create a new file in config/environments/ and give it a suitable name - eg: staging.rb
You can then call Rails.env.staging? where ever you like.
Anyway back to the main event...
To intercept the emails first create an intercept class:
class StagingEmailInterceptor
def self.delivering_email(message)
message.to = ['my#email.com']
end
end
and then create an initializer file, eg:
config/initializers/staging_email_interceptor.rb
and inside do this:
if Rails.env.staging?
ActionMailer::Base.register_interceptor(StagingEmailInterceptor)
end
That way all emails sent in the staging environment will be sent to your email.

reset_password_instructions.html.erb uses what layout

I'm using Rails and Devise for user management.
I'd like all my emails to be consistent in style and modify of Devise password reset email.
reset_password_instructions.html.erb features only contents of the . There has to be a layout it uses somewhere, but I cannot find it...
You can define a layout for all Devise mail using an initializer.
config/initializer/devise.rb
Devise.setup do |config|
# Other options here...
config.to_prepare do
Devise::Mailer.layout "email" # email.haml or email.erb
end
end
https://github.com/plataformatec/devise/wiki/How-To:-Create-custom-layouts
You would have to create a new email layout with the name you identified in Devise::Mailer.layout but that's a good thing since now you have complete control over the code.

Override to field in ActionMailer based on environment

I'm using Rails 4.2 want to override the to field for all ActionMailer mailers for a certain environment. In this case I want to override the to field for all mailers used in Staging. My goal is for the staging environment to deliver mail exactly the same way as production, but to dump it all into a testing inbox.
I know there are services that assist with this, but my goal is to use my production API for staging delivery as a thorough test.
I'm hoping I can use a mixin or something to reset the to field before the mailer fires off.
Not sure what version of Rails you are using, but you might consider using the new mail interceptors to accomplish this.
Main advantage is that it doesn't clutter your ActionMailer classes directly.
http://guides.rubyonrails.org/action_mailer_basics.html#intercepting-emails
Copying their example:
class SandboxEmailInterceptor
def self.delivering_email(message)
message.to = ['sandbox#example.com']
end
end
config/initializers/sandbox_email_interceptor.rb:
ActionMailer::Base.register_interceptor(SandboxEmailInterceptor) if Rails.env.staging?
The simplest way would be to check which environment is running and set the to field accordingly. For example, a simple password reset mailer might look something like:
class UserMailer < ActionMailer::Base
default from: "support#example.com"
def reset_password(user_id)
#user = User.find(user_id)
#url = reset_password_users_url(token: #user.password_reset_token)
mail(to: #user.email, subject: '[Example] Please reset your password')
end
end
Now to check for the staging environment and route all of these emails to admin#example.com:
class UserMailer < ActionMailer::Base
default from: "support#example.com"
def reset_password(user_id)
#user = User.find(user_id)
#url = reset_password_users_url(token: #user.password_reset_token)
to = Rails.env.staging? ? 'admin#example.com' : #user.email
mail(to: to, subject: '[Example] Please reset your password')
end
end

=0A in the subject of an email sent with Rails?

I have this in my user_mailer.rb
class UserMailer < ActionMailer::Base
default from: ["no-reply##{CONFIG[:domain]}"]
def password_reset(user, portal_name)
#user = user
mail to: #user.email, subject: t('emails.password_reset.subject')
end
end
I have this in my yml translation file:
emails:
password_reset:
subject: You've requested to reset your password
There are no characters at the end of the translation string, however when the email is sent the subject appears like this in the email: "You've requested to reset your password=0A"
I've tried searching for an answer and I found Rails used to have an ActionMailer::Quoting.quoted_printable method, but it seems this no longer exists in rails 4.
Where is the "=0A" coming from? Any built-in solution to this in rails?
I managed to solve the problem by adding a chomp at the end:
mail to: user.email, subject: t('emails.password_reset.subject').chomp
It seems a newline was being introduced somewhere!
I also encountered this problem when using the 'X-SMTPAPI' header(SendCloud Mail Service).This is because Mail gem will handle the headers:
def encode_crlf(value)
value.gsub!(CR, CR_ENCODED)
value.gsub!(LF, LF_ENCODED)
value
end
When I tried using Mail gem only, it worked. I think this is because the charset is different with Rails' default setting. I solved the issue like this:
headers["X-SMTPAPI"] = Base64.encode64(JSON.dump({"to" => emails, "sub" => {"%name%" => names}})).gsub!(/\n/,'')

Resources