Send Email using Mailform gem and Sendgrid on Heroku using Rails 5

Published Dec 20, 2017

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 %>

    <%= f.label :email %> <br>
    <%= f.text_field :email, required: true %>

    <%= 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 =

  def create
    @contact =[:contact])
    @contact.request = request
    if @contact.deliver[:error] = nil
  redirect_to root_path, notice: 'Message sent successfully'
    else[:error] = 'Cannot send message'
      render :new

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.


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 => "",
      :from => %("#{name}" <#{email}>)

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 Verify now
▸ at

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' }
  config.action_mailer.delivery_method = :smtp

  ActionMailer::Base.smtp_settings = {
  :user_name => ENV['SENDGRID_USERNAME'],
  :password => ENV['SENDGRID_PASSWORD'],
  :domain => '',
  :address => '',
  :port => 587,
  :authentication => :plain,
  :enable_starttls_auto => true

We can now deploy our changes and try to send an email.
This should work perfectly.

Discover and read more posts from Simi
get started