# Mail

> Give WebSpaces mailboxes with docker-mailserver or mailcow on a FeatherQuilld web node, add Roundcube webmail, or connect an external mail provider.

Source: https://featherpanel.com/docs/quilld/mail/

FeatherQuilld runs one mail stack per web node and gives the WebSpaces on that node mailboxes, aliases, forwarding,
autoresponders, mailing lists and spam settings. Owners manage them on the WebSpace's Email page, which also shows the
DNS records to publish and the client settings.

## Choosing a backend

| Backend | `system.mail.backend` | What it is |
|---------|-----------------------|------------|
| docker-mailserver (default) | `docker-mailserver` (also `docker`, `docker-mail-server`, `dms`) | One container, managed through its `setup` command |
| mailcow: dockerized | `mailcow` (also `mailcow-dockerized`) | The full mailcow stack, managed through mailcow's API, on this node or another host |

An unknown value is rejected with an error instead of falling back to the other stack. The mail API is the same for
both, so the panel does not care which one answers.

## docker-mailserver on the node

1. Open the web node's **Package manager** and install **Mail server (docker-mailserver)**. Docker must be installed.
   Quilld writes a compose file under `/var/lib/featherquilld/mail` (or `system.mail.data_path`), publishes ports `25`,
   `587` and `993`, and starts the `featherquilld-mailserver` container. The panel registers a mail host for the node.
2. Set `system.mail.hostname` (for example `mail.example.com`) through the config overrides if the machine's hostname
   is not the name your MX records should use.
3. Open `25`, `587` and `993` on the firewall and add a PTR record for the mail hostname at your server provider.

## mailcow on the node

1. Install **Mail server (mailcow: dockerized)** from the Package manager. It needs Docker with the compose plugin,
   `git`, `curl` and `tar`, and about 4 GiB of free memory (below 2.5 GiB ClamAV is turned off). Quilld runs mailcow's
   own config generator, binds the mailcow UI to loopback ports `8080` and `8443`, turns off mailcow's ACME client and
   writes an API key to `feather-api-key` next to the compose file.
2. Switch the backend in the web node's **Advanced Config Overrides (JSON)**:

   ```json
   { "system": { "mail": { "backend": "mailcow" } } }
   ```

3. Register the mail host on the admin **Mail** page if the node is listed under Finish mail setup.

## mailcow on another host

If you already run mailcow somewhere else, point the node at it:

```json
{
  "system": {
    "mail": {
      "backend": "mailcow",
      "hostname": "mail.example.com",
      "mailcow": {
        "url": "https://mail.other-host.example.com",
        "api_key": "<write API key>",
        "mail_host": "mail.other-host.example.com"
      }
    }
  }
}
```

mailcow must allow the node's IP in its API allow list (`API_ALLOW_FROM`). Everything works remotely except
autoresponders, which need shell access to the mailcow host. Set `mail.hostname` or `mailcow.mail_host`, or the DNS
hints would publish an MX name that does not exist.

## Webmail

**Webmail (Roundcube)** in the Package manager needs a mail server package first. It runs Roundcube on a loopback port
and the node's reverse proxy publishes it over HTTPS on `system.mail.webmail_hostname`. Users can open webmail from the
Email page without typing their password again.

## DNS records

For each domain the node computes the records to publish: `MX` to the mail host, an SPF `TXT`
(`v=spf1 mx a:<mailhost> -all`), the DKIM key at `<selector>._domainkey` (selector `mail` by default) and `_dmarc`.
Autodiscover, autoconfig and SRV records are optional but let mail clients set themselves up. The WebSpace Email page
shows them.

## External mail providers

The admin **Mail** page can also add a mail host that FeatherQuilld does not run:

- **External (manual mailboxes)**. Enter the mail hostname and the IMAP and SMTP hosts. The panel only stores the
  mailboxes; you create them on the provider yourself.
- **Webhook API**. The panel POSTs each mailbox action as JSON to your provision URL, with the API key as a Bearer
  token. You need your own bridge on the other side.

## Settings

| Key | Default | Meaning |
|-----|---------|---------|
| `system.mail.enabled` | `true` | Turn the mail API on or off |
| `system.mail.backend` | `docker-mailserver` | Mail stack |
| `system.mail.hostname` | empty | Public mail hostname for MX and SPF |
| `system.mail.webmail_hostname` | empty | Hostname for Roundcube |
| `system.mail.data_path` | empty | Mail data folder, defaults to `<root>/mail` |
| `system.mail.smtp_port`, `imap_port` | `587`, `993` | Client ports |
| `system.mail.dkim_selector` | `mail` | DKIM selector |
| `system.mail.mailcow.*` | see the [config reference](https://featherpanel.com/docs/quilld/config-reference) | mailcow path, URL, API key, ports and limits |

`GET /api/mail/probe` on the node (with the node token) reports the backend, whether the stack runs and whether the mail
ports are open. Check it before you publish DNS.

## Frequently asked questions

### I installed the mailcow package but the node still uses docker-mailserver.

Installing the package does not switch the backend. Add {"system":{"mail":{"backend":"mailcow"}}} to the web node's Advanced Config Overrides.

### Mailboxes are created but no mail arrives.

Check that inbound port 25 reaches the node, that the MX record points at a name that resolves, and that the sending IP has a PTR record. Many VPS providers block port 25.
