@kurtbruns/kestrel 1.16.0 → 1.18.0
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/.dev.vars.example +10 -0
- package/CHANGELOG.md +38 -1
- package/bin/kestrel.mjs +1 -1
- package/cli/dev.mjs +3 -3
- package/cli/init.mjs +98 -4
- package/dist/public/dashboard/app.js +288 -286
- package/dist/public/dashboard/app.js.map +4 -4
- package/dist/public/dashboard/index.html +6 -3
- package/dist/public/dashboard/styles.css +10 -0
- package/dist/worker/index.js +5607 -5096
- package/docs/README.md +5 -3
- package/docs/get-started/02-deploy.md +25 -23
- package/docs/get-started/03-access.md +13 -7
- package/docs/get-started/04-aws-account.md +68 -0
- package/docs/get-started/05-ses.md +307 -0
- package/docs/get-started/06-production-access.md +64 -0
- package/docs/get-started/07-verify.md +121 -0
- package/docs/get-started/{06-go-live.md → 08-go-live.md} +2 -2
- package/docs/guides/01-allow-claude.md +2 -2
- package/docs/guides/02-automate.md +1 -1
- package/docs/guides/03-notifications.md +4 -4
- package/docs/guides/07-upgrade.md +4 -4
- package/docs/guides/09-as-your-list-grows.md +8 -18
- package/docs/publishing/02-sending-rules.md +3 -3
- package/docs/publishing/03-name-your-publication.md +3 -1
- package/docs/publishing/04-write-a-post.md +1 -1
- package/docs/publishing/06-troubleshooting.md +33 -68
- package/docs/publishing/09-share-your-subscribe-link.md +1 -1
- package/docs/publishing/10-check-your-setup.md +4 -2
- package/docs/reference/01-configuration.md +17 -13
- package/docs/reference/02-sending-domain-dns.md +5 -5
- package/migrations/0015_provider_account.sql +18 -0
- package/package.json +1 -1
- package/template/claude/CLAUDE.md +3 -3
- package/template/wrangler.jsonc +1 -1
- package/docs/get-started/04-ses.md +0 -343
- package/docs/get-started/05-verify.md +0 -135
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
# Verify it works
|
|
2
|
-
|
|
3
|
-
Some things only show up with real email: whether inboxes trust your mail, how it looks in a real mail client, and whether bounces and unsubscribes come back to the app. Check them now, while the list is empty and every email goes only to you.
|
|
4
|
-
|
|
5
|
-
In this guide, you send yourself a test email, reply to it, and check that it passes authentication. Then you set up notifications, send a real post to yourself as a subscriber, and unsubscribe. Finally, you check that bounces and complaints reach the app, read the app's logs, check that SES can send to anyone, and clean up the test subscribers.
|
|
6
|
-
|
|
7
|
-
## Before you begin
|
|
8
|
-
|
|
9
|
-
- Two email addresses you own, such as a personal address and a work address. Some steps use both. While your SES account is in the sandbox, verify both in SES first, as [Connect Amazon SES](04-ses.md#5-request-production-access) describes.
|
|
10
|
-
- A Gmail address, or another mail client that shows a message's original source and an **Unsubscribe** button.
|
|
11
|
-
|
|
12
|
-
## 1. Send yourself a test email
|
|
13
|
-
|
|
14
|
-
A test email goes through the same code as a real send. If the test looks right, the real send looks the same.
|
|
15
|
-
|
|
16
|
-
1. In the editor at `https://newsletter.example.com/dashboard/`, create a post with a subject, a short body, and an image.
|
|
17
|
-
|
|
18
|
-
1. Select **Send test email**, enter your address, and send it.
|
|
19
|
-
|
|
20
|
-
1. Open the email. It should arrive in your inbox, not in spam. The image loads and the subject reads as you wrote it. Its **View in browser** link opens "Nothing here yet" until the post goes out, and its unsubscribe link opens the page a subscriber sees, marked as a test and showing a sample address. Its button walks through to the confirmation, but a test email unsubscribes no one. Section 5 unsubscribes for real.
|
|
21
|
-
|
|
22
|
-
1. Reply to it, as a reader would. Reply from an address other than the inbox your From address forwards to, such as your second address. Gmail doesn't show you a message you sent when it comes back to you. Send that address a test email too if you need one. The reply arrives in the inbox you chose in [Connect Amazon SES](04-ses.md#3-receive-replies-at-your-from-address). The app can't see your forwarding, so this is the only proof that readers can reach the publisher. If the reply bounces, check the routing rule and the destination address there.
|
|
23
|
-
|
|
24
|
-
## 2. Check that it passes authentication
|
|
25
|
-
|
|
26
|
-
Inboxes trust mail that passes DKIM and DMARC for the domain it's from. Passing both is the best single sign that your mail reaches the inbox.
|
|
27
|
-
|
|
28
|
-
1. Open the test email's original source. In Gmail, open the message's menu and select **Show original**.
|
|
29
|
-
|
|
30
|
-
1. Find the `Authentication-Results` header. It shows:
|
|
31
|
-
|
|
32
|
-
- `dkim=pass` for `send.example.com`
|
|
33
|
-
- `dmarc=pass` for `send.example.com`
|
|
34
|
-
- `spf=pass`, for a hostname under `send.example.com`
|
|
35
|
-
|
|
36
|
-
With no custom MAIL FROM domain, SPF passes for `amazonses.com` instead. That's expected, and DMARC still passes.
|
|
37
|
-
|
|
38
|
-
If a check fails, compare your DNS records with the ones in [Connect Amazon SES](04-ses.md#1-verify-your-sending-hostname). [Sending-domain DNS](../reference/02-sending-domain-dns.md#verify-alignment) explains each result.
|
|
39
|
-
|
|
40
|
-
## 3. Set up notifications
|
|
41
|
-
|
|
42
|
-
Kestrel emails the notifications address when a send finishes, and right away when one runs into a problem. Notifications go through your email provider. To send them through Cloudflare instead, see [Notifications through Cloudflare's email](../guides/03-notifications.md).
|
|
43
|
-
|
|
44
|
-
1. In the editor, open **Settings → Notifications**.
|
|
45
|
-
|
|
46
|
-
1. Enter your address, and select **Save**.
|
|
47
|
-
|
|
48
|
-
1. Select **Send a test notification**. It arrives at that address.
|
|
49
|
-
|
|
50
|
-
Use your own address to test. If you're not the publisher, they set theirs in [Check your setup](../publishing/10-check-your-setup.md).
|
|
51
|
-
|
|
52
|
-
## 4. Send a real post to yourself
|
|
53
|
-
|
|
54
|
-
This is a real send, to a list of one. It proves the whole path: subscribing, confirming, scheduling, and sending.
|
|
55
|
-
|
|
56
|
-
1. Open `https://newsletter.example.com/subscribe`, and subscribe with your second address.
|
|
57
|
-
|
|
58
|
-
1. Open the confirmation email, follow its link, and select **Confirm**. In the editor, **Subscribers** shows the address as **Confirmed**.
|
|
59
|
-
|
|
60
|
-
1. Open the post, select **Schedule**, and then **Send now**. Every send waits at least five minutes before it goes out, so you can cancel a mistake.
|
|
61
|
-
|
|
62
|
-
1. Uncheck **Include in archive**. The post still goes to subscribers, but it's sent as email only: it isn't in the public archive or on the home page. That way the test proves the send without becoming the publication's first archived post, and the dashboard keeps its **Finish setting up** steps for the publisher.
|
|
63
|
-
|
|
64
|
-
1. Cancel the send, to see that canceling stops it. Then select **Schedule** and **Send now** again, check that **Include in archive** is still unchecked, and let it go.
|
|
65
|
-
|
|
66
|
-
1. When the send finishes, the post arrives at your second address. A notification arrives at your first, with the subject `Sent:` and the post's title.
|
|
67
|
-
|
|
68
|
-
If you verified this instance before Email only existed, the test post is in the archive. Open it under **Sent**, and select **Remove from archive…**.
|
|
69
|
-
|
|
70
|
-
## 5. Unsubscribe
|
|
71
|
-
|
|
72
|
-
Every email carries an unsubscribe link, and a header that lets mail clients show their own **Unsubscribe** button. Both work in one step, with no login.
|
|
73
|
-
|
|
74
|
-
1. Open the post from section 4 in your mail client. It shows an **Unsubscribe** button next to the sender.
|
|
75
|
-
|
|
76
|
-
1. Select it. In the editor, **Subscribers** shows the address as **Unsubscribed**, and later sends leave it out.
|
|
77
|
-
|
|
78
|
-
## 6. Check that bounces and complaints come back
|
|
79
|
-
|
|
80
|
-
When an address bounces or marks your mail as spam, SES tells the app through SNS. The app then stops mailing that address: a bounce suppresses it, and a complaint unsubscribes it. SES has test addresses that act out each case without reaching a real person, and the sandbox lets you mail them.
|
|
81
|
-
|
|
82
|
-
1. Open `https://newsletter.example.com/subscribe`, and subscribe each test address:
|
|
83
|
-
|
|
84
|
-
- `bounce@simulator.amazonses.com`, which bounces
|
|
85
|
-
- `complaint@simulator.amazonses.com`, which marks your mail as spam
|
|
86
|
-
|
|
87
|
-
Each one gets a confirmation email, which bounces or is marked as spam.
|
|
88
|
-
|
|
89
|
-
1. In the editor, **Subscribers** lists the bounce address as **Pending** with a **bounced** flag, and the complaint address as **Unsubscribed**. Open its row: its page says it left by a complaint. The app mails neither again.
|
|
90
|
-
|
|
91
|
-
If the bounce address has no flag, or the complaint address is still pending, SES's events aren't reaching the app. Check the configuration set and the SNS subscription in [Connect Amazon SES](04-ses.md#6-send-bounces-and-complaints-to-sns).
|
|
92
|
-
|
|
93
|
-
## 7. Read the logs
|
|
94
|
-
|
|
95
|
-
The app writes a log line for each thing it does, and Cloudflare keeps them for a few days, depending on your plan. Nothing else tells you if the once-a-minute schedule that sends posts stops, so it's worth knowing where to look.
|
|
96
|
-
|
|
97
|
-
1. In the Cloudflare dashboard, go to **Workers & Pages**, select `kestrel-production`, and select **Observability**.
|
|
98
|
-
|
|
99
|
-
1. Filter on `event` equal to `sweep.tick`. A line arrives every minute.
|
|
100
|
-
|
|
101
|
-
1. Filter on `event` equal to `send.completed`. Your send from section 4 is there.
|
|
102
|
-
|
|
103
|
-
1. Filter on `event` equal to `send.scheduled`. Your two sends from section 4 are there, each with `act` equal to `send_now`, `principal` equal to `human`, and `client` equal to `editor`, and `send.canceled` shows the one you canceled. Each line that records an action, such as `send.canceled` or `import.committed`, says who took it the same way: `principal` is `human` for a person or `service` for a service token, and `client` names the program a person used. A service token's lines have no `client`, and neither does a person's through a program that doesn't name itself.
|
|
104
|
-
|
|
105
|
-
1. Filter on `principal` equal to `service` to see what automation changed. On a new instance it finds nothing. Filter on `client` equal to `claude` or `claude-code` to see what Claude changed.
|
|
106
|
-
|
|
107
|
-
1. Filter on `level` equal to `error`. A healthy instance shows nothing.
|
|
108
|
-
|
|
109
|
-
If you search a long time range, Cloudflare may show only a sample of the matching lines. To follow one send, narrow the range to a few hours and filter on its `sendId`. On the Free plan, Cloudflare stops keeping logs for the rest of the day once the day's allowance is used up, so a very large send can leave the rest of that day unlogged. [Cloudflare's pricing page](https://developers.cloudflare.com/observability/pricing/) has the current limits and how long each plan keeps logs.
|
|
110
|
-
|
|
111
|
-
## 8. Check that SES can send to anyone
|
|
112
|
-
|
|
113
|
-
[Connect Amazon SES](04-ses.md#5-request-production-access) asked AWS for production access. Until AWS grants it, the sandbox mails only your verified addresses, so check it before you go live.
|
|
114
|
-
|
|
115
|
-
1. In SES, open the **Account dashboard** in the region the app sends from. It no longer says your account is in the sandbox, and it shows your daily quota and maximum send rate.
|
|
116
|
-
|
|
117
|
-
1. Check that `SES_MAX_SEND_RATE` in `wrangler.jsonc` matches that rate, and that you deployed after setting it, as [Connect Amazon SES](04-ses.md#8-set-the-provider-and-deploy) describes.
|
|
118
|
-
|
|
119
|
-
If the dashboard still says sandbox, AWS hasn't answered yet. Every other section works in the sandbox, so come back to this one when it does.
|
|
120
|
-
|
|
121
|
-
## 9. Clean up the test subscribers
|
|
122
|
-
|
|
123
|
-
The checks leave test addresses on the list. Erase them, so the publisher starts with only real readers.
|
|
124
|
-
|
|
125
|
-
1. In the editor, open **Subscribers**.
|
|
126
|
-
|
|
127
|
-
1. Erase `bounce@simulator.amazonses.com` and `complaint@simulator.amazonses.com`. Open each one's menu (⋯), and select **Erase**.
|
|
128
|
-
|
|
129
|
-
1. Erase your second address too, if it won't be a reader.
|
|
130
|
-
|
|
131
|
-
Erasing keeps only the address, so it's never mailed again, but the person can subscribe again through the subscribe page. Erasing your own address doesn't lock you out.
|
|
132
|
-
|
|
133
|
-
When every section gives the result it describes, your instance is ready for subscribers.
|
|
134
|
-
|
|
135
|
-
Next, [go live](06-go-live.md).
|