Sending mail to other servers, and DKIM
Mail your users send through submission (port 465 or 587) to addresses on other domains is signed with the sending domain's DKIM key and put in an outbound queue. A worker inside corpsuited delivers it to the recipient domain's mail servers. Mail for addresses on your own server is delivered at once, as before. Port 25 only ever accepts mail for hosted domains; it never relays.
What a domain needs in DNS
GET /v1/tenants/{id}/domains/{domain}/dns (or GET /v1/shared-domains/{domain}/dns for a shared domain) lists every record. For sending, three matter:
| Record | Name | Why |
|---|---|---|
| TXT (SPF) | the domain | says this server may send for the domain |
| TXT (DKIM) | <selector>._domainkey.<domain> | the public key receivers check signatures with |
| TXT (DMARC) | _dmarc.<domain> | tells receivers what to do when SPF and DKIM do not match |
Every new domain gets a 2048-bit RSA key the moment it is created. Domains that existed before DKIM, or whose key could not be made, get one when the server starts. Until the DKIM record is published, receivers cannot check the signature, so publish it before sending much mail. The record is longer than one DNS string can hold, so the checklist shows it split into quoted strings; see Long TXT records for what to paste where.
The server's own host name (CORPSUITE_HOSTNAME) is used in EHLO. Give it an A and AAAA record and set the PTR (reverse DNS) of the server's addresses to the same name; many receivers refuse mail without it. With a pool of outbound addresses, each address says its own name instead: see Outbound IP addresses.
Rotating a DKIM key
POST .../dkimwith{"algorithm": "rsa"}creates a pending key. It does not sign yet.- Publish its TXT record (
dnsName,dnsValuein the response, also in the DNS listing). - Wait for DNS to update; a day is safe.
POST .../dkim/{selector}/activate. The new key signs from now on and the old one becomes retired.- After a few days, when no mail signed with the old key is still in transit,
DELETE .../dkim/{old selector}and remove its record.
The active key cannot be deleted. Ed25519 keys (RFC 8463) can be created, but not every receiver checks them yet, so keep an RSA key active.
Where the private keys are
Private keys are encrypted (AES-256-GCM) before they go into the database, with the key in CORPSUITE_KEY_FILE (/var/lib/corpsuite/master.key in the installed configuration). The server creates that file, readable only by the service user, on first start, and refuses to start if others can read it. Back it up with the database: without it the DKIM keys cannot be read, and every domain needs a new key and new DNS records.
Mail between users here stays here
Mail to any address on a domain hosted on this server, in any tenant and on shared domains, is filed directly in the recipient's mailbox. It never goes out by DNS and MX, whatever the domain's MX records say, so it does not leave the server.
- An address that does not exist on a hosted domain is refused at once ("No such user here"); it is never relayed elsewhere.
- If the server cannot tell whether a domain is hosted (say the database is briefly unavailable), the sender gets "try again later" rather than the mail being sent out.
- Mail already waiting in the outbound queue for a domain that is then added here (a customer moving their domain over) is filed here too when its turn comes, with a
Received: from outbound-queueline, and never sent to the old provider.
Vacation replies and filter redirects follow the same rule.
Delivery, retries and failure notices
- The worker looks up the recipient domain's MX records and tries them in order of preference. A domain without MX records is tried directly; a domain with a "null MX" (RFC 7505) does not accept mail, and the sender is told at once.
- TLS is used whenever the receiving server offers STARTTLS. Without an MTA-STS policy the certificate is not required to be valid, which protects against eavesdropping but not against an attacker who can redirect the connection. Domains with an MTA-STS policy in enforce mode only get mail over TLS with a valid certificate, to the MX hosts the policy names; see MTA-STS.
- A temporary refusal (a 4xx reply, a connection that fails, greylisting) is retried after 1, 5, 15 and 30 minutes, 1 and 2 hours, then every 4 hours. After five days the recipient fails for good.
- A permanent refusal (a 5xx reply) fails the recipient at once.
- When a recipient fails, the sender gets a "Undelivered mail returned to sender" notice in their inbox, one per destination domain, naming each failed address and the reason the other server gave.
- The server never connects to loopback, private or link-local addresses, even if a domain's MX record points there.
GET /v1/tenants/{id}/queue shows what is still waiting, with the attempts so far and the last error.
Limits
Sending limits from the tenant's plan (recipients per message, per hour and per day) apply to every recipient, on your server or elsewhere. See Plans, free mail and signup.
Not yet
- Outbound IP pools (a unique IPv6 per domain, dedicated IPv4 for paid tiers): the server sends from its default address for now.
- DANE, TLS-RPT, ARC.
- A copy in the sender's Sent folder is up to the mail app, as with any submission server.