Save All App Email to Amazon S3 Nick Quinlan January 17, 2014 Technical // SUMMARIES ?> Sending email is great, but sometimes you want a little more. Maybe you want to store every email you send your users. Or maybe you want to allow your users to share your emails on their social networks. Maybe, you simply want to allow users to see the email online, in case their email reader breaks it. Well, I made a simple app to do that, with Amazon S3. The app (available on Github) is relatively small and easy to implement. Follow the Quick Start Guide to get an instance of the app up and running. This will get you a Heroku instance running the app and the SendGrid Parse Webhook configured. Now you have an application that will store any email it recieves, however, it’s not yet storing all email you send. To have the app store every email you send, you’ll simply need to enable the BCC app, found in your app dashboard. Set the app to BCC all mail to an address on the Parse Webhook domain you setup earlier. Now, all email you send will be stored on S3. You may, however, want to link to the stored email, when you send it. Luckily with this app, you may. To do so, include an X-Save-Mail-ID header in the email you’re sending. This header, tells the app what to name the saved file (so you can link to it, before it’s been created). You can make the filename anything as long as you ensure it will be unique. Most languages have a Universally Unique Identifier (UUID) function that will allow you to do this, although you can also simply hash the email contents with the microtime and be fairly safe. If your UUID or approximation is “ABC”, you may then link to the file in the email with the URL: http://s3.amazonaws.com/your-bucket-name/ABC.html. An example makes this a little more clear (it’s in PHP but you can do this in any language): <?php // Include the SendGrid PHP library // if you're not using PHP we likely have a different library for you: // http://sendgrid.com/docs/Integrate/libraries.html require("vendor/autoload.php"); // Initialize SendGrid (and pass your credentials) $sendgrid = new SendGrid(YOUR_USERNAME, YOUR_PASSWORD); // Initialize the email object $email = new SendGrid\Email(); // Fill out the basic email object $email ->addTo('firstname.lastname@example.org') ->setFrom('email@example.com') ->setSubject('This is an awesome email.'); // Generate a Unique ID that will become the filename // For sorting's sake, you might want to add the date to the begining of the unique ID $unique_id = uniqid(); // As the file will be stored on S3 and we're providing the filename, we can construct a URL $email_url = "https://s3.amazonaws.com/your-bucket-of-awesome/" . $unique_id . ".html"; // Provide the X-Save-Mail-ID as a header & the email URL in the body of the message $email ->addMessageHeader('X-Save-Mail-ID', $unique_id); ->setHtml( '<strong>This is a demonstration.</strong> ' . '<a href="' . $email_url . '">Click here to view this online</a>' ); // Send The Message // (it'll be automatically BCC'd to your Parse Webhook's email, if you've setup the BCC app) $sendgrid->web->send($email); ?> There you have it. With this app you can send email with SendGrid (or any other mechanism) and have it stored to S3. You can even configure the app to change the template on the fly. Since it’s on S3 you can do other things, like make the links expire after a certain period by using Lifecycle Rules. There’s one caveat to all this, however, there is a race condition. If for some reason, the email is processed slowly by the app and your user opens the email upon receiving it and tries to click through to the S3 hosted version, they’ll receive a 404. I feel this is unlikely, however, if you wish to fully prevent it, you must store your emails in S3 prior to sending the message. Hopefully armed with this app, you can get a little more out of your emails; whether that be happy users or simply a permanent record of the messages you sent.