Self-hosted disposable email addresses with AHEM

Screenshot of webpage showing AHEM email service

I’ve run my own mailserver for years now, with a catch-all on some domains.

This means that, whenever a shop or service asks for my email address, I can give them a unique address, specific to them, without needing to configure anything.

This has a number of uses, but the main ones for me are:

One thing this setup does not do well, though, is deal with the situation in which I want a disposable email address: an email address which exists long enough to receive one email.

That’s because, once I’ve given someone their unique address, they can continue sending to it, and it will continue to funnel their email into my mailbox, until I take action to stop them.

Sometimes, I want — well, am forced — to give over an email address just to access something. (For example, I wanted to download a cycle map from Sustrans the other day, and they insisted on having an email address, which is nonsensical as they just emailed me a link to a PDF on their website. Why not just hyperlink the PDFs from the website, and skip the hassle?! (Spoiler: probably some kind of tracking.).)

In that kind of situation, I want a system for disposable email addresses, which exist only for a very short period of time, and which do not clog up my mailbox.

#Just use a third party service?

There are loads of services which offer this, some free and some paid, and, to date, I’ve just used one of those. Since I’ve not used them for anything private, it didn’t matter too much to me that someone else can see the content of the email.

Indeed, if you are looking for privacy from “hiding in a crowd”, using a third party service is probably preferable to hosting your own service.

However, that trade-off was acceptable to me, and since I prefer to host my own tools, having my own setup seemed like a useful thing to have, if it was relatively easy to do.

And it was.


#AHEM: the Ad-Hoc-Email-Server

It took me about 30 minutes to get a disposable email server running using AHEM.

The instructions on github sort of worked, and I can’t tell if the bits which did not work out of the box are because of my lack of familiarity with node.js, or incomplete / no longer accurate instructions. Let’s assume it’s my ignorance!

I had a bit of a fight with angular, to make the project build, and I solved the error message by forcibly installing a particular version of it. Not ideal, but it worked.

After that, it built with some warnings but no more errors.

#A and MX records

Since it’s an email service, you need to set an MX record for the domain you want to use, pointing to a record pointing to the IP address on which you’re running AHEM.

I chose a sub-domain of my normal domain. I’m using it for both the email addresses, and also for accessing the web server (via nginx).

AHEM can support multiple email domains, so if I wanted to do the same for one of Sandra’s domains, it would be a simple case of adding the domain to AHEM’s .env file.

#Making it more privacy-friendly

I can understand why people do it, but it bugs me all the same: why use static files hosted by a third party CDN, rather than just hosting them yourself?

Out of the box, AHEM uses some JavaScript resources hosted on Cloudflare. I used wget to download the scripts, and then replaced the references in index.html with localhost references instead.


#Proxying via nginx

By default, it runs on localhost:3000. Fine for testing, but not what I wanted permanently.

Since I had nginx on the server already, reverse-proxying to give a web interface over port 80, using the same sub-domain as for the email address itself (although anything else would work too; they are not connected) was easy.

It also meant that it was trivial (using certbot) to pop a TLS certifcate on the proxy, giving me TLS over 443. Even though the web interface will be firewalled off and accessible only without our private network, I’d prefer to have TLS in place anyway.

I’m not sure why, but the basic config was 404’ing traffic to /, so I added a specific Location section for that:

location / {
	proxy_pass http://localhost:3000;       
	proxy_http_version 1.1;
	proxy_set_header Upgrade $http_upgrade;
	proxy_set_header Connection "Upgrade";
	proxy_set_header Host $host;

#Making it persistent

I’m not that familiar with node.js, so there might be a better way of doing this, but I was struggling to keep it running when I closed my ssh connection.

I could just run it as a background process (by appending & to the command), but I installed pm2:

npm install pm2 -g

and then ran it using:

pm2 start ahem.js

#The outcome

Now, I have a simple to use, self-hosted, web page, which lets me generate random email addresses to paste into webforms when I want a disposable address.

I need to refresh the page to check if an email has arrived, but that’s fine. I should check if there’s something I’ve not configured correctly, as I’d have thought it would refresh periodically, if nothing fancier existed to show an email when it arrives.

Email are deleted automatically when they are 24 hours old; again, this is something configurable via .env, but that seems fine as a default.

#AHEM’s licensing status

A couple of weeks ago, AHEM changed its licence from an in-house job to Apache 2.0.

This is a good decision, IMHO, but still needs to be reflected in the AHEM interface, since this says that it’s only “available for personal and internal use”.