<!--    Configure sendmail en dialup - SGML     -->
<!--          Jean Charles Delepine             -->
<!--         delepine@neuronnexion.fr           -->
<!--    http://www.neuronnexion.fr/~delepine    -->

<!doctype linuxdoc system>

<article>

<title>Configurer sendmail en dialup avec M4
<author>Jean Charles Delépine, <tt>delepine@neuronnexion.fr</tt>

<date>Version 0.7, 19 mai 1998.

<toc>

<sect>Préambule<p>

Régulièrement, sur <tt>fr.comp.os.linux</tt> ou sur
<tt>fr.comp.mail</tt>, 
la question de la configuration de <tt>sendmail</tt> pour des sites sans
liaison permanente est posée.<p> Des solutions existent dans différents
documents :
<itemize>
<item>
<url name="Guide du Rootard"
url="http://www.linux-france/article/grl/">
<item>
le package <url
url="http://www.linux-france.com/article/connex/cfg_dialup.tar.gz"
name="cfg_dialup">
<item>
le <url
url="http://www.freenix.fr/linux/HOWTO/mini/Sendmail+UUCP.html"
name="mini Howto Sendmail+UUCP">. 
</itemize>
Aucune d'elles ne me satisfait car elles
proposent de modifier (très légèrement) le source de sendmail quand de
simples options de configuration suffiraient (Guide, cfg_dialup) et/ou
sont basées sur de vieilles versions de sendmail (Sendmail+UUCP) et
ne fonctionnent plus depuis les versions 8.7.<p> 

Il m'a toujours semblé qu'il devait être possible d'obtenir une solution
utilisant le package de configuration <tt>m4</tt> fourni avec sendmail
et ce sans modifier les options de compilation de sendmail... et que
cette solution reste compréhensible par le plus grand nombre. C'est
l'objet de ce document.<p>

Un autre document du même type existe&nbsp;: <url
url="http://www.linux-france.com/article/mail/sendmail/" name="Lire et
envoyer du courrier off-line sur sa machine"> par Éric Jacoboni, je
vous recommande de le lire dans un premier temps si vous n'avez
aucune expérience du courier électronique&nbsp;: il est mieux rédigé
et plus didactique que ce document. Cependant, la solution
donnée me semble incomplète et trop axée sur une seule distribution
et je n'ai pas encore eu le temps de proposer des corrections à
Éric... je pense que nos deux documents se complètent et de toute façon, 
trop de documents valent mieux que trop peu.<p>

<sect>Le but du jeu :<p>
<itemize>
<item>obtenir un fichier de configuration sendmail (souvent
<tt>/etc/sendmail.cf</tt>) fonctionnant avec un sendmail quelconque
fourni par une distribution (par exemple Red Hat)
<item>les adresses locales doivent être réécrites de façon à
correspondre à l'adresse fournie par le fournisseur d'accès
<item>le courrier doit être converti en 8 bits quoi qu'il arrive
<item>utiliser m4 afin de générer automatiquement le sendmail.cf (un
fichier compliqué !) à partir d'un script .mc (simple, lui !)
</itemize><p>

Vous pouvez conserver le <tt>sendmail</tt> fourni par votre
distribution mais je vous recommande fortement de compiler vous même
la dernière version disponible que vous trouverez par exemple au <url
url="ftp://ftp.lip6.fr/pub/unix/mail/sendmail/ucb" name="LIP6">.

<sect>On y va...<p>

<sect1>introduction<p>

Vous trouverez dans le répertoire <tt>sendmail-ver/cf/cf</tt> une liste de
fichier .mc prédéfinis... vous pouvez vous baser sur ceux ci, sur le
fichier <tt>sendmail-ver/cf/README</tt> et sur le fichier
<tt>sendmail-ver/doc/op/op.me</tt> pour vous faire un fichier
<em>linux.rtc.mc</em> à votre convenance. Pensez aussi à consulter la <url
url="http://www.sendmail.org/faq/" name="FAQ de comp.mail.sendmail"><p>

Voici un exemple commenté basé sur la configuration suivante :<p>
<itemize>
<item>Domaine local non routable : <tt>mondomaine.a.moi</tt>
<item>Serveur SMTP du fournisseur d'accès : <tt>mail.domaine.fr</tt>
</itemize><p>

