← Back home

2026.10 / domain routing 072

Docker Mailserver “mail for domain loops back to myself”

Postfix defers or bounces a message with mail for example.com loops back to myself. DNS says this server is the best mail exchanger for the domain, so Postfix connects back to itself. The receiving Postfix instance does not classify that domain as one it should deliver locally, host virtually, or relay deliberately. Sending it out again would repeat the same route, so Postfix stops the loop.

In Docker Mailserver, the most common causes are a mailbox domain that never reached the active account maps, a conflict between the server hostname and a hosted mail domain, or MX records that still point at this server even though mail is meant to live elsewhere.

Do not silence the error with a broad relay rule or a transport map pointing back to the MX. First decide whether this Docker Mailserver is the final destination for the domain, then make DNS and the effective Postfix address class agree.

What this error actually means

Postfix divides recipient domains into address classes. The important ones here are:

Address classTypical roleRelevant setting
LocalPostfix’s own host identities and traditional system usersmydestination
Virtual mailboxHosted mail domains with non-system mailboxesvirtual_mailbox_domains
Virtual aliasHosted domains whose addresses redirect elsewherevirtual_alias_domains
RelayDomains this server forwards for intentionallyrelay_domains
DefaultRemote Internet destinations for authorised sendersNormal SMTP routing

Postfix’s official virtual-domain guide explicitly says that omitting a hosted domain from its virtual domain class can produce either Relay access denied or mail for example.com loops back to myself. The error is therefore about domain ownership and routing. It is not, by itself, a DNS timeout, password failure, DKIM failure, or missing TLS certificate.

1. Preserve the exact queue evidence

Capture a narrow log window around one current attempt:

docker compose logs --since 10m mailserver

Privately record the queue ID, envelope recipient domain, relay target, and exact diagnostic. A representative line may contain:

status=bounced (mail for example.com loops back to myself)

Do not publish full logs: they can expose real addresses, message IDs, hostnames, and network details. Also distinguish this diagnostic from mail forwarding loop or too many Received headers. Those can indicate an address-level forwarding cycle or repeated hand-offs between servers, while mail for domain loops back to myself commonly appears when the SMTP client resolves the destination back to its own server without a matching destination class.

2. Decide which server should own the domain

Before changing anything, choose the intended model:

This decision prevents the most dangerous false repair: making an arbitrary domain relayable merely because Postfix reported a loop.

3. Read public MX and both address families

Query the recipient domain from a normal recursive resolver, then resolve every MX hostname:

dig +short MX example.com

dig +short A mail.example.com
dig +short AAAA mail.example.com

The MX target must be a hostname, not a raw address. Check all returned MX records, including lower-priority backup hosts. If mail recently moved, compare authoritative answers as well as cached recursive answers and allow for the previous TTL.

If another provider should receive the mail but MX still points to your DMS hostname, fix DNS at the zone source. If DMS should receive the mail, continue: DNS may be correct while the live container’s domain maps are not.

4. Inspect the live Postfix identity and domain classes

Read the effective configuration from the running container, not a copied forum example:

docker compose exec mailserver postconf \
  myhostname mydomain mydestination \
  virtual_mailbox_domains virtual_alias_domains \
  relay_domains relayhost

Keep the real output private. For the usual DMS mailbox model, a server identity such as mail.example.com belongs to myhostname, while the mailbox domain example.com is represented through the virtual mailbox configuration derived from provisioned accounts.

Look for four specific failures:

  1. the recipient domain appears in none of the intended destination classes;
  2. the same domain appears in both mydestination and virtual_mailbox_domains;
  3. the bare mailbox domain was also used as the DMS hostname;
  4. a custom relayhost or transport rule sends the domain back to this server.

Docker Mailserver’s debugging guide calls out the warning do not list domain ... in BOTH mydestination and virtual_mailbox_domains. DMS also warns that assigning the same FQDN to its hostname and to mail accounts is not supported by the default arrangement. Fix that model rather than editing generated main.cf inside the container.

5. Prove that Docker Mailserver knows the hosted domain

DMS normally derives hosted mail domains from provisioned accounts. For the default file provisioner, list accounts and aliases through the supported setup interface:

docker compose exec mailserver setup email list

docker compose exec mailserver setup alias list

If example.com should be hosted but there is no account under that domain, add the smallest correct account interactively so its password does not enter shell history:

