Autokonfiguration für alle Clients
Man richtet für einen Kunden oder sich selbst eine neue E-Mail-Adresse ein und das Rätselraten geht los: „War der Port jetzt 143 oder 993? Und brauche ich STARTTLS oder SSL/TLS?“ Als IT-Dienstleister oder Server-Administrator kann man diese Fragen zwar im Schlaf beantworten, aber für Endanwender ist das oft ein Buch mit sieben Siegeln. Die Lösung: Autokonfiguration.
In diesem Beitrag geht es darum wie mann einen zentralen Server aufsetzt, der für Mozilla Thunderbird, Microsoft Outlook und Apple-Geräte (iOS & macOS) die Mail-Einstellungen automatisch per DNS-Abfrage bereitstellt. Das Ganze funktioniert dynamisch für beliebig viele Domains.
Das Konzept: Wie finden die Clients die Einstellungen?
E-Mail-Programme kochen leider alle ihr eigenes Süppchen, wenn es um die automatische Suche nach Serverdaten geht:
- Thunderbird sucht nach
http://autoconfig.deine-domain.de/mail/config-v1.1.xml. - Outlook sucht per POST-Request nach
https://autodiscover.deine-domain.de/autodiscover/autodiscover.xml. - Apple (iOS/macOS) nutzt am liebsten signierte
.mobileconfig-Profile, die man im Browser herunterlädt.
Man baut eine zentrale PHP-Datei, die per Apache-Routing alle diese Anfragen abfängt und beantwortet.
Schritt 1: Die PHP-Zentrale (index.php)
Man erstellt im Web-Verzeichnis (z. B. /var/www/autoconfig/) eine index.php. Diese Datei prüft die URL der Anfrage und liefert je nachdem das passende XML oder eine Weiche (Webansicht für Besucher) aus.
In diesem Beispiel nutzen wir beispielhaft Port 143 (IMAP mit STARTTLS) und Port 25 (SMTP mit STARTTLS).
<?php
// Zentrale Einstellungen für deinen Mailserver
$mailSettings = [
'imap' => 'mail.dein-zentraler-server.de',
'smtp' => 'mail.dein-zentraler-server.de',
'imap_port' => 143,
'smtp_port' => 25,
'company' => 'Deine IT-Firma GmbH'
];
$host = $_SERVER['HTTP_HOST'];
// Wir isolieren die Hauptdomain (entfernen autoconfig. und autodiscover.)
$domain = str_replace(['autoconfig.', 'autodiscover.'], '', $host);
function generateUUID($data) {
return md5($data);
}
// FALL 1: Apple Mobile Config Profil
if (preg_match('/(apple|iphone)/i', $_SERVER['REQUEST_URI'])) {
header("Content-Type: application/x-apple-aspc-config; charset=utf-8");
header('Content-Disposition: attachment; filename="mail-config.mobileconfig"');
echo '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>EmailAccountName</key>
<string>' . $mailSettings['company'] . '</string>
<key>EmailAccountType</key>
<string>EmailTypeIMAP</string>
<key>IncomingMailServerAuthentication</key>
<string>EmailAuthPassword</string>
<key>IncomingMailServerHostName</key>
<string>' . $mailSettings['imap'] . '</string>
<key>IncomingMailServerPortNumber</key>
<integer>' . $mailSettings['imap_port'] . '</integer>
<key>IncomingMailServerUseSSL</key>
<true/>
<key>OutgoingMailServerAuthentication</key>
<string>EmailAuthPassword</string>
<key>OutgoingMailServerHostName</key>
<string>' . $mailSettings['smtp'] . '</string>
<key>OutgoingMailServerPortNumber</key>
<integer>' . $mailSettings['smtp_port'] . '</integer>
<key>OutgoingMailServerUseSSL</key>
<true/>
<key>PayloadDescription</key>
<string>E-Mail Setup für ' . $domain . '</string>
<key>PayloadDisplayName</key>
<string>E-Mail (' . $domain . ')</string>
<key>PayloadIdentifier</key>
<string>com.example.mail.' . $domain . '</string>
<key>PayloadType</key>
<string>com.apple.mail.managed</string>
<key>PayloadUUID</key>
<string>' . generateUUID($domain . 'mail') . '</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</array>
<key>PayloadDisplayName</key>
<string>' . $mailSettings['company'] . ' Mail Setup</string>
<key>PayloadIdentifier</key>
<string>com.example.config.' . $domain . '</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>' . generateUUID($domain . 'config') . '</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>';
exit;
}
// FALL 2: Outlook Autodiscover
if (strpos($_SERVER['REQUEST_URI'], 'autodiscover.xml') !== false) {
header("Content-Type: application/xml; charset=utf-8");
echo '<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
<Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
<Account>
<AccountType>email</AccountType>
<Action>settings</Action>
<Protocol>
<Type>IMAP</Type>
<Server>' . $mailSettings['imap'] . '</Server>
<Port>' . $mailSettings['imap_port'] . '</Port>
<SSL>on</SSL>
<LoginName>%EmailAddress%</LoginName>
</Protocol>
<Protocol>
<Type>SMTP</Type>
<Server>' . $mailSettings['smtp'] . '</Server>
<Port>' . $mailSettings['smtp_port'] . '</Port>
<SSL>on</SSL>
<LoginName>%EmailAddress%</LoginName>
</Protocol>
</Account>
</Response>
</Autodiscover>';
exit;
}
// FALL 3: Mozilla Thunderbird
if (strpos($_SERVER['REQUEST_URI'], 'config-v1.1.xml') !== false) {
header("Content-Type: application/xml; charset=utf-8");
echo '<?xml version="1.1"?>
<clientConfig version="1.1">
<emailProvider id="' . $domain . '">
<domain>' . $domain . '</domain>
<displayName>' . $mailSettings['company'] . '</displayName>
<displayShortName>Mail</displayShortName>
<incomingServer type="imap">
<hostname>' . $mailSettings['imap'] . '</hostname>
<port>' . $mailSettings['imap_port'] . '</port>
<socketType>STARTTLS</socketType>
<authentication>password-cleartext</authentication>
<username>%EMAILADDRESS%</username>
</incomingServer>
<outgoingServer type="smtp">
<hostname>' . $mailSettings['smtp'] . '</hostname>
<port>' . $mailSettings['smtp_port'] . '</port>
<socketType>STARTTLS</socketType>
<authentication>password-cleartext</authentication>
<username>%EMAILADDRESS%</username>
</outgoingServer>
</emailProvider>
</clientConfig>';
exit;
}
// FALL 4: Echte Menschen im Browser (Landingpage)
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>E-Mail Einrichtung | <?php echo $mailSettings['company']; ?></title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; text-align: center; padding: 50px; background: #f5f5f7; color: #1d1d1f; }
.box { background: white; padding: 40px; border-radius: 12px; display: inline-block; box-shadow: 0 4px 20px rgba(0,0,0,0.08); max-width: 500px; }
h1 { color: #0071e3; margin-bottom: 10px; }
.button { background: #0071e3; color: white !important; padding: 12px 24px; text-decoration: none; border-radius: 8px; display: inline-block; margin-top: 20px; font-weight: bold; }
.button:hover { background: #0077ed; }
hr { border: 0; height: 1px; background: #e3e3e3; margin: 25px 0; }
</style>
</head>
<body>
<div class="box">
<h1>E-Mail Einrichtung</h1>
<p>Geben Sie in Outlook oder Thunderbird einfach Ihre E-Mail-Adresse und Ihr Passwort ein. Die Einstellungen werden automatisch geladen.</p>
<hr>
<h3>Nutzen Sie ein iPhone oder iPad?</h3>
<p>Tippen Sie in Safari auf diesen Button, um Ihren Mail-Account automatisch auf diesem Gerät einzurichten:</p>
<a href="https://<?php echo $host; ?>/apple" class="button">Apple Profil herunterladen</a>
</div>
</body>
</html>
Schritt 2: Die Apache-Konfiguration (Multi-Domain fähig!)
Damit die Datei aufgerufen werden kann, muss man Apache beibringen, alle eingehenden Anfragen für die Subdomains auf diese Datei umzulenken. Man erstellt eine Datei wie /etc/apache2/sites-available/autoconfig.conf:
<VirtualHost *:80>
ServerName autoconfig.deine-hauptdomain.de
# Hier listest du alle Kundendomains auf:
ServerAlias autoconfig.kunde1.de autodiscover.kunde1.de autoconfig.kunde2.de autodiscover.kunde2.de
DocumentRoot /var/www/autoconfig
</VirtualHost>
<VirtualHost *:443>
ServerName autoconfig.deine-hauptdomain.de
ServerAlias autoconfig.kunde1.de autodiscover.kunde1.de autoconfig.kunde2.de autodiscover.kunde2.de
DocumentRoot /var/www/autoconfig
# SSL Einstellungen (Hier greift dein Let's Encrypt Zertifikat)
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/autoconfig.deine-hauptdomain.de/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/autoconfig.deine-hauptdomain.de/privkey.pem
</VirtualHost>
Schritt 3: Das SSL-Zertifikat mit Certbot (Der dynamische Weg)
Da Outlook und Co. Zertifikatsfehler hassen und sofort die Arbeit verweigern, muss das SSL-Zertifikat alle Domains abdecken. Mit folgendem dynamischen Bash-Skript kann man neue Domains hinzufügen, ohne die alten zu löschen:
#!/bin/bash
# Skript zum Hinzufügen einer neuen Mail-Domain zu Certbot
if [ -z "$1" ]; then
echo "Nutzung: $0 neue-domain.de"
exit 1
fi
NEW_DOMAIN=$1
CERT_NAME="autoconfig.deine-hauptdomain.de"
echo "1. Lese aktuell aktive Domains aus dem Zertifikat aus..."
CURRENT_DOMAINS=$(sudo certbot certificates --cert-name $CERT_NAME | grep "Domains:" | sed 's/Domains: //g')
# Wir bauen die Argumente für Certbot zusammen
DOMAIN_ARGS=""
for d in $CURRENT_DOMAINS; do
DOMAIN_ARGS="$DOMAIN_ARGS -d $d"
done
# Neue Domains anhängen
DOMAIN_ARGS="$DOMAIN_ARGS -d autoconfig.$NEW_DOMAIN -d autodiscover.$NEW_DOMAIN"
echo "2. Erweitere das Certbot-Zertifikat..."
sudo eval "certbot certonly --webroot -w /var/www/autoconfig --expand $DOMAIN_ARGS"
echo "Fertig! Bitte trage die Domains noch im Apache ein und lade ihn neu."
Weitere Tipps
- Port 25 Fallstrick: Viele Provider sperren Port 25 für Endkunden (Spamschutz). Wenn der Mail-Client im Heimnetz deines Kunden trotz gefundener Settings streikt, ziehe die Öffnung von Port
587(SMTP Submission mit STARTTLS) auf deinem Mailserver in Erwägung! - Automatischer Apache-Reload: Vergiss nicht, in den Certbot-Renewal-Parametern einen
renew_hook = systemctl reload apache2zu setzen, damit Apache nach der automatischen Zertifikatserneuerung im Hintergrund auch die neuen Schlüssel lädt.
So kann man neue Domains künftig innerhalb kürzester Zeit hinzufügen.