Ce document présente l'une des possibilités de sendmail qui permet de
définir un mailer particulier comme coûteux. Une autre option disant à
<tt>sendmail</tt> de garder en attente les messages utilisant de tels
médias, il nous suffit de définir le mailer <em>smtp</em> comme étant
<em>coûteux</em> pour voir tous les messages à destination de l'extérieur
rester <em>dans la queue</em> jusqu'à ce qu'on les en chasse explicitement
par un <tt>sendmail -q</tt>, placé par exemple dans le script ip-up lors
d'une connexion PPP.<p>

<sect1>Le fichier linux.rtc.mc<p>
<verb>
divert(-1)
#   linux.rtc.mc, version dialup
#   Copyright (C) 1998 Jean Charles Delépine
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
divert(0)
include(`../m4/cf.m4')dnl On récupère les macros générales...
dnl
VERSIONID(`@(#)linux.rtc.mc, 0.5 (Delépine) 17/05/1998')dnl
dnl
dnl ********************************************************************
OSTYPE(linux)dnl
dnl
dnl A priori on tournera sous linux cette ligne ne fait que définir
dnl un mailer local que l'on va s'empresser de redéfinir mais il vaut 
dnl mieux la laisser au cas où les futures versions de sendmail y
dnl ajouttent de nouvelles fonctionalités.
dnl
dnl ********************************************************************
DOMAIN(generic)dnl 
dnl
dnl le domaine 'generic' défini le nom des .forward, la feature 'redirect'
dnl et l'utilisation de sendmail.cw
dnl
dnl ********************************************************************
GENERICS_DOMAIN(mondomaine.a.moi mondomain)
dnl
dnl défini la classe des domaines influencés par les genericstables
dnl utilisées plus bas. Y mettre tous les noms que votre serveur peut 
dnl prendre suivant les outils utilisés (pine, netscape, mail...) 
dnl
dnl ********************************************************************
FEATURE(always_add_domain)dnl
dnl
dnl j'aime bien recevoir mes courriers locaux avec l'adresse réécrite
dnl
dnl ********************************************************************
FEATURE(masquerade_envelope)dnl
dnl
dnl pour que le from de l'enveloppe soit correct... nécessaire pour
dnl pouvoir contacter certains domaines bien gérés comme pasteur.fr ou 
dnl usenet.fr.net (posts dans des groupe modérés)  
dnl
dnl ********************************************************************
FEATURE(local_procmail)dnl
dnl
dnl Par défaut le mailer local pour linux est mail.local, je lui préfère 
dnl procmail d'autant plus que mail.local n'est généralement pas
dnl fourni avec les distributions actuelles de linux. Il peut être
dnl trouvé dans le package sources de sendmail.
dnl
dnl ATTENTION, procmail est sensé être dans /usr/local/bin mais si vous ne
dnl l'avez pas compilé vous même il est certainement dans /usr/bin... 
dnl FEATURE(local_procmail,``/usr/bin/procmail'')dnl
dnl
dnl ********************************************************************
FEATURE(genericstable,``hash -N /etc/revaliases'')dnl
dnl
dnl un FEATURE(genericstable) suffirait mais je veux rester cohérent
dnl avec la solution "Kit de Jussieu" fournie par le Guide du Rootard,
dnl je renomme donc /etc/genericstable en /etc/revaliases
dnl C'est dans ce fichier que nous définierons les règles de
dnl transcription d'adresse entre adresse locale -> adresse provider.
dnl ex: machin@mondomaine.a.moi -> ftif681124@wanadoo.fr 
dnl
dnl ********************************************************************
FEATURE(nocanonify)dnl
dnl
dnl On ne cherchera pas a canoniser les domaines des messages à
dnl envoyer.
dnl
dnl ********************************************************************
dnl define(`confDOMAIN_NAME',`ppp.domaine.fr')dnl
dnl 
dnl Afin d'être accepté par certains serveurs, il nous faut un nom 
dnl valide... c'est en particulier obligatoire pour pouvoir poster 
dnl des messages dans les groupes modérés de fr.
dnl Si vous disposez d'une adresse IP fixe, vous pouvez mettre ici
dnl le nom DNS de votre machine lors de sa connexion PPP.
dnl
dnl Si votre fournisseur d'accés utilise des adresses dynamiques,
dnl reportez vous à la section 
dnl "Que faire en cas d'attribution dynamique de l'adresse IP" 
dnl
dnl ********************************************************************
define(`confDEF_CHAR_SET', `ISO-8859-1')dnl
dnl
dnl pour que le destinataire sache comment lire notre 8bit
dnl
dnl ********************************************************************
define(`confCON_EXPENSIVE',`True')dnl
dnl
dnl Ce qui coûte cher doit attendre un 'sendmail -q'
dnl
dnl ********************************************************************
define(`confCOPY_ERRORS_TO', `Postmaster')dnl
dnl
dnl Les messages d'erreur doivent être envoyés en copie au Postmaster
dnl
dnl ********************************************************************
define(`confME_TOO', `True')dnl
dnl
dnl Pour que les messages envoyés à une liste locale soit aussi envoyés
dnl à l'auteur
dnl
dnl ********************************************************************
define(`SMART_HOST', `smtp8:[mail.domaine.fr]')dnl
dnl
dnl Ce n'est pas à moi de négocier avec le bout du monde et de toute façon,
dnl n'ayant pas de DNS, je ne saurais pas le faire...
dnl On utilise smtp8 pour envoyer les accents en 8 bits sans passage
dnl par le quoted unreadable. Attention, on considère ici que
dnl mail.domaine.fr dispose d'un MTA correct acceptant les messages en 
dnl 8 bits (soit la plupart si ce n'est tout les fournisseurs d'accès)
dnl
dnl ********************************************************************
define(`SMTP_MAILER_FLAGS', `e')dnl
dnl
dnl Le flag 'e' est là pour expensive : smtp coûte cher !
dnl
dnl ********************************************************************
dnl
MAILER(local)dnl
MAILER(smtp)dnl
dnl 
dnl Définition des mailers qui seront utilisés.
dnl
dnl ********************************************************************
</verb>

<sect1>Création du sendmail.cf<p>
Placez votre <em>linux.rtc.mc</em> modifié dans le repertoire
<tt>sendmail-ver/cf/cf</tt>, puis lancez les commandes :<p>

<verb>
cd sendmail-ver/cf/cf
m4 < linux.rtc.mc > sendmail.cf
</verb>

Copiez le <tt>sendmail.cf</tt> dans <tt>/etc</tt>

<sect1>Atteindre le serveur du fournisseur d'accès<p>

À partir des versions 8.7 de <tt>sendmail</tt> (si votre version est 
antérieure&nbsp;: changez-en !) <tt>sendmail</tt> utilise les
<em>service&nbsp;switch</em> sur les systèmes les supportant (Ultrix,
Solaris, OSF/1, linux-libc6...) et implante lui même ces services
via le fichier <tt>/etc/service.switch</tt> sur les autres systèmes
(SunOS, HP-UX, BSD, <em>Linux-libc5</em>, ...)<p> 

Si votre système utilise la Glibc2 (RedHat 5, Debian Hamm,...) vous devrez 
utiliser un fichier <tt>/etc/nsswitch.conf</tt> dont voici un exemple :
<verb>
     # /etc/nsswitch.conf
     #
     # Name Service Switch configuration file.
     #
     
     passwd:     files
     shadow:     files
     group:      files

     # On veut que le fichier /etc/hosts soit visité en
     # premier. 
     # Attention de bien laisser une référence au service de noms (DNS)
     # ou vous ne pourrez plus utiliser d'outils réseaux compilés en libc6 !
       
     hosts:      files dns

     networks:   files
     
     ethers:     files
     protocols:  files
     rpc:        db files
     services:   files
</verb>

Si vous utilisez encore la libc5, le fichier <tt>/etc/host.conf</tt> n'est
pas pris en compte par sendmail et vous devrez utiliser un fichier
<tt>/etc/service.switch</tt> contenant l'unique ligne :<p>
<verb>
hosts files
</verb>

Ainsi, quand <tt>sendmail</tt> cherchera le relai smtp, il ira 
directement voir dans <tt>/etc/hosts</tt> sans se soucier du 
<tt>DNS</tt>.<p>

Il est maintenant nécessaire de définir l'adresse IP du serveur SMTP dans 
<tt>/etc/hosts</tt><p>.
<verb>
xxx.xxx.xxx.xxx          mail.domaine.fr  mail
</verb>

<sect1>La réecriture des adresses<p>
Enfin, il faut réécrire l'adresse locale pour que les messages envoyés
aient un champ <tt>From</tt> correspondant à l'adresse fournie par le 
fournisseur. Il suffit d'ajouter dans <tt>/etc/revaliases</tt>
une ligne du style&nbsp;:<p>
<verb>
NomLocal:       NomFournisseur@fournisseur.fr
</verb>
Je vous recommande d'y ajouter aussi les diverses adresses que votre
serveur peut utiliser pour communiquer avec le reste du monde :<p>
<verb>
root:           NomFournisseur@fournisseur.fr
news:           NomFournisseur@fournisseur.fr
postmaster:     NomFournisseur@fournisseur.fr
...
</verb>

et ensuite de régénérer la base avec :<p>
<verb>
/usr/sbin/sendmail -bi -oA/etc/revaliases
</verb>

<sect1>Fin de la manip, lancement du serveur.<p>
Si un démon sendmail tourne actuellemnt, tuez le :<p>
<verb>
 kill `head -1 /var/run/sendmail.pid`
</verb>

Puis relancez le :<p>
<verb>
/usr/sbin/sendmail -bd -os
</verb>

Éditez vos fichiers de démarrage (souvent dans <tt>/etc/rc.?d</tt> ou
<tt>/etc/init.d</tt>) afin de modifier si nécessaire la ligne lançant sendmail
au moment du boot en la remplaçant par
<tt>/usr/sbin/sendmail&nbsp;-bd&nbsp;-os'.</tt> 
   
Voilà ! Les mails sont stockés dans <tt>/var/spool/mqueue</tt>.
Lorsque vous êtes connecté par PPP et que vous souhaitez envoyer votre 
courier, il vous suffit de faire 
<verb>
/usr/sbin/sendmail -q 
</verb>

Commande que j'ai personnellement ajouté au script
<tt>/etc/ppp/ip-up</tt>...<p>


<sect>Que faire en cas d'attribution dynamique de l'adresse IP<p>
<sect1>Quel est le problème ?<p>
sendmail lorsqu'il communique avec un autre MTA se présente
(commande HELO ou EHLO) en utilisant le contenu de la macro $j
qui est généralement le résultat de la commande <tt>hostname</tt>
sur le système hôte.<p>

Dans le cas d'une machine reliée de façon intermitente à l'Internet ce
résultat n'est généralement pas adresse officielle, déclarée, donc connue
du service de noms (DNS).<p>

Nous avons vu que la solution quand on dispose d'une adresse IP fixe
et valide consistait en forcer la définition de la macro $j par la
commande du kit m4 :<p>
<verb>
 define(`confDOMAIN_NAME',`ppp.domaine.fr')dnl
</verb>
Mais il faut, pour utiliser cette solution, connaître à l'avance le
nom qui sera attribué à notre machine lors de la future
connexion... ce n'est donc pas envisageable dans le cas qui nous
préoccupe.<p>

<sect1>Une solution.<p>
Dans le fichier <tt>/etc/sendmail.cf</tt> que nous venons de générer,
nous pouvons voir :<p>

<verb>
# my official domain name
# ... define this only if sendmail cannot automatically determine your domain
#Dj$w.Foo.COM
</verb>

C'est à cet endroit qu'a eventuellement lieu la définition de la macro
$j qui nous intéresse.<p>

Lors d'une connexion PPP, le script ip-up, lancé au début de la
connexion, reçoit en argument l'adresse IP qui nous a été
attribuée. Il est donc possible, dans ce script, de demander au
serveur de noms (le nôtre ou celui du provider) de transcrire cette
adresse IP en un nom de domaine pleinement qualifié, de modifier
<tt>/etc/sendmail.cf</tt> puis de relancer sendmail avec cette
nouvelle définition.<p>
 
Différentes méthodes et programmes le permettent mais la plupart sont
verbeux et nécessiteraient un filtre awk ou grep pour extraire le nom
qui nous intéresse... j'ai donc écrit un petit utilitaire très simple
<tt>gethost</tt> dans cet unique but.<p>
Pour pouvoir utiliser le script ip-up que je fournis plus loin :<p>
<itemize> 
<item>
copiez <tt>/etc/sendmail.cf</tt> en <tt>/etc/sendmail.cf.base</tt>
afin de disposer d'une base à partir de laquelle <tt>ip-up</tt> pourra
travailler.<p> 
<item>
Compilez <tt>gethost</tt> :
<verb>
cc -o gethost gethost.c 
</verb>
et placez-le dans le repertoire /usr/local/bin.<p>
</itemize>
Il vous reste à modifier votre fichier <tt>/etc/ppp/ip-up</tt> en y
intégrant le mien.

<sect1>Un exemple de script ip-up<p>
<verb>
#!/bin/sh
#   /etc/ppp/ip-up   script permettant de configurer correctement
#                    sendmail dans le cas des attributions 
#                    dynamique d'adresse IP
# 
#   Copyright © 04/1998 Jean Charles Delépine
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.

# Les paramètres passés à ip-up par pppd (man pppd) :
# $1 = nom de l'interface (ppp0)  
# $2 = périférique utilisé (/dev/modem)  
# $3 = vitesse de transmission
# $4 = adresse IP locale (celle qui nous intéresse)
# $5 = adresse IP distante (le serveur de modem du provider, sera
#      notre passerelle vers le reste du monde)
# $6 = ipparam (option donnée par l'utilisateur via l'option ipparam
#      de pppd)

HOST=`/usr/local/bin/gethost $4`

sed s/'#Dj.*'/"Dj$HOST"/ /etc/sendmail.cf.base >/etc/sendmail.cf 

kill -1 `head -1 /var/run/sendmail.pid` 

/usr/sbin/sendmail -q&

exit 0
</verb>

<sect1>Le programme gethost.c<p>
<verb>
/* 
    gethost.c, récupère le nom canonique d'une machine 
               à partir de son adresse IP.

    Copyright © 04/1998 Jean Charles Delépine
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
*/

#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>

int main(argc,argv)
char argc;
char *argv[];
{
  struct hostent *host;
  struct in_addr ia;

  if (argc < 2) {
    fprintf(stderr,"Usage : %s addr\n",argv[0]);
    exit(1);
  }
  if (!inet_aton (argv[1],&amp;ia)) {
      fprintf(stderr,"Erreur: adresse invalide\n");
      exit(1);
  } 
      
  host=gethostbyaddr((char *) &amp;ia, sizeof(ia), AF_INET);

  if (!host) {
    fprintf(stderr,"Erreur: adresse non trouvée ou pas de DNS\n");
    exit(1);
  }
  printf("%s\n",host->h_name);
  exit(0);
}
</verb>
<sect>Remarque<p>
Il est à noter que les sendmail.cf générés en suivant les indications du
Guide du Rootard (Kit de Jussieu) ou celles de cfg_dialup fonctionnent 
parfaitement sans modification des sendmail "constructeur" à condition 
de créer le fichier <tt>/etc/service.switch</tt> ou
<tt>/etc/nsswitch.conf</tt>susmentionné.<p>

<sect>Remerciements<p>
Je tiens à remercier tous les participants du groupe fr.comp.mail et
en particulier Alain Thivillon, Stéphane Bortzmeyer, Ollivier Robert et
Laurent Wacrenier pour les réponses qu'ils ont fourni et fournissent,
à moi et à d'autres. Ils m'ont permis d'affûter/corriger mes arguments
et par là même d'améliorer ce document.<p>
Je reserve un merci particulier à Denis Braussen qui n'est pas avare en 
questions pertinentes... Et qui propose ce document pour un oui ou pour
un non :-)<p>
Un petit mot pour Laurent Frigault qui a proposé la solution "Kit de
Jussieu" exposée dans le Guide du Rootard et à qui je voulais prouver
que le Kit m4 fonctionnait très bien.<p>
Merci enfin à Nat Makarevitch qui héberge ce document sur son site <url
url="http://www.linux-france.com/" name="linux-france"> et qui lors de 
chaque nouvelle version m'envoie un patch de corrections.

<sect>Fin<p>
Pour toute remarque quant à ce document, corrections, louanges, insultes,
écrire à <tt>delepine@neuronnexion.fr</tt><p>
</article>
