Not the usual spam mail

How I built a disposable email service in two hours

Lukas Klein
3 min readJan 30, 2018

--

There are times when you need a disposable email address (e.g. when signing up for a newsletter to get that discount code). Even though there are many existing services out there already, most of them are blacklisted on many websites. For this reason and since I like digging into new technology, I set out to build my own: Muellpost.de (“Müll” is German for trash).

The requirements were clear: I didn’t want to have to maintain a huge backend service that potentially breaks at some point and runs into scaling issues. Sounds like the perfect reason to give the revamped Firebase a try. I worked with Firebase in the past, back when it was just a realtime database and before they got acquired by Google. Since then, much has changed. They offer not only the realtime database anymore, but also many other services like a “real” datastore, Cloud Functions (everyone’s talking serverless nowadays, right?) and many mobile SDKs for error tracking, analytics and so on.

I knew from the start that I was probably going to use Postmark Inbound email processing to receive the emails, since it worked great for other projects in the past. What it does is it provides you with a unique email address (like 123xyz@inbound.postmarkapp.com) that will call a webhook with the parsed email as JSON whenever an email arrives. I usually write a Django app to process the JSON and store it in some kind of database but since I wanted to go full “serverless” this time, this wasn’t an option. This is where Firebase’ Cloud Functions come in handy. They can be configured to run code whenever an URL is called. I’m using a cloud function to process the incoming JSON and store it in a Firebase realtime database. The whole code for the inbound email processing is only about 13 lines of code:

const functions = require('firebase-functions');
const admin = require('firebase-admin');


admin.initializeApp(functions.config().firebase);

exports.receiveEmail = functions.https.onRequest((req, res) => {
// Helper function to encode to base64
const encodeAddress = address => Buffer.from(address).toString('base64');

// An email can have multiple receivers. Using `.map` and `Promise.all` to process all of them before returning success
Promise.all(req.body.ToFull.map(to => admin.database().ref(`/emails/${encodeAddress(to.Email)}`).push(req.body))).then(() => {
res.status(200).send('k thx bye');
});
});

All it does is it exports the receiveEmail endpoint that will take the receiver email address from the JSON body, encode it to Base64 (to use it as a Firebase ref), push the email into the database and finally return an HTTP 200. After deploying the function and setting the Postmark webhook, that’s all the magic needed to store incoming emails in a database.

Right now, you have to send the email to the unique Postmark address. Even though you can set up your own inbound email address with Postmark, you are limited to a single domain. Since I wanted to be able to expand the service to multiple domains, I needed a different solution.

That’s where Namecheap Free Dns comes in. It allows you to configure a catchall email address on your domain that forwards to a given email address. Problem solved ¯\_(ツ)_/¯

To display the emails, I wrote a really simple React front-end using react-redux-firebase which I’m hosting on Firebase hosting (obviously). To ensure security, I’m rendering the emails inside a sandboxed Iframe.

One last thing was left to do: I wanted the users to be able to delete emails. This can be accomplished quite easily using Firebase security rules, which ended up looking something like this:

{
"rules": {
".read": "auth != null",
".write": "auth != null",
"emails": {
"$inboxhash": {
".read": true,
"$email": {
".write": "data.exists() && !newData.exists()"
}
}
}
}

They basically allow you to read the emails of a given inboxhash (the Base64-encoded receiver email address) and delete individual emails (but not tamper with the data).

Conclusion

Using readily available technology, I was able to build a disposable email address service in about two hours. The operation costs are very marginal (at the moment only the domain cost, all other services like Postmark and Firebase have a very generous free tier).

Technologies used

  • Namecheap Free Dns
  • Postmark Inbound
  • Firebase Cloud Functions
  • Firebase Realtime Database
  • Firebase Hosting
  • Front-end: react, react-redux-firebase, react-router, moment.js

--

--

Lukas Klein

All things IoT / Python / Django / React. Founder @datacake.