...

", // optional "text": "...", // optional (one of html/text required) "cc": ["..."], // optional, array "bcc": ["..."], // optional, array "reply_to": "...", // optional, single string "headers": {"List-Unsubscribe": "<...>"} // optional, e.g. for newsletters } ``` Success response: HTTP 200 + `{"success":true,"result":{"delivered":[],"queued":[],"permanent_bounces":[]}}`. Failure: non-200 OR `success:false` OR non-empty `permanent_bounces`. Always check all three. Pricing: $5/mo Workers Paid plan + 3,000 emails free + $0.35 per 1k after. Roughly 5× cheaper than Postmark. No batch send endpoint — loop single sends. ## Steps you should follow ### 1. Verify prerequisites with me Before writing any code, ask me to confirm: - I have a Cloudflare Workers Paid plan ($5/mo) - I've onboarded my sender domain(s) in Cloudflare dashboard → Email → Email Sending → Onboard Domain (this auto-adds SPF/DKIM/DMARC + cf-bounce MX records) - I have an API token with `email_sending:write` scope (created at https://t.co/s5aigJ6CKV → Custom Token) - I have my Cloudflare account ID Don't proceed until you have these. ### 2. Recommend a domain reputation strategy Most apps should split senders across 2-3 subdomains so spam complaints on one don't drag down deliverability on others: - `mail.` or `members.` → transactional (login, receipts, password reset, in-app notifications) - `e.` → cold/recovery (abandoned cart, win-back campaigns) - `newsletter.` → opt-in newsletters with List-Unsubscribe headers Each subdomain needs to be onboarded separately in Cloudflare. Ask me which I want. ### 3. Audit existing email sends Use grep/search to find every place in this codebase that sends email. Look for: - The current provider's SDK class names, API URLs, env/config vars - Generic patterns like `mail()`, SMTP usage, `nodemailer`, etc. Group findings by email type/purpose (e.g. "magic-link login", "payment receipt", "weekly newsletter") rather than by file. Tell me what you found before changing anything. ### 4. Add a single helper function Don't sprinkle Cloudflare API calls across the codebase. Add one helper (provider-specific name like `sendEmailViaCloudflare()`) that: - Defaults `from` from a config var (don't hardcode) - Parses `"Name "` strings into the API's `{address, name}` object form - Accepts `cc`/`bcc` as either string or array - Accepts a `headers` dict (newsletters need `List-Unsubscribe` + `List-Unsubscribe-Post`) - Returns `bool` (true on success, false on any failure) - On failure, logs/alerts somewhere I can see (Telegram, Sentry, log file — match what the codebase already does) - Sets curl/fetch timeouts (5s connect, 15s total) so a stuck CF API can't hang the request - Treats `permanent_bounces: [...]` non-empty as a soft failure ### 5. Migrate one low-stakes email type first Don't migrate everything at once. Pick the lowest-stakes email type in the audit (something where landing in spam wouldn't lose me money or users — e.g. "internal admin alert", "profile photo rejection") and migrate just that one. Test it end-to-end. Confirm the email actually arrives. Only then propose the next migration. ### 6. Stop me from migrating login email yet If my codebase sends magic-link login or password-reset emails, do not migrate those to Cloudflare yet. Cloudflare Email Service is brand new (~1 month old at writing). Its IP/domain reputation is unproven. Login emails landing in spam = users locked out. Keep those on the current provider until at least 3 months of clean deliverability data on the lower-stakes types. Tell me this explicitly. ### 7. Suggest commit boundaries After each successful migration, suggest a focused git commit with a clear message. Don't bundle unrelated changes. ## Important caveats to surface to me - Beta product. Pricing isn't fully finalized. SLA undefined. Could change. - No batch endpoint. Mass sends (newsletters to 1000+ recipients) need a loop — at ~150ms/send that's ~2.5min per 1000. Fine for crons, bad for sync user-facing flows. - No bounce webhooks yet. Surface failures via the response body's `permanent_bounces` array. - Suppression list auto-managed. Hard bounces, repeated soft bounces, and spam complaints get blocked. Spam-complaint suppressions are hard to remove (anti-abuse). - No per-message logs/dashboard yet. Use the response's `messageId` for tracking if I need it. - List-Unsubscribe headers are passed through verbatim — Gmail's bulk-sender requirement still met, but only if I include them in `headers`. ## Your first action Before writing any code: do step 1 (ask for prerequisites) and step 3 (audit existing sends), then propose the migration order with a brief explanation of the reasoning. Wait for my confirmation before making changes." /> ...

