vybekiit 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +1697 -562
- package/dist/global-skills/add-ai/SKILL.md +1 -1
- package/dist/global-skills/add-analytics/SKILL.md +1 -1
- package/dist/global-skills/add-blog/SKILL.md +1 -1
- package/dist/global-skills/add-crud/SKILL.md +1 -1
- package/dist/global-skills/add-files/SKILL.md +1 -1
- package/dist/global-skills/add-images/SKILL.md +1 -1
- package/dist/global-skills/add-language/SKILL.md +1 -1
- package/dist/global-skills/add-notifications/SKILL.md +1 -1
- package/dist/global-skills/add-realtime/SKILL.md +1 -1
- package/dist/global-skills/add-route/SKILL.md +1 -1
- package/dist/global-skills/add-search/SKILL.md +1 -1
- package/dist/global-skills/add-signin/SKILL.md +1 -1
- package/dist/global-skills/add-teams/SKILL.md +1 -1
- package/dist/global-skills/add-upload/SKILL.md +1 -1
- package/dist/global-skills/aws-serverless/SKILL.md +44 -44
- package/dist/global-skills/aws-serverless/assets/powertools-handler.py +1 -2
- package/dist/global-skills/aws-serverless/references/api-gateway.md +470 -50
- package/dist/global-skills/aws-serverless/references/architecture.md +186 -47
- package/dist/global-skills/aws-serverless/references/concurrency.md +158 -44
- package/dist/global-skills/aws-serverless/references/deployment.md +1 -1
- package/dist/global-skills/aws-serverless/references/event-sources.md +391 -72
- package/dist/global-skills/aws-serverless/references/lambda.md +428 -69
- package/dist/global-skills/aws-serverless/references/orchestration.md +384 -65
- package/dist/global-skills/aws-serverless/references/production.md +415 -78
- package/dist/global-skills/aws-serverless/references/troubleshooting.md +626 -79
- package/dist/global-skills/back-up-my-code/SKILL.md +1 -1
- package/dist/global-skills/buy-domain/SKILL.md +1 -1
- package/dist/global-skills/check-safety/SKILL.md +1 -1
- package/dist/global-skills/configure-capabilities/SKILL.md +1 -1
- package/dist/global-skills/connect-account/SKILL.md +1 -1
- package/dist/global-skills/connect-account-backend/SKILL.md +1 -1
- package/dist/global-skills/design-my-data/SKILL.md +1 -1
- package/dist/global-skills/doctor/SKILL.md +1 -1
- package/dist/global-skills/feedback/SKILL.md +63 -0
- package/dist/global-skills/go-live/SKILL.md +1 -1
- package/dist/global-skills/harden/SKILL.md +1 -1
- package/dist/global-skills/instrument-feature-flags/references/usage.md +0 -35
- package/dist/global-skills/instrument-product-analytics/SKILL.md +1 -1
- package/dist/global-skills/instrument-product-analytics/references/android.md +0 -36
- package/dist/global-skills/instrument-product-analytics/references/configuration.md +0 -1
- package/dist/global-skills/instrument-product-analytics/references/flutter.md +0 -37
- package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +2 -3
- package/dist/global-skills/instrument-product-analytics/references/usage.md +0 -35
- package/dist/global-skills/manifest.json +2 -1
- package/dist/global-skills/neon/SKILL.md +20 -27
- package/dist/global-skills/neon-ai-gateway/SKILL.md +2 -68
- package/dist/global-skills/neon-functions/SKILL.md +7 -7
- package/dist/global-skills/neon-object-storage/SKILL.md +2 -2
- package/dist/global-skills/neon-postgres/SKILL.md +5 -5
- package/dist/global-skills/neon-postgres-branches/SKILL.md +1 -1
- package/dist/global-skills/onboarding/SKILL.md +1 -1
- package/dist/global-skills/plan-my-idea/SKILL.md +1 -1
- package/dist/global-skills/publish-app/SKILL.md +1 -1
- package/dist/global-skills/publish-extension/SKILL.md +1 -1
- package/dist/global-skills/reset-password/SKILL.md +1 -1
- package/dist/global-skills/save-data/SKILL.md +1 -1
- package/dist/global-skills/setup-email/SKILL.md +1 -1
- package/dist/global-skills/setup-payments/SKILL.md +1 -1
- package/dist/global-skills/setup-sms/SKILL.md +1 -1
- package/dist/global-skills/sign-in-with-email-link/SKILL.md +1 -1
- package/dist/global-skills/sign-in-with-google/SKILL.md +1 -1
- package/dist/global-skills/sign-in-with-phone/SKILL.md +1 -1
- package/dist/global-skills/stripe-best-practices/SKILL.md +6 -11
- package/dist/global-skills/stripe-best-practices/references/billing.md +0 -5
- package/dist/global-skills/stripe-best-practices/references/payments.md +2 -4
- package/dist/global-skills/stripe-best-practices/references/tax.md +8 -78
- package/dist/global-skills/track-errors/SKILL.md +1 -1
- package/dist/global-skills/update-kit/SKILL.md +1 -1
- package/dist/global-skills/wire-auth/SKILL.md +1 -1
- package/dist/global-skills/wire-database/SKILL.md +1 -1
- package/dist/global-skills/wire-email/SKILL.md +1 -1
- package/dist/global-skills/wire-payments/SKILL.md +1 -1
- package/package.json +8 -8
- package/dist/global-skills/email-best-practices/.github/workflows/sync-skills.yml +0 -30
- package/dist/global-skills/email-best-practices/README.md +0 -63
- package/dist/global-skills/email-best-practices/references/accessibility.md +0 -189
- package/dist/global-skills/email-best-practices/references/compliance.md +0 -125
- package/dist/global-skills/email-best-practices/references/deliverability.md +0 -121
- package/dist/global-skills/email-best-practices/references/email-capture.md +0 -129
- package/dist/global-skills/email-best-practices/references/email-types.md +0 -173
- package/dist/global-skills/email-best-practices/references/list-management.md +0 -157
- package/dist/global-skills/email-best-practices/references/marketing-emails.md +0 -115
- package/dist/global-skills/email-best-practices/references/sending-reliability.md +0 -155
- package/dist/global-skills/email-best-practices/references/transactional-email-catalog.md +0 -418
- package/dist/global-skills/email-best-practices/references/transactional-emails.md +0 -92
- package/dist/global-skills/email-best-practices/references/webhooks-events.md +0 -167
- package/dist/global-skills/email-best-practices/tests/README.md +0 -35
- package/dist/global-skills/email-best-practices/tests/scenarios/01-spam-deliverability.md +0 -46
- package/dist/global-skills/email-best-practices/tests/scenarios/02-multi-region-compliance.md +0 -48
- package/dist/global-skills/email-best-practices/tests/scenarios/03-retry-idempotency.md +0 -36
- package/dist/global-skills/email-best-practices/tests/scenarios/04-webhook-bounce-handling.md +0 -52
- package/dist/global-skills/email-best-practices/tests/scenarios/05-new-saas-email-plan.md +0 -51
- package/dist/global-skills/neon-postgres/references/neon-sdk.md +0 -262
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
```
|
|
2
|
-
╔══════════════════════════════════════╗
|
|
3
|
-
║ _____ __ __ _ ___ _ ║
|
|
4
|
-
║ | ____| \/ | / \ |_ _| | ║
|
|
5
|
-
║ | _| | |\/| | / _ \ | || | ║
|
|
6
|
-
║ | |___| | | |/ ___ \ | || |___ ║
|
|
7
|
-
║ |_____|_| |_/_/ \_\___|_____| ║
|
|
8
|
-
║ ║
|
|
9
|
-
║ Best Practices ║
|
|
10
|
-
╚══════════════════════════════════════╝
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
# Email Best Practices Skill
|
|
14
|
-
|
|
15
|
-
A comprehensive agent skill for building production-ready email systems. Covers everything from DNS authentication to webhook processing, with a focus on deliverability, compliance, and reliability.
|
|
16
|
-
|
|
17
|
-
## Installation
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
npx skills add resend/email-best-practices
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## What This Skill Covers
|
|
24
|
-
|
|
25
|
-
**Getting Started**
|
|
26
|
-
- Planning which emails your app needs (password reset, verification, order confirmations)
|
|
27
|
-
- Setting up email authentication (SPF, DKIM, DMARC) so emails reach inboxes
|
|
28
|
-
|
|
29
|
-
**Sending Emails**
|
|
30
|
-
- Transactional email design (subject lines, content structure, mobile-first)
|
|
31
|
-
- Marketing email best practices (consent, segmentation, unsubscribe)
|
|
32
|
-
- Compliance requirements by region (CAN-SPAM, GDPR, CASL)
|
|
33
|
-
|
|
34
|
-
**Production Infrastructure**
|
|
35
|
-
- Idempotency and retry logic to prevent duplicates
|
|
36
|
-
- Webhook processing for delivery events
|
|
37
|
-
- Suppression lists and list hygiene automation
|
|
38
|
-
|
|
39
|
-
## Structure
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
email-best-practices/
|
|
43
|
-
├── SKILL.md # Start here - routes to the right resource
|
|
44
|
-
└── references/
|
|
45
|
-
├── deliverability.md # SPF/DKIM/DMARC, sender reputation
|
|
46
|
-
├── transactional-emails.md # Password resets, OTPs, confirmations
|
|
47
|
-
├── transactional-email-catalog.md # Email combinations by app type
|
|
48
|
-
├── marketing-emails.md # Newsletters, campaigns, consent
|
|
49
|
-
├── email-capture.md # Validation, verification, opt-in
|
|
50
|
-
├── compliance.md # CAN-SPAM, GDPR, CASL
|
|
51
|
-
├── email-types.md # Transactional vs marketing
|
|
52
|
-
├── sending-reliability.md # Idempotency, retry logic, errors
|
|
53
|
-
├── webhooks-events.md # Delivery events, webhook setup
|
|
54
|
-
└── list-management.md # Suppression lists, hygiene
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Quick Start
|
|
58
|
-
|
|
59
|
-
Open `SKILL.md` - it has a routing table that directs you to the right resource based on what you need to do.
|
|
60
|
-
|
|
61
|
-
## License
|
|
62
|
-
|
|
63
|
-
MIT
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
# Email Accessibility
|
|
2
|
-
|
|
3
|
-
Emails must be readable by screen readers, dark-mode clients, translation tools, and AI agents — not just sighted readers on a default inbox. The rules below are mechanical. Apply them every time.
|
|
4
|
-
|
|
5
|
-
## Rules
|
|
6
|
-
|
|
7
|
-
### Set `lang` and `dir` on `<html>` and on `<body>`'s direct children (Serious)
|
|
8
|
-
|
|
9
|
-
Both attributes are needed in **two places**: on `<html>` *and* on the direct children of `<body>`. Several email clients strip the attributes from `<html>`, which is why duplicating them on the body's children is the single most common accessibility failure in production email.
|
|
10
|
-
|
|
11
|
-
```html
|
|
12
|
-
<html lang="en" dir="ltr">
|
|
13
|
-
<head>
|
|
14
|
-
<title>Your weekly product updates</title>
|
|
15
|
-
</head>
|
|
16
|
-
<body>
|
|
17
|
-
<div lang="en" dir="ltr">
|
|
18
|
-
<!-- email content -->
|
|
19
|
-
</div>
|
|
20
|
-
</body>
|
|
21
|
-
</html>
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
- `lang`: a [BCP 47 language tag](https://developer.mozilla.org/en-US/docs/Glossary/BCP_47_language_tag) (`en`, `pt-BR`, `ja`, `ar`)
|
|
25
|
-
- `dir`: `ltr`, `rtl`, or `auto`
|
|
26
|
-
|
|
27
|
-
**Fallbacks when the correct values aren't available** (use only when you genuinely don't know):
|
|
28
|
-
|
|
29
|
-
- `dir="auto"` — lets the user agent infer direction from content
|
|
30
|
-
- `lang="und"` — marks the language as undetermined
|
|
31
|
-
|
|
32
|
-
Both fallbacks are worse than the correct value but much better than nothing. For multi-locale templates, pass the locale through; do not hardcode `en`.
|
|
33
|
-
|
|
34
|
-
### Mark layout tables as presentational (Serious)
|
|
35
|
-
|
|
36
|
-
Any `<table>` used for layout must have `role="presentation"` (or the equivalent `role="none"`). Otherwise screen readers announce "table, row 1 of N" for every layout row and the email becomes unusable. Prefer avoiding layout tables entirely; when you can't, mark them.
|
|
37
|
-
|
|
38
|
-
```html
|
|
39
|
-
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
|
|
40
|
-
<tr>
|
|
41
|
-
<td>...</td>
|
|
42
|
-
</tr>
|
|
43
|
-
</table>
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Leave a `<table>` without `role="presentation"` only when the data is genuinely tabular (line items, comparison rows). Tabular data should also use `<th scope="col">` for column headers.
|
|
47
|
-
|
|
48
|
-
### Use a single `<h1>` and nest headings in order (Mild)
|
|
49
|
-
|
|
50
|
-
Most emails should have one `<h1>` that names the email, with subheadings nested in order:`<h1>` → `<h2>` → `<h3>`. Never skip levels. Never fake a heading with bold `<p>`.
|
|
51
|
-
|
|
52
|
-
```html
|
|
53
|
-
<h1>Order confirmation</h1>
|
|
54
|
-
<h2>Items</h2>
|
|
55
|
-
<h2>Shipping</h2>
|
|
56
|
-
<h3>Address</h3>
|
|
57
|
-
<h3>Tracking</h3>
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
Headings are how assistive tech and AI clients navigate and summarize the email.
|
|
61
|
-
|
|
62
|
-
**Exception:** very short messages (SMS-style notifications, single-sentence alerts) may not need a heading at all. If the email body is one or two sentences, skip the `<h1>` rather than wrap a heading around the only content.
|
|
63
|
-
|
|
64
|
-
### Every link must have discernible text (Serious)
|
|
65
|
-
|
|
66
|
-
Every `<a>` must contain text content that a screen reader can announce. The most common failure is a linked image with no alt text.
|
|
67
|
-
|
|
68
|
-
A **linked image is never decorative.** It's functional, so its `alt` must describe what clicking does, not just what the image looks like.
|
|
69
|
-
|
|
70
|
-
```html
|
|
71
|
-
<!-- Wrong: linked image with no accessible name -->
|
|
72
|
-
<a href="/order/123">
|
|
73
|
-
<img src="view-order.png" alt="">
|
|
74
|
-
</a>
|
|
75
|
-
|
|
76
|
-
<!-- Right: alt describes the action -->
|
|
77
|
-
<a href="/order/123">
|
|
78
|
-
<img src="view-order.png" alt="View order #123">
|
|
79
|
-
</a>
|
|
80
|
-
|
|
81
|
-
<!-- Also right: visible text alongside the image -->
|
|
82
|
-
<a href="/order/123">
|
|
83
|
-
<img src="icon.png" alt="">
|
|
84
|
-
View order #123
|
|
85
|
-
</a>
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
When the visible link text can't carry enough information, add visually hidden text inside the `<a>` (see [goodemailcode.com/email-accessibility/visually-hidden-text](https://www.goodemailcode.com/email-accessibility/visually-hidden-text)). `aria-label` and `title` on `<a>` have limited support in email clients. Prefer real text content or visually hidden text.
|
|
89
|
-
|
|
90
|
-
### Link text must describe the destination (Moderate)
|
|
91
|
-
|
|
92
|
-
Even when a link has text, it must describe where the link goes. Never use "click here," "learn more," "read more," or bare URLs. Screen reader users often navigate by jumping between link texts with no surrounding context.
|
|
93
|
-
|
|
94
|
-
```html
|
|
95
|
-
<!-- Wrong -->
|
|
96
|
-
<a href="...">click here</a>
|
|
97
|
-
<a href="...">https://resend.com/blog/...</a>
|
|
98
|
-
|
|
99
|
-
<!-- Right -->
|
|
100
|
-
<a href="...">Read the 2026 accessibility report</a>
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### Write meaningful alt text — and use `alt=""` for decorative images (Critical)
|
|
104
|
-
|
|
105
|
-
Two distinct rules, both mandatory. `alt` must always be present; the value depends on the image's role.
|
|
106
|
-
|
|
107
|
-
**Meaningful images** (product shots, charts, screenshots, anything carrying information): describe purpose and key details in context.
|
|
108
|
-
|
|
109
|
-
```html
|
|
110
|
-
<!-- Wrong: redundant, vague -->
|
|
111
|
-
<img src="..." alt="image">
|
|
112
|
-
<img src="..." alt="photo of a bike">
|
|
113
|
-
|
|
114
|
-
<!-- Right: purpose + key details -->
|
|
115
|
-
<img src="..." alt="Red bicycle leaning against a brick wall on a rainy street">
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
**Decorative images** (spacers, dividers, background flourishes, pure branding ornaments): use an empty `alt=""`. This tells screen readers to skip them. Never omit the attribute entirely — omitting it and `alt=""` are not equivalent; some screen readers announce the filename when `alt` is absent.
|
|
119
|
-
|
|
120
|
-
```html
|
|
121
|
-
<img src="divider.png" alt="" role="presentation">
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
If an image conveys no information that isn't already in the surrounding text, it is decorative. If it's inside an `<a>`, it is **not** decorative — see the "Every link must have discernible text" rule.
|
|
125
|
-
|
|
126
|
-
### Include a `<title>` tag (Serious)
|
|
127
|
-
|
|
128
|
-
Many clients and assistive technologies read `<title>` before anything else. It's also shown when the email is viewed as a web page. Treat it like the subject line, not the brand name.
|
|
129
|
-
|
|
130
|
-
```html
|
|
131
|
-
<head>
|
|
132
|
-
<title>Your weekly product updates from Resend</title>
|
|
133
|
-
</head>
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
If the per-email title is hard to populate, a generic but specific fallback like `"Email from {Brand Name}"` still beats nothing.
|
|
137
|
-
|
|
138
|
-
### Hit 4.5:1 color contrast, then check dark mode (Serious)
|
|
139
|
-
|
|
140
|
-
- Body text and links: **4.5:1** minimum against the background (WCAG AA)
|
|
141
|
-
- Large text (≥18pt, or ≥14pt bold): **3:1** minimum
|
|
142
|
-
- Never rely on color alone to convey meaning (error states, status badges) — pair it with text or an icon
|
|
143
|
-
|
|
144
|
-
Verify with the [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/) or browser devtools.
|
|
145
|
-
|
|
146
|
-
**Dark mode.** Outlook, Apple Mail, and others force dark mode and derive dark colors from your light ones. Healthy starting contrast keeps the auto-inverted version readable. Always preview in dark mode before shipping.
|
|
147
|
-
|
|
148
|
-
## Priority order
|
|
149
|
-
|
|
150
|
-
When you can't fix everything, fix in this order:
|
|
151
|
-
|
|
152
|
-
1. **Critical** — missing or misused `alt` on images
|
|
153
|
-
2. **Serious** — `lang`/`dir` (on `<html>` and body children), `role="presentation"` on layout tables, links without discernible text, missing `<title>`, color contrast
|
|
154
|
-
3. **Moderate** — non-descriptive link text ("click here")
|
|
155
|
-
4. **Mild** — missing `<h1>` (skip the fix for very short messages)
|
|
156
|
-
|
|
157
|
-
## Authoring checklist
|
|
158
|
-
|
|
159
|
-
Run this on every template:
|
|
160
|
-
|
|
161
|
-
- [ ] `<html>` has `lang` and `dir`; direct children of `<body>` also have `lang` and `dir`
|
|
162
|
-
- [ ] `<title>` set on `<head>`, specific to this email (not the brand name)
|
|
163
|
-
- [ ] Layout `<table>` elements have `role="presentation"` (or `role="none"`)
|
|
164
|
-
- [ ] At most one `<h1>` (or none, for very short messages); `<h2>`/`<h3>` nested in order
|
|
165
|
-
- [ ] Every `<a>` has discernible text — visible text, descriptive alt on linked images, or visually hidden text
|
|
166
|
-
- [ ] Every link describes its destination — no "click here," "learn more," or bare URLs
|
|
167
|
-
- [ ] Every meaningful image has descriptive `alt`; every decorative image has an explicit `alt=""`
|
|
168
|
-
- [ ] No linked image with `alt=""` (linked images are functional, never decorative)
|
|
169
|
-
- [ ] Body text passes 4.5:1 contrast and stays readable in dark mode
|
|
170
|
-
- [ ] Plain-text alternative is sent alongside the HTML version
|
|
171
|
-
|
|
172
|
-
## Testing
|
|
173
|
-
|
|
174
|
-
- **Automated.** Run the email through [Parcel's accessibility checker](https://parcel.io/docs/dev-tools/accessibility-checker) (the same tool the EMC report uses; available on the free plan). It catches most of the rules above.
|
|
175
|
-
- **Screen reader pass.** macOS VoiceOver (`Cmd+F5`) or NVDA on Windows. Listen top to bottom; if anything is confusing, fix the markup.
|
|
176
|
-
- **Contrast.** [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/).
|
|
177
|
-
- **Dark mode.** Send a test to Outlook (Windows/web), Apple Mail with dark appearance, Gmail iOS and Android.
|
|
178
|
-
|
|
179
|
-
Automated tests do not catch everything. They will not tell you whether alt text actually matches the image, whether headings make semantic sense, or whether text inside an image is readable on narrow viewports. Even the three brands that passed every automated check in the EMC 2026 report had judgment-level issues like generic alt text on decorative images, alt text that didn't match the image, and 10px footer text. Treat automation as a floor, not a ceiling.
|
|
180
|
-
|
|
181
|
-
## Related
|
|
182
|
-
|
|
183
|
-
- [Transactional Emails](./transactional-emails.md) — content patterns for password resets, OTPs, receipts
|
|
184
|
-
- [Marketing Emails](./marketing-emails.md) — newsletter and campaign best practices
|
|
185
|
-
- [Compliance](./compliance.md) — legal requirements that overlap with accessibility (e.g., clear unsubscribe text)
|
|
186
|
-
|
|
187
|
-
## Tooling
|
|
188
|
-
|
|
189
|
-
When generating templates with React Email, the latest version handles several of the structural rules: `<Html>` sets `lang`/`dir`, `<Img>` defaults to `alt=""`, `<Markdown>` tables render `role="presentation"`, and `<Preview>` emits a `<title>`. Upgrade with `npm install react-email@latest`. The content rules — heading hierarchy, descriptive alt and link text, contrast, the linked-image rule — still have to be applied by hand.
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
# Email Compliance
|
|
2
|
-
|
|
3
|
-
Legal requirements for email by jurisdiction. **Not legal advice—consult an attorney for your specific situation.**
|
|
4
|
-
|
|
5
|
-
## Quick Reference
|
|
6
|
-
|
|
7
|
-
| Law | Region | Key Requirement | Penalty |
|
|
8
|
-
|-----|--------|-----------------|---------|
|
|
9
|
-
| CAN-SPAM | US | Opt-out mechanism, physical address | $53k/email |
|
|
10
|
-
| GDPR | EU | Explicit opt-in consent | €20M or 4% revenue |
|
|
11
|
-
| CASL | Canada | Express consent, opt-out mechanism | $1M (individual) to $10M (organization) CAD |
|
|
12
|
-
|
|
13
|
-
## CAN-SPAM (United States)
|
|
14
|
-
|
|
15
|
-
**Requirements:**
|
|
16
|
-
- Accurate header info (From, To, Reply-To)
|
|
17
|
-
- Non-deceptive subject lines
|
|
18
|
-
- Physical mailing address in every email
|
|
19
|
-
- Clear opt-out mechanism
|
|
20
|
-
- Honor opt-out within 10 business days
|
|
21
|
-
|
|
22
|
-
**Transactional emails:** Can send without opt-in if related to a transaction and not promotional.
|
|
23
|
-
|
|
24
|
-
## GDPR (European Union)
|
|
25
|
-
|
|
26
|
-
**Requirements:**
|
|
27
|
-
- Explicit opt-in consent (not pre-checked boxes)
|
|
28
|
-
- Consent must be freely given, specific, informed
|
|
29
|
-
- Easy to withdraw consent (as easy as giving it)
|
|
30
|
-
- Right to access data and deletion ("right to be forgotten")
|
|
31
|
-
- Process unsubscribe immediately
|
|
32
|
-
|
|
33
|
-
**Consent records:** Document who, when, how, and what they consented to.
|
|
34
|
-
|
|
35
|
-
**Transactional emails:** Can send based on contract fulfillment or legitimate interest.
|
|
36
|
-
|
|
37
|
-
## CASL (Canada)
|
|
38
|
-
|
|
39
|
-
**Consent types:**
|
|
40
|
-
- **Express consent:** Explicit opt-in (ideal)
|
|
41
|
-
- **Implied consent:** Existing business relationship (2 years) or inquiry (6 months)
|
|
42
|
-
|
|
43
|
-
**Requirements:**
|
|
44
|
-
- Clear sender identification that will be valid for 60 days after send
|
|
45
|
-
- Unsubscribe functional for 60 days after send
|
|
46
|
-
- Process unsubscribe no later than 10 business days
|
|
47
|
-
- Keep consent records 3 years after expiration
|
|
48
|
-
|
|
49
|
-
## Other Regions
|
|
50
|
-
|
|
51
|
-
| Region | Law | Key Points |
|
|
52
|
-
|--------|-----|------------|
|
|
53
|
-
| Australia | Spam Act 2003 | Consent required, honor unsubscribe within 5 days |
|
|
54
|
-
| UK | PECR + GDPR | Same as GDPR |
|
|
55
|
-
| Brazil | LGPD | Similar to GDPR, explicit consent for marketing |
|
|
56
|
-
|
|
57
|
-
## Unsubscribe Requirements Summary
|
|
58
|
-
|
|
59
|
-
| Law | Timing | Notes |
|
|
60
|
-
|-----|--------|-------|
|
|
61
|
-
| CAN-SPAM | 10 business days | Must work 30 days after send |
|
|
62
|
-
| GDPR | Immediately | Must be as easy as opting in |
|
|
63
|
-
| CASL | 10 business days | Must work 60 days after send |
|
|
64
|
-
|
|
65
|
-
**Universal best practices:** Prominent link, one-click when possible, no login required, free, confirm action.
|
|
66
|
-
|
|
67
|
-
### List-Unsubscribe Header (Required for Bulk Senders)
|
|
68
|
-
|
|
69
|
-
Gmail, Yahoo, and Microsoft require `List-Unsubscribe` headers. Without them, bulk emails may be rejected or spam-filtered.
|
|
70
|
-
|
|
71
|
-
**Required headers:**
|
|
72
|
-
|
|
73
|
-
```typescript
|
|
74
|
-
headers: {
|
|
75
|
-
'List-Unsubscribe': '<https://example.com/unsubscribe>',
|
|
76
|
-
'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click',
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
**Your unsubscribe endpoint must:**
|
|
81
|
-
- Accept POST requests — return `200` or `202` with a blank page
|
|
82
|
-
- Display standard unsubscribe page for GET requests
|
|
83
|
-
- Stop sending within 48 hours of the request
|
|
84
|
-
|
|
85
|
-
## Managing preferences vs Unsubscribe from all
|
|
86
|
-
|
|
87
|
-
Most legistlations require a one-click unsubscribe. `Managing preferences` is a nice-to-have and can lead to lower unsubscribe rate but doesn't replace `Unsubscribe`. If possible, offer both.
|
|
88
|
-
|
|
89
|
-
## Consent Management
|
|
90
|
-
|
|
91
|
-
**Record:**
|
|
92
|
-
- Email address
|
|
93
|
-
- Date/time of consent
|
|
94
|
-
- Method (form, checkbox)
|
|
95
|
-
- What they consented to
|
|
96
|
-
- Source (which page/form)
|
|
97
|
-
|
|
98
|
-
**Storage:** Database with timestamps, audit trail of changes, link to user account.
|
|
99
|
-
|
|
100
|
-
## Data Retention
|
|
101
|
-
|
|
102
|
-
| Law | Requirement |
|
|
103
|
-
|-----|-------------|
|
|
104
|
-
| GDPR | Keep only as long as necessary, delete when no longer needed |
|
|
105
|
-
| CASL | Keep consent records 3 years after expiration |
|
|
106
|
-
|
|
107
|
-
**Best practice:** Have clear retention policy, honor deletion requests promptly, review and clean regularly.
|
|
108
|
-
|
|
109
|
-
## Privacy Policy Must Include
|
|
110
|
-
|
|
111
|
-
- What data you collect
|
|
112
|
-
- How you use data
|
|
113
|
-
- Who you share data with
|
|
114
|
-
- User rights (access, deletion)
|
|
115
|
-
- How to contact about privacy
|
|
116
|
-
|
|
117
|
-
## International Sending
|
|
118
|
-
|
|
119
|
-
**Best practice:** Follow the most restrictive requirements (usually GDPR) to ensure compliance across all regions.
|
|
120
|
-
|
|
121
|
-
## Related
|
|
122
|
-
|
|
123
|
-
- [Email Capture](./email-capture.md) - Implement consent forms and double opt-in
|
|
124
|
-
- [Marketing Emails](./marketing-emails.md) - Consent and unsubscribe requirements
|
|
125
|
-
- [List Management](./list-management.md) - Handle unsubscribes and deletion requests
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
# Email Deliverability
|
|
2
|
-
|
|
3
|
-
Maximizing the chances that your emails are delivered successfully to the recipients.
|
|
4
|
-
|
|
5
|
-
## Email Authentication
|
|
6
|
-
|
|
7
|
-
**Required by Gmail/Yahoo/Microsoft** - unauthenticated emails will be rejected or spam-filtered.
|
|
8
|
-
|
|
9
|
-
### SPF (Sender Policy Framework)
|
|
10
|
-
|
|
11
|
-
Specifies which servers can send email for your domain.
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
v=spf1 include:amazonses.com ~all
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
- Add TXT record to DNS
|
|
18
|
-
- Use `~all` (soft fail)
|
|
19
|
-
|
|
20
|
-
### DKIM (DomainKeys Identified Mail)
|
|
21
|
-
|
|
22
|
-
Cryptographic signature proving email authenticity.
|
|
23
|
-
|
|
24
|
-
- Your email service will provide you with a TXT record
|
|
25
|
-
|
|
26
|
-
### DMARC
|
|
27
|
-
|
|
28
|
-
Policy for handling SPF/DKIM failures + reporting.
|
|
29
|
-
|
|
30
|
-
```
|
|
31
|
-
v=DMARC1; p=none; rua=mailto:dmarc@example.com
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
**Rollout:** `p=none` (monitor) → `p=quarantine; pct=25` → `p=reject`
|
|
35
|
-
|
|
36
|
-
Learn more: https://resend.com/blog/dmarc-policy-modes
|
|
37
|
-
|
|
38
|
-
### Verify Your Setup
|
|
39
|
-
|
|
40
|
-
Check DNS records directly:
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
# SPF record
|
|
44
|
-
dig TXT example.com +short
|
|
45
|
-
|
|
46
|
-
# DKIM record (replace 'resend' with your selector)
|
|
47
|
-
dig TXT resend._domainkey.example.com +short
|
|
48
|
-
|
|
49
|
-
# DMARC record
|
|
50
|
-
dig TXT _dmarc.example.com +short
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
**Expected output:** Each command should return your configured record. No output = record missing.
|
|
54
|
-
|
|
55
|
-
## Sender Reputation
|
|
56
|
-
|
|
57
|
-
### IP Warming
|
|
58
|
-
|
|
59
|
-
New IP/domain? Gradually increase volume:
|
|
60
|
-
|
|
61
|
-
| Week | Daily Volume |
|
|
62
|
-
|------|-------------|
|
|
63
|
-
| 1 | 50-100 |
|
|
64
|
-
| 2 | 200-500 |
|
|
65
|
-
| 3 | 1,000-2,000 |
|
|
66
|
-
| 4 | 5,000-10,000 |
|
|
67
|
-
|
|
68
|
-
Start with engaged users. Send consistently. Don't rush.
|
|
69
|
-
|
|
70
|
-
Learn more: https://resend.com/docs/knowledge-base/warming-up
|
|
71
|
-
|
|
72
|
-
### Maintaining Reputation
|
|
73
|
-
|
|
74
|
-
**Do:** Send to engaged users, keep bounce <4%, complaints <0.1%, remove inactive subscribers.
|
|
75
|
-
|
|
76
|
-
**Don't:** Send to purchased lists, ignore bounces/complaints, send inconsistent volumes
|
|
77
|
-
|
|
78
|
-
## Bounce Handling
|
|
79
|
-
|
|
80
|
-
| Type | Cause | Action |
|
|
81
|
-
|------|-------|--------|
|
|
82
|
-
| Hard bounce | Permanent failure to deliver | Remove immediately |
|
|
83
|
-
| Soft bounce | Transient failure to deliver | Retry: 1h → 4h → 24h, remove after 3-5 failures |
|
|
84
|
-
|
|
85
|
-
**Targets:** <1% good, 1-3% acceptable, 3-4% concerning, >4% critical
|
|
86
|
-
|
|
87
|
-
## Complaint Handling
|
|
88
|
-
|
|
89
|
-
**Targets:** <0.01% excellent, 0.01-0.05% good, >0.05% critical
|
|
90
|
-
|
|
91
|
-
**Reduce complaints:**
|
|
92
|
-
- Only send to opted-in users
|
|
93
|
-
- Make unsubscribe easy and immediate
|
|
94
|
-
- Use clear sender names and "From" addresses
|
|
95
|
-
|
|
96
|
-
**Feedback loops:** Set up with Gmail (Postmaster Tools), Yahoo, Microsoft SNDS. Remove complainers immediately.
|
|
97
|
-
|
|
98
|
-
## Infrastructure
|
|
99
|
-
|
|
100
|
-
**Dedicated sending domain:** Use different subdomains for different sending purposes (e.g., `t.example.com` for transactional emails and `m.example.com` for marketing emails).
|
|
101
|
-
|
|
102
|
-
**DNS TTL:** Low (300s) during setup, high (3600s+) after stable.
|
|
103
|
-
|
|
104
|
-
## Troubleshooting
|
|
105
|
-
|
|
106
|
-
**Emails going to spam?** Check in order:
|
|
107
|
-
1. Authentication (SPF, DKIM, DMARC)
|
|
108
|
-
2. List-Unsubscribe header — required by Gmail/Yahoo since Feb 2024 (see [Compliance](./compliance.md))
|
|
109
|
-
3. Sender reputation (blacklists, complaint rates)
|
|
110
|
-
4. Content
|
|
111
|
-
5. Sending patterns (sudden volume spikes)
|
|
112
|
-
|
|
113
|
-
**Diagnostic tools:**
|
|
114
|
-
- [Google Postmaster Tools](https://postmaster.google.com) - Domain reputation and spam rates
|
|
115
|
-
- [mail-tester.com](https://www.mail-tester.com) - Send a test email, get deliverability score
|
|
116
|
-
- [MXToolbox](https://mxtoolbox.com/blacklists.aspx) - Check blacklist status
|
|
117
|
-
|
|
118
|
-
## Related
|
|
119
|
-
|
|
120
|
-
- [List Management](./list-management.md) - Handle bounces and complaints to protect reputation
|
|
121
|
-
- [Sending Reliability](./sending-reliability.md) - Retry logic and error handling
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
# Email Capture Best Practices
|
|
2
|
-
|
|
3
|
-
Collecting email addresses responsibly with validation, verification, and proper consent.
|
|
4
|
-
|
|
5
|
-
## Email Validation
|
|
6
|
-
|
|
7
|
-
### Client-Side
|
|
8
|
-
|
|
9
|
-
**HTML5:**
|
|
10
|
-
```html
|
|
11
|
-
<input type="email" required>
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
**Best practices:**
|
|
15
|
-
- Validate on blur or with short debounce
|
|
16
|
-
- Show clear error messages
|
|
17
|
-
- Don't be too strict (allow unusual but valid formats)
|
|
18
|
-
- Client-side validation ≠ deliverability
|
|
19
|
-
|
|
20
|
-
### Server-Side (Recommended)
|
|
21
|
-
|
|
22
|
-
Always validate server-side—client-side can be bypassed.
|
|
23
|
-
|
|
24
|
-
**Check:**
|
|
25
|
-
- Email format (RFC 5322)
|
|
26
|
-
- Domain exists (DNS lookup)
|
|
27
|
-
- Domain has MX records
|
|
28
|
-
- Optionally: disposable email detection
|
|
29
|
-
|
|
30
|
-
Recommended tools: https://resend.com/blog/best-email-verification-apis
|
|
31
|
-
|
|
32
|
-
## Double opt-in
|
|
33
|
-
|
|
34
|
-
Confirms address belongs to user and is deliverable.
|
|
35
|
-
|
|
36
|
-
### Process
|
|
37
|
-
|
|
38
|
-
1. User submits email
|
|
39
|
-
2. Send verification email with unique link/token
|
|
40
|
-
3. User clicks link
|
|
41
|
-
4. Mark as verified
|
|
42
|
-
5. Allow access/add to list
|
|
43
|
-
|
|
44
|
-
**Timing:** Send immediately, include expiration (24-48 hours), allow resend after 60 seconds, limit resend attempts (3/hour).
|
|
45
|
-
|
|
46
|
-
### Single vs Double Opt-In
|
|
47
|
-
|
|
48
|
-
| | Single Opt-In | Double Opt-In |
|
|
49
|
-
|--|---------------|---------------|
|
|
50
|
-
| **Process** | Add to list immediately | Require email confirmation first |
|
|
51
|
-
| **Pros** | Lower friction, faster growth | Verified addresses, better engagement, meets GDPR/CASL |
|
|
52
|
-
| **Cons** | Higher invalid rate, lower engagement | Some users don't confirm |
|
|
53
|
-
| **Use for** | Account creation, transactional | Marketing lists, newsletters |
|
|
54
|
-
|
|
55
|
-
**Recommendation:** Double opt-in for all marketing emails.
|
|
56
|
-
|
|
57
|
-
## Form Design
|
|
58
|
-
|
|
59
|
-
### Email Input
|
|
60
|
-
|
|
61
|
-
- Use `type="email"` for mobile keyboard
|
|
62
|
-
- Include placeholder ("you@example.com")
|
|
63
|
-
- Clear error messages ("Please enter a valid email address" not "Invalid")
|
|
64
|
-
|
|
65
|
-
### Consent Checkboxes (Marketing)
|
|
66
|
-
|
|
67
|
-
- **Unchecked by default** (required)
|
|
68
|
-
- Specific language about what they're signing up for
|
|
69
|
-
- Separate checkboxes for different email types
|
|
70
|
-
- Link to privacy policy
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
☐ Subscribe to our weekly newsletter with product updates
|
|
74
|
-
☐ Send me promotional offers and deals
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
**Don't:** Pre-check boxes, use vague language, hide in terms.
|
|
78
|
-
|
|
79
|
-
### Form Layout
|
|
80
|
-
|
|
81
|
-
- Keep simple and focused
|
|
82
|
-
- One primary action
|
|
83
|
-
- Clear value proposition
|
|
84
|
-
- Mobile-friendly
|
|
85
|
-
- Accessible (labels, ARIA)
|
|
86
|
-
|
|
87
|
-
## Error Handling
|
|
88
|
-
|
|
89
|
-
### Invalid Email
|
|
90
|
-
|
|
91
|
-
- Show clear error message
|
|
92
|
-
- Suggest corrections for common typos (@gmial.com → @gmail.com)
|
|
93
|
-
- Allow user to fix and resubmit
|
|
94
|
-
|
|
95
|
-
### Already Registered
|
|
96
|
-
|
|
97
|
-
- Accounts: "This email is already registered. [Sign in]"
|
|
98
|
-
- Marketing: "You're already subscribed! [Manage preferences]"
|
|
99
|
-
- Don't reveal if account exists (security)
|
|
100
|
-
|
|
101
|
-
### Rate Limiting
|
|
102
|
-
|
|
103
|
-
- Limit verification emails (3/hour per email)
|
|
104
|
-
- Rate limit form submissions
|
|
105
|
-
- Use CAPTCHA sparingly if needed
|
|
106
|
-
- Monitor for abuse patterns
|
|
107
|
-
|
|
108
|
-
## Verification Emails
|
|
109
|
-
|
|
110
|
-
**Content:**
|
|
111
|
-
- Clear purpose ("Verify your email address")
|
|
112
|
-
- Prominent verification button
|
|
113
|
-
- Expiration time
|
|
114
|
-
- Resend option
|
|
115
|
-
- "I didn't request this" notice
|
|
116
|
-
- Don't include OTP/2FA codes in subject line or preview text as it discourages opens
|
|
117
|
-
|
|
118
|
-
**Design:**
|
|
119
|
-
- Mobile-friendly
|
|
120
|
-
- Large, tappable button
|
|
121
|
-
- Clear call-to-action
|
|
122
|
-
|
|
123
|
-
See [Transactional Emails](./transactional-emails.md) for detailed email design guidance.
|
|
124
|
-
|
|
125
|
-
## Related
|
|
126
|
-
|
|
127
|
-
- [Compliance](./compliance.md) - Legal requirements for consent (GDPR, CASL)
|
|
128
|
-
- [Marketing Emails](./marketing-emails.md) - What happens after capture
|
|
129
|
-
- [Deliverability](./deliverability.md) - How validation improves sender reputation
|