I'm struggling with Heroku sending gmail with actionmailer in my Rails app.
I've got my gmail username and password correctly set as Heroku config vars, but I still get authentication errors. I finally discovered that I need to create an initializer but I'm having trouble hooking everything together. The following code brings up the correct username and password in the heroku logs, but with a NoMethodError. Not sure where to put the method to make it all work. I've tried putting it in my users_controller but that makes the whole thing crash.
I'm planning to add my S3 stuff to this initializer once I get this working.
my initializers/heroku.rb
GMAIL_CREDENTIALS = { :username => ENV['GMAIL_USERNAME'],
:password => ENV['GMAIL_PASSWORD'] }
my mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
default from: "mygmailaddress", :gmail_credentials => GMAIL_CREDENTIALS
def signup_confirmation(user)
#user = user
mail to: user.email, subject: "Sign Up Confirmation"
end
end
and create in my users_controller:
def create
#user = User.new(params[:user])
if #user.save
UserMailer.signup_confirmation(#user).deliver
sign_in #user
flash[:success] = "Welcome to Plain Vanilla!"
redirect_to #user
else
render 'new'
end
end
The error message in heroku logs:
Completed 500 Internal Server Error in 482ms
app/controllers/users_controller.rb:21:in `create'
NoMethodError (undefined method `encoding' for {:username=>"mygmailusername",
:password=>"mypassword"}:Hash):
Thanks for any help!
Charlie
I normally put my gmail credentials in an intializer called mailer.rb. It looks like this:
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "mail.google.com",
:user_name => ENV['MY_GMAIL_USER_NAME'],
:password => ENV['MY_GMAIL_PASSWORD'],
:authentication => "plain",
:enable_starttls_auto => true
}
Where did you get the code you're using? I'd try dropping the :gmail_credentials line from your user_mailer and using an initializer that's more like mine. Don't forget to restart your app if you change these files.
Hope this helps,
Related
UPDATE:
I got it to send emails by actually accessing my app through heroku's website, but it still fails when I run the app from a production server in my cloud9 ide. Is that normal? Is that the way the tutorial wants me to do it?
In chapter 11 of Michael Hartl's Ruby on Rails Tutorial you are asked to signup for the Sample App in deployment mode with an email you control and check your email account for the account activation email. I did not receive any emails and the sendgrid add-on for heroku reports that no email requests have been sent. However, in the cloud 9 ide puma server console it reports that the email was sent with the correct format, to the correct address, and I can retrieve the activation token and email address from the console. I'm not sure what I'm doing wrong. Hopefully, all the relevant code is included below. Please help.
I actually went to the sample app website and clicked sign-up and then waited for the email. Is this not what Hartl means by "sign-up for a new account in production"?
config/environment.rb:
# Load the Rails application.
require_relative 'application'
# Initialize the Rails application.
Rails.application.initialize!
#Sendgrid configurations from their website
ActionMailer::Base.smtp_settings = {
:user_name =>ENV['SENDGRID_USERNAME'],
:password =>ENV['SENDGRID_PASSWORD'],
:domain => 'heroku.com',
:address => 'smtp.sendgrid.net',
:port => 587,
:authentication => :plain,
:enable_starttls_auto => true
}
mailers/application_mailer:
class ApplicationMailer < ActionMailer::Base
default from: 'noreply#example.com'
layout 'mailer'
end
environments/production.rb:
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
host = 'gentle-lake-88943.herokuapp.com'
config.action_mailer.default_url_options = { host: host }
ActionMailer::Base.smtp_settings = {
:address => 'smtp.sendgrid.net',
:port => '587',
:authentication => :plain,
:user_name => ENV['SENDGRID_USERNAME'],
:password => ENV['SENDGRID_PASSWORD'],
:domain => 'heroku.com',
:enable_starttls_auto => true
}
users_controller.rb:
def create
#user = User.new(user_params)
if #user.save
#user.send_activation_email
flash[:info] = "Please check your email to activate your account"
redirect_to root_url
else
render 'new'
end
end
user.rb:
def activate
update_columns(activated: true, activated_at: Time.zone.now)
end
def send_activation_email
UserMailer.account_activation(self).deliver_now
end
routes.rb:
resources :account_activations, only: [:edit]
I just resolved this tutorial's problem. My initial problem was i did not write the variable name correctly. I had reviewed my code and I fixed it. My app works fine now, as tutorial says.
As Igor says at his last answer, you dont need any special code in config/environments.rb so you should erase it if you keep it.
Check your environment's variables in Heroku with heroku run printenv. If those are correct, try the BAD way, just as test: replace ENV['SENDGRID_xxx'] by your sendgrid's username and password.
Thanks to Nathan Road
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",
I am a complete beginner in Rails and I'm trying to send an email after someone signs up using Action Mailer.
My logs say that the email is sending, but Gmail never gets it.
config/initializers/setup_mail.rb
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "asciicasts.com",
:user_name => "asciicasts",
:password => "secret",
:authentication => "plain",
:enable_starttls_auto => true
}
mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
default :from => "eifion#asciicasts.com"
def registration_confirmation(user)
mail(:to => user.email, :subject => "Registered")
end
end
controllers/users_controller.rb
...
def create
#user = User.new(params[:user])
if #user.save
UserMailer.registration_confirmation(#user).deliver
sign_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
...
Thanks!
Make sure you have this option set in your config/environments/development.rb :
config.action_mailer.delivery_method = :smtp
Also, in ActionMailer::Base.smtp_settings you need to specify a valid gmail account. Copy-pasting (asciicasts) is not gonna cut it here.
See this question for reference: Sending mail with Rails 3 in development environment
Instead of 'smtp' you can use 'sendmail'
ActionMailer::Base.delivery_method = :sendmail
ActionMailer::Base.sendmail_settings = { :address => "smtp.gmail.com",
:port => "587", :domain => "gmail.com", :user_name => "xxx#gmail.com",
:password => "yyy", :authentication => "plain", :enable_starttls_auto => true }
I ran into this same problem for a new mailer I had setup. I couldn't figure out for the life of me why this new mailer couldn't send emails, or even get to the method in the mailer when I stepped through it.
Solution
It ended up being that if you put the deliver_now or deliver* code within the mailer, it does not send the email.
Example Broken
def email_message()
message = mail(to: User.first, subject: 'test', body: "body text for mail")
message.deliver_now
end
Corrected
#Different class; in my case a service
def caller
message = MyMailer.email_message
message.deliver_now
end
def email_message()
mail(to: User.first, subject: 'test', body: "body text for mail")
end
This solved the problem for me, I hope it solves it for someone else.
I am creating a simple non-profit application with Ruby on Rails. I have to set up the following settings in order to be able to send emails with Gmail:
Depot::Application.configure do
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address:"smtp.gmail.com",
port:587,
domain:"domain.of.sender.net",
authentication: "plain",
user_name:"dave",
password:"secret",
enable_starttls_auto: true
}
end
I am completely new with this stuff and have no idea what exactly I should do.
How to populate the settings above if I have gmail account? Do I
need to buy a domain and can be it bought from google in order to
use the settings above?
Is it better to set up mail server on my PC? I looked though
this tutorial but as far as I understand I still need to buy a
domain.
Also, as it is said here:
Setting up an email server is a difficult process involving a number
of different programs, each of which needs to be properly configured.
because of this and my poor skills I am looking for the simplest solution.
I have read the rails action mailer tutorial and have an idea about what these parameters are used for, but the things around the Gmail and the mail server are not clear at all.
The configuration of your mailer should/can be defined in both development and production the purpose of this configuration is that when you set this up when you use the actionmailer these SMTP options will be used. You could have a simple mailer like the following:
Mailer
class UserMailer < ActionMailer::Base
default :from => DEFAULT_FROM
def registration_confirmation(user)
#user = user
#url = "http://portal.herokuapp.com/login"
mail(:to => user.email, :subject => "Registered")
end
end
Controller
def create
#title = 'Create a user'
#user = User.new(params[:user])
if #user.save
UserMailer.registration_confirmation(#user).deliver
redirect_to usermanagement_path
flash[:success] = 'Created successfully.'
else
#title = 'Create a user'
render 'new'
end
end
So what happens here is that when the create action is being used this fires the mailer UserMailer Looking at the above UserMailer it uses the ActionMailer as the base. Following the SMTP setup shown below which can be defined in both config/environments/production.rb and development.rb
You would have the following:
config.action_mailer.default_url_options = { :host => 'portal.herokuapp.com' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => 'smtp.gmail.com',
:port => 587,
:domain => 'gmail.com',
:user_name => 'EMAIL_ADDRESS#gmail.com',
:password => 'pass',
:authentication => 'login',
:enable_starttls_auto => true
}
If you want to define the SMTP settings in development mode you would replace
config.action_mailer.default_url_options = { :host => 'portal.herokuapp.com' }
with
config.action_mailer.default_url_options = { :host => 'IP ADDRESS HERE:3000' }
This should be a thorough enough explanation to kick start you in the right direction.
The above answer worked for me in development once I changed it to
authentication: 'plain'
and included
config.action_mailer.raise_delivery_errors = true
in my development environment.
I'm trying to implement a "contact us" form on my rails 3.0.10 project. Following the RailsGuides I created a mailer.
class QuestionMailer < ActionMailer::Base
default :to => "%mail#mydomain" #gmail for domains
def ask(message)
#content = message.content
unless message.name.nil? or message.name.empty?
from = "#{message.name} <#{message.email}>"
else
from = message.email
end
mail(:subject => message.subject, :from => from)
end
end
In my controller I have these lines:
if #question.valid?
QuestionMailer.ask(#question).deliver
redirect_to root_url, :notice => "Сообщение отправлено"
else
Production.rb:
config.action_mailer.delivery_method = :smtp
config.action_mailer.default_url_options = { :host => '%mydomain%' }
ActionMailer::Base.smtp_settings = {
:address => "smtp.sendgrid.net",
:port => "25",
:authentication => :plain,
:user_name => ENV['SENDGRID_USERNAME'],
:password => ENV['SENDGRID_PASSWORD'],
:domain => ENV['SENDGRID_DOMAIN']
}
I didn't have this config at first, but when I didn't receive the email, I added it.
The problem is, the Heroku log says, that the corresponding view has been rendered, but I don't receive the email. And because I use sendgrid, I cant test it locally.
upd
Note to self. After creating gmail for domain account, don't forget to your DNS settings. >_<
You can test locally still using sendgrid - from the command line do heroku config and you can grab the values that Heroku has set for sendgrid username, password and domain and then set them in your development.rb along with the actionmailer settings and it will route your message through sendgrid from your local development app.
I also find this heroku plugin https://github.com/hone/heroku-sendgrid-stats very useful for checking on my message sending numbers.