INTEGRITY Dokumentace

Synchronizace záznamů příjemců

Použijte Odběry událostí Email Sending k aktualizaci záznamů aplikace po problémech s doručením. Tento příklad používá Cloudflare Queues a Workers KV k odstranění příjemců z transakčních oznámení.

Připravte prostředky

Než začnete:

Každou způsobilou adresu příjemce uložte jako klíč v KV. Hodnota může obsahovat předvolby oznámení nebo související metadata.

Projděte si tok událostí

  1. Email Sending publikuje události bounce a complaint.
  2. Fronta (Queue) doručuje tyto události Workeru.
  3. Worker odstraňuje nezpůsobilé záznamy příjemců z KV.

Vyberte události odebrání

Odstraňte záznamy pro každou message.complained událost. Tyto události signalizují, že příjemce označil zprávu jako spam.

Odstraňte záznamy o bounce pouze pokud payload.bounce.type je "hard". Dočasná selhání generují message.deferred události, dokud zbývají pokusy o opakování. Vyčerpané dočasné pokusy o opakování mohou vyvolat message.bounced události s "soft" typu bounce.

Podrobnosti o obsahu požadavku najdete v Dostupné události Email Sending.

Vytvořte frontu a odběr

Vytvořte frontu a přihlaste ji k odběru u vaší odesílající domény:

  1. V dashboardu Cloudflare přejděte na Queues stránce. Vytvořte frontu s názvem email-events.

    Přejděte na Queues ↗
  2. Vyberte email-events, pak vyberte Předplatné > Odběr událostí.

  3. Zadejte název odběru a vyberte Email Sending jako zdroj.

  4. Vyberte odesílající doménu a message.bounced a message.complained události.

  5. Vyberte Přihlásit k odběru.

Nakonfigurujte Worker

Přiřaďte KV namespace a zaregistrujte Worker jako consumer fronty:

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "name": "recipient-record-sync",
  "main": "src/index.ts",
  // Set this to today's date
  "compatibility_date": "2026-08-28",
  "kv_namespaces": [
    {
      "binding": "RECIPIENTS",
      "id": "<RECIPIENTS_KV_NAMESPACE_ID>"
    }
  ],
  "queues": {
    "consumers": [
      {
        "queue": "email-events",
        "max_batch_size": 10,
        "max_retries": 3,
        "dead_letter_queue": "email-events-dlq"
      }
    ]
  }
}
name = "recipient-record-sync"
main = "src/index.ts"
# Set this to today's date
compatibility_date = "2026-08-28"

[[kv_namespaces]]
binding = "RECIPIENTS"
id = "<RECIPIENTS_KV_NAMESPACE_ID>"

[[queues.consumers]]
queue = "email-events"
max_batch_size = 10
max_retries = 3
dead_letter_queue = "email-events-dlq"

Konfigurace vytváří email-events-dlq během nasazení. Queues tam přesune události po třech neúspěšných pokusech.

Přidejte consumer fronty

queue() handler zpracovává každou událost nezávisle. Odstraňuje příslušné záznamy příjemců a opakuje neúspěšné operace KV.

src/index.js
export default {
	async queue(batch, env) {
		for (const message of batch.messages) {
			try {
				const event = message.body;

				if (shouldRemove(event)) {
					await removeRecipient(env, event);
				}

				message.ack();
			} catch (error) {
				console.error("Failed to process Email Sending event", {
					eventId: message.body.payload.eventId,
					error,
				});
				message.retry();
			}
		}
	},
};

function shouldRemove(event) {
	if (event.type === "cf.email.sending.message.complained") {
		return true;
	}

	return (
		event.type === "cf.email.sending.message.bounced" &&
		event.payload.bounce?.type === "hard"
	);
}

async function removeRecipient(env, event) {
	await env.RECIPIENTS.delete(event.payload.recipient);
	console.log("Removed recipient record", {
		eventId: event.payload.eventId,
		reason: event.type,
	});
}
src/index.ts
interface Env {
	RECIPIENTS: KVNamespace;
}

interface EmailSendingEvent {
	type:
		| "cf.email.sending.message.bounced"
		| "cf.email.sending.message.complained";
	payload: {
		eventId: string;
		recipient: string;
		bounce?: {
			type: "hard" | "soft";
		};
	};
}

export default {
	async queue(batch, env): Promise<void> {
		for (const message of batch.messages) {
			try {
				const event = message.body;

				if (shouldRemove(event)) {
					await removeRecipient(env, event);
				}

				message.ack();
			} catch (error) {
				console.error("Failed to process Email Sending event", {
					eventId: message.body.payload.eventId,
					error,
				});
				message.retry();
			}
		}
	},
} satisfies ExportedHandler<Env, EmailSendingEvent>;

function shouldRemove(event: EmailSendingEvent): boolean {
	if (event.type === "cf.email.sending.message.complained") {
		return true;
	}

	return (
		event.type === "cf.email.sending.message.bounced" &&
		event.payload.bounce?.type === "hard"
	);
}

async function removeRecipient(
	env: Env,
	event: EmailSendingEvent,
): Promise<void> {
	await env.RECIPIENTS.delete(event.payload.recipient);
	console.log("Removed recipient record", {
		eventId: event.payload.eventId,
		reason: event.type,
	});
}

Odstranění neexistujícího klíče KV proběhne úspěšně. Díky tomu je opakované doručení události bezpečné.

Handler potvrzuje každou úspěšně zpracovanou zprávu. Neúspěšné operace se přesunou do fronta nedoručených zpráv (dead letter queue) po třech pokusech o opakování.

Nasazení Workeru

Nasaďte Worker a konfiguraci jeho konzumenta fronty:

npx wrangler deploy

Sledujte dead letter queue s neúspěšnými událostmi. Po odstranění příčiny chyby je znovu zpracujte.