diff --git a/README.md b/README.md
index 4c19ad78..0d8402f5 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ Features
Main features include:
-- **Standard email server**, IMAP and IMAP+, SMTP and Submission
+- **Standard email server**, IMAP and IMAP+, SMTP and Submission with autoconfiguration profiles for clients
- **Advanced email features**, aliases, domain aliases, custom routing
- **Web access**, multiple Webmails and administration interface
- **User features**, aliases, auto-reply, auto-forward, fetched accounts
diff --git a/core/admin/mailu/internal/views/__init__.py b/core/admin/mailu/internal/views/__init__.py
index 762b2a38..5ebd6ff8 100644
--- a/core/admin/mailu/internal/views/__init__.py
+++ b/core/admin/mailu/internal/views/__init__.py
@@ -1,3 +1,3 @@
__all__ = [
- 'auth', 'postfix', 'dovecot', 'fetch', 'rspamd'
+ 'auth', 'autoconfig', 'postfix', 'dovecot', 'fetch', 'rspamd'
]
diff --git a/core/admin/mailu/internal/views/autoconfig.py b/core/admin/mailu/internal/views/autoconfig.py
new file mode 100644
index 00000000..bf116f4b
--- /dev/null
+++ b/core/admin/mailu/internal/views/autoconfig.py
@@ -0,0 +1,183 @@
+from mailu.internal import internal
+
+from flask import current_app as app
+import flask
+import xmltodict
+
+@internal.route("/autoconfig/mozilla")
+def autoconfig_mozilla():
+ # https://wiki.mozilla.org/Thunderbird:Autoconfiguration:ConfigFileFormat
+ hostname = app.config['HOSTNAME']
+ xml = f'''
+
{%- for line in domain.dns_autoconfig %}
{{ line }}
diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt
index d6c7aca3..f14e484c 100644
--- a/core/admin/requirements-prod.txt
+++ b/core/admin/requirements-prod.txt
@@ -73,3 +73,4 @@ webencodings==0.5.1
Werkzeug==2.0.2
WTForms==2.3.3
WTForms-Components==0.10.5
+xmltodict==0.12.0
diff --git a/core/admin/requirements.txt b/core/admin/requirements.txt
index 65130a8c..61fbd92c 100644
--- a/core/admin/requirements.txt
+++ b/core/admin/requirements.txt
@@ -25,3 +25,4 @@ srslib
marshmallow
flask-marshmallow
marshmallow-sqlalchemy
+xmltodict
diff --git a/core/nginx/conf/nginx.conf b/core/nginx/conf/nginx.conf
index 11b7468c..4e6919f8 100644
--- a/core/nginx/conf/nginx.conf
+++ b/core/nginx/conf/nginx.conf
@@ -120,6 +120,30 @@ http {
add_header X-XSS-Protection '1; mode=block';
add_header Referrer-Policy 'same-origin';
+ # mozilla autoconfiguration
+ location ~ ^/(\.well\-known/autoconfig/)?mail/config\-v1\.1\.xml {
+ rewrite ^ /internal/autoconfig/mozilla break;
+ include /etc/nginx/proxy.conf;
+ proxy_pass http://$admin;
+ }
+ # microsoft autoconfiguration
+ location ~* ^/Autodiscover/Autodiscover.json {
+ rewrite ^ /internal/autoconfig/microsoft.json break;
+ include /etc/nginx/proxy.conf;
+ proxy_pass http://$admin;
+ }
+ location ~* ^/Autodiscover/Autodiscover.xml {
+ rewrite ^ /internal/autoconfig/microsoft break;
+ include /etc/nginx/proxy.conf;
+ proxy_pass http://$admin;
+ }
+ # apple mobileconfig
+ location ~ ^/(apple\.)?mobileconfig {
+ rewrite ^ /internal/autoconfig/apple break;
+ include /etc/nginx/proxy.conf;
+ proxy_pass http://$admin;
+ }
+
{% if TLS_FLAVOR == 'mail-letsencrypt' %}
location ^~ /.well-known/acme-challenge/ {
proxy_pass http://127.0.0.1:8008;
diff --git a/core/nginx/letsencrypt.py b/core/nginx/letsencrypt.py
index 48316c1c..9c998fe2 100755
--- a/core/nginx/letsencrypt.py
+++ b/core/nginx/letsencrypt.py
@@ -4,10 +4,12 @@ import os
import time
import subprocess
+hostnames = ','.join(set(host.strip() for host in os.environ['HOSTNAMES'].split(',')))
+
command = [
"certbot",
"-n", "--agree-tos", # non-interactive
- "-d", os.environ["HOSTNAMES"],
+ "-d", hostnames, "--expand", "--allow-subset-of-names",
"-m", "{}@{}".format(os.environ["POSTMASTER"], os.environ["DOMAIN"]),
"certonly", "--standalone",
"--cert-name", "mailu",
@@ -20,7 +22,7 @@ command = [
command2 = [
"certbot",
"-n", "--agree-tos", # non-interactive
- "-d", os.environ["HOSTNAMES"],
+ "-d", hostnames, "--expand", "--allow-subset-of-names",
"-m", "{}@{}".format(os.environ["POSTMASTER"], os.environ["DOMAIN"]),
"certonly", "--standalone",
"--cert-name", "mailu-ecdsa",
diff --git a/docs/faq.rst b/docs/faq.rst
index 4757e6a1..264fbcb8 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -396,58 +396,6 @@ Mailu can serve an `MTA-STS policy`_; To configure it you will need to:
.. _`1798`: https://github.com/Mailu/Mailu/issues/1798
.. _`MTA-STS policy`: https://datatracker.ietf.org/doc/html/rfc8461
-How do I setup client autoconfiguration?
-````````````````````````````````````````
-
-Mailu can serve an `XML file for autoconfiguration`_; To configure it you will need to:
-
-1. add ``autoconfig.example.com`` to the ``HOSTNAMES`` configuration variable (and ensure that a valid SSL certificate is available for it; this may mean restarting your smtp container)
-
-2. configure an override with the policy itself; for example, your ``overrides/nginx/autoconfiguration.conf`` could read:
-
-.. code-block:: bash
-
- location ^~ /mail/config-v1.1.xml {
- return 200 "
-
-
- %EMAILDOMAIN%
-
- Email
- Email
-
-
- mailu.example.com
- 993
- SSL
- %EMAILADDRESS%
- password-cleartext
-
-
-
- mailu.example.com
- 465
- SSL
- %EMAILADDRESS%
- password-cleartext
- true
- true
-
-
-
- Configure your email client
-
-
- \r\n";
- }
-
-3. setup the appropriate DNS/CNAME record (``autoconfig.example.com`` -> ``mailu.example.com``).
-
-*issue reference:* `224`_.
-
-.. _`224`: https://github.com/Mailu/Mailu/issues/224
-.. _`XML file for autoconfiguration`: https://wiki.mozilla.org/Thunderbird:Autoconfiguration:ConfigFileFormat
-
Technical issues
----------------
diff --git a/docs/index.rst b/docs/index.rst
index 238cea5d..6a3c42b7 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -23,7 +23,7 @@ popular groupware.
Main features include:
-- **Standard email server**, IMAP and IMAP+, SMTP and Submission
+- **Standard email server**, IMAP and IMAP+, SMTP and Submission with autoconfiguration profiles for clients
- **Advanced email features**, aliases, domain aliases, custom routing
- **Web access**, multiple Webmails and administration interface
- **User features**, aliases, auto-reply, auto-forward, fetched accounts
diff --git a/docs/reverse.rst b/docs/reverse.rst
index 91c6f67e..0f516d26 100644
--- a/docs/reverse.rst
+++ b/docs/reverse.rst
@@ -59,14 +59,14 @@ Then on your own frontend, point to these local ports. In practice, you only nee
REAL_IP_FROM=x.x.x.x,y.y.y.y.y
#x.x.x.x,y.y.y.y.y is the static IP address your reverse proxy uses for connecting to Mailu.
-Because the admin interface is served as ``/admin``, the Webmail as ``/webmail``, the single sign on page as ``/sso``, webdav as ``/webdav`` and the static files endpoint as ``/static``, you may also want to use a single virtual host and serve other applications (still Nginx):
+Because the admin interface is served as ``/admin``, the Webmail as ``/webmail``, the single sign on page as ``/sso``, webdav as ``/webdav``, the client-autoconfiguration and the static files endpoint as ``/static``, you may also want to use a single virtual host and serve other applications (still Nginx):
.. code-block:: nginx
server {
# [...] here goes your standard configuration
- location ~ ^/(admin|sso|static|webdav|webmail) {
+ location ~* ^/(admin|sso|static|webdav|webmail|(apple\.)?mobileconfig|(\.well\-known/autoconfig/)?mail/|Autodiscover/Autodiscover) {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr
proxy_pass https://localhost:8443;
diff --git a/towncrier/newsfragments/224.feature b/towncrier/newsfragments/224.feature
new file mode 100644
index 00000000..4200a5da
--- /dev/null
+++ b/towncrier/newsfragments/224.feature
@@ -0,0 +1 @@
+Provide auto-configuration files (autodiscover, autoconfig & mobileconfig); Please update your DNS records