", // optional "text": "...", // optional (one of html/text required) "cc": ["..."], // optional, array "bcc": ["..."], // optional, array "reply_to": "...", // optional, single string "headers": {"List-Unsubscribe": "<...>"} // optional, e.g. for newsletters } ``` Success response: HTTP 200 + `{"success":true,"result":{"delivered":[],"queued":[],"permanent_bounces":[]}}`. Failure: non-200 OR `success:false` OR non-empty `permanent_bounces`. Always check all three. Pricing: $5/mo Workers Paid plan + 3,000 emails free + $0.35 per 1k after. Roughly 5× cheaper than Postmark. No batch send endpoint — loop single sends. ## Steps you should follow ### 1. Verify prerequisites with me Before writing any code, ask me to confirm: - I have a Cloudflare Workers Paid plan ($5/mo) - I've onboarded my sender domain(s) in Cloudflare dashboard → Email → Email Sending → Onboard Domain (this auto-adds SPF/DKIM/DMARC + cf-bounce MX records) - I have an API token with `email_sending:write` scope (created at https://t.co/s5aigJ6CKV → Custom Token) - I have my Cloudflare account ID Don't proceed until you have these. ### 2. Recommend a domain reputation strategy Most apps should split senders across 2-3 subdomains so spam complaints on one don't drag down deliverability on others: - `mail.` or `members.` → transactional (login, receipts, password reset, in-app notifications) - `e.` → cold/recovery (abandoned cart, win-back campaigns) - `newsletter.` → opt-in newsletters with List-Unsubscribe headers Each subdomain needs to be onboarded separately in Cloudflare. Ask me which I want. ### 3. Audit existing email sends Use grep/search to find every place in this codebase that sends email. Look for: - The current provider's SDK class names, API URLs, env/config vars - Generic patterns like `mail()`, SMTP usage, `nodemailer`, etc. Group findings by email type/purpose (e.g. "magic-link login", "payment receipt", "weekly newsletter") rather than by file. Tell me what you found before changing anything. ### 4. Add a single helper function Don't sprinkle Cloudflare API calls across the codebase. Add one helper (provider-specific name like `sendEmailViaCloudflare()`) that: - Defaults `from` from a config var (don't hardcode) - Parses `"Name "` strings into the API's `{address, name}` object form - Accepts `cc`/`bcc` as either string or array - Accepts a `headers` dict (newsletters need `List-Unsubscribe` + `List-Unsubscribe-Post`) - Returns `bool` (true on success, false on any failure) - On failure, logs/alerts somewhere I can see (Telegram, Sentry, log file — match what the codebase already does) - Sets curl/fetch timeouts (5s connect, 15s total) so a stuck CF API can't hang the request - Treats `permanent_bounces: [...]` non-empty as a soft failure ### 5. Migrate one low-stakes email type first Don't migrate everything at once. Pick the lowest-stakes email type in the audit (something where landing in spam wouldn't lose me money or users — e.g. "internal admin alert", "profile photo rejection") and migrate just that one. Test it end-to-end. Confirm the email actually arrives. Only then propose the next migration. ### 6. Stop me from migrating login email yet If my codebase sends magic-link login or password-reset emails, do not migrate those to Cloudflare yet. Cloudflare Email Service is brand new (~1 month old at writing). Its IP/domain reputation is unproven. Login emails landing in spam = users locked out. Keep those on the current provider until at least 3 months of clean deliverability data on the lower-stakes types. Tell me this explicitly. ### 7. Suggest commit boundaries After each successful migration, suggest a focused git commit with a clear message. Don't bundle unrelated changes. ## Important caveats to surface to me - Beta product. Pricing isn't fully finalized. SLA undefined. Could change. - No batch endpoint. Mass sends (newsletters to 1000+ recipients) need a loop — at ~150ms/send that's ~2.5min per 1000. Fine for crons, bad for sync user-facing flows. - No bounce webhooks yet. Surface failures via the response body's `permanent_bounces` array. - Suppression list auto-managed. Hard bounces, repeated soft bounces, and spam complaints get blocked. Spam-complaint suppressions are hard to remove (anti-abuse). - No per-message logs/dashboard yet. Use the response's `messageId` for tracking if I need it. - List-Unsubscribe headers are passed through verbatim — Gmail's bulk-sender requirement still met, but only if I include them in `headers`. ## Your first action Before writing any code: do step 1 (ask for prerequisites) and step 3 (audit existing sends), then propose the migration order with a brief explanation of the reasoning. Wait for my confirmation before making changes." /> ...

