guide

Email

Your app sends three kinds of email from your own domain: sign-in codes, notifications your server sends a person, and your answers from the Inbox. Replies land in the Inbox.

An order is ready, and your server tells the person:

import { gemmeinServer } from "@gemmein/sdk";
const server = gemmeinServer(process.env.GEMMEIN_SECRET_KEY);

await server.notify(order.ownerUserId, {
  subject: "Your poster is ready",
  text: "Your print-ready file is in your Library. Reply to this email if anything looks off.",
  key: `ready:${order.id}`,
});
// → { sent: true, id, threadId, replyRail: true }

What it is. All email your app sends leaves from your domain once it is verified on the Domains page with a purpose of email or both. Each email goes out as <word>@yourdomain (see Sender addresses), and a person who answers reaches your Inbox. Every email is plain text, carries a footer saying why it was sent, and is rate-capped.

What it does.

  • Sends a sign-in code to anyone who signs in.
  • Sends a plain-text notification to one of your app's own people when your server calls notify() or a relay runs email_person. The footer says why it was sent. Limits: 5 per person per day, 200 per app per hour.
  • Emails the buyer once per payment after a paid product purchase, Stripe or relay-sold: Your <product> is ready, with a link to your Library (see The purchase email).
  • Sends an account notice (kind: "account") outside the per-person cap.
  • Keeps every send in your Inbox as a conversation. Once receiving is verified, a reply lands in the same thread, labelled by the address they replied to. Your Inbox answers go out from support.
  • Sends at most once through retries when you give it a key.

What it does not.

  • Send notify() or email_person from a Gemmein address. Until your domain is verified, both are refused with 409 sender_domain_required: nothing leaves, no cap is spent, and the same key sends once you verify. Emails to real people go out from your own verified domain only; a test member’s email in Development needs no domain and lands in the test mailbox.
  • Address an email to a string. The recipient is a person id, so someone who never signed in cannot be emailed.
  • Send HTML, a template, a campaign or a no-reply. Every kind can be answered.
  • Touch the mailbox your domain already has. Receiving is on mail.yourdomain (for shop.example.com, mail.shop.example.com) unless you choose the domain itself.
  • Retry a send from a Gemmein address when your provider refuses yours. You get 502 send_failed and may retry.

Needs something else when.

  • You want a newsletter or an announcement to everyone at once. Broadcasts are not a Gemmein feature; each send goes to one person.
  • You want rich HTML. Send it from your own tool.
  • You want to email someone who has never signed in. They must sign in first: a secret key addresses people by id.
  • Your sign-in codes arrive as <App name> (via Gemmein). That is the one email Gemmein sends on your behalf before a domain is verified. Add the domain with a purpose of email and the sign-in code arrives from account.

Example. An order ships; your server tells the person (the code above).

In this section

The Inbox

Every send appears in the dashboard's Inbox as a conversation. Once receiving is verified, a person's reply lands in the same thread. Your answer goes out from support, so the whole exchange stays in one place for both of you.

Step-by-step: see the Inbox and Domains dashboard guides.

Was this page helpful?

Last updated