Blocking Disposable Emails
Tags: webdev, go, security, programming
Published: 2020-03-23 17:27:47


There are legitimate reasons why some users decide to use a disposable or temporary email to sign up for a service.  They just want to try it out and don't want more email (or spam) in their inbox, I get it.

However, there's other users, and some bots, where it's a means to stuff accounts on your website or abuse your service.  

This can also mess with metrics your tracking.  Are you building an email list for a newsletter?  Trying to gauge interest and collect leads for your new idea through a landing page?  

Disposable emails can degrade your efforts here.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/cj52h8gr5nd6rxpfj8ej.jpg)

Even though a disposable email can serve legitimate scenarios, you may want to consider how you deal with them and if it's worth the effort to block those services or at least distinguish those users.

# My Projects Concerns

The SaaS I build, [Packetriot](https://packetriot.com), provides an application tunnelling service and it's used primarily by developers that are building an application and want to host it instantly.  This could be an MVP or a iteration you want to show a client or a colleague.

There's many people that use Packetriot to just self-host applications.  Some want more control over their data and others because storage and cloud computing are just expensive.  If you know how to configure a Linux instance on AWS then you can probably self-host many services yourself for much cheaper.

Unfortunately, it can also be used to host a spam link or phishing website and I don't want Packetriot to be used a delivery system for bad actors.  Similar services like [Serveo](http://serveo.net) were shutdown because of abuse.  I want to protect my users, my business and other Internet users.

I wanted to share the strategy I took to stop spammy users and bots stuffing accounts on my website.  I also have some [code](https://github.com/packetriot/abuse) to share that I wrote to help me add this in my registration and other workflows.  I'll also discuss how effective this was as well, TLDR; it worked well!

# Goals

In the case of Packetriot there's a big opportunity for abuse by spammers and phishers.  Both these groups want to send you a link to click on... never click the link!!  My goal is to prevent abuse the best I can but also avoid creating more onboarding obstacles for potential users.

Many Packetriot alternatives have different levels of onboarding.  All of the registration-less services eventually fail due to abuse.  In addition, I want to prevent the resource utilization by abusive users and maintain the highest quality of service.

Packetriot has a free-tier that provides with enough features for casual users or those who want to try the service, integrate our client into their workflow and evaluate how well we can host their website or app.

We use link confirmations to begin onboarding a new user.  You'd be surprised how well bots are programmed to automatically traverse this workflow.  To combat this, I use [reCAPTCHA V3](https://google.com/recaptcha).  However, they're lots of people manually doing this, and that's where disposable emails broke my captcha.

# Some Code

Packetriot is written in Go and our package [abuse](https://github.com/packetriot/abuse) is a small library I wrote to perform checks on email address or domains during registration and email confirmation.  It's opensource and free to use and contribute to.

To start using, import into your Go app.  Calling the `Init()` function isn't necessary, but if you want to be able to update the list of abusive domains you'll need to do this.  Later on in this article I share a behavior by most disposable email providers that enable us to add their new domains automatically :)


```
import (
	"github.com/packetriot/abuse"
)

func main() {
	abuse.Init("/path/to/app-data/abusive-domains.txt")
	defer abuse.Close()
}

```

During registration I check if the domain in the email address is already in my list abusive domains.

```
func registerUser(w http.ResponseWriter, r *http.Request) {

	// parse email from HTML form submission
	email := "..."

	if abuse.IsTempEmail(email) {
		serveNoTempEmail(w, r)
		return
	}
}
```

We created an update mechanism into our package that leverage how some disposable email services work.  For example, the domain names of the email addresses generated change over time, but the primary sitename, and thus `Referrer`, does not.  So when a user clicks on a confirmation link we send them, the provider's sitename is set as the `Referrer` value in the HTTP header.

This simple check helps us keep up with providers automatically.  We can add the domain from this new email address to our list and then the next time we see an email address with this domain, they won't be able to get passed the registration screen.

Here is an example of how to implement this.  The important function is the `abuse.Add(domain string)` function.  Once we discover the `Referrer` is a domain we already have in our list then we can add this new domain and automatically keep up with the new domains that are generated almost weekly from some providers.

```
func confirmEmail(w http.ResponseWriter, r *http.Request) {
	user := getUserFromSession(r)
	if referrer :=  r.Header.Get("Referrer"); len(referrer) > 0 {
		u, _ := url.Parse(referrer)
		if abuse.IsAbusiveDomain(u.Host) {
			// Must be a new domain for emails but coming from a provider we know
			abuse.Add(u.Host)

			serveNoTempEmail(s, w, r)
			return
		}
	}

	// ...
}

func getUserFromSession(r *http.Request) *User {
	// ...
	return user
}

type User struct {
	Email string
	// ...
}

```

# Conclusion
Incorporating this in my site has eliminated a vast majority of accounts that I eventually find were created with a disposable email.  In your scenario, you may want to just flag a user that is using a temporary email and then deal with them in some other way.

Many of my competitors are outright blocked on corporate networks because they're abused by bad actors and Infosec professionals don't trust them.  I want to build trust with them and my users. Ideally, I don't want my network to ever carry malicious traffic.

For Packetriot it's the right call because we don't want malicious actors using our service to perpetuate their bad stuff on the Internet.

I played cat-and-mouse with disposable email services for months, and I routinely found that the people using them (on my service) were never up to any good.  If this is an issue that impacts your project then I hope this article was helpful.

I routinely update our [package](https://github.com/packetriot/abuse) when I discover new services.  If you'd like to use it and want any help with integrating it please feel free to reach out.  Also, let me know if you add it to your website.  Cheers!