DEV Community

Sriram Thiagarajan
Sriram Thiagarajan

Posted on • Originally published at tsriram.in

Deconstructing Stripe's email verification flow

I came across this tweet from @championswimmer and was intrigued about the feature & implementation.

Screenshot of the linked tweet

Let's dig deeper.

Stripe's signup flow

When you sign up for a Stripe account, the app takes you to a dashboard page as soon as your account is created and shows a message asking you to verify your email address by clicking on the link sent to you email. Pretty standard right? Well, Stipe steps this UX up a notch by having a button on this landing page to open your email. And they take this to the next level by opening your email with a search query embedded to filter out only the emails sent by Stripe. This is an amazing UX.

As you might think, this doesn't work for all email addresses obviously because it's hard to know the URL for ton of email providers and not all of them support a search query in the URL to filter emails.

This flow works only for Gmail (both personal gmail.com accounts and other domains that have email hosted by Google Workspace). From my experiments, this button to open email works for Gmail & Outlook and the button clearly shows this with Open Gmail & Open Outlook labels respectively. I tried signing up with a Hey email address and there was no button to open email. Only a message was displayed to

Note: Both the email addresses shown below are not mine, Stripe one should've been obvious though :) Apologies to the owners of these emails. Sorry I had to test :P

Here's how it looks for a Hey email address:

Screenshot of Stripe's welcome message for a user with hey.com email

And here's how it looks for a Gmail address (Stripe uses Gmail):

Screenshot of Stripe's welcome message for a user with Gmail

This is the URL the Open Gmail button opens:

https://mail.google.com/mail/u/sriram@stripe.com/#search/from:support@stripe.com
Enter fullscreen mode Exit fullscreen mode

As you can see in the above URL, it has the search query which filters emails from support@stripe.com which is used to send out these verification emails.

Another learning from this exercise is that Gmail can take the email address in URL instead of numbers (0/ 1/ 2) as route param and open the correct one if you've logged into multiple accounts in your browser. You might have seen URLs like these:

  • mail.google.com/u/0
  • mail.google.com/u/1

You can actually put mail.google.com/u/<email> and it'll automatically redirect you to the correct account. It's brilliant that Gmail supports this and Stripe's team learnt & used it in their email verification flow to ensure that users don't land on their default Gmail account when they click on Open Gmail.

The How

So we want to find if an email address belongs to Gmail. The implementation of this seems to be fairly straightforward. If I want to implement this, I'd probably follow these steps:

1. Get the domain name from email address

This one's easy. Also check if the email is a valid one first. If the domain is gmail.com, you don't have to anything else :)

2. Do a DNS lookup and get MX records

If you're familiar with DNS records, you'd know that MX records are used for routing emails. Since we want to find if an email is hosted by Gmail, we need to first get these records for the domain.

This is quite easy with DNS-over-HTTPS (DoH). You could use the service from Google or Cloudflare.

3. Verify if MX records belong to Gmail

Google publishes MX records that one need to set if they want to get their domain configured for Google Workspace. You can find them here - https://support.google.com/a/answer/140034. So once you have the MX records of the domain, it's simply verifying if the records match at least one of the records provided by Google for Gmail. If it does, you can be sure that the email is provided by Gmail.

That's pretty much it. Once you know that the email is hosted on Gmail, you can use the same technique to add search query to the URL to filter out the mails sent by you.

What do you think about this? Have a different solution in mind? Feel free to ping me on twitter :)

Top comments (0)