Logiciel libre, droits d'utilisation précisés en français
dans le fichier : licence-fr.txt
Traductions des droits d'utilisation dans les fichiers :
licence-de.txt , licence-en.txt , licence-es.txt ,
licence-it.txt , licence-nl.txt , licence-pt.txt ,
licence-eo.txt , licence-eo-utf.txt
Droits d'utilisation également sur la page web :
http://libremail.tuxfamily.org/voir.php?page=droits
Ce programme affiche les caractéristique de chaque mail
en attente de téléchargement (ou de destruction).
Il y a 3 formats d'affichage.
Le format détaillé (option -d) donne plusieurs lignes d'information :
- date et heure d'envoi
- expéditeur et destinataire(s) + éventuelle adresse de réponse
- sujet du mail
- format du message (texte, html ...)
- éventuellement premières lignes du message
Le format simplifié (option -s) affiche une ligne par message :
nom expéditeur sujet date et heure d'envoi
La variante du format simplifié (option -e) affiche une ligne par message :
adresse expéditeur sujet date et heure d'envoi
Un fichier de configuration est utilisé pour se connecter à la
boite aux lettres.
*/
#define appli // pour la déclaration de variables globales à l'application
/* variables globales au source
(pour éviter des tonnes de passages de paramètres) */
int nblig_mes; // nombre de lignes à afficher pour chaque message
int opt_aff; // option affichage (simple = -s et -e, détaillé = -d)
int opt_inv = 0; // option inversion de l'ordre d'affichage des mails
int test_xorig; // traitement ou non du champ X-Original-From
// largeur des champs affichés en mode simplifié (options -s et -e)
int sz_nom, sz_adr, sz_avantdate;
/* programme principal */
int main (int nbarg, char *varg[])
{
FILE *fconf; // descripteur du fichier de configuration
int numes, nbmes; // numéro du mail courant et nombre de mails
int lg_num; // nombre caractères pour afficher tous numéros mails
int sup_nbmes; // variable pour calculer lg_num
char format_numes [6]; // format affichage numéros mails
int largeur; // largeur de l'affichage si option -s ou -e
char *varenv_xorig; // variable d'environnement libremail_xorig
// récupération du nom de l'exécutable
memcom (*varg);
// se positionner sur le premier argument de sjmails
varg ++;
nbarg --;
// initialisation options de fonctionnement
opt_aff = opt_s;
nblig_mes = 0;
largeur = 0; // la valeur sera fixée plus tard
// récupération des options de fonctionnement éventuelles
while (nbarg > 0 && **varg == '-' && varg [0][2] == '\0')
{
switch (varg [0][1])
{
// option affichage détaillé
case 'd' : opt_aff = opt_d;
// recupération du nombre de lignes s'il existe
nblig_mes = atoi (varg [1]);
// dans ce cas, décompter l'argument traité
if (nblig_mes || *varg [1] == '0')
{
varg ++;
nbarg --;
}
// affichage détaillé ou résumé de l'entête des mails
if (opt_aff == opt_d)
{
// l'ordre d'affichage dépend de l'option -i éventuelle
if (opt_inv)
{
// option -i : on affiche les mails
// du plus récent au plus ancien
for (numes = nbmes; numes >= 1; numes--)
aff_detail (numes);
}
else
{
// pas d'option : on affiche les mails
// dans leur ordre d'arrivée sur le serveur
for (numes = 1; numes <= nbmes; numes++)
aff_detail (numes);
}
}
else
{
// auparavant calcul nbre min de car pour n° messages
lg_num = 1;
sup_nbmes = 10;
// et fabrication de la chaine de format d'affichage
sprintf (format_numes, "%%%dd ", lg_num++);
// valeur par défaut de la largeur
// d'affichage si elle n'a pas été fixée
if (! largeur)
largeur = 80;
// calcul de la taille des différentes zones d'affichage
sz_nom = (largeur / 4) + lg_num;
sz_adr = (largeur / 3) + lg_num - 2;
sz_avantdate = largeur - 13;
// affichage résumé des entêtes de mails
// l'ordre d'affichage dépend de l'option -i éventuelle
if (opt_inv)
{
// option -i : on affiche les mails
// du plus récent au plus ancien
for (numes = nbmes; numes >= 1; numes--)
{
printf (format_numes, numes);
aff_resume (numes, lg_num);
}
}
else
{
// pas d'option : on affiche les mails
// dans leur ordre d'arrivée sur le serveur
for (numes = 1; numes <= nbmes; numes++)
{
printf (format_numes, numes);
aff_resume (numes, lg_num);
}
}
}
// se déconnecter proprement du serveur pop
deconnect_pop ();
}
// on n'a plus besoin du fichier de configuration
fclose (fconf);
}
}
else
// "Syntaxe : %s [-(s|e|d [nb_lignes_messages])]
// [-w largeur] [-i] fichier_configuration"
psyntaxe ("SYNT_SJMAILS");
// pour faire plaisir à gcc qui veut une fonction main de type int
return (0);
}
/* lit l'entête d'un message et affiche certaines lignes */
void aff_detail (int numes)
{
char bufw [120]; // buffer d'envoi d'une requête
// buffers pour affichage ordonné des caractéristiques du message
char bufFrom [120], bufTo [120], bufCc [120], bufReply [120],
bufSubject [120], bufContent [120], bufXorig [120];
int i, j; // simples compteurs
// lire la première ligne de l'entête du message
lire_pop ();
// terminé pour ce mail si erreur d'envoi coté serveur
if (memcmp (buf_lect, "-ERR ", 5) == 0)
{
puts (buf_lect);
return;
}
// lecture et mémorisation des caractéristiques du message
do
{
// si c'est le champ sujet
if (start ("Subject"))
{
// mémoriser la ligne
memconvbuf (bufSubject);
// on va tester la ligne qui suit
lire_pop ();
majlignentete ();
// si c'est encore une ligne du sujet
if (*buf_lect == ' ' || *buf_lect == '\t')
{
// initialisation compteurs
i = 1;
j = strlen (bufSubject);
// compléter le sujet du mail
while (buf_lect [i] && j < sizeof (bufSubject) - 1)
bufSubject [j++] = buf_lect [i++];
// terminer la chaine de caractères
bufSubject [j] = '\0';
}
}
// mémorisation des autres caractéristiques importantes
if (start ("Date"))
puts (buf_lect); // la date est affichée directement
else if (start ("From"))
memconvbuf (bufFrom);
else if (start ("X-Original-From") && test_xorig)
memconvbuf (bufXorig);
else if (start ("To"))
memconvbuf (bufTo);
else if (start ("Cc"))
memconvbuf (bufCc);
else if (start ("Reply-To"))
memconvbuf (bufReply);
else if (start ("Content-Type"))
{
membuf (bufContent);
if (recup_ctype () == TextPlain)
lire_charset ();
}
else if (start ("Content-Transfer-Encoding"))
mem_encodage ();
// lire la ligne suivante de l'entête du message
lire_pop ();
}
while (buf_lect [0] != '\0'); // lecture entête terminée si ligne vide
// affichage des caractéristiques mémorisées
if (bufFrom [0])
puts (bufFrom);
if (bufXorig [0])
puts (bufXorig);
if (bufTo [0])
puts (bufTo);
if (bufCc [0])
puts (bufCc);
if (bufReply [0])
puts (bufReply);
if (bufSubject [0])
puts (bufSubject);
if (bufContent [0])
puts (bufContent);
// sauter la ligne blanche qui précède le message
lire_pop ();
// lecture de la fin du message jusqu'a une ligne limitée a un .
while (buf_lect [0] != '.' || buf_lect [1] != '\0')
{
// affichage éventuel des dernières lignes lues
if (nblig_mes)
{
// on prend en compte les nouveaux champs Content éventuels
if (start ("Content-Type") && recup_ctype () == TextPlain)
lire_charset ();
else if (start ("Content-Transfer-Encoding"))
mem_encodage ();
// convertir la ligne lue et l'afficher
majligne ();
printf ("%s", buf_lect);
}
// et lecture de la suivante
lire_pop ();
}
}
/* lit l'entête d'un message et affiche un résumé sur une ligne */
void aff_resume (int numes, int lg_num)
{
char bufw [120]; // buffer d'envoi d'une requête
// buffers pour affichage ordonné des caractéristiques du message
char bufFrom [120], bufSubject [120], bufDate [120];
// 1ère et éventuellement 3ème lettre des noms de mois
static char *mois [] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
int sz_champ1; // nombre max de caractères du champ expéditeur
int i, j; // simples compteurs
// demande de lecture de l'entête du message
if (nblig_mes)
sprintf (bufw, "TOP %d %d", numes, nblig_mes);
else
sprintf (bufw, "TOP %d 1", numes);
env_pop (bufw);
// lire la première ligne de l'entête du message
lire_pop ();
// terminé pour ce mail si erreur d'envoi coté serveur
if (memcmp (buf_lect, "-ERR ", 5) == 0)
{
puts (buf_lect);
return;
}
// lecture et mémorisation des caractéristiques du message
do
{
// si c'est le champ sujet
if (start ("Subject"))
{
// mémoriser la ligne
memconvbuf (bufSubject);
// on va tester la ligne qui suit
lire_pop ();
majlignentete ();
// si c'est encore une ligne du sujet
if (*buf_lect == ' ' || *buf_lect == '\t')
{
// initialisation compteurs
i = 1;
j = strlen (bufSubject);
// compléter le sujet du mail
while (buf_lect [i] && j < sizeof (bufSubject) - 1)
bufSubject [j++] = buf_lect [i++];
// terminer la chaine de caractères
bufSubject [j] = '\0';
}
}
// mémorisation des autres caractéristiques importantes
if (start ("Date"))
membuf (bufDate);
else if (start ("From") && ! *bufFrom)
memconvbuf (bufFrom);
else if (start ("X-Original-From") && test_xorig)
memconvbuf (bufFrom);
// lire la ligne suivante de l'entête du message
lire_pop ();
}
while (buf_lect [0] != '.' || buf_lect [1] != '\0');
// initialisation : on est en début de ligne
i = lg_num;
// affichage du nom ou de l'adresse de l'expéditeur du message
if (*bufFrom)
{
if (tolower (*bufFrom) == 'x')
j = 16;
else
j = 6;
// option -s : affichage du nom de l'expéditeur
if (opt_aff == opt_s)
{
while (bufFrom [j] == '"' || bufFrom [j] == ' ')
j++;
putchar (bufFrom [j++]);
// si affichage avec un jeu de caractères ISO-8859
if (! util_utf8 ())
{
// on affichera sz_nom caractères maximum
while (++i < sz_nom && bufFrom [j] && bufFrom [j] != '<'
&& bufFrom [j] != '"' && bufFrom [j] != '=')
putchar (bufFrom [j++]);
}
// sinon (affichage avec le jeu de caractères UTF-8)
else
{
// on affichera toujours sz_nom caractères maximum
while (++i < sz_nom && bufFrom [j] && bufFrom [j] != '<'
&& bufFrom [j] != '"' && bufFrom [j] != '=')
{
// mais certains caractères ne seront pas comptés
/* il serait plus logique de ne pas compter les caractères
entre 0x80 et 0xBF, mais certains caractères UTF8 codés
sur 3 (ou 4 ?) octets s'affichent en largeur double, ce
qui décale les autres colonnes et génère un saut de ligne
intempestif après la date */
if ((bufFrom [j] & 0xC0) == 0xC0)
i--;
putchar (bufFrom [j++]);
}
}
}
// option -e : affichage de l'adresse de l'expéditeur
else
{
// recherche de la partie adresse de l'expéditeur
while (bufFrom [j] != '@' && bufFrom [j])
j++;
// positionnement au début de cette adresse
while (bufFrom [j] != '<' && bufFrom [j] != ' ')
j--;
j++;
// copie de l'adresse
putchar (tolower (bufFrom [j++]));
// pour ne pas tronquer l'adresse, on
// accepte de déborder sur le champ sujet
while (++i < sz_avantdate && bufFrom [j]
&& bufFrom [j] != '>')
putchar (tolower (bufFrom [j++]));
}
}
// détermination nombre de caractères réservé au champ expéditeur
if (opt_aff == opt_s)
sz_champ1 = sz_nom;
else
sz_champ1 = sz_adr;
// compléter ce champ par des blancs
while (i++ <= sz_champ1)
putchar (' ');
// affichage du sujet du message
if (*bufSubject)
{
j = 9;
// on saute les blancs inutiles
while (bufSubject [j] == ' ')
j++;
// si affichage avec un jeu de caractères ISO-8859
if (! util_utf8 ())
{
// on affichera jusqu'à sz_avantdate caractères maximum
while (++i < sz_avantdate && bufSubject [j])
{
// si présence d'une tabulation
if (bufSubject [j] == '\t')
{
// afficher un blanc pour une meilleure mise en page
putchar (' ');
j++;
}
else
// sinon affichage du caractère
putchar (bufSubject [j++]);
}
}
// sinon (affichage avec le jeu de caractères UTF-8)
else
{
// on affichera jusqu'à sz_avantdate caractères maximum
while (++i < sz_avantdate && bufSubject [j])
{
// si présence d'une tabulation
if (bufSubject [j] == '\t')
{
// afficher un blanc pour une meilleure mise en page
putchar (' ');
j++;
}
// sinon affichage du caractère
else
{
// mais certains caractères ne seront pas comptés
// même remarque que pour bufFrom
if ((bufSubject [j] & 0xC0) == 0xC0)
i--;