Blocking functions need your project upgraded to Firebase Authentication with Identity Platform, from Authentication then
Refuse Firebase signups whose address cannot receive mail
Add a blocking function to Firebase Authentication that checks each new address with PricklyMails and refuses the account when it cannot receive mail.
No connector needed: at each signup, Firebase calls the PricklyMails API from a beforeUserCreated blocking function, and an address that cannot receive mail is refused before the account exists.
Check each signup in four steps
Before you start
- In PricklyMails
Create an API key in PricklyMails
- In the dashboard, open API Keys and click New key.
- Under Environment, pick Test first: the key starts with
pm_test_, answers from canned results, bills nothing and contacts no mail server. - Copy the key as soon as it shows: it is shown only once.
Tip
The Free plan holds one key: once everything works, revoke the test key, then create the one under Live.
- In Firebase
Store the key and add the function in Firebase
The code is a Cloud Functions for Firebase function (2nd gen, Node.js) that Firebase Authentication runs before it saves a new user. The key stays in Cloud Secret Manager, where only the functions that bind it can read it.
- In your project directory, run
firebase init functionsand choose JavaScript, unless the project already has afunctionsfolder. - Run
firebase functions:secrets:set PRICKLYMAILS_KEY, then enter your test key when the CLI asks for its value. - Add the code below to
functions/index.js.
The code asks PricklyMails to answer within a few seconds (
Prefer: wait) and stops waiting soon after, so a signup never hangs on the answer. It refuses the signup only when the recommendation isremove, and lets it through otherwise: a risky address, no answer in time, an error.How the API answers in one callfunctions/index.jsconst { defineSecret } = require('firebase-functions/params') const { beforeUserCreated, HttpsError, } = require('firebase-functions/v2/identity') const VERIFY_URL = 'https://api.pricklymails.com/api/verify' const REFUSAL = 'This email address cannot receive mail. ' + 'Check it for a typo, or use another one.' const pricklymailsKey = defineSecret('PRICKLYMAILS_KEY') // Firebase gives the function 7 seconds: wait 3 for the answer, give up at 4. async function recommendationFor(email, key) { try { const response = await fetch(VERIFY_URL, { method: 'POST', headers: { Authorization: `Bearer ${key}`, 'Content-Type': 'application/json', Prefer: 'wait=3', }, body: JSON.stringify({ email }), signal: AbortSignal.timeout(4000), }) if (200 !== response.status) { return null } const { verification } = await response.json() return verification?.recommendation ?? null } catch { return null } } exports.beforecreated = beforeUserCreated( { secrets: [pricklymailsKey] }, async (event) => { const email = event.data?.email const key = pricklymailsKey.value() if (email && 'remove' === (await recommendationFor(email, key))) { throw new HttpsError('invalid-argument', REFUSAL) } }, )Tip
To limit cold starts, keep an instance warm with
minInstances: 1next tosecretsin the function options. An instance kept running is billed at idle rates.SourceFirebase's official help center- Extend Firebase Authentication with blocking functions (opens in a new tab)firebase.google.com
- Configure your environment (opens in a new tab)firebase.google.com
- Get started: write, test, and deploy your first functions (opens in a new tab)firebase.google.com
- Manage functions (opens in a new tab)firebase.google.com
- In your project directory, run
- In Firebase
Deploy the function to Firebase
Deploying the function is what turns it on: from then on, Firebase Authentication creates an account only when the function completes without an error.
- From your project directory, run
firebase deploy --only functions. - After each change to the code, or to the value of
PRICKLYMAILS_KEY, run the same command again.
Warning
Deleting the function is not enough to turn it off: also unregister its trigger from Firebase Authentication, or no one can sign up or sign in to your app anymore.
SourceFirebase's official help center- Extend Firebase Authentication with blocking functions (opens in a new tab)firebase.google.com
- Manage functions (opens in a new tab)firebase.google.com
- Configure your environment (opens in a new tab)firebase.google.com
- From your project directory, run
- In Firebase
Try it with the test key
- Sign up with an address that starts with
invalid, such asinvalid@example.com: the test key answersremove, and the signup is refused. - Sign up with another address, such as
valid@example.com: the account is created. - Where you stored the key, replace it with a key created under Live, which starts with
pm_live_: from then on, each signup is verified for real and billed like any verification.
- Sign up with an address that starts with
What each signup gets
The code reads the recommendation the API gives the address, the same one a list's report gives.
- Remove
Refused: the address does not exist, its domain cannot receive mail, or it is disposable.
Firebase Authentication does not create the account. In your app, the client SDK rejects the signup call with an internal error,
auth/internal-error, whose message holds the refusal text among technical details. Catch it in your signup form and, when the message mentionsCloud Function, show the person the refusal text or your own words rather than the raw message.- Review
Let through: a domain that accepts any address, a generic address such as contact@, or a server that did not answer. The address may work.
- Send
Let through: the address is valid, or hosted by a large provider that accepts every address.
- No answer in time
- Firebase gives the function 7 seconds: past that, Firebase Authentication returns an error and the signup fails, whatever the address. The code stops waiting for PricklyMails after 4 seconds and lets the signup through, which leaves the function time to start and answer.
- Extend Firebase Authentication with blocking functions (opens in a new tab)firebase.google.com
- Customize the authentication flow using blocking functions (opens in a new tab)docs.cloud.google.com
Frequently asked questions
Which signups go through the function?
Every new user Firebase Authentication creates, whatever the sign-in method, except with anonymous and custom authentication, which never trigger blocking functions. A user created without an email address, with a phone number for instance, goes through unchecked: the code returns before it calls PricklyMails.
- Extend Firebase Authentication with blocking functions (opens in a new tab)firebase.google.com
Does the function run at every sign-in?
No. Firebase runs beforeUserCreated only before it saves a new user. An existing user signing in triggers beforeUserSignedIn, which this code does not use: a sign-in never calls PricklyMails and costs no verification.
- Extend Firebase Authentication with blocking functions (opens in a new tab)firebase.google.com
What does the setup cost on the Firebase side?
On the Blaze plan, Firebase Authentication with Identity Platform bills monthly active users beyond a no-cost tier of 50,000 for email and social sign-in. Cloud Functions has a monthly no-cost quota, then pay-as-you-go pricing, and Secret Manager holds 6 active secret versions at no cost.
- Firebase Authentication (opens in a new tab)firebase.google.com
- Firebase pricing plans (opens in a new tab)firebase.google.com
- Configure your environment (opens in a new tab)firebase.google.com
Is there a PricklyMails extension for Firebase?
No, and there is nothing to install: the code above calls the PricklyMails API with your key.
These trademarks belong to their respective owners. Naming them implies no partnership.
Check your list before your next send.
1,000 tokens free when you sign up, no credit card. After that, you only pay for answers.