HTML Forms in HTML Emails
Published by Chris Coyier
You know how you can send HTML email?
You know how things like text areas and radio buttons are HTML elements?
I got thinking about this after getting this email from Google:
So clearly, it can be done. Inspecting the source of the Google email, it's nothing special. Just an HTML form like any other.
I decided to try it myself, so I made a quick PHP page to send myself an HTML email.
<?php $to = 'email@example.com'; $subject = 'HTML Form in HTML Email'; $headers = "From: firstname.lastname@example.org\r\n"; $headers .= "MIME-Version: 1.0\r\n"; $headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n"; $message = '<html><body>'; $message .= '<form action="http://mysite.com/process.php" method="post" target="_blank">'; $message .= '<label>How did you like the movie <strong>Turfnuts</strong>?</label><br />'; $message .= '<input name="rating" type="radio" /> ★☆☆☆<br />'; $message .= '<input name="rating" type="radio" /> ★★☆☆<br />'; $message .= '<input name="rating" type="radio" /> ★★★☆<br />'; $message .= '<input name="rating" type="radio" /> ★★★★<br />'; $message .= '<br />'; $message .= '<label for="commentText">Leave a quick review:</label><br />'; $message .= '<textarea cols="75" name="commentText" rows="5"></textarea><br />'; $message .= '<br />'; $message .= '<input type="submit" value="Submit your review" /> </form>'; $message .= '</body></html>'; mail($to, $subject, $message, $headers); ?>
I have only tested GMail so far. GMail gives this warning when submitting the form:
It's just a warning. It doesn't sound too scary. But it's not as clean as submitting a form on a regular website. There are certainly some users that will cancel and not go through with submission. Google's own email does this as well. If you click "OK", the form submits as you expect it would.
Notice the Google email (or my quick test) doesn't include fields like "Name" and "Email". That would be silly wouldn't it? Anyone sending an email like this already knows that information. But how do you know it when you receive the form data? One way would be to pass it along with the post data in a hidden input. Whatever system you use to generate these emails could also drop that email in the value of the input:
<input type="hidden" name="email" value="[[prefill with email]]">
But that's not particularly secure. Anyone digging around could see how you are posting that data and submit bogus posts with real email addresses. Not good. It's probably better to post the form with secret codes that identify the user (and anything else you want to identify securely, like the product they are reviewing).
<input type="hidden" name="email" value="90d8a0f9d87a0987d098ad87fa0ds7fd"> <input type="hidden" name="product" value="0870n89f7cxz98f7e0qwd87sdf">
Those gibberish values would be salted hashes that you store on your end before sending out. Then when you receive them back, you can match them up and know exactly what user and product the review is for. Now I'm no security expert, so let me know if there is a smarter way.
Mark Wyner blogged about this for Campaign Monitor in 2007. Here is the support from back then:
I'd love to update this chart with more current email clients. If anyone can run a test, let me know, we'll get started building it.
Because of that blog post on Campaign Monitor, I can only assume they allow you to send emails that include forms, but I haven't tested it. I did try sending one from MailChimp, but it appeared that they stripped form before sending the email. According to that old article, some email clients consider emails with forms "insecure", so it might be a play on MailChimp's part to prevent bad experiences for users like that and increase deliverability.
If you are thinking of using this idea in practice, for a use case like presented above, you won't be able to use a service to send the emails anyway (since you'll need to generate, store, send those salted hashes securely).
It looks like older versions of Outlook strip the forms functionality. So that's a problem. Hopefully new versions don't do that. Older versions of outlook also used Internet Explorer as the rendering engine, which means that you could use conditional tags to help:
<!--[if IE]> <a href="http://yourwebsite.com/review.php?whatever"> Review this product </a> <![endif]--> <!--[if !IE]><!--> <form> <!-- Actual review form --> </form> <!--<![endif]-->
Milage on that may vary... apparently Outlook 2007 and Outlook 2010 use Microsoft Word (WTF) as the rendering engine instead of Internet Explorer. Not sure how conditional tags work in Microsoft Word (again, WTF).