Workaround

Supabase Auth Emails Not Arriving on Outlook: The Two Real Causes

If users with work emails say your login link is "expired" before they even clicked it, your code is fine. A security scanner opened it first.

July 16, 20263 min26 views

The symptom

Someone signs up with their work email. The magic link email arrives. They click it and get "link expired or already used". Or worse: signup emails to Outlook and Microsoft accounts never arrive at all, while Gmail works perfectly.

I've now seen this exact story three times: a hackathon organizer with a venue booked and attendees locked out, a small business owner, and just this week a dev on Reddit who thought his SMTP config was broken.

Nothing was broken. Something was eating the links.

What's actually happening

Corporate email security (Microsoft Defender, Proofpoint, Mimecast) does two things to your auth emails:

1. It clicks your links before the user does. Scanners open every link in an email to check if it's safe. Magic links are one-time use. The scanner's visit consumes the link, so when the human clicks, it's already dead.

2. It flags cross-domain links. Your email comes from yourdomain.com but the verification link points to xyz.supabase.co. Sender says one thing, link says another. To Microsoft, that's exactly what phishing looks like.

Gmail is more forgiving on both. That's why "works on Gmail, dies on Outlook" is the classic signature of this problem.

The fixes, from cleanest to most infrastructure

1. Switch to OTP codes. Instead of a link, email a 6-digit code. There's nothing to click, so there's nothing for a scanner to consume or flag. In Supabase this means using the {{ .Token }} variable in your email template instead of {{ .ConfirmationURL }}, and verifying with verifyOtp in your app. The Reddit dev who fought this for days confirmed this is what finally worked in production.

2. Put a button between the link and the token. If you want to keep links, make them land on a page in YOUR app with a "Confirm my email" button. The scanner follows the link but never presses the button, so the token only gets exchanged by the actual human.

3. Buy the custom domain add-on. On a paid Supabase plan you can move your auth endpoints to auth.yourdomain.com, so the link domain matches your sending domain and the phishing heuristic goes quiet. One rule I've learned supporting these cases: custom domain and custom SMTP go together. Doing one without the other is where the weird failures live.

The takeaway

If auth emails work on Gmail and fail on Microsoft, stop debugging your SMTP config. Your emails are being delivered, inspected, and killed by the receiving side. Change what you send (a code, not a link) or make your domains agree with each other.

Enjoyed this?

Carol Ships: building, shipping, figuring it out.

Have another workaround to share?

Start the thread below!

Comments

No comments yet. Be the first to share your thoughts!