ShareOut runs without email on purpose — password sign-in is the default path and needs no mail provider at all. Email is what you add when you want invites, digests and one-time codes to reach an inbox instead of a log.
What is off without it
Section titled “What is off without it”| Feature | Without the EMAIL binding |
|---|---|
| One-time sign-in codes | Written to the Worker log. Usable for a solo operator, not for a team |
| Workspace invites | Not mailed — hit Copy link and send the join URL yourself (below) |
| Weekly digest, notifications | Not delivered |
| Artifact email, crew email delivery | Not delivered |
| Password sign-in | Unaffected. This is why an instance is usable with no email at all |
Sending
Section titled “Sending”The binding ships commented out in wrangler.toml. Uncomment it:
[[send_email]]name = "EMAIL"Set the sender and redeploy:
[vars]EMAIL_DEFAULT_FROM = "shareout@yourcompany.com"npm run deployBindings and vars are deploy-time — unlike secrets, they do not take effect until the redeploy lands.
Verify by reading the config back:
curl -sS "$ORIGIN/v1/admin/instance" -H "Authorization: Bearer $SHAREOUT_TOKEN" | jq '.email'binding: true and a default_from means sending is live. Then actually send one —
invite yourself to a workspace and watch it arrive.
Receiving
Section titled “Receiving”Artifacts and workspaces can accept inbound mail: a file inbox per workspace, and per-artifact addresses.
-
Enable Email Routing on your domain in Cloudflare.
-
Route a catch-all to this Worker. The Worker exports an
email()handler; Cloudflare delivers to it. -
Set the domain those addresses live on:
[vars]EMAIL_INBOX_DOMAIN = "inbox.yourcompany.com"Unset, it defaults to
inbox.<your instance host>.
The inbox subdomain is deliberately separate from your apex so a catch-all never swallows
real mailboxes like hello@yourcompany.com.
Once it is live, Admin → Settings shows the workspace’s inbox address. If that section is missing, the instance has no email binding — the address is hidden rather than shown as something that cannot receive.
Deliverability
Section titled “Deliverability”Whatever you send, you own the reputation of the sending domain:
- SPF, DKIM and DMARC on the sending domain — Cloudflare’s dashboard walks these
- a real, monitored
Fromaddress, notnoreply@ - ShareOut keeps a suppression list and honours unsubscribes per category; a bounce or a complaint stops future sends to that address on its own
Inviting people without email
Section titled “Inviting people without email”Invite as normal — Admin → Members, enter the address. The invite is created whether or not mail can go out. It then appears under Pending invites with two buttons:
- Copy link — mints a join URL and copies it. Send it however you like: Slack, chat, out loud. Nothing is emailed.
- Resend — mails the invite again. Does nothing useful without the
EMAILbinding.
The link looks like {origin}/invite/{code}. It is single-use, expires in 7 days, and only
works for the address it was issued to.
Copying a link never invalidates one you sent earlier — each press mints an additional claim, and every unclaimed one stays redeemable until it expires. Use Revoke (×) to kill all of them at once.
# Same thing over the API — notify:false mints a link without sending mailcurl -sS -X POST "$ORIGIN/v1/workspaces/$WORKSPACE_ID/invites/$INVITE_ID/resend" \ -H "Authorization: Bearer $SHAREOUT_TOKEN" -H 'Content-Type: application/json' \ -d '{"notify":false}' | jq -r '.inviteUrl'Running deliberately without email
Section titled “Running deliberately without email”A private instance for a small team is a legitimate no-email configuration:
- people sign in with email and password (
/setupfor the first admin) - invites work through Copy link, above — no mail provider needed
- one-time codes still work if you can read the Worker log
/v1/admin/instancelists theEMAIL bindinggap so it stays a visible decision rather than a thing you forgot
