Sending Email directly to Gmail From Contact Us Form in Front-End (React & Redux) Using Mail_Form gem in Back-End (RoR)

Hima Chitalia
Coffee and Codes
Published in
8 min readSep 6, 2017
contact form to send email directly to Gmail Account

The journey of learning Web Development has been very challenging but at the same time interesting.

Coming from a Marketing background, each and every concept were brand new. But my dedication and support from my family are enough to help me cross the road.

I am into the last section of my Online Web Development Course and need to make a Web Application using React and Redux in front-end for client-side application and Ruby on Rails in the back-end for the API.

I thought a lot about what should I make. The one thing I finalized was to dedicate this project to my support system, my loving husband — Trushal Chitalia.

He works at New York Life Insurance as an Accountant and he is also a part-time Real Estate Agent. He wants to grow more as a realtor. So, I decided to build a website for him.

While building this web application, I learned a lot about React, Redux, how to connect it to backend API, fetch results, send it to reducers and finally render on the page through components.

But I was really puzzled when I received a demand from my client (my husband) to show a contact form which on submission sends an email directly to my husband. Ugrrrrr…..!

Clients are demanding, so my husband! To make this happen, I googled, read many documents on RoR and Stack Overflow answers. And one thing, I decided to use was gem ‘mail_form’ in my back-end app — https://trushal-chitalia-api.herokuapp.com/.

Now, before I start using this gem, I needed to configure my mailer. So, first of all, I created a new Gmail account. Now, I needed to configure this account in the mailer for the Local Development Environment and Production Environment on Heroku using environment variables.

Setting Up Development Environment (Local Environment)

In config/environments/development.rb, I wrote this line..

config.action_mailer.default_url_options = { :host => ‘localhost:3001’ }

Next, I turned on the option to raise an exception if there is an error when sending an email.

config.action_mailer.raise_delivery_errors = true

Next, I will add the email delivery method in the same file. In this section, I used Environment variables that I will set up using gem dotenv for the domain, username, and password so that I can hide my information on open-source software sites like Github.

config.action_mailer.delivery_method = :smtpconfig.action_mailer.smtp_settings = {
address: ‘smtp.gmail.com’,
port: 587,
domain: ENV[‘GMAIL_DOMAIN’],
authentication: “plain”,
enable_starttls_auto: true,
user_name: ENV[‘GMAIL_USERNAME’],
password: ENV[‘GMAIL_PASSWORD’]
}

Setting Up Production Environment

Now I needed to edit the file config/environments/production.rb so that gem mail_form also works on Heroku. So, I added below lines to this file:

config.action_mailer.default_url_options = { :host => ‘yoursite.herokuapp.com’ }Rails.application.routes.default_url_options[:host] = ‘yoursite.herokuapp.com’config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = false
config.action_mailer.default :charset => “utf-8”
config.action_mailer.smtp_settings = {
address: “smtp.gmail.com”,
port: 587,
domain: ENV[“GMAIL_DOMAIN”],
authentication: “plain”,
enable_starttls_auto: true,
user_name: ENV[“GMAIL_USERNAME”],
password: ENV[“GMAIL_PASSWORD”]
}

Here again, I decided to use Environment variables which I will set up using gem dotenv to make sure that my personal information is not visible on any open-source platform.

Adding Local Environment Variables

Now it was time to set up my local variables to my local host and my production site on Heroku.

Here, I assume that you are already familiar with gem dotenv but if you need guidance, please follow this post .

Now, in .env file, I wrote below variables:

GMAIL_DOMAIN=gmail.com
GMAIL_USERNAME=yourusername@gmail.com
GMAIL_PASSWORD=password

Here, domain is gmail.com but username and password are my personal email and password of Gmail account. Now my development environment will use these variables for sending an email.

Next, I created a file in the root directory called Procfile. This file will tell the application which files should be run. Inside the Procfile, I added:

web: bundle exec rails s

Now was the time to update my .gitignore file because I don’t want my information in the .env file to be publicized anywhere. I also added Procfile to .gitignore so that Heroku does not receive an R11 — Bad Bind Error.

.env
Procfile

Now I had to add the my environment variables to Heroku. To add the variables to Heroku, from the root directory of my project, I typed:

heroku config:add GMAIL_DOMAIN=gmail.com
heroku config:add GMAIL_USERNAME=yourusername@gmail.com
heroku config:add GMAIL_PASSWORD=password

Now I am good for the mailer configuration part. Next step is to work on Route, Controller, and model. I started with creating a post route in config/routes.rb:

resources “contacts”, only: [ :create]

