Vor einigen Jahren habe ich bereits etwas zu Microsoft Outlook und dessen Autodiscover geschrieben. Microsoft Office Outlook Autodiscover
Ich setze es noch immer in recht ähnlicher Form ein und möchte den aktuellen Stand kurz beschreiben.
Primär habe ich eine Autodiscoverdomain https://autodiscover.kernel-error.de hinter dieser steht ein nginx und er liefert unter diesem Pfad https://autodiscover.kernel-error.de/Autodiscover/Autodiscover.xml die Konfigurationsinformationen für verschiedene Maildomains für smtps und imaps aus.
Die Konfiguration vom nginx ist recht überschaubar. Klar, https und der spannende Teil der Konfiguration ist folgender:
location ~ /(?:a|A)utodiscover/(?:a|A)utodiscover.xml {
root /usr/local/www/autodiscover.kernel-error.de;
try_files /autodiscover/autodiscover.php =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $request_filename;
include fastcgi_params;
fastcgi_cache MYAPP;
fastcgi_cache_valid 200 60m;
}
Wie man gut sehen kann wird einfach jede Anfrage nach /autodiscover/autodiscover.xml (egal ob am Anfang groß oder klein geschrieben), im Hintergrund weitergeleitet an das php file autodisvocer.php:
<?php
/********************************
* Autodiscover responder
********************************
* This PHP script is intended to respond to any request to http(s)://mydomain.com/autodiscover/autodiscover.xml.
* If configured properly, it will send a spec-complient autodiscover XML response, pointing mail clients to the
* appropriate mail services.
* If you use MAPI or ActiveSync, stick with the Autodiscover service your mail server provides for you. But if
* you use POP/IMAP servers, this will provide autoconfiguration to Outlook, Apple Mail and mobile devices.
*
* To work properly, you'll need to set the service (sub)domains below in the settings section to the correct
* domain names, adjust ports and SSL.
*/
//get raw POST data so we can extract the email address
$request = file_get_contents("php://input");
// optional debug log
# file_put_contents( 'request.log', $request, FILE_APPEND );
// retrieve email address from client request
preg_match( "/\<EMailAddress\>(.*?)\<\/EMailAddress\>/", $request, $email );
// check for invalid mail, to prevent XSS
if (filter_var($email[1], FILTER_VALIDATE_EMAIL) === false) {
throw new Exception('Invalid E-Mail provided');
}
/**************************************
* Port and server settings below *
**************************************/
// IMAP settings
$imapServer = 'imap.kernel-error.de'; // imap.example.com
$imapPort = 993;
$imapSSL = true;
// SMTP settings
$smtpServer = 'smtp.kernel-error.de'; // smtp.example.com
$smtpPort = 465;
$smtpSSL = true;
//set Content-Type
header( 'Content-Type: application/xml' );
?>
<?php echo '<?xml version="1.0" encoding="utf-8" ?>'; ?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
<Account>
<AccountType>email</AccountType>
<Action>settings</Action>
<Protocol>
<Type>IMAP</Type>
<Server><?php echo $imapServer; ?></Server>
<Port><?php echo $imapPort; ?></Port>
<DomainRequired>off</DomainRequired>
<LoginName><?php echo $email[1]; ?></LoginName>
<SPA>off</SPA>
<SSL><?php echo $imapSSL ? 'on' : 'off'; ?></SSL>
<AuthRequired>on</AuthRequired>
</Protocol>
<Protocol>
<Type>SMTP</Type>
<Server><?php echo $smtpServer; ?></Server>
<Port><?php echo $smtpPort; ?></Port>
<DomainRequired>off</DomainRequired>
<AuthRequired>on</AuthRequired>
<LoginName><?php echo $email[1]; ?></LoginName>
<SPA>off</SPA>
<SSL><?php echo $imapSSL ? 'on' : 'off'; ?></SSL>
<AuthRequired>on</AuthRequired>
<SMTPLast>off</SMTPLast>
<UsePOPAuth>off</UsePOPAuth>
</Protocol>
</Account>
</Response>
</Autodiscover>
Das kleine php script macht auch nicht viel mehr als die im Post übermittelte E-Mail Adresse in eine Variable zu schieben, zu prüfen ob es wirklich eine E-Mail Adresse ist und dann am Ende einfach das fertige xml zurück zu liefern.
Besonders wichtig dabei ist:
<AuthRequired>on</AuthRequired> <SMTPLast>off</SMTPLast> <UsePOPAuth>off</UsePOPAuth>
Sonst darf man für den Postausgangsserver nämlich immer manuell den Haken setzen bei: „Gleiche Einstellungen wie für den Posteingangsserver verwenden“ Welches sicher einige Anwender vor einer nur schwer zu überwindenden Hürde stell.
Damit dieses nicht nur für E-Mail Adresse der Domain kernel-error.de funktioniert gibt es in den anderen DNS Zonen SRV RRs welche auf diese Autodiscoverdomain verweisen:
➜ ~ dig _autodiscover._tcp.kernel-error.com IN SRV +short 0 0 443 autodiscover.kernel-error.de.
Nun sorgt dieses bei Outlook für eine kleine Warnmeldung bei der Konfiguration, ob man diesem Verweis wirklich folgen möchte.

