Twitter: raymondcamden


Address: Lafayette, LA, USA

Building a Contact Form with Parse and Mailgun

11-12-2013 8,838 views jQuery, JavaScript, HTML5 8 Comments

I'm currently working on an article that discusses various third party services that can help flesh out a static web site. While researching that article, I got to thinking about contact forms and how (or if) I could use Parse to power them. Parse is built for ad hoc data storage of - well - anything. I wouldn't typically think of contact forms as being something I'd want to save, but the more I thought about it, the more I thought that in some organizations this could be a powerful feature. You can track communication over time as well as use the email addresses as a list to contact in the future. There are probably multiple ways of doing this, but here is what I came up with.

I began with - of course - the contact form. I built something short and sweet that I thought would be fairly typical. It asks for a name, email address, an "area" (i.e., why are you contacting us), and has a box for the comment.

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<title></title>
		<meta name="description" content="">
		<meta name="viewport" content="width=device-width">
	</head>
	<body>
		
		<h2>Contact Form</h2>
		
		<form id="commentForm">
			
			<p>
			<label for="name">Your Name</label>
			<input type="text" name="name" id="name" required>
			</p>

			<p>
			<label for="email">Your Email</label>
			<input type="email" name="email" id="email" required>
			</p>

			<p>
			<label for="area">Your question involves:</label>
			<select name="area" id="area">
			<option value="stuff">Stuff</option>	
			<option value="otherstuff">Other Stuff</option>	
			<option value="starwars">Star Wars</option>	
			<option value="startrek">Star Trek</option>	
			</select>
			</p>

			<p>
			<label for="comments">Your Comments<br/></label>
			<textarea name="comments" id="comments" required></textarea>
			</p>
			
			<p>
			<input type="submit" value="Send Comments">
			</p>
		</form>
		
		<script src="http://www.parsecdn.com/js/parse-1.2.12.min.js"></script>
		<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
		<script src="app.js"></script>
	
	</body>
</html>

I assume none of this needs to be explained, but I will point out I'm using HTML5 form validation here. At the bottom I'm loading jQuery, Parse's library, and my own JavaScript file app.js. I began by building a simple shell of a form handler.

/* global $,document,console */
$(document).ready(function() {
		
	$("#commentForm").on("submit", function(e) {
		e.preventDefault();

		console.log("Handling the submit");
		//add error handling here
		//gather the form data

		var data = {};
		data.name = $("#name").val();
		data.email = $("#email").val();
		data.area = $("#area option:selected").val();
		data.comments = $("#comments").val();

	});
	
});

Again - I assume this is pretty boilerplate. Note that I intentionally skipped doing form validation. As that's been done about eleven billion times or so I wanted to keep this proof of concept as simple as possible.

Ok, so let's talk Parse. I'm going to assume you've read my earlier posts on Parse. I went ahead and set up a new application on Parse and copied down my appropriate keys. My HTML file already had Parse's JavaScript library included so I didn't need to do anything there. I knew I could easily take the comment data and store it in Parse. Here is the updated version with Parse enabled.

/* global $,document,console,Parse */
$(document).ready(function() {
	
	var parseAPPID = "1xW2AmMzvU7pukTxmXycGC6zVIsC9llnLesiGvXZ";
	var parseJSID = "k8dOFpCbQcdyaGCDk9jytrlaGezfnGMIKsuy8veX";
	
	Parse.initialize(parseAPPID, parseJSID);
	var CommentObject = Parse.Object.extend("CommentObject");
	
	$("#commentForm").on("submit", function(e) {
		e.preventDefault();

		console.log("Handling the submit");
		//add error handling here
		//gather the form data

		var data = {};
		data.name = $("#name").val();
		data.email = $("#email").val();
		data.area = $("#area option:selected").val();
		data.comments = $("#comments").val();

		var comment = new CommentObject();
		comment.save(data, {
			success:function() {
				console.log("Success");
				//Alerts are lame - but quick and easy
				alert("Thanks for filling the form!");
			},
			error:function(e) {
				console.dir(e);
			}
		});
		
	});
	
});

