← Cloudflare Email Service / email-service / examples / email-sending
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:
- Povolte Doména Email Sending.
- Vytvořte Projekt Workeru.
- Vytvořte Workers KV namespace.
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í
- Email Sending publikuje události bounce a complaint.
- Fronta (Queue) doručuje tyto události Workeru.
- 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:
-
V dashboardu Cloudflare přejděte na Queues stránce. Vytvořte frontu s názvem
Přejděte na Queues ↗email-events. -
Vyberte
email-events, pak vyberte Předplatné > Odběr událostí. -
Zadejte název odběru a vyberte Email Sending jako zdroj.
-
Vyberte odesílající doménu a
message.bouncedamessage.complainedudálosti. -
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.
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,
});
}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 deploySledujte dead letter queue s neúspěšnými událostmi. Po odstranění příčiny chyby je znovu zpracujte.
Podívejte se na související zdroje
- Odběry událostí : přehled schémat událostí.
- Seznamy vyloučených adres : vysvětlení automatického potlačování.
- Fronta opakovaných pokusů : řízení opakování odesílání zpráv.
- Konzistence Workers KV : zohledněte zpoždění šíření.