Using SendGrid and ActionMailer in a Rails Development Environment

I will be using ActionMailer and SendGrid to setup a basic contact mailer, where a person can fill out a contact form, and an email will be sent to the site owner’s email address. I like SendGrid because it works well with Heroku which is the service I use to deploy my apps in production.

Prerequisites

  • Rails 5
  • Send Grid Account (remember your username and password)
  • PostgreSQL (recommended, but not needed for development).
  • A GUI for either PostgreSQL or SQLite.

Getting Setup

Working in the terminal, create a new Rails application, if you don’t have PostgreSQL you can skip the -d postgresql in the command below.

rails new sendgrid -T -d postgresql

Move into your newly created app.

cd sendgrid

Create your database (this step is only for those using PostgreSQL)

rake db:create

Start your server and check localhost:3000 to make sure that everything is working.

rails s

Saving to the Database

In the terminal create your model. My contact model will have four fields. Data types for subject, name, and email will all be strings, and my message field will have a text data type.

rails g model Contact subject name email message:text

Migrate the newly created fields.

rake db:migrate

Create a controller for your contacts.

rails g controller contacts

Open your app up in your text editor.

In config/routes.rb create your routes for contacts, I’ve set my index route as my root.

Rails.application.routes.draw do
  root 'contacts#index'
  resources :contacts
end

In app/controllers/contacts_controller.rb make sure to create an empty index method so you can access your root page. Give the new method access to the @contact instance variable. In a private method create strong params for the data fields you will be sending across the interwebs. In your create method, make a new Contact object that calls the contact_params you just made. Add happy and sad paths for saving, or not saving, to the database. If you successfully save to the database redirect to the show page. Create a show method that finds the id of newly created Contact object.

class ContactsController < ApplicationController
  def index

  end

  def new
    @contact = Contact.new
  end

  def create
    @contact = Contact.new(contact_params)
    if @contact.save
      redirect_to contact_path(@contact.id)
    else
      render :new
    end
  end

  def show
    @contact = Contact.find_by(id: params[:id])
  end

  private 

  def contact_params
    params.require(:contact).permit(
      :subject,
      :name,
      :email,
      :message
    )
  end
end

Inside app/views/contacts create index.html.erb and make a link to the “New Page.”

<h1>Contact</h1>
<p><%= link_to "New Contact", "/contacts/new" %></p>

Inside app/views/contacts create new.html.erb create your form for a new contact.

<h1>New Contact</h1>
<%= form_for @contact, url: {action: "create"} do |f| %>
  <div>
    <%= f.label :subject %>
    <%= f.text_field :subject %>
  </div>
  <div>
    <%= f.label :name %>
    <%= f.text_field :name %>
  </div>
  <div>
    <%= f.label :email %>
    <%= f.text_field :email %>
  </div>
  <div>
    <%= f.label :message %>
    <%= f.text_area :message %>
  </div>
  <div>
    <%= f.submit "submit" %>
  </div>
<% end %>

Inside app/views/contacts make a show.html.erb file. Create a list of fields that shows all the data for a particular contact.

<h1><%= @contact.name %></h1>
<p><%= @contact.subject %></p>
<p><%= @contact.email %></p>
<p><%= @contact.message %></p>

Finally open your app in the browser at localhost:3000 and test to see if you’re able to save data to the database (ie. check your database’s GUI).

Setting Up The Mailer

Back in the terminal create your mailer.

rails g mailer ContactsMailer

In the text editor travel to the newly created app/mailer/contacts_mailer.rb file. Set the default “from” email to whatever email address you want your emails to come from. Next create an email method that takes in a single parameter. Inside this mailer method make sure to set your function parameter to an instance variable, set the value of :to to your email address, and a value for :subject for what ever you want your email subjects to say.

class ContactsMailer < ApplicationMailer
  default :from => 'youremail@gmail.com'

  def contact_email(contact)
    @contact = contact
    mail( :to => 'youremail@gmail.com',
    :subject => 'Personal Contact Info Filled Out' )
  end
end

Returning to app/controllers/contacts_controller.rb In the create action call the mailer method you just created after a contact has been saved and pass the @contact instance variable in as an argument.

 def create
   @contact = Contact.new(contact_params)
   if @contact.save
     ContactsMailer.contact_email(@contact).deliver_now
     redirect_to contact_path(@contact.id)
   else
     render :new
   end
 end

Inside app/views/contacts_mailer make a contact_email.html.erb file. This is the HTML email template that will be sent to your email address after a user submits a contact form.

<h1>Contact Form Submitted</h1>
<br>
<p>Subject: <%= @contact.subject %></p>
<p>Name: <%= @contact.name %></p>
<p>Email: <%= @contact.email %></p>
<p>Message: <%= @contact.message %></p>
<p>Sincerely,</p>
<p>The Contact Mailer</p>

Inside app/views/contacts_mailer make a contact_email.text.erb file. If the HTML email template can’t be sent, a text file can be sent in its place. Make sure there is no HTML in this file.

Contact Form Submitted
 
Subject: <%= @contact.subject %>

Name: <%= @contact.name %>

Email: <%= @contact.email %>

Message: <%= @contact.message %> 

Sincerely,
The Contact Mailer

Environment Variable Setup

Before I finally configure this Rails app to my SendGrid account I want to make sure that the username and password I have for my SendGrid account are stored in secure files. I will use the dotenv gem to do this, and that can be found at Ruby’s gem site.

https://rubygems.org/

Search for dotenv-rails, copy the file, and paste it in your Gemfile’s development section (use the most recent working version, and make sure it is dotenv-rails).

group :development, :test do
  gem 'dotenv-rails', '~> 2.2'
end

Bundle your new gem file in the terminal.

bundle install

In sendgrid (or the name of your app) create a new file called .env

When you get a pop up warning about using “.” files, click “Use”

In the .env file enter your send grid username and password

SENDGRID_USERNAME=your_sendgrid_username
SENDGRID_PASSWORD=your_send_grid_password

If you plan on pushing this up to Github, then in your .gitignore file add

#environmental variables
.env

And finally in config/environments/development.rb set .raise_delivery_errors = true (this line is already in the file, but it’s set to false. It should be set to false if you ever deploy this to production). For default_url_options make sure you set the host to localhost (if that’s what you’re using) and the port to 3000 (again if that’s the port you’re using). Make sure to set the delivery_method = :smtp. In the smtp_settings object add all the information below, just make sure your username, password, and domains match the username, passwords, and domains that you’re using in your app.


 config.action_mailer.raise_delivery_errors = true
 config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
 config.action_mailer.perform_deliveries = true
 config.action_mailer.delivery_method = :smtp
 config.action_mailer.smtp_settings = {
   address: "smtp.sendgrid.net",
   port: 587,
   authentication: "plain",
   user_name: ENV["SENDGRID_USERNAME"],
   password: ENV["SENDGRID_PASSWORD"],
   domain: 'localhost:3000',
   enable_starttls_auto: true,
 }

Restart your server (you must do this anytime you bundle or change a config file) and test your new mailer.

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s