", // optional "text": "...", // optional (one of html/text required) "cc": ["..."], // optional, array "bcc": ["..."], // optional, array "reply_to": "...", // optional, single string "headers": {"List-Unsubscribe": "<...>"} // optional, e.g. for newsletters } ``` Success response: HTTP 200 + `{"success":true,"result":{"delivered":[],"queued":[],"permanent_bounces":[]}}`. Failure: non-200 OR `success:false` OR non-empty `permanent_bounces`. Always check all three. Pricing: $5/mo Workers Paid plan + 3,000 emails free + $0.35 per 1k after. Roughly 5× cheaper than Postmark. No batch send endpoint — loop single sends. ## Steps you should follow ### 1. Verify prerequisites with me Before writing any code, ask me to confirm: - I have a Cloudflare Workers Paid plan ($5/mo) - I've onboarded my sender domain(s) in Cloudflare dashboard → Email → Email Sending → Onboard Domain (this auto-adds SPF/DKIM/DMARC + cf-bounce MX records) - I have an API token with `email_sending:write` scope (created at https://t.co/s5aigJ6CKV → Custom Token) - I have my Cloudflare account ID Don't proceed until you have these. ### 2. Recommend a domain reputation strategy Most apps should split senders across 2-3 subdomains so spam complaints on one don't drag down deliverability on others: - `mail.` or `members.` → transactional (login, receipts, password reset, in-app notifications) - `e.` → cold/recovery (abandoned cart, win-back campaigns) - `newsletter.` → opt-in newsletters with List-Unsubscribe headers Each subdomain needs to be onboarded separately in Cloudflare. Ask me which I want. ### 3. Audit existing email sends Use grep/search to find every place in this codebase that sends email. Look for: - The current provider's SDK class names, API URLs, env/config vars - Generic patterns like `mail()`, SMTP usage, `nodemailer`, etc. Group findings by email type/purpose (e.g. "magic-link login", "payment receipt", "weekly newsletter") rather than by file. Tell me what you found before changing anything. ### 4. Add a single helper function Don't sprinkle Cloudflare API calls across the codebase. Add one helper (provider-specific name like `sendEmailViaCloudflare()`) that: - Defaults `from` from a config var (don't hardcode) - Parses `"Name "` strings into the API's `{address, name}` object form - Accepts `cc`/`bcc` as either string or array - Accepts a `headers` dict (newsletters need `List-Unsubscribe` + `List-Unsubscribe-Post`) - Returns `bool` (true on success, false on any failure) - On failure, logs/alerts somewhere I can see (Telegram, Sentry, log file — match what the codebase already does) - Sets curl/fetch timeouts (5s connect, 15s total) so a stuck CF API can't hang the request - Treats `permanent_bounces: [...]` non-empty as a soft failure ### 5. Migrate one low-stakes email type first Don't migrate everything at once. Pick the lowest-stakes email type in the audit (something where landing in spam wouldn't lose me money or users — e.g. "internal admin alert", "profile photo rejection") and migrate just that one. Test it end-to-end. Confirm the email actually arrives. Only then propose the next migration. ### 6. Stop me from migrating login email yet If my codebase sends magic-link login or password-reset emails, do not migrate those to Cloudflare yet. Cloudflare Email Service is brand new (~1 month old at writing). Its IP/domain reputation is unproven. Login emails landing in spam = users locked out. Keep those on the current provider until at least 3 months of clean deliverability data on the lower-stakes types. Tell me this explicitly. ### 7. Suggest commit boundaries After each successful migration, suggest a focused git commit with a clear message. Don't bundle unrelated changes. ## Important caveats to surface to me - Beta product. Pricing isn't fully finalized. SLA undefined. Could change. - No batch endpoint. Mass sends (newsletters to 1000+ recipients) need a loop — at ~150ms/send that's ~2.5min per 1000. Fine for crons, bad for sync user-facing flows. - No bounce webhooks yet. Surface failures via the response body's `permanent_bounces` array. - Suppression list auto-managed. Hard bounces, repeated soft bounces, and spam complaints get blocked. Spam-complaint suppressions are hard to remove (anti-abuse). - No per-message logs/dashboard yet. Use the response's `messageId` for tracking if I need it. - List-Unsubscribe headers are passed through verbatim — Gmail's bulk-sender requirement still met, but only if I include them in `headers`. ## Your first action Before writing any code: do step 1 (ask for prerequisites) and step 3 (audit existing sends), then propose the migration order with a brief explanation of the reasoning. Wait for my confirmation before making changes." /> ...

