Email
Candydati needs a real email provider. Account confirmation, password reset, invitations, application receipts and every message to candidates are emails: if they do not arrive, people cannot sign in and candidates do not get their answer. That is why, until email works, an instance refuses invitations, publishing and applications.
You can set it on the server (below) or, if the server leaves it empty, from the app: Settings, Email, choose SMTP or Resend, fill in the sending domain and press Save and send a test email. Only the first owner (or an INSTANCE_ADMIN_EMAILS address) can change it, and nothing is saved unless the test email went through.
Two options, chosen during the installation (CANDYDATI_EMAIL_PROVIDER):
| Option | When it fits |
|---|---|
| SMTP | you already have a mailbox or a sending service: the company mailbox (Google Workspace, Microsoft 365, Aruba, Register.it, OVH...) or any transactional provider that offers SMTP |
| Resend | you want a transactional provider with an API, domain verification and inbound email in one place |
To change provider later, run candydati config and edit the EMAIL_*, SMTP_* or RESEND_API_KEY lines.
SMTP
The installer asks for:
| Field | Variable | Example |
|---|---|---|
| Host | SMTP_HOST | the SMTP server of your provider |
| Port | SMTP_PORT | 587 (STARTTLS) or 465 (TLS) |
| Security | SMTP_SECURE | true for port 465, false for 587 |
| User | SMTP_USER | usually the full mailbox address |
| Password | SMTP_PASSWORD | the mailbox password or an app password |
| Sender domain | EMAIL_DOMAIN | the domain after the @ of the sender |
Emails are sent from noreply@<EMAIL_DOMAIN> (EMAIL_FROM_LOCAL changes the part before the @). The mailbox you authenticate with must be allowed to send as that address: with most providers, use an address of the same domain.
Host, port and security are on the settings page of your provider ("SMTP", "outgoing mail" or "mail client settings"). Some notes:
- Google Workspace: with 2-step verification on, sign in with an app password generated in the Google account, not the normal password; or use the SMTP relay service from the Workspace admin console. Workspace has daily sending limits per user: check them against the number of candidates you write to.
- Microsoft 365: SMTP AUTH must be enabled for the mailbox (it is off by default in many tenants); the admin turns it on in the Microsoft 365 admin center.
- Aruba, Register.it, OVH and other hosting providers: the mailbox's outgoing server, port and security are in the provider's guide to configuring a mail client. Use the same values.
A company mailbox is fine for a small team. If you write to many candidates every day, a transactional provider keeps those messages away from the reputation of your normal company mail.
Resend
- Create an account on resend.com and an API key with sending permission.
- Add and verify your sender domain in Resend, preferably a dedicated subdomain such as
mail.example.com: Resend shows the DNS records to publish. - During the installation choose
resend, paste the key (RESEND_API_KEY) and set the same sender domain (EMAIL_DOMAIN).
With Resend, each organization can also send from an address of its own domain: in the app, under Settings, Email, it enters the address, and the page shows the DNS records to publish and their status (pending, verified, failed). Until the domain is verified, emails go out from the instance address. With SMTP, emails always go out from the instance address.
Deliverability: SPF, DKIM, DMARC
Whatever the provider, mail arrives in the inbox only if the sending domain is set up. At your DNS provider:
- SPF: one TXT record on the sending domain that includes the provider (
v=spf1 include:<provider> ~all). A domain has a single SPF record: if one exists, add the provider to it. - DKIM: the records shown by the domain verification (Resend) or generated by your SMTP provider.
- DMARC: a
_dmarcTXT record. Start withv=DMARC1; p=none; rua=mailto:dmarc@your-domain, read the reports for a few weeks, then move toquarantine. - Use a dedicated subdomain (
mail.example.com) for transactional mail, so a reputation problem never touches the company mail.
If you send through your company mailbox, SPF and DKIM for that domain are usually already in place.
After every DNS change, send a test to your own inbox or to a checker such as mail-tester.
Replies from candidates (inbound email)
Messages to candidates are sent with a reply address reply+<token>@<EMAIL_INBOUND_DOMAIN>. When a candidate answers, the reply is attached to their record in the app. This needs a provider that receives mail for that domain and forwards it to Candydati:
- Choose a domain for replies, for example
reply.example.com, and setEMAIL_INBOUND_DOMAINwithcandydati config. - Point its MX record to the inbound host of your provider.
- Configure the provider to call your instance for each received message:
- Resend:
https://<your domain>/api/v1/inbound/email/resend, with the webhook signing secret of Resend (whsec_...) asINBOUND_WEBHOOK_SECRET. - Any other provider that can post the raw message:
https://<your domain>/api/v1/inbound/email/raw, signed with HMAC-SHA256 of<timestamp>.<body>usingINBOUND_WEBHOOK_SECRET, the signature in thex-candydati-signatureheader and the unix timestamp in seconds inx-candydati-timestamp. A timestamp older than 5 minutes, or more than 1 minute ahead, is refused.
- Resend:
Every message carries that reply address, so set this up before you write to candidates: without it, their replies reach nobody. A plain SMTP mailbox cannot call a webhook: with SMTP for sending, use a provider that offers inbound email (Resend does) for the reply domain.