Beta privataMailbeam è in beta privata: l'API pubblica non è ancora aperta.Iscriviti alla lista d'attesa

Mailbeam
Firebase + Cloud FunctionsIntermedio25 minutiAggiornato a gennaio 2025

Verifica delle email con Firebase

Firebase Authentication permette di intercettare gli eventi di registrazione con funzioni bloccanti beforeCreate. Questo tutorial aggiunge la verifica di Mailbeam a quell'hook, così le email non valide e usa e getta vengono bloccate prima che il record dell'utente venga creato in Firebase.

Prerequisiti

  • Un progetto Firebase con piano Blaze (necessario per le Cloud Functions)
  • La CLI di Firebase installata
  • Una chiave API di Mailbeam (iscriviti gratis)

Preparazione

firebase init functions
cd functions
npm install axios

Definisci la chiave di Mailbeam come variabile d'ambiente di Firebase:

firebase functions:config:set mailbeam.key="mb_live_xxxxxxxxxxxxxxxxxxxx"

Crea la funzione bloccante

// functions/index.js
const functions = require("firebase-functions");
const { getAuth } = require("firebase-admin/auth");
const axios = require("axios");

// beforeCreate viene eseguita PRIMA che l'utente venga scritto in Firebase Auth
exports.validateEmailBeforeCreate = functions.auth
  .user()
  .beforeCreate(async (user, context) => {
    const email = user.email;
    if (!email) return; // Senza email: altri provider, salta

    const apiKey = functions.config().mailbeam.key;

    try {
      const { data } = await axios.post(
        "https://api.mailbeam.dev/v1/verify",
        { email },
        {
          headers: { Authorization: `Bearer ${apiKey}` },
          timeout: 5000,
        }
      );

      const { valid, score, reason } = data;

      if (!valid || score < 60) {
        const message =
          reason === "disposable_domain"
            ? "Usa un indirizzo email permanente, non uno temporaneo."
            : "Inserisci un indirizzo email valido e raggiungibile.";

        throw new functions.auth.HttpsError("invalid-argument", message);
      }
    } catch (err) {
      // Se è già il nostro HttpsError, rilancialo
      if (err.code === "functions/invalid-argument") throw err;
      // Altrimenti: registra l'errore e lascia passare
      functions.logger.error("Verifica di Mailbeam fallita", { error: err.message });
    }
  });

Versione in TypeScript

// functions/src/index.ts
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
import axios from "axios";

admin.initializeApp();

export const validateEmailBeforeCreate = functions.auth
  .user()
  .beforeCreate(async (user) => {
    if (!user.email) return;

    const apiKey = functions.config().mailbeam.key;

    try {
      const { data } = await axios.post<{
        valid: boolean;
        score: number;
        reason: string | null;
      }>(
        "https://api.mailbeam.dev/v1/verify",
        { email: user.email },
        { headers: { Authorization: `Bearer ${apiKey}` }, timeout: 5000 }
      );

      if (!data.valid || data.score < 60) {
        throw new functions.auth.HttpsError(
          "invalid-argument",
          data.reason === "disposable_domain"
            ? "Usa un indirizzo email permanente."
            : "Usa un indirizzo email valido e raggiungibile."
        );
      }
    } catch (err: unknown) {
      if ((err as { code?: string }).code === "functions/invalid-argument") throw err;
      functions.logger.error("Errore di Mailbeam", err);
    }
  });

Pubblicazione

firebase deploy --only functions

Prove

// Usa la Emulator Suite di Firebase per provare in locale
firebase emulators:start

// Prova a creare un utente con un'email usa e getta dall'SDK di Firebase
const { createUserWithEmailAndPassword } = require("firebase/auth");

try {
  await createUserWithEmailAndPassword(auth, "temp@mailinator.com", "password");
} catch (error) {
  console.log(error.code);    // "auth/invalid-argument"
  console.log(error.message); // "Usa un indirizzo email permanente."
}

Buone pratiche

  • Usa beforeCreate, non onCreate: beforeCreate gira prima che il record venga salvato, onCreate dopo
  • Rilancia sempre functions.auth.HttpsError e lascia passare davanti a qualsiasi altro errore
  • Usa functions.logger.error, non console.error, per avere registri strutturati in Firebase

Prossimi passi