Rails send mail with gmail development mode - ruby-on-rails

I didn't figure out how I send mail from gmail in development environment.It didn't send email. I didn't understand the rails guide, and also I wonder if the production env is the same ?
config/development.rb
config.action_mailer.raise_delivery_errors = true
config.action_mailer.default_url_options = { :host => 'something.com' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'mail.google.com',
user_name: 'myusername#gmail.com',
password: 'mypassword',
authentication: 'plain',
enable_starttls_auto: true }
mailer/user_mailer.rb
default :from => 'something.com'
def welcome_email(user)
#user = user
#url = 'http://something.com'
mail(to: #user.email, subject: 'Welcome')
end
edit
where I call, in users create method,
UserMailer.welcome_email(#user).deliver_now

config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
Try this in development.rb It will either send mail or raise delivery error in console.

You can call your mailer methods in two way to send email,
In UsersController's create action
def create
#your codes and logics to save user...
UserMailer.welcome_email(#user).deliver_now
#your codes goes here ...
end
In User model after_create callback
class User < ActiveRecord::Base
after_create :send_email
def send_email
UserMailer.welcome_email(self).deliver_now
end
end
I would prefer second one for sending email, use model callback rather in controller.

Related

Rails mailer does not send email

When I try to use rails (5.1.4) mailer, I don't receive any email like I should do. I followed the official rails guide to make it. My config/environment/development.rb :
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'gmail.com',
user_name: 'username#gmail.com',
password: 'app-password-from-google',
authentication: 'plain',
enable_starttls_auto: true
}
With this config I made a new mailer in mailers/appointement_mailer.rb :
class AppointementMailer < ApplicationMailer
default :from => "username#gmail.com"
def appointement_information(user_email, data)
#email = user_email
#body = data
mail(:to => "username#gmail.com", :subject => "xxx")
end
end
This mailer is triggered by a form controlled by a controller, it is located under controllers/contacts_controller.rb :
def new
end
def create
#appointement = appointement_params
AppointementMailer.appointement_information(#appointement['email'], #appointement['body'])
flash[:notice] = "Some message"
redirect_to articles_path
end
private
def appointement_params
params.require('appointement').permit(:email, :body)
end
The form correctly display the flash "Some Message" and no error is written in the console.
You need to call deliver_now on your call to the mailer.
AppointementMailer.appointement_information(#appointement['email'], #appointement['body']).deliver_now

Rails devise with gmail errors

I'm currently working on an application with a mailer system. It was working fine, sending a welcome email and sending instructions to reset password, but now and only when I try to send reset instructions I have this error.
ArgumentError (SMTP From address may not be blank: nil):
I'm using a custom domain like so noreply#mycustomdomain.com
And here is my configuration
development.rb
config.action_mailer.raise_delivery_errors = true
config.action_mailer.perform_caching = false
config.action_mailer.default_url_options = { host: 'localhost:3000' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: '587',
domain: 'gmail.com',
authentication: :plain,
enable_starttls_auto: true,
user_name: Rails.application.secrets.mailer_username,
password: Rails.application.secrets.mailer_password
}
Any idea ?
Edit
class UserMailer < ApplicationMailer
default from: 'noreply#mycustomdomain.com'
def welcome_email(user)
#user = user
#url = 'http://localhost:3000/users/sign_in'
mail(to: #user.email, subject: 'Bienvenue')
end
def generate_new_password_email
user = User.find(params[:user_id])
user.send_reset_password_instructions
end
def reset_password; end
end
You could try setting :from in your config, using the default_option like this,
config.action_mailer.default_options = { from: 'noreply#mycustomdomain.com' }
It looks like you don't have a From header in your email. A good practice would be to put the following line into your ApplicationMailer:
class ApplicationMailer
default from: 'noreply#mycustomdomain.com'
# ...
end
To override this in your inheriting mailers, simply declare the same statement. To override it in individual mail methods, put it into the mail call like so:
def new_message(user, message)
mail(
to: user.email,
subject: "New message from #{message.sender.name}",
from: message.sender.email
)
end
Hope that helps
In devise.rb config.mailer_sender = 'please-change-me-at-config-initializers-devise#example.com' had been commented.
Config.mailer_sender was never initialized and so always nil even if I set it with default from:
I had the same problem, and the reason behind that was i working in development but my mailer was searching the smtp_settings in the production, so to solve the issue you can change the mailer settings or you can copy the same smtp_settings into production.
I stumbled upon the same problem. My solution was, I edited config/initializers/devise.rb changed a line from config.mailer_sender = 'please-change-me-at-config-initializers-devise#example.com'
to config.mailer_sender = ENV["default_from_email"]

How to send email in rails

The following is my controller file:
class BiodataController < ApplicationController
def store
#user=params[:username]
#age=params[:age]
#gender=params[:gender]
#mstatus=params[:mstatus]
#language=params[:language]
#email=params[:email]
#mobile=params[:mobile]
if params[:username].present? && params[:age].present? && params[:gender].present? && params[:mstatus].present? && params[:language].present? && params[:email].present? && params[:mobile].present?
Biodatum.create(name: #user, age: #age, gender: #gender, mstatus: #mstatus, language: #language, email: #email, mobile: #mobile)
Infomail.sendmail(#email)
render 'store'
else
render 'Error'
end
end
end
My requirement is to send email to the address stored in #email. So I created the mailer as 'Infomail'. The following is my mailer file.
class Infomail < ApplicationMailer
default from: 'abc#xyz.co.in'
def sendmail(user)
#user = user
mail(to: #user.email, subject: 'sample mail')
end
end
And I also have html file under 'app/views/infomail/sendmail.html.erb'. But it doesn't work. Can any one explain me what is the bug in
my code.
I'll recommend that you take a look at http://guides.rubyonrails.org/action_mailer_basics.html for starters.
For sending mails, you'll have to use the deliver_now (Immediate) or deliver_later (Queue for worker) methods, like so:
InfoMailer.sendmail(#user).deliver_now
Note that I renamed it to InfoMailer, because that's the standard naming, of mailers.
If you want to test you mailer into development environment just open your development.rb file and write below code inside for smtp configuration.
config.action_mailer.default_url_options = { host: 'url of your application' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'address of your mailer',
port: 465,
domain: ENV['YOUR_DOMAIN_NAME'],
user_name: ENV['YOUR_USER_NAME'],
password: ENV['YOUR_PASSWORD'],
authentication: :plain,
ssl: true,
tls: true,
enable_starttls_auto: true
}
please change above configuration as per your mailer smtp settings.
Now create tamp let of your mail as per you requirements. file path as per below:
app -> view -> common_mailer inside of this please make sendmail.html.erb file.
You are sending #email which is a String in params while you are expecting Object on which you can call .email
#bio = Biodatum.create(name: #user, age: #age, gender: #gender, mstatus: #mstatus, language: #language, email: #email, mobile: #mobile)
Infomail.sendmail(#bio)
This will pass Biodatum instance on which you can call .email
Also to avoid confusion you can change your mailer method
def sendmail(bio)
#bio = bio
mail(to: #bio.email, subject: 'sample mail')
end
If you are making these changes, you will also need to change them in sendmail.html
EDIT
Make sure you have configured the settings in /config/environments/development.rb and /config/environments/production.rb
config.action_mailer.delivery_method = :smtp
# SMTP settings for gmail
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:user_name => ENV['gmail_username'],
:password => ENV['gmail_password'],
:authentication => "plain",
:enable_starttls_auto => true
}

ActionMailer not delivering mail when SMTP settings configured dynamically

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 ;-)

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

Resources