Email Verification with Auth0
Auth0 Actions are serverless functions that run during the authentication pipeline. The pre-user-registration trigger runs before a new user is created in Auth0, making it the perfect place to verify email addresses with Mailbeam.
Prerequisites
- Auth0 account with a tenant
- A Mailbeam API key (sign up free)
Create the Action
In the Auth0 Dashboard → Actions → Library, create a new Action for the Pre User Registration trigger.
// Auth0 Action: pre-user-registration
exports.onExecutePreUserRegistration = async (event, api) => {
const email = event.user.email;
// Skip for social logins (no email address provided at this stage)
if (!email) return;
const MAILBEAM_KEY = event.secrets.MAILBEAM_KEY;
const MIN_SCORE = 60;
try {
const response = await fetch("https://api.mailbeam.dev/v1/verify", {
method: "POST",
headers: {
Authorization: `Bearer ${MAILBEAM_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ email }),
});
if (!response.ok) {
// API error — fail open
console.log("[Mailbeam] API returned non-200, failing open");
return;
}
const { valid, score, reason } = await response.json();
if (!valid || score < MIN_SCORE) {
const message = reason === "disposable_domain"
? "Please use a permanent email address."
: "Please provide a valid, reachable email address.";
api.access.deny("invalid_email", message);
}
} catch (err) {
// Network error — fail open
console.error("[Mailbeam] verify error:", err.message);
}
};Add the API key as a secret
In the Action editor, go to Secrets and add:
| Name | Value |
|---|---|
MAILBEAM_KEY | mb_live_xxxxxxxxxxxxxxxxxxxx |
Deploy and attach
- Click Deploy in the Action editor
- Go to Actions → Flows → Pre User Registration
- Drag your new Action into the flow
- Click Apply
Test
// Test via Auth0's built-in Action Testing tab with:
{
"user": {
"email": "temp@mailinator.com"
}
}
// Expected: api.access.deny is called with "invalid_email" errorHow api.access.deny works
When api.access.deny is called, Auth0 returns an error to the client:
{
"error": "invalid_email",
"error_description": "Please use a permanent email address."
}Your frontend receives this as part of the Auth0 error callback and can display it to the user.
Best practices
- Always fail open (return without calling
api.access.deny) on API errors - Use
event.secretsfor the API key — never hardcode it - Log errors with
console.error— they appear in Auth0 tenant logs