Send Email using Mailform gem and Sendgrid on Heroku using Rails 5
Rails is popularly known for building web applications, sometimes you need to send email on your platform. This tutorial is going to take you through a step by step method on how to send a basic welcome email in your Rails application.
Before we begin, let’s ensure that you have the following versions of ruby and rails installed on your PC
Ruby: >= 2.4.1
Rails: >= 5.1.3
If you need to update your ruby version, you can use the ruby version manager like rvm.
cd into your working directory and run rvm install 2.4.1
To set this as the default version, run rvm use ruby-2.4.1 --default
To install or update rails gem install rails --version=5.1.3
After the following have been set, we can then start with setting up our application for emailing. We will be using the mail_form gem, sendgrid heroku addon and heroku for hosting.
First of all, we need to install Mailform. Let’s add gem 'mail_form' to your gemfile, and run bundle install
We need to prepare our view where the mail would be sent from.
run rails generate controller contact new
In the app/views/contacts/new.html.erb
add the following
<%= form_for @contact do |f| %>
<% if flash[:error].present? %>
<p> flash[:error]</p>
<% end %>
<%= f.label :name %> <br>
<%= f.text_field :name, required: true %>
<br>
<%= f.label :email %> <br>
<%= f.text_field :email, required: true %>
<br>
<%= f.label :message %> <br>
<%= f.text_area :message, as: :text %>
<%= f.label :nickname %> <br>
<%= f.text_field :nickname, hint: 'leave this field blank' %>
<%= f.submit 'Send Message', class: "button" %>
<% end %>
We will have a nickname field. This field should be left blank by users. This is a sort of validation in the event that a third party wants to spam your email. If the field is filled, then an error would be raised and the email would not be sent. Always remember to hide the nickname field using CSS.
Navigate to the app/controllers/contacts_controller.rb
class ContactsController < ApplicationController
def new
@contact = Contact.new
end
def create
@contact = Contact.new(params[:contact])
@contact.request = request
if @contact.deliver
flash.now[:error] = nil
redirect_to root_path, notice: 'Message sent successfully'
else
flash.now[:error] = 'Cannot send message'
render :new
end
end
end
We still need to add the contact resource to the routes.rb
In the config/routes.rb
resources :contacts, only: [:new, :create]
Navigate to the app/models directory then create a contact.rb
file.
app/models/contact.rb
class Contact < MailForm::Base
attribute :name, :validate => true
attribute :email, :validate => /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
attribute :message, :validate => true
attribute :nickname, :captcha => true
def headers
{
:subject => "Contact Form",
:to => "youremail@foo.com",
:from => %("#{name}" <#{email}>)
}
end
end
Now we need to add the Sendgrid heroku addon to the application to enable us send emails.
In the command line run heroku addons:create sendgrid ensure that you have logged into heroku. If you have not, run heroku login and enter your credentials followed by heroku create appname if you have not done that already before running the command.
The heroku addons:create sendgrid command would add SENDGRID_PASSWORD and SENDGRID_USERNAME to applications config variables on heroku.
If for any reason you run into the error below:
▸ Please verify your account to install this add-on plan (please enter a credit card)
▸ For more information, see https://devcenter.heroku.com/categories/billing Verify now
▸ at https://heroku.com/verify
You can fix this by following steps below:
- Go to your account page.
- Click the Billing tab.
- Click Add Credit Card.
After doing this, run the command again.
Note: Sendgrid is free for 400 messages per day but once you reach the limit for the day, you might have to pay. Adding your credit card details to heroku will not cost you anything so you don’t have to worry about deduction from your account.
For Sendgrid to work, we need to set up ActionMailer base.
In the config/environments/production.rb
, add the following:
config.action_mailer.default_url_options = { host: 'https://your app.herokuapp.com' }
config.action_mailer.delivery_method = :smtp
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
}
We can now deploy our changes and try to send an email.
This should work perfectly.
Hey, Simi. Very nice post, though I noticed tiny mistake: in “run rails generate controller contact new” controller_name should be plural
Hi Simi, thanks for this tutorial, it helped me a lot.
I was wondering how can I send attachment as well, but I have not found a solution yet. Would you know how to do it ? Thank you!
Thank your for your tutorial !
Something is not working as expected tough, maybe I missed something…
The mail sent by this form is wrong concerning :from email
:from => %("#{name}" <#{email}>)
In the console everything looks fine, the sender name and email are correct
but in the actual email, the sender email get overrided by my ENV smtp user_name, while the name is correct
So I end up with a mail from Sender user Name admin_email@mydomain.com
Ever happened to you ? Maybe I got something wrong in my dev/prod configuration ?
The values inside the mail body are alright too… having a hard time figuring out what i’m missing :/