From 30f9025d40c0a416aa90b3e5e24de3d4c25fa893 Mon Sep 17 00:00:00 2001 From: Bendik Lynghaug Date: Wed, 7 Oct 2026 09:29:06 +0200 Subject: [PATCH] Serve mail autoconfiguration on the bare domain Thunderbird asks /.well-known/autoconfig, Outlook POSTs to /Autodiscover, and both fell into portal's catch-all, which answers 200 with an HTML page - so a client got markup where it expected XML and went back to guessing. Both prefixes now go to Stalwart, which already generates the answers, templated on the address asked about. No static copy to drift out of date and no hostname of their own to certify. Host is rewritten to the name Stalwart has always answered for, and all three spellings of /Autodiscover are matched because Outlook is not consistent about it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_015GeH3y8fwTaTudaD88P57o --- .gitea/workflows/deploy.yml | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 79b5526..035ecaa 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -114,7 +114,32 @@ jobs: } {$DOMAIN} { - reverse_proxy host.docker.internal:3010 + # Mail clients look for their configuration on the bare domain - + # Thunderbird at /.well-known/autoconfig, Outlook by POSTing to + # /Autodiscover. Stalwart already generates both, templated on the + # address asked about, so these two paths go to it instead of being + # copied into this repo: one source of truth, and no second + # hostname to certify. Host is rewritten to the name Stalwart + # answers for; it never sees a request for the bare domain + # otherwise. (MTA-STS cannot be served here - RFC 8461 requires + # mta-sts. - so it keeps its own record and route.) + handle /.well-known/autoconfig/* { + reverse_proxy stalwart:8080 { + header_up Host mail.{$DOMAIN} + } + } + + @autodiscover path /Autodiscover/* /autodiscover/* /AutoDiscover/* + handle @autodiscover { + reverse_proxy stalwart:8080 { + header_up Host mail.{$DOMAIN} + } + } + + handle { + reverse_proxy host.docker.internal:3010 + } + log { output file /var/log/caddy/www.log }