AutoDiscover & AutoConfig IMAP/SMTP

En 2020, pour m'occuper pendant le confinement, j'avais écrit un article sur la configuration automatique des clients POP/IMAP. Ca fonctionnait sur Thunderbird, mais pas sur les clients Microsoft... Bon, les clients Microsoft il y en a de plusieurs sorte (Courrier, Outlook nouveau, ancien, 365, jadis Express et j'en passe) et la chose n'est (volontairement ?) pas simple. On va oublier les versions 365 qui même si elles supportent IMAP le font mal et ne sont pas vraiment destinés à cet usage mais plus à du MAPI.

Pour cet article j'ai monté un serveur Cloudron. Ce projet gère très bien le mail dans sa version de base gratuite. Hélas il ne gère pas la configuration des clients, ce qui est regrettable car il pourrait très facilement intégrer ce qui suit afin d'être totalement dans la philosophie du projet intégré !

Il existe plusieurs façons de faire de l'AutoDiscovery ou de l'AutoConfig

La méthode RFC 6186

Elle se base sur des enregistrements DNS :

_imap._tcp 300 IN SRV 0 0 0 .
_imaps._tcp 300 IN SRV 0 1 993 mail.domain.tld.
_pop3._tcp 300 IN SRV 0 0 0 .
_pop3s._tcp 300 IN SRV 10 1 995 mail.domain.tld.
_submission._tcp 300 IN SRV 0 0 0 .
_submissions._tcp 300 IN SRV 0 1 587 mail.domain.tld.

Normalisée mais visiblement trop simple est abandonnée. Encore que certaines versions d'Outlook utiliseraient ça. Etrange.

La méthode Thunderbird 

Thunderbird va chercher les paramètres dans un fichier XML sur l'url :

http://autoconfig.domain.tld/mail/config-v1.1.xml

La méthode Outlook

Outlook cherche l’enregistrement DNS de type SRV :

_autodiscover._tcp.domain.tld 3600 IN SRV 10 10 443 autodiscover.domain.tld.

qui va lui donner l'adresse ou interroger le fichier XML, donc un CNAME qui pointe sur le serveur web qui héberger le fichier XML, ce qui au final donnera une requête sur

https://autodiscover.domain.tld/AutoDiscover/AutoDiscover.xml

Simple ! Attention à bien respecter la casse du mot AutoDiscover... Et ne pas oublier que dans le cas Microsoft on travaille en HTTPS. Dans certains cas on pourrait faire pointer ça sur n'importe quelle url, mais il semblerait que certaines versions d'Outlook (et il y en a !) cherchent une url qui commence par autodiscover...

Un site pour les rassembler

Dans la méthode qui va suivre on va utiliser un seul site capable de répondre aux url autoconfig et autodiscover, on renseignera donc ces enregistrement dans le dns :

_autodiscover._tcp.domain.tld 1800 IN SRV 10 10 443 autodiscover.domain.tld.
autoconfig 1800 IN CNAME web_server.domain.tld.
autodiscover 1080 IN CNAME web_server.domain.tld.

Ensuite on crée un site web capable de répondre à ces deux url pour l'ensemble des domaines de messagerie pour lesquels on souhaite proposer ce service. Le site doit répondre en HTTP et HTTPS, mais surtout sans redirection automatique HTTP vers HTTPS. Pour cet exemple j'ai utilisé un serveur web NGINX avec du PHP.

On va utiliser ce code que j'ai trouvé ici, je l'ai utilisé tel que en adaptant les enregistrements DNS et les redirections pour NGINX que l'on verra après le code. On copie donc ce code PHP dans autoconfig-mail.php :

<?php
 
/*
By David Mercereau
Licence Beerware
*/
 
function extract_domain($domain) {
    if(preg_match("/(?P<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i", $domain, $matches)) {
        return $matches['domain'];
    } else {
        return $domain;
    }
}
 
$domain = extract_domain($_SERVER['SERVER_NAME']);
$mailServeur='mail.'.$domain;
 
if (preg_match('/^\/mail\/config-v1\.1\.xml/', $_SERVER['REQUEST_URI'])) {
    header('Content-Type: text/xml');
    header('Content-Type: application/xml');
    ?>
<clientConfig version="1.1">
    <emailProvider id="<?= $domain ?>">
      <domain><?= $domain ?></domain>
      <displayName><?= $domain ?></displayName>
      <displayShortName><?= $domain ?></displayShortName>
      <incomingServer type="imap">
         <hostname><?= $mailServeur ?></hostname>
         <port>143</port>
         <socketType>STARTTLS</socketType>
         <username>%EMAILADDRESS%</username>
         <authentication>password-cleartext</authentication>
      </incomingServer>
      <outgoingServer type="smtp">
         <hostname><?= $mailServeur ?></hostname>
         <port>587</port>
         <socketType>STARTTLS</socketType>
         <username>%EMAILADDRESS%</username>
         <authentication>password-cleartext</authentication>
      </outgoingServer>
      <documentation url="https://webmail.<?= $domain ?>">
          <descr lang="fr">Connexion Webmail</descr>
          <descr lang="en">Webmail connexion</descr>
      </documentation>
      <documentation url="http://projet.retzo.net/projects/hebergement/wiki">
        <descr lang="fr">Documentation</descr>
        <descr lang="en">Generic settings page</descr>
      </documentation>
    </emailProvider>
</clientConfig>
    <?php
} else {
    // Outlook
    //get raw POST data so we can extract the email address
    $data = file_get_contents("php://input");
    preg_match("/\<EMailAddress\>(.*?)\<\/EMailAddress\>/", $data, $matches);
 
    //set Content-Type
    header('Content-Type: text/xml');
    header('Content-Type: application/xml');
    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><?= $mailServeur ?></Server>
               <Port>993</Port>
               <DomainRequired>off</DomainRequired>
               <LoginName><?php echo $matches[1]; ?></LoginName>
               <SPA>off</SPA>
               <SSL>on</SSL>
               <AuthRequired>on</AuthRequired>
           </Protocol>
           <Protocol>
               <Type>POP3</Type>
               <Server><?= $mailServeur ?></Server>
               <Port>995</Port>
               <DomainRequired>off</DomainRequired>
               <LoginName><?php echo $matches[1]; ?></LoginName>
               <SPA>off</SPA>
               <SSL>on</SSL>
               <AuthRequired>on</AuthRequired>
           </Protocol>
           <Protocol>
               <Type>SMTP</Type>
               <Server><?= $mailServeur ?></Server>
               <Port>587</Port>
               <DomainRequired>off</DomainRequired>
               <LoginName><?php echo $matches[1]; ?></LoginName>
               <SPA>off</SPA>
               <Encryption>TLS</Encryption>
               <AuthRequired>on</AuthRequired>
               <UsePOPAuth>off</UsePOPAuth>
               <SMTPLast>off</SMTPLast>
           </Protocol>
       </Account>
   </Response>
</Autodiscover>
    <?php
}
 
?>

Ensuite dans configuration NGINX on ajoute les redirections suivantes qui va permettre de servir la bonne version XML selon que la requête utilise la méthode Outlook ou Thunderbird (attention à la casse...) :

location /AutoDiscover {
  rewrite ^/AutoDiscover/AutoDiscover.xml /autoconfig-mail.php;
}
location /mail {
  rewrite ^/mail/config-v1.1.xml /autoconfig-mail.php;
}

Sources


https://github.com/gronke/email-autodiscover
https://github.com/SpicyWeb-de/isp-mailConfig

Configuration automatique POP/IMAP

Quand on configure sous Outlook un compte Exchange, Office 365, Google et quelques autres fournisseurs, celà se fait tout seul, il suffit de rentrer son adresse mail et son mot de passe et un obscur mécanisme nommé AutoDiscover se mets en place et le tour est joué. Vous imaginez qu'il y a un peu de mécanique derrière cette automatisation. Que ça utilise MAPI ou EAS, votre fournisseur le fera pour vous et si vous gérez votre propre serveur Exchange on premise vous trouverez plein de documentation en ligne sur ce sujet.

Et en POP3/IMAP4 ?

C'est pareil, certains gros services de mail proposent cette automatisation (Google par exemple), par contre si vous gérez votre propre serveur de messagerie ou que vous utilisez votre nom de domaine sur les serveurs de Gandi ou OVH par exemple, il y a peu de chances que celà se fasse tout seul et il faudra que vos utilisateurs renseignent manuellement les noms de serveurs IMAP/POP/SMTP, les différents ports en SSL/TLS, etc... C’est fastidieux, d'un autre âge et c'est également pitoyable que des fournisseurs tels OVH ou Gandi laissent leurs services de mail en l'état, ils ne proposent d'ailleurs toujours pas de connexion EAS pour les mobiles.

Il ne reste donc plus qu'à faire le travail.

La première solution consiste à aller déposer un fichier /autodiscover/autodiscover.xml sur un serveur que l'on adressera dans le DNS avec un CNAME du genre autodiscover.domain.tld. Ça peut suffire dans certains cas, mais à cause d'un bugg dans Outlook on ne récupérera que le username sans le domaine. Et si le serveur l'exige il faudra alors terminer la configuration manuellement. Ce n'est pas très propre et tant qu'à automatiser autant aller au bout des choses.

La seconde solution consiste à mettre un peu de code et la façon la plus simple que j'ai trouvée, j'y ai tout de même passé 8 heures..., est de le faire en PHP. On monte un petit serveur web avec du PHP, on crée un enregistrement DNS autodiscover.domain.tld qui pointe dessus et on le configure avec un certificat valide (un Let's Encrypt par exemple). Ce point est important car sans SSL Outlook ne reconnaîtra rien. On teste que ça fonctionne et que le certificat est valide. Dans la racine on crée un fichier autodiscover.php, en gros c'est surtout un XML, la partie PHP ne servant qu'à récupérer l'adresse mail pour la transformer en LoginName. Bien sur on adapte aux besoin, POP/IMAP, etc...

<?php
//get raw POST data so we can extract the email address
$data = file_get_contents("php://input");
preg_match("/\<EMailAddress\>(.*?)\<\/EMailAddress\>/", $data, $matches);

//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">
    <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
        <Account>
            <AccountType>email</AccountType>
            <Action>settings</Action>
            <Protocol>
                <Type>IMAP</Type>
                <Server>mail.gandi.net</Server>
                <Port>993</Port>
                <DomainRequired>off</DomainRequired>
                <LoginName><?php echo $matches[1]; ?></LoginName>
                <SPA>off</SPA>
                <SSL>on</SSL>
                <AuthRequired>on</AuthRequired>
            </Protocol>
            <Protocol>
                <Type>SMTP</Type>
                <Server>mail.gandi.net</Server>
                <Port>465</Port>
                <DomainRequired>off</DomainRequired>
                <LoginName><?php echo $matches[1]; ?></LoginName>
                <SPA>off</SPA>
                <Encryption>TLS</Encryption>
                <AuthRequired>on</AuthRequired>
                <UsePOPAuth>off</UsePOPAuth>
                <SMTPLast>off</SMTPLast>
            </Protocol>
        </Account>
    </Response>
</Autodiscover>

Ensuite on va faire en sorte que le serveur retourne le contenu XML nécessaire à Outlook quelque soit l'URL ou la casse utilisée. Si dans le monde Windows il n'y a pas de différence entre les majuscules et les minuscules, ce n’est pas le cas sous Linux. Et Microsoft à codé en dur dans ses clients de messagerie tantôt en majuscule tantôt en minuscule, voire souvent la première lettre en majuscule, il va falloir ajuster... Pour y palier on va utiliser la fonction REWRITE et coller ça dans un fichier .htacess si on utilise un serveur Apache :

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ autodiscover.php [NC,L]

Ou le convertir (ici) et le placer dans le fichier de configuration si on utilise un serveur Nginx :

if (-e $request_filename){
	set $rule_0 1;
}
if ($request_filename ~ "-l"){
	set $rule_0 1;
}
if (-d $request_filename){
	set $rule_0 1;
}
if ($rule_0 = "1"){
#ignored: "-" thing used or unknown variable in regex/rew 
}
	rewrite ^/.*$ /autodiscover.php last;

Il ne reste plus qu'à tester sous Outlook ou Courrier (Mail) sous Windows 10.

Attention toutefois, sous Outlook 2016/2019 Microsoft a changé les règles du jeu. Le pernicieux but est certainement de pousser les clients vers Office 365, ce système s'appuie sur la fonction Simplified Account Creation introduite après le rachat de la société Acompli (Outlook mobile). Ce système gère les domaines Microsoft, ceux enregistrés sur Office 365 et quelques autres selon leur importance et de façon plus ou moins obscure. On ne trouve nulle par le moyen d'ajouter un domaine à ce service et certaines discutions qui en parlaient sur les forums Technet sont maintenant effacées. On peu donc penser à des ajouts de gré à gré pour les sociétés sous contrat avec Microsoft.

il ne faut donc pas ajouter un compte depuis Outlook mais contourner la chose en passant par l'ancien panneau de contrôle (WIN+R+Control) tant qu'il existe. C'est d'autant plus curieux que ça fonctionne très bien sous l'application Courrier de Windoiws 10, qui au passage s'est bien améliorée. Il existe toutefois un moyen simple de désactiver Simplified Account Creation via le registre ou par GPO.

Et si j'ai plusieurs domaines ?

Dans tous les cas il faudra un serveur web par fournisseur de messagerie. Par contre ayant plusieurs domaines chez Gandi je vais pouvoir tout concentrer sur un seul serveur. Pour y parvenir, deux solutions :

Avec un enregistrement SRV par domaine

Je crée un serveur web générique, par exemple avec comme adresse

autodiscover-gandi.domain-gen.tld

(SSL activé) et dans le DNS de mes domaines je crée un enregistrement SRV de type

_autodiscover._tcp 1800 IN SRV 10 10 443 autodiscover-gandi.domain-gen.tld. 

La résolution sera un peu plus longue car c’est la dernière chose que recherchera Outlook, mais ça fonctionnera.

Avec un certificat multiple sur le serveur

Dans ce cas je fais pointer tous mes domaines sur le même serveur, par contre j'ajoute tous ces domaines (autodiscover.domain1.tld, autodiscover.domain2.tld...) au certificat du serveur, ce qui du reste est très facile avec Let's Encrypt.

Et Thunderbird ?

Même si plus grand monde utilise ce client, il existe une possibilité (que je n'ai pas testé et je suis preneur de vos retours). Et cette possibilité semble plus simple car elle permet de base de gérer plusieurs domaines que l'on appellera depuis le client avec une url : 

http://autoconfig.domain.tld/mail/[email protected]

Je ne pense pas qu'il soit utile de disposer de PHP, un simple fichier XML faisant l'affaire :

/wwwroot/domains/domain.tld/public_html/autoconfig/mail/config-v1.1.xml

<clientConfig version="1.1">
 <emailProvider id="domain.tld">
   <domain>domain.tld</domain>
   <displayName>%EMAILADDRESS%</displayName>
   <incomingServer type="imap">
     <hostname>mail.domain.tld</hostname>
     <port>993</port>
     <socketType>SSL</socketType>
     <username>%EMAILADDRESS%</username>
     <authentication>password-cleartext</authentication>
   </incomingServer>
   <outgoingServer type="smtp">
     <hostname>smtp.domain.tld</hostname>
     <port>587</port>
     <socketType>STARTTLS</socketType>
     <username>%EMAILADDRESS%</username>
     <authentication>password-cleartext</authentication>
   </outgoingServer>
 </emailProvider>
</clientConfig>

Une dernière chose, pour faire tout ça j'ai utilisé aaPanel, j'en parlerais bientôt mais je vous encourage à découvrir !

Sources

Etant donné que je n'ai bien sur rien inventé, voici de la lecture...

 

S/Mime pour chiffrer et signer vos e-mails

Quand on envoie un mail on ignore bien souvent que le niveau de confidentialité équivaut à peu près à une carte postale. En effet, tout comme la carte postale pourra être lue par le facteur, un mail pourra être lu par les différents services d’acheminement. De même ce n’est parce que l’adresse de l’expéditeur est emmanuel.macron@elysée.fr que c’est forcément le Président qui vous a contacté, tant il est simple de falsifier une adresse d’expéditeur.

On souhaite donc parfois d’une part garantir à un contact la provenance d’un message et d’autre par en assurer la confidentialité.

Pour y parvenir il existe plusieurs solutions, certaines sont propriétaires comme ce qui est offert (contre monnaie) par Office 365, plutôt simples à mettre en œuvre, d’autres s’appuient sur des utilitaires pour chiffrer le contenu et on peut également penser à PGP pour les plus geeks. Enfin, S/Mime répond à un standard défini en 1999 (RFC 1847) que l’on peut utiliser sur tous les clients de messagerie, et bien sûr moins facilement sur les Webmail qui eux ont tendance à rendre l’Internet de plus en plus propriétaire.

Pour faire court S/Mime est une méthode de chiffrement asymétrique qui utilise une paire de clés, l’une est privée, la vôtre, l’autre est publique, celle qui est transmise à vos correspondants.

Obtenir un certificat

Pour utiliser S/Mime il va falloir se procurer un certificat auprès d’une autorité de certification. Il existe plusieurs classes de certificats en fonction de la méthode de vérification. Cela va du simple échange de mails avec un niveau de sécurisation basic à un passage devant un notaire, qui, grace à la fourniture de documents, attestera de votre identité. On va ici s’en tenir à des certificats basics et gratuits, mais le principe d’utilisation reste le même.

La durée de vie d’un certificat ne peut pas excéder deux ans, voire moins pour certains. Dans notre cas, les certificats gratuits pour un usage personnel proposés par Actalis ou Comodo (il existe d'autres sources) ont une durée de validité de un an. Pour en faire la demande c’est très simple, il suffit de remplir un formulaire et de valider grâce aux informations reçues par mail, ce qui constitue la preuve de validation. (A une époque le site impots.gouv.fr en fournissait pour se connecter, cela aurait pu être une opportunité formidable de fournir des certificats aux citoyens, mais l’idée a été écartée).

Une fois le certificat obtenu, il faut l’importer dans son système d’exploitation, via une MMC sous Windows, ou via le trousseau de sécurité sur MacOS (ou sur votre mobile). Il n’y a plus ensuite qu’à configurer son logiciel de messagerie pour qu’il l’utilise et le tour est joué. On choisira soit de l’utiliser systématiquement pour signer ses messages, soit ponctuellement. Pour le chiffrement il faudra au préalable que votre correspondant ait reçu de votre part un message signé et vous en ayez reçu un de sa part afin de disposer de sa clé publique. Par ailleurs il est également possible d’utiliser de tels certificats pour signe des documents PDF par exemple.

Je ne vais pas vous expliquer pas à pas comment faire tout cela, d’autres l’ont très bien fait (Google est votre ami... avec le mot clé S/Mime). Le but était simplement de rappeler que cette possibilité existe, et qu’elle est définie par un standard.

Attention : la signature numérique prouve l'origine et authentifie l'expéditeur du message (le changement invaliderait la signature). Un chiffrement du message est conçu pour protéger le contenu secret du message.
Rappel : avant d’envoyer un message chiffré, vous aurez besoin de certificat S/MIME du destinataire. Principe de chiffrement des messages - le client chiffre un message avec la clé publique du destinataire qui le déchiffre avec sa clé privée.

Sources