", // optional "text": "...", // optional (one of html/text required) "cc": ["..."], // optional, array "bcc": ["..."], // optional, array "reply_to": "...", // optional, single string "headers": {"List-Unsubscribe": "<...>"} // optional, e.g. for newsletters } ``` Success response: HTTP 200 + `{"success":true,"result":{"delivered":[],"queued":[],"permanent_bounces":[]}}`. Failure: non-200 OR `success:false` OR non-empty `permanent_bounces`. Always check all three. Pricing: $5/mo Workers Paid plan + 3,000 emails free + $0.35 per 1k after. Roughly 5× cheaper than Postmark. No batch send endpoint — loop single sends. ## Steps you should follow ### 1. Verify prerequisites with me Before writing any code, ask me to confirm: - I have a Cloudflare Workers Paid plan ($5/mo) - I've onboarded my sender domain(s) in Cloudflare dashboard → Email → Email Sending → Onboard Domain (this auto-adds SPF/DKIM/DMARC + cf-bounce MX records) - I have an API token with `email_sending:write` scope (created at https://t.co/s5aigJ6CKV → Custom Token) - I have my Cloudflare account ID Don't proceed until you have these. ### 2. Recommend a domain reputation strategy Most apps should split senders across 2-3 subdomains so spam complaints on one don't drag down deliverability on others: - `mail.` or `members.` → transactional (login, receipts, password reset, in-app notifications) - `e.` → cold/recovery (abandoned cart, win-back campaigns) - `newsletter.` → opt-in newsletters with List-Unsubscribe headers Each subdomain needs to be onboarded separately in Cloudflare. Ask me which I want. ### 3. Audit existing email sends Use grep/search to find every place in this codebase that sends email. Look for: - The current provider's SDK class names, API URLs, env/config vars - Generic patterns like `mail()`, SMTP usage, `nodemailer`, etc. Group findings by email type/purpose (e.g. "magic-link login", "payment receipt", "weekly newsletter") rather than by file. Tell me what you found before changing anything. ### 4. Add a single helper function Don't sprinkle Cloudflare API calls across the codebase. Add one helper (provider-specific name like `sendEmailViaCloudflare()`) that: - Defaults `from` from a config var (don't hardcode) - Parses `"Name "` strings into the API's `{address, name}` object form - Accepts `cc`/`bcc` as either string or array - Accepts a `headers` dict (newsletters need `List-Unsubscribe` + `List-Unsubscribe-Post`) - Returns `bool` (true on success, false on any failure) - On failure, logs/alerts somewhere I can see (Telegram, Sentry, log file — match what the codebase already does) - Sets curl/fetch timeouts (5s connect, 15s total) so a stuck CF API can't hang the request - Treats `permanent_bounces: [...]` non-empty as a soft failure ### 5. Migrate one low-stakes email type first Don't migrate everything at once. Pick the lowest-stakes email type in the audit (something where landing in spam wouldn't lose me money or users — e.g. "internal admin alert", "profile photo rejection") and migrate just that one. Test it end-to-end. Confirm the email actually arrives. Only then propose the next migration. ### 6. Stop me from migrating login email yet If my codebase sends magic-link login or password-reset emails, do not migrate those to Cloudflare yet. Cloudflare Email Service is brand new (~1 month old at writing). Its IP/domain reputation is unproven. Login emails landing in spam = users locked out. Keep those on the current provider until at least 3 months of clean deliverability data on the lower-stakes types. Tell me this explicitly. ### 7. Suggest commit boundaries After each successful migration, suggest a focused git commit with a clear message. Don't bundle unrelated changes. ## Important caveats to surface to me - Beta product. Pricing isn't fully finalized. SLA undefined. Could change. - No batch endpoint. Mass sends (newsletters to 1000+ recipients) need a loop — at ~150ms/send that's ~2.5min per 1000. Fine for crons, bad for sync user-facing flows. - No bounce webhooks yet. Surface failures via the response body's `permanent_bounces` array. - Suppression list auto-managed. Hard bounces, repeated soft bounces, and spam complaints get blocked. Spam-complaint suppressions are hard to remove (anti-abuse). - No per-message logs/dashboard yet. Use the response's `messageId` for tracking if I need it. - List-Unsubscribe headers are passed through verbatim — Gmail's bulk-sender requirement still met, but only if I include them in `headers`. ## Your first action Before writing any code: do step 1 (ask for prerequisites) and step 3 (audit existing sends), then propose the migration order with a brief explanation of the reasoning. Wait for my confirmation before making changes." />
@levelsio
@levelsio
📸 $100K/m 🛰 $44K/m 🎮 $39K/m 🏡 $35K/m 👙 + @X $14K/m 🌍 $10K/m 💾 $0/m
Joined July 2013
3K Following    864.4K Followers
If you wanna switch to @Cloudflare Email Sending today, here's my prompt for you, as always I'm unaffiliated, not paid, not sponsored, but I like it, make sure you remove the space before the .com in the API url I added to avoid it becoming a link in this tweet: # Prompt: Migrate transactional email to Cloudflare Email Service Paste this into Claude Code (or Cursor, or any agent) running inside your project. --- I want to migrate this codebase's outbound email from its current provider (Postmark / SES / Resend / SendGrid / Mailgun / etc.) to Cloudflare Email Service (public beta, launched April 2026). Help me do this carefully. ## Context: what Cloudflare Email Service is A new transactional email API from Cloudflare. Endpoint: ``` POST .com/client/v4/accounts/{ACCOUNT_ID}/email/sending/send Authorization: Bearer {API_TOKEN} Content-Type: application/json ``` Request body: ```json { "to": "user@example.com", // string OR array of strings "from": "no-reply@yourdomain.com", // string OR {"address":"x@y","name":"Display"} "subject": "...", "html": "

