Quando si verificano migliaia o milioni di indirizzi email, attendere sincronamente ogni risultato non è pratico. I webhook per la verifica email offrono una soluzione elegante notificando la tua applicazione quando le attività di verifica sono completate, eliminando la necessità di polling costante e abilitando flussi di lavoro asincroni efficienti. Questa guida completa esplora tutto ciò che gli sviluppatori devono sapere sull'implementazione dei webhook per la verifica email, dalla configurazione di base ai pattern avanzati per gestire operazioni di verifica su larga scala.
Comprendere i Webhook per la Verifica Email
I webhook sono callback HTTP che inviano dati alla tua applicazione quando si verificano eventi specifici. Nel contesto della verifica email, i webhook notificano i tuoi sistemi quando i lavori di verifica in blocco sono completati, quando la verifica di singole email termina in modalità asincrona, o quando si verificano altri eventi significativi durante il processo di verifica.
Perché Usare i Webhook per la Verifica Email?
I pattern tradizionali request-response funzionano bene per la verifica di singole email, ma le operazioni in blocco presentano sfide. Verificare 100.000 email potrebbe richiedere ore, e mantenere una connessione HTTP aperta per così tanto tempo non è fattibile. Il polling per gli aggiornamenti di stato spreca risorse e crea carico API non necessario.
Eliminazione del Sovraccarico di Polling
Senza webhook, dovresti interrogare ripetutamente l'API per verificare se i lavori in blocco sono stati completati. Questo crea traffico di rete non necessario, consuma limiti di rate API e aggiunge complessità alla tua applicazione. I webhook inviano notifiche push esattamente quando sono necessarie.
Processamento in Tempo Reale
I webhook abilitano azioni immediate quando la verifica è completata. La tua applicazione può elaborare i risultati, aggiornare i database e attivare azioni successive senza ritardi introdotti dagli intervalli di polling.
Architettura Scalabile
Le architetture basate su webhook scalano naturalmente. Che tu stia elaborando un lavoro in blocco o centinaia simultaneamente, il tuo endpoint webhook riceve notifiche man mano che arrivano, e puoi elaborarle in modo asincrono utilizzando code o worker.
Efficienza delle Risorse
Invece di mantenere connessioni o eseguire loop di polling, la tua applicazione rimane inattiva fino all'arrivo dei webhook. Questo riduce i costi di calcolo e semplifica i requisiti infrastrutturali.
Eventi Webhook nella Verifica Email
I servizi di verifica email tipicamente attivano webhook per diversi tipi di eventi:
Completamento Lavoro in Blocco
L'evento webhook più comune si attiva quando un lavoro di verifica in blocco termina l'elaborazione. Il payload include lo stato del lavoro, statistiche di riepilogo e informazioni sul download dei risultati.
Progresso Lavoro in Blocco
Alcuni servizi inviano webhook di progresso a intervalli durante l'elaborazione in blocco, permettendoti di tracciare il progresso della verifica e stimare il tempo di completamento.
Fallimento Lavoro in Blocco
Quando un lavoro in blocco incontra errori che impediscono il completamento, i webhook di fallimento forniscono dettagli su cosa è andato storto e se sono disponibili risultati parziali.
Verifica Singola Email (Modalità Asincrona)
Per scenari di verifica in tempo reale ad alto volume, la verifica asincrona di singole email invia i risultati tramite webhook invece di attendere una risposta sincrona.
Configurazione degli Endpoint Webhook
L'implementazione dei webhook richiede la creazione di un endpoint nella tua applicazione che possa ricevere ed elaborare i payload webhook.
Struttura Base dell'Endpoint
Un endpoint webhook è semplicemente un endpoint HTTP POST che accetta payload JSON:
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhooks/email-verification', async (req, res) => {
const { event_type, job_id, status, data } = req.body;
console.log(`Received webhook: ${event_type} for job ${job_id}`);
// Process the webhook
try {
await handleWebhookEvent(req.body);
// Always respond quickly to acknowledge receipt
res.status(200).json({ received: true });
} catch (error) {
console.error('Webhook processing error:', error);
// Still acknowledge receipt to prevent retries
res.status(200).json({ received: true, error: error.message });
}
});
async function handleWebhookEvent(payload) {
switch (payload.event_type) {
case 'bulk.completed':
await handleBulkCompleted(payload);
break;
case 'bulk.failed':
await handleBulkFailed(payload);
break;
case 'bulk.progress':
await handleBulkProgress(payload);
break;
default:
console.log(`Unknown event type: ${payload.event_type}`);
}
}
Best Practice per le Risposte Webhook
I servizi di verifica email si aspettano risposte rapide dagli endpoint webhook. Se il tuo endpoint impiega troppo tempo a rispondere, il servizio potrebbe presumere che la consegna sia fallita e riprovare.
Rispondi Immediatamente
Conferma la ricezione del webhook immediatamente, quindi elabora il payload in modo asincrono:
app.post('/webhooks/email-verification', async (req, res) => {
// Immediately acknowledge receipt
res.status(200).json({ received: true });
// Process asynchronously
setImmediate(async () => {
try {
await handleWebhookEvent(req.body);
} catch (error) {
console.error('Async webhook processing error:', error);
// Log for retry or manual processing
await logFailedWebhook(req.body, error);
}
});
});
Usa Code di Messaggi per Elaborazione Pesante
Per i sistemi di produzione, accoda i payload webhook per l'elaborazione da parte di processi worker:
const Queue = require('bull');
const webhookQueue = new Queue('email-verification-webhooks');
app.post('/webhooks/email-verification', async (req, res) => {
// Queue the webhook for processing
await webhookQueue.add('process-webhook', req.body, {
attempts: 3,
backoff: {
type: 'exponential',
delay: 1000
}
});
res.status(200).json({ received: true });
});
// Worker process
webhookQueue.process('process-webhook', async (job) => {
const payload = job.data;
await handleWebhookEvent(payload);
});
Configurazione dei Webhook con l'API
Registra il tuo endpoint webhook con il servizio di verifica email:
async function registerWebhook(webhookUrl, events, secret) {
const response = await fetch('https://api.billionverify.com/v1/webhooks', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.BILLIONVERIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: webhookUrl,
events: events,
secret: secret
})
});
const result = await response.json();
if (!response.ok) {
throw new Error(`Failed to register webhook: ${result.error}`);
}
console.log(`Webhook registered: ${result.webhook_id}`);
return result;
}
// Register for bulk job events
await registerWebhook(
'https://yourapp.com/webhooks/email-verification',
['bulk.completed', 'bulk.failed', 'bulk.progress'],
process.env.WEBHOOK_SECRET
);
Sicurezza degli Endpoint Webhook
Gli endpoint webhook sono accessibili pubblicamente, rendendo essenziale la sicurezza. Senza una verifica adeguata, gli aggressori potrebbero inviare payload webhook falsi per manipolare la tua applicazione.
Verifica della Firma
La maggior parte dei servizi di verifica email firma i payload webhook utilizzando HMAC-SHA256 con un segreto condiviso. Verifica le firme prima dell'elaborazione:
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
// Use timing-safe comparison to prevent timing attacks
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
app.post('/webhooks/email-verification', async (req, res) => {
const signature = req.headers['x-webhook-signature'];
if (!signature) {
return res.status(401).json({ error: 'Missing signature' });
}
const isValid = verifyWebhookSignature(
req.body,
signature,
process.env.WEBHOOK_SECRET
);
if (!isValid) {
console.warn('Invalid webhook signature received');
return res.status(401).json({ error: 'Invalid signature' });
}
// Signature valid, process webhook
await handleWebhookEvent(req.body);
res.status(200).json({ received: true });
});
Validazione del Timestamp
Previeni attacchi replay validando i timestamp dei webhook:
function isTimestampValid(timestamp, toleranceSeconds = 300) {
const webhookTime = new Date(timestamp).getTime();
const currentTime = Date.now();
const difference = Math.abs(currentTime - webhookTime);
return difference <= toleranceSeconds * 1000;
}
app.post('/webhooks/email-verification', async (req, res) => {
const { timestamp } = req.body;
if (!isTimestampValid(timestamp)) {
console.warn('Webhook timestamp outside acceptable range');
return res.status(400).json({ error: 'Invalid timestamp' });
}
// Continue with signature verification and processing
});
Whitelist IP
Per sicurezza aggiuntiva, limita l'accesso webhook agli indirizzi IP conosciuti:
const allowedIPs = [
'203.0.113.0/24', // BillionVerify webhook servers
'198.51.100.0/24'
];
function isIPAllowed(clientIP) {
// Implement CIDR range checking
return allowedIPs.some(range => isIPInRange(clientIP, range));
}
app.post('/webhooks/email-verification', async (req, res) => {
const clientIP = req.ip || req.connection.remoteAddress;
if (!isIPAllowed(clientIP)) {
console.warn(`Webhook from unauthorized IP: ${clientIP}`);
return res.status(403).json({ error: 'Forbidden' });
}
// Continue with processing
});
Gestione dell'Idempotenza
I webhook possono essere consegnati più volte a causa di problemi di rete o tentativi. Implementa l'idempotenza per gestire i duplicati in sicurezza:
const processedWebhooks = new Set(); // Use Redis in production
async function handleWebhookIdempotent(payload) {
const webhookId = payload.webhook_id || payload.event_id;
// Check if already processed
if (processedWebhooks.has(webhookId)) {
console.log(`Duplicate webhook ignored: ${webhookId}`);
return;
}
// Mark as processing
processedWebhooks.add(webhookId);
try {
await handleWebhookEvent(payload);
} catch (error) {
// Remove from processed set to allow retry
processedWebhooks.delete(webhookId);
throw error;
}
}
Per i sistemi di produzione, usa Redis per l'idempotenza distribuita:
const Redis = require('ioredis');
const redis = new Redis();
async function isWebhookProcessed(webhookId) {
const key = `webhook:processed:${webhookId}`;
const result = await redis.set(key, '1', 'NX', 'EX', 86400); // 24 hour expiry
return result === null; // Already exists
}
app.post('/webhooks/email-verification', async (req, res) => {
const webhookId = req.body.webhook_id;
if (await isWebhookProcessed(webhookId)) {
console.log(`Duplicate webhook: ${webhookId}`);
return res.status(200).json({ received: true, duplicate: true });
}
await handleWebhookEvent(req.body);
res.status(200).json({ received: true });
});
Elaborazione dei Payload Webhook
Eventi webhook diversi richiedono logiche di gestione diverse. Esploriamo i pattern comuni per elaborare i webhook di verifica email.
Gestione del Completamento Lavoro in Blocco
Quando un lavoro di verifica in blocco si completa, scarica ed elabora i risultati:
async function handleBulkCompleted(payload) {
const { job_id, status, summary, download_url } = payload;
console.log(`Bulk job ${job_id} completed with status: ${status}`);
console.log(`Summary: ${summary.valid} valid, ${summary.invalid} invalid`);
// Download results
const results = await downloadResults(download_url);
// Process results
await processVerificationResults(job_id, results);
// Update job status in database
await updateJobStatus(job_id, 'completed', summary);
// Notify relevant parties
await sendCompletionNotification(job_id, summary);
}
async function downloadResults(url) {
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${process.env.BILLIONVERIFY_API_KEY}`
}
});
if (!response.ok) {
throw new Error(`Failed to download results: ${response.status}`);
}
return await response.json();
}
async function processVerificationResults(jobId, results) {
// Batch update contacts in database
const validEmails = results.filter(r => r.is_valid);
const invalidEmails = results.filter(r => !r.is_valid);
await db.transaction(async (trx) => {
// Update valid emails
for (const batch of chunkArray(validEmails, 1000)) {
await trx('contacts')
.whereIn('email', batch.map(r => r.email))
.update({
email_verified: true,
verification_date: new Date(),
verification_job_id: jobId
});
}
// Handle invalid emails
for (const batch of chunkArray(invalidEmails, 1000)) {
await trx('contacts')
.whereIn('email', batch.map(r => r.email))
.update({
email_verified: false,
email_invalid_reason: trx.raw('CASE email ' +
batch.map(r => `WHEN '${r.email}' THEN '${r.reason}'`).join(' ') +
' END'),
verification_date: new Date(),
verification_job_id: jobId
});
}
});
}
Gestione dei Fallimenti dei Lavori in Blocco
Quando i lavori falliscono, cattura le informazioni sull'errore e determina se il recupero è possibile:
async function handleBulkFailed(payload) {
const { job_id, error_code, error_message, partial_results_available } = payload;
console.error(`Bulk job ${job_id} failed: ${error_message}`);
// Update job status
await updateJobStatus(job_id, 'failed', {
error_code,
error_message
});
// Try to retrieve partial results if available
if (partial_results_available) {
console.log('Attempting to retrieve partial results...');
try {
const partialResults = await downloadPartialResults(job_id);
await processVerificationResults(job_id, partialResults);
// Identify unprocessed emails for retry
const processedEmails = new Set(partialResults.map(r => r.email));
const originalEmails = await getOriginalJobEmails(job_id);
const unprocessedEmails = originalEmails.filter(e => !processedEmails.has(e));
if (unprocessedEmails.length > 0) {
// Schedule retry for unprocessed emails
await scheduleRetryJob(job_id, unprocessedEmails);
}
} catch (error) {
console.error('Failed to retrieve partial results:', error);
}
}
// Notify about failure
await sendFailureNotification(job_id, error_message);
}
async function scheduleRetryJob(originalJobId, emails) {
// Create new job for remaining emails
const response = await fetch('https://api.billionverify.com/v1/bulk/verify', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.BILLIONVERIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
emails,
metadata: {
retry_of: originalJobId
}
})
});
const { job_id: newJobId } = await response.json();
console.log(`Scheduled retry job ${newJobId} for ${emails.length} emails`);
}
Gestione degli Aggiornamenti di Progresso
I webhook di progresso aiutano a tracciare i lavori di lunga durata:
async function handleBulkProgress(payload) {
const { job_id, processed_count, total_count, estimated_completion } = payload;
const percentComplete = Math.round((processed_count / total_count) * 100);
console.log(`Job ${job_id}: ${percentComplete}% complete (${processed_count}/${total_count})`);
// Update progress in database
await updateJobProgress(job_id, {
processed_count,
total_count,
percent_complete: percentComplete,
estimated_completion: new Date(estimated_completion)
});
// Optionally notify users of progress
if (percentComplete % 25 === 0) {
await sendProgressNotification(job_id, percentComplete);
}
}
Pattern Webhook Avanzati
I sistemi di produzione beneficiano di pattern avanzati che migliorano affidabilità e manutenibilità.
Dead Letter Queue per Webhook Falliti
Quando l'elaborazione dei webhook fallisce ripetutamente, sposta i payload in una dead letter queue per revisione manuale:
const webhookQueue = new Queue('email-verification-webhooks');
const deadLetterQueue = new Queue('webhook-dead-letters');
webhookQueue.process('process-webhook', async (job) => {
try {
await handleWebhookEvent(job.data);
} catch (error) {
// Check if this is the final retry
if (job.attemptsMade >= job.opts.attempts - 1) {
// Move to dead letter queue
await deadLetterQueue.add('failed-webhook', {
original_payload: job.data,
error: error.message,
failed_at: new Date().toISOString(),
attempts: job.attemptsMade + 1
});
}
throw error; // Re-throw to trigger retry
}
});
// Process dead letters manually or with alerts
deadLetterQueue.on('completed', async (job) => {
await sendAlert({
type: 'webhook_dead_letter',
job_id: job.data.original_payload.job_id,
error: job.data.error
});
});
Event Sourcing dei Webhook
Memorizza tutti gli eventi webhook per tracce di audit e capacità di replay:
async function handleWebhookWithEventSourcing(payload) {
// Store raw event
const eventId = await storeWebhookEvent(payload);
try {
// Process event
await handleWebhookEvent(payload);
// Mark as processed
await markEventProcessed(eventId);
} catch (error) {
// Mark as failed
await markEventFailed(eventId, error);
throw error;
}
}
async function storeWebhookEvent(payload) {
const result = await db('webhook_events').insert({
event_type: payload.event_type,
job_id: payload.job_id,
payload: JSON.stringify(payload),
received_at: new Date(),
status: 'pending'
});
return result[0];
}
// Replay failed events
async function replayFailedEvents() {
const failedEvents = await db('webhook_events')
.where('status', 'failed')
.where('retry_count', '<', 3);
for (const event of failedEvents) {
try {
await handleWebhookEvent(JSON.parse(event.payload));
await markEventProcessed(event.id);
} catch (error) {
await incrementRetryCount(event.id);
}
}
}
Routing Webhook Multi-Tenant
Per applicazioni SaaS, indirizza i webhook ai gestori specifici del tenant:
async function handleMultiTenantWebhook(payload) {
const { tenant_id, event_type, data } = payload;
// Get tenant configuration
const tenant = await getTenantConfig(tenant_id);
if (!tenant) {
console.error(`Unknown tenant: ${tenant_id}`);
return;
}
// Route to tenant-specific handler
switch (event_type) {
case 'bulk.completed':
await handleTenantBulkCompleted(tenant, data);
break;
case 'bulk.failed':
await handleTenantBulkFailed(tenant, data);
break;
}
// Forward to tenant webhook if configured
if (tenant.webhook_url) {
await forwardToTenant(tenant.webhook_url, tenant.webhook_secret, payload);
}
}
async function forwardToTenant(url, secret, payload) {
const signature = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Webhook-Signature': signature
},
body: JSON.stringify(payload)
});
}
Gestione degli Errori e Affidabilità
Implementazioni webhook robuste gestiscono i fallimenti con eleganza e garantiscono che nessun dato venga perso.
Strategie di Retry
Implementa il backoff esponenziale per fallimenti transitori:
async function processWebhookWithRetry(payload, maxRetries = 5) {
const delays = [1000, 5000, 30000, 120000, 300000]; // 1s, 5s, 30s, 2m, 5m
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
await handleWebhookEvent(payload);
return; // Success
} catch (error) {
const isRetryable = isRetryableError(error);
if (!isRetryable || attempt === maxRetries - 1) {
// Log to dead letter queue
await logFailedWebhook(payload, error, attempt + 1);
throw error;
}
console.log(`Retry ${attempt + 1}/${maxRetries} after ${delays[attempt]}ms`);
await sleep(delays[attempt]);
}
}
}
function isRetryableError(error) {
// Network errors, timeouts, and 5xx responses are retryable
const retryableCodes = ['ECONNRESET', 'ETIMEDOUT', 'ENOTFOUND'];
return retryableCodes.includes(error.code) ||
(error.status && error.status >= 500);
}
Pattern Circuit Breaker
Previeni fallimenti a cascata quando i servizi downstream non sono disponibili:
class CircuitBreaker {
constructor(options = {}) {
this.failureThreshold = options.failureThreshold || 5;
this.resetTimeout = options.resetTimeout || 60000;
this.state = 'CLOSED';
this.failures = 0;
this.lastFailure = null;
}
async execute(fn) {
if (this.state === 'OPEN') {
if (Date.now() - this.lastFailure > this.resetTimeout) {
this.state = 'HALF_OPEN';
} else {
throw new Error('Circuit breaker is OPEN');
}
}
try {
const result = await fn();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
onSuccess() {
this.failures = 0;
this.state = 'CLOSED';
}
onFailure() {
this.failures++;
this.lastFailure = Date.now();
if (this.failures >= this.failureThreshold) {
this.state = 'OPEN';
console.warn('Circuit breaker opened due to failures');
}
}
}
const databaseCircuitBreaker = new CircuitBreaker();
async function handleBulkCompletedSafely(payload) {
await databaseCircuitBreaker.execute(async () => {
await processVerificationResults(payload.job_id, payload.results);
});
}
Monitoraggio e Alerting
Traccia le metriche di salute dei webhook:
const metrics = {
received: 0,
processed: 0,
failed: 0,
latency: []
};
app.post('/webhooks/email-verification', async (req, res) => {
const startTime = Date.now();
metrics.received++;
try {
await handleWebhookEvent(req.body);
metrics.processed++;
} catch (error) {
metrics.failed++;
throw error;
} finally {
metrics.latency.push(Date.now() - startTime);
// Keep only last 1000 measurements
if (metrics.latency.length > 1000) {
metrics.latency.shift();
}
}
res.status(200).json({ received: true });
});
// Expose metrics endpoint
app.get('/metrics/webhooks', (req, res) => {
const avgLatency = metrics.latency.reduce((a, b) => a + b, 0) / metrics.latency.length;
res.json({
received: metrics.received,
processed: metrics.processed,
failed: metrics.failed,
success_rate: (metrics.processed / metrics.received * 100).toFixed(2) + '%',
avg_latency_ms: Math.round(avgLatency)
});
});
// Alert on high failure rate
setInterval(() => {
const failureRate = metrics.failed / metrics.received;
if (failureRate > 0.1) { // More than 10% failures
sendAlert({
type: 'high_webhook_failure_rate',
failure_rate: failureRate,
total_received: metrics.received,
total_failed: metrics.failed
});
}
}, 60000);
Test delle Implementazioni Webhook
Test approfonditi assicurano che i gestori webhook funzionino correttamente in produzione.
Test Locale con ngrok
Usa ngrok per esporre endpoint locali per il test dei webhook:
# Start your local server node server.js # In another terminal, expose it via ngrok ngrok http 3000
Registra l'URL ngrok come tuo endpoint webhook durante lo sviluppo.
Payload Webhook Mock
Crea fixture di test per diversi tipi di eventi:
const mockPayloads = {
bulkCompleted: {
event_type: 'bulk.completed',
job_id: 'job_123456',
status: 'completed',
timestamp: new Date().toISOString(),
summary: {
total: 1000,
valid: 850,
invalid: 120,
risky: 30
},
download_url: 'https://api.billionverify.com/v1/bulk/download/job_123456'
},
bulkFailed: {
event_type: 'bulk.failed',
job_id: 'job_789012',
error_code: 'PROCESSING_ERROR',
error_message: 'Internal processing error',
partial_results_available: true
},
bulkProgress: {
event_type: 'bulk.progress',
job_id: 'job_345678',
processed_count: 5000,
total_count: 10000,
estimated_completion: new Date(Date.now() + 3600000).toISOString()
}
};
// Test endpoint
describe('Webhook Handler', () => {
it('should process bulk.completed event', async () => {
const response = await request(app)
.post('/webhooks/email-verification')
.set('X-Webhook-Signature', generateSignature(mockPayloads.bulkCompleted))
.send(mockPayloads.bulkCompleted);
expect(response.status).toBe(200);
expect(response.body.received).toBe(true);
// Verify side effects
const job = await db('verification_jobs').where('job_id', 'job_123456').first();
expect(job.status).toBe('completed');
});
});
Test di Integrazione
Testa il flusso webhook completo includendo la verifica della firma:
describe('Webhook Security', () => {
it('should reject requests without signature', async () => {
const response = await request(app)
.post('/webhooks/email-verification')
.send(mockPayloads.bulkCompleted);
expect(response.status).toBe(401);
});
it('should reject requests with invalid signature', async () => {
const response = await request(app)
.post('/webhooks/email-verification')
.set('X-Webhook-Signature', 'invalid_signature')
.send(mockPayloads.bulkCompleted);
expect(response.status).toBe(401);
});
it('should accept requests with valid signature', async () => {
const signature = generateSignature(mockPayloads.bulkCompleted);
const response = await request(app)
.post('/webhooks/email-verification')
.set('X-Webhook-Signature', signature)
.send(mockPayloads.bulkCompleted);
expect(response.status).toBe(200);
});
});
Integrazione Webhook BillionVerify
BillionVerify fornisce un supporto webhook completo per gli eventi di verifica email, rendendo facile costruire flussi di lavoro di verifica asincroni.
Configurazione dei Webhook
Configura i webhook tramite il dashboard BillionVerify o l'API:
// Register webhook via API
async function setupBillionVerifyWebhooks() {
const webhook = await registerWebhook(
'https://yourapp.com/webhooks/billionverify',
['bulk.completed', 'bulk.failed', 'bulk.progress'],
process.env.BILLIONVERIFY_WEBHOOK_SECRET
);
console.log('Webhook configured:', webhook);
}
Formato Payload Webhook
I webhook BillionVerify includono informazioni complete sugli eventi di verifica:
{
"event_type": "bulk.completed",
"webhook_id": "wh_abc123",
"job_id": "job_xyz789",
"timestamp": "2025-01-15T10:30:00Z",
"status": "completed",
"summary": {
"total": 10000,
"valid": 8500,
"invalid": 1200,
"risky": 300,
"disposable": 150,
"catch_all": 200
},
"processing_time_ms": 45000,
"download_url": "https://api.billionverify.com/v1/bulk/download/job_xyz789"
}
Esempio di Integrazione Completa
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
// Webhook endpoint for BillionVerify
app.post('/webhooks/billionverify', async (req, res) => {
// Verify signature
const signature = req.headers['x-billionverify-signature'];
const isValid = verifySignature(req.body, signature);
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Acknowledge immediately
res.status(200).json({ received: true });
// Process asynchronously
processWebhookAsync(req.body);
});
async function processWebhookAsync(payload) {
try {
switch (payload.event_type) {
case 'bulk.completed':
await handleBulkCompleted(payload);
break;
case 'bulk.failed':
await handleBulkFailed(payload);
break;
case 'bulk.progress':
await handleBulkProgress(payload);
break;
}
} catch (error) {
console.error('Webhook processing error:', error);
await logFailedWebhook(payload, error);
}
}
app.listen(3000, () => {
console.log('Webhook server running on port 3000');
});
Conclusione
I webhook per la verifica email trasformano il modo in cui le applicazioni gestiscono la verifica in blocco abilitando un processamento asincrono efficiente, scalabile e affidabile. Implementando una gestione webhook adeguata con misure di sicurezza, gestione degli errori e monitoraggio, puoi costruire flussi di lavoro di verifica email robusti che scalano con le esigenze della tua applicazione.
Punti chiave per implementare webhook di verifica email:
- Rispondi rapidamente alle richieste webhook ed elabora i payload in modo asincrono
- Verifica le firme per garantire che i webhook provengano da fonti legittime
- Implementa l'idempotenza per gestire consegne duplicate in sicurezza
- Usa code di messaggi per un'elaborazione affidabile su scala
- Monitora la salute dei webhook con metriche e alerting
Che tu stia elaborando migliaia o milioni di verifiche email, i webhook forniscono le fondamenta per un processamento asincrono efficiente. Inizia a implementare webhook oggi con il supporto webhook completo di BillionVerify e porta i tuoi flussi di lavoro di verifica email al livello successivo.