I am going to use React in my front-end app to show form and render results, I don’t need a any route to show a form.

Now comes my controller:

app/controllers/contacts_controller.rbclass ContactsController < ApplicationControllerdef create
@contact = Contact.new(params[:contact][:data])
name = params[:contact][:data][:name]
@contact.request = request
if @contact.deliver
render json: {message: “Thank you for your Email, # {name.capitalize}. I will get back to you shortly!”}
else
render json: {message: ‘Error occured. Please try again!’}
end
end
end

Now I needed a model to actually make all of these things work:

app/models/contact.rbclass Contact < MailForm::Base
attribute :name, :validate => true
attribute :email, :validate => /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
attribute :message
attribute :nickname, :captcha => true
def headers
{
:subject => “Contact Inquiry”,
:to => “yourusername@gmail.com”,
:from => %(“#{name}” <#{email}>)
}
end
end

Now I am all set for my back-end part. Till now, I found many tutorials to help me out but to make this work from front-end, I couldn’t find anything. So, I was on my own.

For in my client side app, I have imported ulkit in my index.js. You can find more information about it here.

First off all, I need to do set store in my in my client side app http://trushal-chitalia.herokuapp.com/

In this client-app, I needed to use redux to dispatch actions so I installed it in my app with the command yarn add react-redux redux

Next, I needed to create my store and import all of the necessary modules to make my app work. In /src/redux/store/index.js I wrote this code:

// node modules
import { createStore, applyMiddleware, combineReducers } from ‘redux’;
import thunk from ‘redux-thunk’;
import promise from ‘redux-promise’;
//custom modules
import contacts from ‘../reducers/contactReducer’;
// This will help me state the state for the store, I will set file contactReducer.js later on.const reducers = combineReducers({
contacts
})
const middlewares = [thunk, promise]const store = createStore(
reducers,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
applyMiddleware(…middlewares)
)
export default store;

Now I needed to create a form to send an email. My form looks like this in src/views/Contact/contactForm.js file:

//node modules
import React, { Component } from ‘react’;
import { connect } from ‘react-redux’;
import { bindActionCreators } from ‘redux’;
// custom modules
import { submitContactReqToServer } from ‘../../actions/submitContactReq’;
import EmailMsg from ‘./emailMsg’;
class SendContactInfo extends Component {constructor(props){
super(props)
this.state = {
name: ‘’,
email: ‘’,
message: ‘’
}
}
handleOnSubmit = event => {
event.preventDefault();
this.props.submitContactReqToServer(‘/contacts’, this.state)
this.setState({name: ‘’, email: ‘’, message: ‘’})
}
handleOnChange = event => {
this.setState({
[event.target.name]: event.target.value
});
}
render() {
return (
<div>
<div className=”uk-position-center formMargin”>
<form className=”uk-form” onSubmit={this.handleOnSubmit}>
<fieldset className=”bgColor”>
<h2 className=’uk-text-center’>Get In Touch!</h2>
<div className=”uk-form-row”>
<legend>Name</legend>
<input className=”uk-form-large” type=”text” placeholder=”Your Name” name=”name” onChange={this.handleOnChange} value={this.state.name} />
</div>
<div className=”uk-form-row”>
<legend>Email</legend>
<input className=”uk-form-large” type=”email” placeholder=”Your Email” name=”email” onChange={this.handleOnChange} value={this.state.email} />
</div>
<div className=”uk-form-row”>
<legend>Message</legend>
​<textarea className=”uk-form-large” type=”txtArea” rows=”10" cols=”70" placeholder=”Your Message” name=”message” onChange={this.handleOnChange} value={this.state.message} ></textarea>
</div>
<input type=”submit” value=”Send Email” />
</fieldset>
</form>
</div>
<div>
{ < EmailMsg /> }
</div>
<div className=’uk-text-center uk-position-bottom’>
<h5 > When It Comes To Real Estate, Think Of Me — Trushal Chitalia </h5>
</div>
</div>
);
}
};
const mapDispatchToProps = dispatch => {
return bindActionCreators(
{ submitContactReqToServer }, dispatch);
};
export default connect(null, mapDispatchToProps)(SendContactInfo)

This is my EmailMsg component in src/views/Contact/emailMsg.js file:

