Rails 4 ActionMailer headers - ruby-on-rails

I'm on Rails 4 and I've got one mailer. This was created following the tutorial in the docs.
class UserMailer < ActionMailer::Base
#delivery_options = {
user_name: 'user_name',
password: 'password',
address: 'smtp.sendgrid.net'
}
default from: "Auto <auto#mysite.me>"
def welcome_email (user, password)
#user = user
#password = password
#url = "http://url.com"
mail(to: #user.email, subject: "Welcome to my site", delivery_method_options: #delivery_options)
end
def project_invite_email (email, project)
#project = project
mail(to: email, subject: "#{#project.user.first_name} #{#project.user.last_name} requests a video from you", delivery_method_options: #delivery_options)
end
end
During the course of troubleshooting some deliverability issues, I found that some emails included different headers than others. It turned out that a combination of SPF, DKIM, and adjustments to the email copy were able to resolve the deliverability problems (many were previously caught by spam filters), but I'd still like to know more about how Rails is creating the headers for these emails.
For example, the second one includes this in the header: Content-Transfer-Encoding: 7bit but the first has this: Content-Transfer-Encoding: quoted-printable
As you can see, they both use the exact same configurations. The only difference is the content of the views (both have an HTML & text version).
Is rails adjusting the headers based on content?

Ok. I'll post it as a question next time. Thanks.
I've got this resolved now with the help of the other post.
How to change the mailer Content-Transfer-Encoding settings in Rails?
m = mail(...)
m.transport_encoding = "quoted-printable"
m.deliver

Yes, rails automatically adjusts Content-Transfer-Encoding. If you have non-standard characters in your mailer view, the header may randomly switch between 7bit and quoted-printable (or just stick to quoted-printable).
If required, you can force the mailer to use the default encoding (7bit).
class Mailer < ActionMailer::Base
default from: 'from#example.com',
content_transfer_encoding: '7bit'
...
end
However it is most likely caused by an invalid character, which should be visible (such as Â) once you force the header to 7bit.

Related

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/,'')

Rails contact form send email to myself

I'm following a paid tutorial exactly and setting up a contact page where when a visitors fills out the form and submits, I, the website owner, get an email with their name, email, and comment. The goal is to allow me to easily hit reply and respond to them.
This seems weird to me, because it's odd that ActionMailer gives you the capability to send from someone else's email account for which there are no SMTP settings defined. In fact, following this tutorial, I don't need to declare any SMTP settings.
But it's not working... would love some troubleshooting help.
My mailer code:
class UserMailer < ActionMailer::Base
def contact_email(contact)
#contact = contact
mail(to: jdong8#gmail.com, from: #contact.email, :subject => "New message at JamesDong.com")
end
end
Controller code snippet:
def create
#contact= Contact.new(secure_params)
if #contact.save
UserMailer.contact_email(#contact).deliver
You can clone the git repo at
https://github.com/RailsApps/learn-rails
to get the code from the book Learn Ruby on Rails. You'll see that the code works as implemented.
If you look at the example code, the SMTP settings are configured in the file config/environments/development.rb and config/environments/production.rb.
config.action_mailer.smtp_settings = {
address: "smtp.gmail.com",
port: 587,
domain: "example.com",
authentication: "plain",
enable_starttls_auto: true,
user_name: ENV["GMAIL_USERNAME"],
password: ENV["GMAIL_PASSWORD"]
}
The GMAIL_USERNAME and GMAIL_PASSWORD set up the SMTP origin for the mail.
The UserMailer code only creates (part of) the header and body of the email message. The "from" and "to" will be displayed, for appearances only. Have a look at the raw email message and you will see the full set of headers, that show the real origin of the email.
So, in short, the UserMailer code sets a fake "from" and the real "from" is set when the email is sent from the Gmail account.
I could be wrong here, but based off of my experience in Rails this isn't possible, you would need to have the SMTP settings for the account you are sending the mail from.
There are a ton of questions on here referring to setting up ActionMailer correctly, but it seems like you're trying to send mail without telling it where to send the mail from.
This question and the best answer on it might be of some help if that's your issue:
How to configure action mailer (should I register domain)?

How to change "Devise: password reset instruction email's subject"

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.

Rails - How do I use full email addresses without triggering Net::SMTPFatalError?

I am new to rails and using rails-2.3.5 and ruby-1.8.7. Here is my notifier.rb model:
# app/models/notifier.rb
class Notifier < ActionMailer::Base
default_url_options[:host] = "foo.com"
#This method sends an email with token to users who request a new password
def password_reset_instructions(user)
subject "Password Reset Instructions"
from "Support Team<support#foo.com>"
recipients user.email
sent_on Time.now
body :edit_password_reset_url =>
edit_password_reset_url(user.perishable_token)
end
end
When I call this method I get the following error:
Net::SMTPFatalError in Password resetsController#create
555 5.5.2 Syntax error. 36sm970138yxh.13
I found an article that said the problem was a bug in ruby-1.8.4 and that the fix is to remove the angle brackets from the :from field. Sure enough, if I just use "support#foo.com" instead of "Support Team<support#foo.com>" everything works fine.
However, there is no reference to this issue in either the rails-2.3.5 API or ActionMailer Basics rails guide, and in fact both show "name<mail address>" in their actionmailer setup examples. Anyone know what I am doing wrong?
From the ticket that Travis referenced, it looks as though you can possibly avoid the problem with:
def password_reset_instructions(user)
subject "Password Reset Instructions"
from "Support Team<support#foo.com>"
+ headers "return-path" => 'support#foo.com'
recipients user.email
sent_on Time.now
body :edit_password_reset_url =>
edit_password_reset_url(user.perishable_token)
end
Otherwise, you can grab one of the patches noted in the ticket or wait for 2.3.6 or 3.x
Rails/ActionMailer broke this:
https://rails.lighthouseapp.com/projects/8994/tickets/2340
And since critical bugs like this don't get high priority or interim releases to fix them in the Rails project, you either have to patch it up yourself or wait a looong time to get it fixed. Just like this insanely bad bug that came out in Rails 2.3.4 that made Rails completely unusable for Ruby 1.9: https://rails.lighthouseapp.com/projects/8994/tickets/3144-undefined-method-for-string-ror-234 . Took months to get a fix for that.
The problem is a perform_delivery_smtp method from ActionMailer::Base used in rails 2.3.4 and 2.3.5. You can always try to monkey-patch-it like that:
class ApplicationMailer < ActionMailer::Base
def welcome_email(user)
recipients user.email from "Site Notifications<notifications#example.com>"
subject "Welcome!"
sent_on Time.now
...
end
def perform_delivery_smtp(mail)
destinations = mail.destinations
mail.ready_to_send
sender = mail['return-path'] || mail.from
smtp = Net::SMTP.new(smtp_settings[:address], smtp_settings[:port])
smtp.enable_starttls_auto if smtp_settings[:enable_starttls_auto] && smtp.respond_to?(:enable_starttls_auto)
smtp.start(smtp_settings[:domain], smtp_settings[:user_name], smtp_settings[:password],
smtp_settings[:authentication]) do |smtp|
smtp.sendmail(mail.encoded, sender, destinations)
end
end
end

Resources