Building a Contact Form with Parse and Mailgun

This post is more than 2 years old.

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>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<meta name="description" content="">
		<meta name="viewport" content="width=device-width">
		<h2>Contact Form</h2>
		<form id="commentForm">
			<label for="name">Your Name</label>
			<input type="text" name="name" id="name" required>

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

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

			<label for="comments">Your Comments<br/></label>
			<textarea name="comments" id="comments" required></textarea>
			<input type="submit" value="Send Comments">
		<script src=""></script>
		<script type="text/javascript" src=""></script>
		<script src="app.js"></script>

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) {

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

		var data = {}; = $("#name").val(); = $("#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) {

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

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

		var comment = new CommentObject();, {
			success:function() {
				//Alerts are lame - but quick and easy
				alert("Thanks for filling the form!");
			error:function(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('', '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");
			to: "",
			from: request.object.get("email"),
			subject: "Comment Form - " + request.object.get("area"),
			text: text
		}, {
		success: function(httpResponse) {
		error: function(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.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by plutov.vy posted on 11/13/2013 at 11: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?

Comment 2 by Andy Bennett posted on 11/13/2013 at 3:53 PM

For the same idea but using Parse and SendGrid, take a look at this one:-

Comment 3 by Raymond Camden posted on 11/13/2013 at 4:00 PM

@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:

Comment 4 by Raymond Camden posted on 11/13/2013 at 4:00 PM

@Andy: Thanks for sharing. "Great minds..." ;)

Comment 5 by steve posted on 11/20/2013 at 10:25 PM

Extremely cool.

Comment 6 by Mike posted on 5/9/2014 at 8:19 PM

Great write up, thanks for the insight!

Comment 7 by jozsef posted on 6/25/2014 at 11: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.

Comment 8 by Raymond Camden posted on 6/25/2014 at 6:02 PM

Sorry, I don't know how their contact form widget works. I'd just insert the HTML.

Comment 9 by Yatheesh posted on 11/18/2014 at 7:59 PM

Thanks for this it helped me a lot.

Can you also say how to retrive data and show on web page?

Comment 10 by Raymond Camden posted on 11/18/2014 at 8:00 PM

Retrieve data from what? Parse? If so, please search for Parse as I've done multiple entries.

If you mean using a random app server, that's a bit too broad.

Comment 11 by mounir benchemled posted on 8/26/2015 at 4:16 PM

Very useful. Thanks !

Comment 12 by Nick Longinow posted on 9/26/2015 at 10:11 AM

thank you so much for this article!

Comment 13 by Andrew Bernard posted on 4/22/2017 at 6:53 AM

Mailgun is alive and well, but parse seems to be dead. I wonder what could be used as a replacement.

Comment 14 (In reply to #13) by Raymond Camden posted on 4/22/2017 at 1:32 PM

A serverless platform like OpenWhisk. :)

Here is a blog entry on it: https://www.raymondcamden.c...

Comment 15 (In reply to #14) by Andrew Bernard posted on 4/23/2017 at 6:18 AM

Thanks! I also found this I'll see which best meets my needs.