Again, I tried to keep it simple so on a successful return I use a lame alert to let you know it went through. I don't even publicly display a message if an error is thrown. Again, bad. But I was trying to make the demo as simple as possible. I ran this and confirmed that I could fill out the form and the results would be stored at Parse.

While this would work, I'd have to constantly check the Parse dashboard to see when someone filled out my contact form. How can I add email support?

One of the more interesting features of Parse is Cloud Code. Cloud Code is JavaScript that runs on the server. One of the best examples of it is performing aggregate operations. Imagine you had a million or so "Rating" objects. If you wanted to get an average for all the objects you could download them all to the client and loop. Or you can run code on Parse's server and do it there instead. Guess which one is better?

Along with having access to your data on the server itself, Parse has a set of Cloud Modules that wrap various third-party services. One of them is Mailgun. Mailgun is a mail API service that provides up to 10000 emails on their free tier. That kicks ass. I think my blog here is reasonably successful for a tech site and I get maybe 100 or so emails per month from my contact form.

I followed the directions for installing a new Cloud Code directory and it created a new file, main.js, with a sample Cloud Code function. The docs have an example of running code on saving data, so I used that as my basis as well as the docs on using the Mailgun module. Here is my final function:

/* global Parse,console,require */

var Mailgun = require('mailgun');
Mailgun.initialize('raymondcamden.mailgun.org', 'mykeysmilkshakeisbetterthanyours');

Parse.Cloud.beforeSave("CommentObject", function(request, response) {

	var text = "Comment Email\n" + 
		"From: "+request.object.get("name") + "\n"+
		"Email: "+request.object.get("email") + "\n"+
		"Area: "+request.object.get("area") + "\n\n"+
		"Comments:\n" + request.object.get("comments");
	
	Mailgun.sendEmail({
			to: "raymondcamden@gmail.com",
			from: request.object.get("email"),
			subject: "Comment Form - " + request.object.get("area"),
			text: text
		}, {
		success: function(httpResponse) {
			response.success();
		},
		error: function(httpResponse) {
			console.error(httpResponse);
			response.error("Uh oh, something went wrong");
		}
	});

});

You can see where I take the data from the Comment object and use that when I speak to Mailgun. I also use the email address on the form as the from value. This makes it easy to reply. I've also taken the "area" field and used that in the subject. That could be useful for filtering emails based on what they concern. And does it work? Yep!

Want to give it a try yourself? Hit the demo and spam me to high heaven.

8 Comments

  • Commented on 11-13-2013 at 12:53 AM
    Thanks for your article. But I have some questions.
    1. Where can i find demo page? Because I don't understand how these forms appear on the page? Should they have some default design?
    2. Application IDS save not securely. So, any other people can grab theirs from your JS and paste to his app?
  • Commented on 11-13-2013 at 4:53 AM
    For the same idea but using Parse and SendGrid, take a look at this one:-

    http://blog.steamshift.com/blog/2013/02/25/parse-p...
  • Commented on 11-13-2013 at 5:00 AM
    @plutov: The demo is linked to in the article (towards the end). The forms are just plain HTML - so they just show up. As for design - well - sure - you could use some CSS to make it prettier, but as it wasn't relevant to the article, I didn't think it was necessary.

    App ID: This is a JavaScript file - you can't hide the App ID. However, Parse actually has quite a few settings you can use to make this safer. Read the "Lock Down" section here: http://www.raymondcamden.com/index.cfm/2012/10/24/...
  • Commented on 11-13-2013 at 5:00 AM
    @Andy: Thanks for sharing. "Great minds..." ;)
  • Commented on 11-20-2013 at 11:25 AM
    Extremely cool.
  • Commented on 05-09-2014 at 11:19 AM
    Great write up, thanks for the insight!
  • jozsef #
    Commented on 06-25-2014 at 2:23 AM
    Hi, have you any idea how can it be done when a site created by Adobe Muse is hosted on a static hosting? I don't want to insert HTML rather use the built in contact form widget.
  • Commented on 06-25-2014 at 9:02 AM
    Sorry, I don't know how their contact form widget works. I'd just insert the HTML.

Post Reply

Please refrain from posting large blocks of code as a comment. Use Pastebin or Gists instead. Text wrapped in asterisks (*) will be bold and text wrapped in underscores (_) will be italicized.

Leave this field empty