...

", // optional "text": "...", // optional (one of html/text required) "cc": ["..."], // optional, array "bcc": ["..."], // optional, array "reply_to": "...", // optional, single string "headers": {"List-Unsubscribe": "<...>"} // optional, e.g. for newsletters } ``` Success response: HTTP 200 + `{"success":true,"result":{"delivered":[],"queued":[],"permanent_bounces":[]}}`. Failure: non-200 OR `success:false` OR non-empty `permanent_bounces`. Always check all three. Pricing: $5/mo Workers Paid plan + 3,000 emails free + $0.35 per 1k after. Roughly 5× cheaper than Postmark. No batch send endpoint — loop single sends. ## Steps you should follow ### 1. Verify prerequisites with me Before writing any code, ask me to confirm: - I have a Cloudflare Workers Paid plan ($5/mo) - I've onboarded my sender domain(s) in Cloudflare dashboard → Email → Email Sending → Onboard Domain (this auto-adds SPF/DKIM/DMARC + cf-bounce MX records) - I have an API token with `email_sending:write` scope (created at → Custom Token) - I have my Cloudflare account ID Don't proceed until you have these. ### 2. Recommend a domain reputation strategy Most apps should split senders across 2-3 subdomains so spam complaints on one don't drag down deliverability on others: - `mail.` or `members.` → transactional (login, receipts, password reset, in-app notifications) - `e.` → cold/recovery (abandoned cart, win-back campaigns) - `newsletter.` → opt-in newsletters with List-Unsubscribe headers Each subdomain needs to be onboarded separately in Cloudflare. Ask me which I want. ### 3. Audit existing email sends Use grep/search to find every place in this codebase that sends email. Look for: - The current provider's SDK class names, API URLs, env/config vars - Generic patterns like `mail()`, SMTP usage, `nodemailer`, etc. Group findings by email type/purpose (e.g. "magic-link login", "payment receipt", "weekly newsletter") rather than by file. Tell me what you found before changing anything. ### 4. Add a single helper function Don't sprinkle Cloudflare API calls across the codebase. Add one helper (provider-specific name like `sendEmailViaCloudflare()`) that: - Defaults `from` from a config var (don't hardcode) - Parses `"Name @domain>"` strings into the API's `{address, name}` object form - Accepts `cc`/`bcc` as either string or array - Accepts a `headers` dict (newsletters need `List-Unsubscribe` + `List-Unsubscribe-Post`) - Returns `bool` (true on success, false on any failure) - On failure, logs/alerts somewhere I can see (Telegram, Sentry, log file — match what the codebase already does) - Sets curl/fetch timeouts (5s connect, 15s total) so a stuck CF API can't hang the request - Treats `permanent_bounces: [...]` non-empty as a soft failure ### 5. Migrate one low-stakes email type first Don't migrate everything at once. Pick the lowest-stakes email type in the audit (something where landing in spam wouldn't lose me money or users — e.g. "internal admin alert", "profile photo rejection") and migrate just that one. Test it end-to-end. Confirm the email actually arrives. Only then propose the next migration. ### 6. Stop me from migrating login email yet If my codebase sends magic-link login or password-reset emails, do not migrate those to Cloudflare yet. Cloudflare Email Service is brand new (~1 month old at writing). Its IP/domain reputation is unproven. Login emails landing in spam = users locked out. Keep those on the current provider until at least 3 months of clean deliverability data on the lower-stakes types. Tell me this explicitly. ### 7. Suggest commit boundaries After each successful migration, suggest a focused git commit with a clear message. Don't bundle unrelated changes. ## Important caveats to surface to me - Beta product. Pricing isn't fully finalized. SLA undefined. Could change. - No batch endpoint. Mass sends (newsletters to 1000+ recipients) need a loop — at ~150ms/send that's ~2.5min per 1000. Fine for crons, bad for sync user-facing flows. - No bounce webhooks yet. Surface failures via the response body's `permanent_bounces` array. - Suppression list auto-managed. Hard bounces, repeated soft bounces, and spam complaints get blocked. Spam-complaint suppressions are hard to remove (anti-abuse). - No per-message logs/dashboard yet. Use the response's `messageId` for tracking if I need it. - List-Unsubscribe headers are passed through verbatim — Gmail's bulk-sender requirement still met, but only if I include them in `headers`. ## Your first action Before writing any code: do step 1 (ask for prerequisites) and step 3 (audit existing sends), then propose the migration order with a brief explanation of the reasoning. Wait for my confirmation before making changes.
Show more
0
52
1.2K
48
Forward to community