docker compose exec mailserver \
  setup email add [email protected]

An alias may be appropriate when an additional address should deliver to an existing mailbox, but an alias and a mailbox account are not interchangeable. Follow the provisioner used by the deployment: an LDAP-backed server will not be repaired by changing the file provisioner.

If the account source lists the address but the effective virtual domain lookup still does not recognize its domain, check that the expected configuration volume is mounted and that the running container was generated from that source. Do not create a catch-all to hide a missing domain or recipient.

6. Query the effective maps

Inspect the exact lookup definitions before issuing a query:

docker compose exec mailserver postconf \
  virtual_mailbox_domains virtual_mailbox_maps virtual_alias_maps

The map type and path vary by DMS version and account provisioner. Use the values returned by your container. The general diagnostic shapes are:

docker compose exec mailserver \
  postmap -q example.com <domain-map-from-postconf>

docker compose exec mailserver \
  postmap -q [email protected] <mailbox-map-from-postconf>

A domain hit proves Postfix classifies the domain as hosted; an address hit proves the recipient map recognizes that mailbox. If the domain is recognized but the recipient is not, the next error is likely to be User unknown in virtual mailbox table. Use the virtual mailbox recipient guide for that branch rather than weakening recipient validation.

7. Recreate through the supported deployment path

Docker Mailserver’s current debugging guidance recommends replacing the container cleanly so startup setup scripts run against the image’s original configuration. After confirming persistent volumes and the intended Compose model, use the documented deployment operation for your pinned version. A typical Compose action is:

docker compose up -d --force-recreate mailserver

Do not rely on edits made only inside the running container. Do not delete mail volumes. Do not run down -v. If this is a production mail host, retain the prior Compose revision and image reference so configuration—not mailbox data—can be rolled back safely.

After recreation, repeat postconf, account listing, and the effective map query. A successful container start is not proof that routing changed.

8. Check for a custom route pointing back to yourself

If the domain is not supposed to be local, inspect only the relevant transport and next-hop settings:

docker compose exec mailserver postconf \
  transport_maps relayhost sender_dependent_relayhost_maps

A custom transport that sends example.com to mail.example.com will loop if that hostname resolves to the same DMS instance and the server does not own the recipient domain. Likewise, using the domain’s public MX as a manual transport does not escape DNS routing—it merely restates it.

Remove stale custom routing through the persistent DMS override or Compose source that created it. Keep smarthost configuration separate from inbound hosted-domain ownership: a relay used for outbound delivery should not become the route for mail destined to a locally hosted domain.

9. Verify at SMTP, queue, and mailbox layers

Use an external system you control to test the final route. First confirm the MX hostname and certificate identity, then issue a recipient probe over port 25:

openssl s_client -quiet -starttls smtp \
  -connect mail.example.com:25 \
  -servername mail.example.com

EHLO test.example.net
MAIL FROM:<[email protected]>
RCPT TO:<[email protected]>
QUIT

Use real domains and addresses you control. A 250-class response to RCPT TO proves recipient acceptance, not final delivery. Complete the check with one harmless message:

  1. send from an external mailbox to the intended recipient;
  2. follow one queue ID through the private logs;
  3. confirm a successful local delivery status rather than another SMTP relay attempt;
  4. open the intended mailbox and verify the message arrived once;
  5. confirm there is no new loop diagnostic or growing deferred queue;
  6. repeat after the next normal container recreation to prove persistence.

Repairs to avoid

Compact diagnosis order

  1. Capture the exact current queue diagnostic and recipient domain.
  2. Decide whether DMS, another provider, or a deliberate relay should own delivery.
  3. Verify all MX, A, and AAAA answers.
  4. Inspect effective myhostname, mydestination, virtual domains, and relay domains.
  5. List accounts and aliases through the active DMS provisioner.
  6. Query the live domain and mailbox maps.
  7. Repair DNS or persistent DMS configuration—never both speculatively.
  8. Recreate safely and repeat the effective checks.
  9. Test external SMTP acceptance, final mailbox delivery, queue stability, and persistence.

Authoritative references: Docker Mailserver’s debugging guide documents hostname/domain conflicts and clean recreation; its account-management overview explains how accounts establish hosted mail domains; and Postfix’s official virtual domain guide and address-class reference define destination classes and the loop condition. Match commands to the DMS image and provisioner you actually run.