Dieses kommt nur einmalig und man könnte es zudem mit deinem Registierungsschlüssel unterbinden aber naja das sollte für jeden klickbar sein, oder?!?! Im Anschluss ist die Konfiguration vom E-Mail Client schon abgeschlossen.

Wie man sieht ist es sehr simpel und sollte von nahezu jedem erledigt werden können, der es schafft seine E-Mail Adresse und sein Kennwort nach dem Outlookstart einzugeben.
Update März 2026 — Aufgeräumt und abgesichert
Das Grundprinzip funktioniert seit 2019 unverändert — Outlook bekommt per POST seine Konfiguration, der Benutzer muss nur E-Mail-Adresse und Passwort eingeben. Ein paar Dinge habe ich aber überarbeitet.
PHP-Script: GET-Requests und fehlende Eingaben abfangen
Das alte Script hat bei GET-Requests oder einem leeren POST-Body mit HTTP 500 geantwortet — das PHP-Script versuchte auf eine Variable zuzugreifen, die bei fehlendem XML-Body nicht existiert. Monitoring-Tools und neugierige Browser liefen damit gegen die Wand.
Die korrigierte Version prüft jetzt sauber:
<?php
// Nur POST erlauben
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
header("HTTP/1.1 405 Method Not Allowed");
header("Allow: POST");
exit;
}
$request = file_get_contents("php://input");
preg_match("/\<EMailAddress\>(.*?)\<\/EMailAddress\>/", $request, $email);
if (empty($email[1]) || filter_var($email[1], FILTER_VALIDATE_EMAIL) === false) {
header("HTTP/1.1 400 Bad Request");
exit;
}
// XSS-Schutz: E-Mail fuer XML-Ausgabe escapen
$loginName = htmlspecialchars($email[1], ENT_XML1, "UTF-8");
GET liefert jetzt 405 Method Not Allowed, ein POST ohne gültigen Body gibt 400 Bad Request. Die E-Mail-Adresse wird zusätzlich mit htmlspecialchars() escaped bevor sie in die XML-Antwort geschrieben wird — nicht dass jemand über eine präparierte Autodiscover-Anfrage XML-Injection versucht.
Nginx: Kein Cache für dynamische Antworten
In der ursprünglichen Konfiguration oben steckt fastcgi_cache MYAPP mit 60 Minuten Gültigkeit. Das ist für Autodiscover falsch — die Antwort enthält die E-Mail-Adresse des anfragenden Benutzers als <LoginName>. Mit Cache bekommt der zweite Benutzer die E-Mail-Adresse des ersten. Ohne Cache:
location ~* ^/autodiscover/autodiscover\.xml$ {
try_files /autodiscover/autodiscover.php =404;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/autodiscover/autodiscover.php;
include fastcgi_params;
}
Das ~* macht den Match case-insensitive — kürzer als die alte Regex mit (?:a|A). Und SCRIPT_FILENAME zeigt jetzt explizit auf das PHP-Script statt auf $request_filename, was bei falscher Root-Konfiguration ins Leere laufen kann.
Thunderbird Autoconfig auf dem gleichen Host
Inzwischen bedient autodiscover.kernel-error.de nicht mehr nur Outlook, sondern auch Thunderbird. Dazu reicht eine zusätzliche Location im gleichen Server-Block:
location /mail/ {
alias /usr/local/www/autoconfig-mail/mail/;
}
Thunderbird fragt https://autoconfig.<domain>/mail/config-v1.1.xml — eine statische XML-Datei mit den Servereinstellungen für IMAP und SMTP. Für jede Maildomain gibt es einen autoconfig.* CNAME und einen eigenen HTTPS-Server-Block mit passendem Zertifikat. Outlook nutzt weiterhin den POST-Endpoint, Thunderbird die statische XML — beide laufen auf der gleichen Infrastruktur.