//node modules
import React, { Component } from ‘react’;
import { connect } from ‘react-redux’;
class EmailMsg extends Component {showLocationInfo = () => {
const { response, message, sendingEmail } = this.props
return response === true ?<div>
<h2 className=’uk-text-center uk-position-center textDown’>{message.message}</h2>
</div> : sendingEmail === true ?
<div> <h2 className=’uk-text-center uk-position-center textDown’ > Sending Your Email to Trushal Chitalia… </h2> </div> :
<div> </div>
}
render() {
return (
<div>
{this.showLocationInfo()}
</div>
)
}
}
function mapStateToProps(state){
console.log(state.contacts)
return {
message: state.contacts.message,
sendingEmail: state.contacts.makeReq,
response: state.contacts.recvdResp
}
}
export default connect(mapStateToProps, null)(EmailMsg)

Now I need to create a file to send an action to the reducer. So I created a file submitContactReq.js in src/actions folder. My file looks like this:

import { API_URL } from ‘../global’;export const makeAPIRequestToSendEmail = () => {
return {
type: ‘MAKE_API_REQUEST_TO_SEND_EMAIL’
};
};
export const clearEmailDetails = () => {
return {
type: ‘CLEAR_EMAIL_DETAILS’
};
};
export const receivedResponse = () => {
return {
type: ‘RECEIVED_RESPONSE’
};
};
export const sentEmail = data => {
return {
type: ‘SENT_EMAIL’,
data
};
};
export const errorEmail = () => {
return {
type: ‘ERROR_EMAIL’
};
};
export function submitContactReqToServer(url, data) {
console.log(JSON.stringify({ data }))
return dispatch => {
dispatch(makeAPIRequestToSendEmail());
dispatch(clearEmailDetails());
return fetch(API_URL + url, {
method: ‘POST’,
headers: {
‘Accept’: ‘application/json’,
‘Content-Type’: ‘application/json’
},
body: JSON.stringify({ data })
})
.then(response => response.json())
.then(emailMessage => {
dispatch(receivedResponse());
console.log(emailMessage)
dispatch(sentEmail(emailMessage));
})
.catch(err => dispatch(errorEmail()));
}
}

Here, API_URL is my back-end app’s global URL, that I have declared in the file global.js. Declaring app’s global URL this way is very convenient when you are having your app in production and development mode.

My global.js file looks like this:

export const API_URL = ‘http://localhost:3001/';export const API_URL = ‘https://trushal-chitalia-api.herokuapp.com/';

Here when I am working in development mode, I comment out export const API_URL = ‘https://trushal-chitalia-api.herokuapp.com/'; but when I am done and want to send code to production, I comment out export const API_URL = ‘http://localhost:3001/';

As I said earlier, I need to set my reducer file contactReducer.js now. this file will help me to set the state for this action in a store. So, I created a file contactReducer.js in src/reducers directory. It looks like this:

export default function updateLocation(state = {
message: {},
makeReq: false,
errorRec: false,
recvdResp: false
}, action){
switch(action.type){case ‘MAKE_API_REQUEST_TO_SEND_EMAIL’:
return Object.assign({}, state, {
makeReq: true
});
case ‘CLEAR_EMAIL_DETAILS’:
return Object.assign({}, state, {
message: {},
recvdResp: false
});
case ‘RECEIVED_RESPONSE’:
return Object.assign({}, state, {
recvdResp: true
});
case ‘SENT_EMAIL’:
return Object.assign({}, state, {
message: action.data
});
case ‘ERROR_EMAIL’:
return Object.assign({}, state, {
errorRec: true
});
default: {
return {
…state
}
}
}
}

Now all set, I just needed two more things, import my reducer in app.js and add a link in the navbar.

So, here is my app.js after I imported my reducer:

import React, { Component } from ‘react’;
import { BrowserRouter as Router, Route, Switch } from ‘react-router-dom’;
//custom modules imports
import SendContactInfo from ‘./Contact/contactForm’;
class App extends Component {
render() {
return (
<Router >
<div className=”App”>
<div className=”navbar”>
<Navbar />
</div>
<Switch>
<Route exact path=”/contact” component={SendContactInfo} />
</Switch>
</div>
</Router >
);
}
}
export default App;

And my navbar.js file looks like this at this point!

import React from ‘react’;
import { NavLink } from ‘react-router-dom’;
const Navbar = () => {
return (
<div className=”App”>
<nav className=”uk-navbar uk-fixed-navigation navbar-color”>
<ul className=”uk-navbar-nav”>
<li><NavLink to=”/contact”>Contact Me!</NavLink></li>
</ul>
</nav>
</div>
)
}
export default Navbar;

All set and done! I can now easily send email information from my front-end to back-end and my back-end will send that email to my husband’s email!

Here is a working demo..

Sending Email to Gmail Account from the React-Redux front-end Client App

Any suggestion or question, please feel free to write me at hima.chhag@gmail.com or in comment section below.

Happy Coding!

--

--