ActionMailer not delivering mail when SMTP settings configured dynamically - ruby-on-rails

I'm trying to set up ActionMailer's SMTP settings to be able to be configured at run time, but when that happens it doesn't seem to connect to the 3rd party service to deliver the mail. Below are 2 scenarios, the first of which the mail will send and deliver, the second of which nothing happens. I'm using the development environment for testing
This configuration is common to both scenarios
# config/environments/development.rb
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = false
config.action_mailer.default :charset => "utf-8"
config.action_mailer.delivery_method = :smtp
This works:
# config/environments/development.rb
config.action_mailer.default_url_options = { host: 'www.mysite.com' }
config.action_mailer.smtp_settings = {
:address => "smtp.thirdpartyservice.com",
:port => 587,
:domain => 'mysite.com',
:user_name => "me#mysite.com",
:password => "my-password",
:authentication => "plain",
:enable_starttls_auto => true
}
This delivers the mail, but also when tailing the logs, there is a slight delay in the request so I know the request is being made to the third party service.
This doesn't work:
This is the setup I want, using a custom mailer that I'm using.
class MyCustomMailer < Devise::Mailer
before_filter :use_smtp_settings
def example_mailer(record)
Rails.logger.warn self.smtp_settings
#resource = record
mail(to: record.email,
from: AppSettings.first.mailer_sender,
subject: "Example")
end
private
def use_smtp_settings
self.default_url_options[:host] = AppSettings.first.domain_address
self.smtp_settings = {
:address => AppSettings.first.smtp_address,
:port => AppSettings.first.smtp_port,
:domain => AppSettings.first.smtp_domain,
:user_name => AppSettings.first.smtp_username,
:password => AppSettings.first.smtp_password,
:authentication => "plain",
:enable_starttls_auto => true
}
end
end
The rails logger in the #example_mailer() method shows the same attributes that are used in the first example, albeit loaded from the app_settings table. However when tailing the logs this time, there is no delay so ActionMailer doesn't seem to even try making a request to the third party service.

This won't work because you're modifying the smtp settings on an instance of your mailer but the underlying mail gem reads it from the mailer class level attribute. The supported way to do this in Rails 4.0 and above is to pass a custom header called :delivery_method_options to the mail call, e.g:
class MyCustomMailer < Devise::Mailer
before_filter set_default_host
def example_mailer(record)
mail to: record.email,
from: app_mailer_sender,
subject: "Example",
delivery_method_options: app_smtp_settings
end
private
def app_settings
#app_settings || AppSettings.first
end
def app_domain_address
app_settings.domain_address
end
def app_mailer_sender
app_settings.mailer_sender
end
def app_smtp_settings
self.smtp_settings = {
address: app_settings.smtp_address,
port: app_settings.smtp_port,
domain: app_settings.smtp_domain,
user_name: app_settings.smtp_username,
password: app_settings.smtp_password,
authentication: "plain",
enable_starttls_auto: true
}
end
def set_default_host
default_url_options[:host] = app_settings.domain_address
end
end
end
One little tip - don't repeatedly call AppSettings.first since that re-queries the database (actually it'll be caught by the AR query cache but a new instance will be created every time). But you knew that right ;-)

Related

actionmailer not sending emails even after setting all the possible configurations

This is the method inside ApplicationMailer
class CancelTrip < ApplicationMailer
default from: 'xyz#gmail.com'
def cancel_trip
#recvr= "ssdd#gmail.com"
mail(to: #recvr, subject: 'Your trip has been cancelled as per your request' )
end
end
And the environmental variables as follows:
SMTP_ADDRESS: 'smtp.gmail.com'
SMTP_PORT: 587
SMTP_DOMAIN: 'localhost:3000'
SMTP_USERNAME: 'xyz#gmail.com'
SMTP_PASSWORD: 'gggh2354'
And I am call the mailer method in my controller as follows:
def cancel
xxxxx
CancelTrip.cancel_trip.deliver_now
end
developement.rb has following
config.action_mailer.raise_delivery_errors = false
config.action_mailer.default_url_options = {host: 'localhost', port:3000}
config.action_mailer.perform_deliveries = true
Log shows the email being sent. But I dont see any email in inbox.
My rails version is 4.2.6.
Add following smtp setting on config/application.rb file:
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.raise_delivery_errors = true
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "gmail.com",
:user_name => "xxxxxxxxx#gmail.com",
:password => "xxxxxxxx",
:authentication => "plain",
:enable_starttls_auto => true
}
Check in junk mail... I had this problem a little while back
use letter opener in development for be sure your actionmailer delivered your mail. after that you can finding deliver error to gmail or other.
Make sure that your ApplicationMailer is inheriting from ActionMailer::Base.
class ApplicationMailer < ActionMailer::Base
default from: 'from#exmaple.com'
layout 'mailer'
end
One possibility may be your firewall not allows to send email. Try connect different network.

Mailer error Gmail Net::SMTPAuthenticationError in EnglishGradesController#create

