Skip to content

Mail

Set up a sending domain

Register a domain your product owns, publish the DNS records Lessly Mail returns, and get it to verified so your confirmations and receipts can leave from it.

Lessly Mail sends only from domains you control. You register one, publish the DNS records Mail returns, and Mail re-checks those records until the domain is verified — from then on you can send from any address at it.

Everything on this page belongs to one product. A domain registered in one product is invisible to every other product.

Choose what to register

A product may register a domain only underneath a domain it already owns: the apex itself, or any subdomain of it. A name that is neither is rejected with 422 and the error name domain_not_governed.

RegisterUse when
A dedicated subdomain, e.g. mail.example.comYour product sends system email(Recommended) — keeps your product’s mail apart from the mail your team sends by hand
The apex, e.g. example.comYou need messages to come from the bare domainPuts your product’s mail DNS in the same zone as everything else you publish

Register the domain

  1. List the apexes you may use. An agent calls mail_domain_allowed_list; over REST it is GET /mail/domains/allowed on the Mail API.

    [
      {
        "domainId": "d3f1…",
        "domain": "example.com",
        "mode": "external",
        "extensionCount": 2
      }
    ]
  2. Register it. An agent calls mail_domain_create; over REST, POST /mail/domains. name is required. region decides where the domain’s sending identity lives, defaults to eu-north-1, and is fixed at creation — to move a domain to another region, delete it and register it again.

    { "name": "mail.example.com", "region": "eu-north-1" }

    The response is the domain, status set to pending, with the records to publish:

    {
      "id": "8e2c…",
      "name": "mail.example.com",
      "region": "eu-north-1",
      "status": "pending",
      "records": [
        {
          "type": "CNAME",
          "name": "abc123._domainkey.mail.example.com",
          "value": "<the signing host Mail returns>",
          "purpose": "dkim",
          "required": true
        },
        {
          "type": "TXT",
          "name": "_dmarc.mail.example.com",
          "value": "v=DMARC1; p=none;",
          "purpose": "dmarc",
          "required": false
        }
      ],
      "verificationStartedAt": "2026-08-02T09:00:00.000Z",
      "verifiedAt": null,
      "active": false
    }
  3. Publish every record in records at your DNS provider, exactly as given, values included. Keep the domain’s id — you need it to ask for a check.

  4. Wait, or check now. An agent calls mail_domain_verify; over REST, POST /mail/domains/:id/verify. The reply adds a resolved flag to each record, so you can see which ones Mail can read yet. resolved appears only in that reply — GET /mail/domains/:id returns the records without it.

Two things stop a registration. The name is already registered in that region, by any product — 409. Or the host is already claimed elsewhere in your product — 409 with the error code host_taken, naming what holds it. Neither leaves anything behind: a failed create is rolled back and the same name can be retried.

The DNS records

Every record carries a type, the name to create it at, its value, a purpose and whether it is required. MX records also carry a priority.

PurposeRecordRequiredWhat it does
dkimOne CNAME per signing key, at <token>._domainkey.<your-domain>YesLets Mail sign your messages, and lets receiving servers confirm the signature really comes from your domain. Without them a domain never verifies.
dmarcA TXT at _dmarc.<your-domain>, value v=DMARC1; p=none;NoTells receiving servers what to do with mail claiming to be from your domain but not signed by it. p=none only asks them to report, so it is safe to publish on day one. Mail does not check it, but publishing it is what lets you tighten the policy later.
spf, return-path-mxA TXT and an MX on a send. subdomainYes, where presentCarry the address receiving servers return bounces to. A domain registered today does not list them; if yours does, they must stay published.

Statuses

StatusMeaning
not_startedRegistered, not yet checked.
pendingBeing checked. The required records are not all readable yet.
verifiedAll required records are in place. The domain can send.
temporary_failureA check failed in a way that may clear by itself. Mail keeps trying.
failedVerification will not complete on its own.

A domain also carries active, which is true only when the domain is verified and its claim on the host is live. active is the honest answer to “can I send from this domain right now”.

Sending from a domain that is not verified fails with 422 and the error name invalid_from_address. Sending from a domain that is not registered in your product fails with 404.

When verification does not complete

Verification starts by itself the moment the domain is created, and Mail re-checks every unsettled domain once a minute. How long it takes is decided by your DNS provider, not by Mail: most domains verify within a few minutes of the records going live, and a provider with a long TTL can take several hours. Mail keeps trying for 72 hours from verificationStartedAt; past that the domain becomes failed.

CauseWhat to do
The records are not published yetAsk for an immediate check and read resolved on each record. Every record with required: true must be true.
A record was alteredSome providers append the zone name to a record you enter, turning abc123._domainkey.mail.example.com into abc123._domainkey.mail.example.com.example.com. Compare what you published against name, character for character.
The value was trimmedDKIM values end in a trailing dot. Publish the value exactly as Mail returns it.
DNS has not propagatedNothing to do but wait. Mail re-checks every minute on its own.
temporary_failureA lookup failed in a way that may clear. Mail keeps checking, and the domain moves on by itself once the records answer.

A failed domain does not resume. Fix the records, then delete the domain and register it again — a fresh registration restarts the 72-hour window.

Change how the domain sends

An agent calls mail_domain_update; over REST, PATCH /mail/domains/:id. Send only the fields you want to change. name and region are fixed at creation and cannot be patched.

FieldValuesDefaultWhat it does
openTrackingtrue / falsefalseAdds a tracking pixel to HTML bodies so opens are reported.
clickTrackingtrue / falsefalseRewrites links so clicks are reported.
trackingSubdomaina host name or nullnullThe host tracked links and the pixel are served from.
tlsopportunistic / enforcedopportunisticenforced refuses to deliver to a server that will not encrypt the connection.

Both tracking settings are off by default, which is usually where they stay for confirmations, receipts and access-recovery mail.

To read domains back: mail_domain_list or GET /mail/domains for every domain in the product, and mail_domain_get or GET /mail/domains/:id for one with its records. An id that belongs to another product is a 404.

Remove a domain

An agent calls mail_domain_delete; over REST, DELETE /mail/domains/:id. The response is { "deleted": true }. The domain stops being able to send at once and its claim on the host is released, so the name is free to register again — in this product or another. Emails already sent from the domain keep their history.

Next steps

Was this page helpful?
Esc

Start typing to search the docs.

navigateselect