Forward Email
You help provision and diagnose Forward Email for the target repository (domains, DNS, aliases, tokens, verify). You do not design email HTML, MJML, or marketing copy.
Read the target repo's Forward Email / notifications docs when present (for example docs/email-forward-email.md). Prefer project docs + this skill over inventing API shapes.
Project facts
Prefer values from the target repository docs and env examples. Typical Singleton SD PoC defaults (override from project docs when they differ):
| Fact | Typical value |
|---|---|
| API base | https://api.forwardemail.net |
| Auth | HTTP Basic — token as username, empty password |
| Runtime env token | FORWARD_EMAIL_TOKEN (legacy accepted: FORWARDEMAIL_API_KEY) |
| KV secret name | forwardemail-api-key |
| Safe default provider | EMAIL_PROVIDER=development |
| Production send | EMAIL_PROVIDER=forward-email and EMAIL_ALLOW_PRODUCTION_SEND=true |
| TS management helpers | packages/email/src/provisioning/forward-email-management.ts |
| Runtime sender | ForwardEmailProvider in @poc-plattform-kit/email |
Marketing contact HTTP uses the marketing-edge Function App and depends on
@poc-plattform-kit/email only — see docs/marketing-edge.md. Do not wire
brochure Contact onto Nest or the Notifications pillar runtime as the
long-term surface.
Safety rules
- Never print, commit, or paste
FORWARD_EMAIL_TOKEN/ Authorization headers / KV secret values into ClickUp, PRs, logs, or chat. - Prefer User/Process env for local ops; production loads via App Config + KV references.
- PR previews / local stay on the development email provider — do not enable
EMAIL_ALLOW_PRODUCTION_SENDthere. - DNS changes go through
provision-forward-email.ps1(or reviewed Route53 batches). Merge SPF; do not blank unrelated TXT. - Do not overwrite organisational DMARC on the exact Forward Email DMARC name when an existing
v=DMARC1differs — warn and skip unless the operator passes-ForceDmarc. - Do not hand-edit
pnpm-lock.yamlor unrelated hubs while fixing email DNS. - Exit 0 with a clear “pending DNS — re-run” message is success for propagation; do not treat it as a hard failure.
- This skill is not for email HTML design, brand templates, or form copy.
Provisioning workflow
# Token must already be set (never echo it)
# $env:FORWARD_EMAIL_TOKEN = '…' # Process scope for this shell only
powershell -File ./scripts/provision-forward-email.ps1 -WhatIf
powershell -File ./scripts/provision-forward-email.ps1
Script steps (idempotent):
- Require
FORWARD_EMAIL_TOKEN(Process → User → Machine). - Ensure domain (GET, POST if missing).
- Read
verification_record+smtp_dns_records. - Unless
-SkipDns: resolve hosted zone; merge SPF; UPSERT MX (mx1/10, mx2/20), verification TXT, DKIM TXT, Return-Path CNAME; DMARC only if safe. - Unless
-SkipVerify:verify-records+verify-smtpwith retries (MaxVerifyAttempts/VerifyDelaySeconds). - Ensure alias (
noreply→hello@singletonsd.comby default) after listing aliases. - Prefer
awsCLI; fallbackpython -m awscli. UTF-8 no BOM change batches.
Diagnostics workflow
When email or DNS is broken, work in this order:
- Config — Is
EMAIL_PROVIDERdevelopment vs forward-email? IsEMAIL_ALLOW_PRODUCTION_SENDset only on prod? IsFORWARD_EMAIL_TOKENpresent in the target process (without printing it)? - Domain —
GET /v1/domains/{domain}— doesverification_record/smtp_dns_recordsexist? - DNS — Compare Route53 TXT/MX/CNAME for the relative name under
singletonsd.comwith API expectations (SPF includespf.forwardemail.net, mx1/mx2, verification TXT, DKIM, Return-Path). - Verify — Re-run provision script or call verify-records / verify-smtp; allow propagation.
- Alias — List aliases; confirm
noreplyrecipients includehello@singletonsd.com. - Send path — Development provider captures only; Forward Email 401 → rotate KV; 429/5xx → retry/backoff already in provider.
Useful commands:
powershell -File ./scripts/provision-forward-email.ps1 -SkipDns -WhatIf
powershell -File ./scripts/provision-forward-email.ps1 -SkipVerify
# Inspect zone (no secrets):
aws route53 list-resource-record-sets --hosted-zone-id <id> --query "ResourceRecordSets[?contains(Name, 'mail.plattform-kit.poc')]"
Example prompts
- “Provision Forward Email for
mail.plattform-kit.poc.singletonsd.comwith noreply → hello@singletonsd.com.” - “Why is verify-smtp still failing after DNS upsert? Diagnose without printing the token.”
- “Merge SPF for Forward Email without clobbering existing TXT on the apex relative name.”
- “Rotate
forwardemail-api-keyin Key Vault and confirm App Config still maps toFORWARD_EMAIL_TOKEN.” - “Add a second alias
support→hello@singletonsd.comusing the provision script.” - “Confirm PR preview cannot send real mail.”
Out of scope
- Email HTML / template design / brand layouts
- Implementing marketing-oauth Contact Azure Functions (separate ticket/agent)
- Approving PRs or writing secrets into git