Aller au contenu

Refuser dans Firebase les adresses qui ne reçoivent pas d'emails

Intégration Inscriptions et authentification

Ajoutez à Firebase Authentication une fonction de blocage qui vérifie chaque nouvelle adresse avec PricklyMails et refuse celles qui ne reçoivent pas d'emails.

Pas besoin de connecteur : à chaque inscription, Firebase appelle l'API PricklyMails depuis une fonction de blocage beforeUserCreated, et une adresse qui ne peut pas recevoir d'emails est refusée avant que le compte n'existe.

Vérifier gratuitement

Pas à pas

Vérifier chaque inscription en quatre étapes

Avant de commencer

Les fonctions de blocage demandent de passer votre projet à Firebase Authentication with Identity Platform, depuis Authentication puis Settings dans la console Firebase. Déployer une fonction demande le forfait Blaze.

  1. Dans PricklyMails

    Créer une clé API dans PricklyMails

    1. Dans le tableau de bord, ouvrez Clés API et cliquez sur Nouvelle clé.
    2. À l'étape Environnement, choisissez d'abord Test : la clé commence par pm_test_, répond par des résultats prédéfinis, ne facture rien et ne contacte aucun serveur de messagerie.
    3. Copiez la clé dès qu'elle s'affiche : elle n'est montrée qu'une fois.

    Astuce

    L'offre Free ne compte qu'une clé : une fois que tout fonctionne, révoquez la clé de test, puis créez-en une en Production.

  2. Dans Firebase

    Ranger la clé et ajouter la fonction dans Firebase

    Le code est une fonction Cloud Functions for Firebase (2e génération, Node.js) que Firebase Authentication exécute avant d'enregistrer un nouvel utilisateur. La clé reste dans Cloud Secret Manager, où seules les fonctions qui la déclarent peuvent la lire.

    1. Dans le dossier de votre projet, lancez firebase init functions et choisissez JavaScript, sauf si le projet a déjà un dossier functions.
    2. Lancez firebase functions:secrets:set PRICKLYMAILS_KEY, puis saisissez votre clé de test quand la CLI demande sa valeur.
    3. Ajoutez le code ci-dessous à functions/index.js.

    Le code demande à PricklyMails de répondre en quelques secondes (Prefer: wait) et cesse d'attendre peu après, pour qu'une inscription ne reste jamais suspendue à la réponse. Il ne refuse l'inscription que si la recommandation est remove, et la laisse passer sinon : adresse risquée, pas de réponse à temps, erreur.

    functions/index.js
    const { 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)
            }
        },
    )
    
    Comment l'API répond en un seul appel

    Astuce

    Pour limiter les démarrages à froid, gardez une instance prête avec minInstances: 1, à côté de secrets dans les options de la fonction. Une instance maintenue en marche est facturée au tarif d'inactivité.

  3. Dans Firebase

    Déployer la fonction sur Firebase

    C'est le déploiement qui met la fonction en service : dès lors, Firebase Authentication ne crée un compte que si la fonction se termine sans erreur.

    1. Depuis le dossier de votre projet, lancez firebase deploy --only functions.
    2. Après chaque modification du code, ou de la valeur de PRICKLYMAILS_KEY, relancez la même commande.

    Attention

    Supprimer la fonction ne suffit pas à l'arrêter : retirez aussi son déclencheur de Firebase Authentication, sinon plus personne ne peut s'inscrire ni se connecter à votre application.

  4. Dans Firebase

    Essayer avec la clé de test

    1. Inscrivez-vous avec une adresse qui commence par invalid, comme invalid@example.com : la clé de test répond remove, et l'inscription est refusée.
    2. Inscrivez-vous avec une autre adresse, comme valid@example.com : le compte est créé.
    3. Là où vous avez rangé la clé, remplacez-la par une clé créée en Production, qui commence par pm_live_ : dès lors, chaque inscription est vérifiée pour de vrai et facturée comme toute vérification.

Ce que devient chaque inscription

Le code lit la recommandation que l'API donne pour l'adresse, la même que dans le rapport d'une liste.

À retirer

Refusée : l'adresse n'existe pas, son domaine ne peut pas recevoir d'emails, ou elle est jetable.

Firebase Authentication ne crée pas le compte. Dans votre application, le SDK client rejette l'inscription avec une erreur interne, auth/internal-error, dont le message contient le texte du refus au milieu de détails techniques. Interceptez-la dans votre formulaire d'inscription et, si le message mentionne Cloud Function, montrez à la personne le texte du refus ou vos propres mots plutôt que le message brut.

À revoir

Acceptée : domaine qui accepte toutes les adresses, adresse générique comme contact@, ou serveur qui n'a pas répondu. L'adresse peut fonctionner.

À envoyer

Acceptée : l'adresse est valide, ou hébergée chez un grand fournisseur qui accepte toutes les adresses.

Pas de réponse à temps
Firebase laisse 7 secondes à la fonction : au-delà, Firebase Authentication renvoie une erreur et l'inscription échoue, quelle que soit l'adresse. Le code cesse d'attendre PricklyMails au bout de 4 secondes et laisse passer l'inscription, ce qui laisse à la fonction le temps de démarrer et de répondre.

Questions fréquentes

Quelles inscriptions passent par la fonction ?

Tout nouvel utilisateur que crée Firebase Authentication, quelle que soit la méthode de connexion, sauf avec l'authentification anonyme ou personnalisée, qui ne déclenche jamais de fonction de blocage. Un utilisateur créé sans adresse email, avec un numéro de téléphone par exemple, passe sans vérification : le code s'arrête avant d'appeler PricklyMails.

SourceAide officielle de Firebase

La fonction tourne-t-elle à chaque connexion ?

Non. Firebase n'exécute beforeUserCreated qu'avant d'enregistrer un nouvel utilisateur. La connexion d'un utilisateur existant déclenche beforeUserSignedIn, que ce code n'utilise pas : une connexion n'appelle jamais PricklyMails et ne coûte aucune vérification.

SourceAide officielle de Firebase

Que coûte la mise en place côté Firebase ?

Avec le forfait Blaze, Firebase Authentication with Identity Platform facture les utilisateurs actifs par mois au-delà d'un niveau sans frais de 50 000 pour la connexion par email ou par réseau social. Cloud Functions offre un quota mensuel sans frais, puis un paiement à l'usage, et Secret Manager garde 6 versions actives de secret sans frais.

SourceAide officielle de Firebase

Existe-t-il une extension PricklyMails pour Firebase ?

Non, et il n'y a rien à installer : le code ci-dessus appelle l'API PricklyMails avec votre clé.

Ces marques appartiennent à leurs propriétaires respectifs. Les citer n'implique aucun partenariat.

Vérifiez votre liste avant votre prochain envoi.

1 000 jetons offerts à l'inscription, sans carte bancaire. Ensuite, vous ne payez que les réponses.