I'm trying to send an email when a new English-Grade is created in my rails app. In this app it may be relevant that Student is an inherited (STI) type of devise User and I'm trying to send them an email when a teacher (another type of inherited devise User) creates a grade.
At the moment just trying to get it to work locally using gmail. I used
rails g mailer UserMailer
to setup.
This is the error I get when I create an English-grade.
Net::SMTPAuthenticationError in EnglishGradesController#create
530-5.5.1 Authentication Required. Learn more at
#student = Student.find_by_id(#english_grade.student_id)
if #english_grade.save
**UserMailer.new_grade(#student).deliver**
redirect_to(student_path(#student), :notice => "Post was successfully created.")
else // etc
(** is the highlighted error)
The above is also where I'm calling the mailer so I won't repeat it.
My development.rb file:
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.default_url_options = { :host => "my ip address" }
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:domain => 'my ip address:3000', //where 3000 is the port I'm running on locally
:port => 587,
:user_name => ENV['example#gmail.com'],
:password => ENV['password'],
:authentication => "plain",
:enable_starttls_auto => true
}
config.action_mailer.perform_caching = false
My mailer:
class UserMailer < ApplicationMailer
default from: "example#gmail.com"
def new_grade(user)
#user = user
mail to: #user.email, subject: "New grade created"
end
end
From reading some of the other Qs:
In the development.rb I have tried without the 'domain:' and without having the host IP address stuff
I have tried:
http://www.google.com/accounts/DisplayUnlockCaptcha
I have also allowed access for less secure apps https://www.google.com/settings/security/lesssecureapps
I have changed my password to something complicated
I also tried changing port to 465 but got an end of file error.
Also if it's of any relevance I created this gmail account today specifically to send emails for the app
Any help would be greatly appreciated, thanks!
The problem was actually that
:authentication => "plain",
needed to be:
:authentication => "login",

Rails app with 2 domains: Define 2 SMTP's in initializers/devise.rb & environments/development.rb?

I have a Rails app that handles two domains. The app is set up like described in this blogpost. In my controllers and views I am using request.domain to determine which app a visitor visits.
When someone signs up for an account, Devise sends out a confirmation email. This process depends on the following lines:
# config/environments/development.rb
MyApp::Application.configure do
...
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => 'localhost',
:user_name => 'my#email.com',
:password => 'MyPassword',
:authentication => 'plain',
:enable_starttls_auto => true
}
...
end
# config/initializers/devise.rb
Devise.setup do |config|
...
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class with default "from" parameter.
config.mailer_sender = "my#email.com"
...
end
I need the :usernamein development.rb and the config.mailer_sender in devise.rb to depend on request.domain, because the user should of course receive an email from the domain he signs up for.
I use SiteSetting model to specify different mailboxes for each Site
SiteSetting contains configs for each mailboxes.
A code for mailer is:
# app/mailers/invitation_mailer.rb
class InvitationMailer < ActionMailer::Base
def invitation(invitation)
#site = invitation.site
#invitation = invitation
email_settings = #site.email_settings.first
mail(to: invitation.email,
from: email_settings.try(:from) || 'notifier#example.com',
subject: "Invitation",
delivery_method_options: delivery_options(email_settings))
end
private
def delivery_options(email_settings)
#_delivery_options ||=
if email_settings
{
address: email_settings.address,
port: email_settings.port,
domain: email_settings.domain,
user_name: email_settings.user_name,
password: email_settings.password,
authentication: email_settings.authentication,
enable_starttls_auto: email_settings.enable_startls_auto
}
else
{
address: 'smtp.google.com',
port: 587,
domain: 'example.com',
user_name: 'notifier#example.com',
password: 'secret',
authentication: 'plain',
enable_starttls_auto: true
}
end
end
end
Update
You can pass username like invitation in this examle
and then you can get acsess to username in your Mailer class (for example InvitationMailer)
# app/controller/users_controller.rb
class UsersController < ApplicationController
def invitation
invitation = Invitation.find(params[:invitation_id])
InvitationMailer.invitation(invitation).deliver
end
end

Mandrill + Rails not sending via controller but sending via console

Hi I am having a very strange problem. I setup mandrill as per the docs and I am now unable to send mail via my controller. Even devise mails do not seem to be going.... But I am able to send it via the console!
My Mail Config
config.action_mailer.default_url_options = { :host => 'smtp.mandrillapp.com' }
config.action_mailer.perform_deliveries = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => "smtp.mandrillapp.com",
:port => 587,
:enable_starttls_auto => true,
:user_name => ENV["MANDRILL_USERNAME"],
:password => ENV["MANDRILL_APIKEY"],
:authentication => 'plain',
:domain => 'yim.mydomain.org',
}
My Mailer
class YimMailer < ActionMailer::Base
default from: "notifier#yim.mydomain.org"
def welcome_email(user, data)
#user = user
#data = data
mail(to: #user.email, subject: 'Welcome!')
end
end
In my controller:
YimMailer.welcome_email(current_user, dummydata).deliver
When i execute the same line via the console, it delivers. What could be the issue?
I am using rails 4
I had the same issue and restarted the server (accidentally), it started working via controller too!

Action Mailer not sending mails although the logs say it is

I have the following code in my registration controller
def new
Rails.logger.debug "#{params[:email]}"
if !params[:email].blank? && !params[:invoke].blank? && params[:invoke].casecmp('Send') == 0
MyMailer.send_email(params[:email]).deliver
end
end
My params[:email] gets populated correctly.
in my_mailer.rb i have the following code
class MyMailer < ActionMailer::Base
default from: 'someaddress#yahoo.com'
def send_email(emailaddress)
#emailaddress=emailaddress
Rails.logger.debug "{#{emailaddress}}"
mail(to: #emailaddress ,subject: 'asdasd')
end
end
I have set the following properties in development.rb
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
I have also done the smtp configurations in setup_mail.rb under the initializers
ActionMailer::Base.smtp_settings = {
:address => "smtp.yahoo.com",
:port => 587,
:domain => "yahoo.com",
:user_name => "someaddress#yahoo.com",
:password => "somepass",
:authentication => "plain",
:enable_starttls_auto => true
}
My logs say that the mail has been sent to the respective person but my gmail shows no mail has arrived . Not even in the spams. Is there any configuration settings i am missing out on ?

Resources