/*
Fichier deplpartiel.c
Auteur Bernard Chardonneau
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 déplace vers une autre boite aux lettres parmi
les mail en attente sur le serveur de messagerie, ceux dont
l'un des champs contient (ou ne contient pas) une chaine de
caractères particulière.
Une option permet de conserver les mails sélectionnés dans la
boite aux lettres initiale. Dans ce cas, les mails sélectionnés
sont seulement copiés.
Un fichier de configuration est utilisé pour se connecter à
la boite aux lettres, pour connaitre l'adresse d'expédition
et pour sélectionner le serveur SMTP servant à la réexpédition
des mails.
Il s'agit d'une variante des fichiers de configuration utilisés
par la plupart des autres outils de libremail.
*/
#define appli // pour la déclaration de variables globales à l'application
/* prototype */
int testchamp (char *nomchamp, char *chainetest, int numes);
/* programme principal */
int main (int nbarg, char *varg[])
{
char serv_smtp [120]; // nom du serveur smtp utilisé
FILE *fconf; // descripteur du fichier de configuration
long nbmes; // nombre de mails sur le serveur
long numail; // numéro du mail à déplacer ou copier
long nbtraites; // récapitulatif nombre de mails copiés ou déplacés
int optc; // option : on conserve les mails déplacés
int optn; // option : mail déplacé si valchamp n'est pas trouvé
// dans le champ nomchamp ou si champ absent
char *nomchamp; // nom du champ sur lequel porte la sélection des mails
char *valchamp; // valeur de nomchamp pour que le mail soit sélectionné
// message signalant la copie ou le déplacement d'un mail
char mess_copdepl [50];
// récupération du nom de l'exécutable
memcom (*varg);
// se positionner sur le premier argument de deplpartiel
varg ++;
nbarg --;
// options de fonctionnement par défaut
optc = 0;
optn = 0;
// récupération des options de fonctionnement éventuelles
while (nbarg > 0 && **varg == '-')
{
switch (varg [0][1])
{
// option copie des mails plutôt que déplacement
case 'c': optc = 1;
break;
// option déplacement du mail si chaine non trouvée
case 'n': optn = 1;
break;
// "Option %s incorrecte"
default : aff_err_arg ("ERR_OPTION", *varg);
nbarg = 0; // pour afficher la syntaxe de la commande
}
// controle du nombre d'arguments restant
if (nbarg == 1)
{
// ouvrir le fichier de configuration
fconf = ouvre_ficonf (*varg);
if (fconf)
{
// connexion sur le compte mail du serveur pop
if (connect_pop (fconf))
{
// récupérer et mémoriser les adresses
// Email d'expédition et de destination
mem_adr (adr_exped, fconf);
mem_adr (adr_dest, fconf);
// récupération du nombre de mails
nbmes = nbmails ();
// si des mails peuvent être traités
if (nbmes)
{
// recupérer le nom du serveur smtp
fgets (serv_smtp, 120, fconf);
serv_smtp [strlen (serv_smtp) - 1] = '\0';
// connexion au serveur smtp pour l'envoi des mails
if (connect_smtp (serv_smtp))
{
// initialisation
nbtraites = 0;
// mémorisation message adapté au traitement des mails
if (optc)
strcpy (mess_copdepl, message ("COPIE_MAIL"));
else
strcpy (mess_copdepl, message ("DEPL_MAIL"));
// pour chaque mail du serveur
for (numail = 1; numail <= nbmes; numail++)
{
// si le champ à tester contient la chaine
// (ou ne la contient pas si option -n)
if (testchamp (nomchamp, valchamp, numail) != optn)
{
// message indiquant copie ou déplacement mail
printf (mess_copdepl, numail);
fflush (stdout);
// envoyer une copie du mail à l'autre adresse
copiemail (numail);
// si déplacement des mails
if (! optc)
// supprimer le mail du premier serveur
detruitmail (numail);
// on compte les mails copiés ou déplacés
nbtraites ++;
}
}
// édition d'un récapitulatif adapté
if (optc)
// "\n%d mails copiés sur %d\n"
printf (message ("TOTAL_COPIES"), nbtraites, nbmes);
else
// "\n%d mails déplacés sur %d\n"
printf (message ("TOTAL_DEPLACES"), nbtraites, nbmes);
// pour l'affichage
putchar ('\n');
// fermeture de la connexion smtp
deconnect_smtp ();
}
}
// se déconnecter proprement du serveur pop
deconnect_pop ();
}
// on n'a plus besoin du fichier de configuration
fclose (fconf);
}
}
else
// "Syntaxe : %s [-c] [-n] nom_champ chaine_champ fichier_configuration"
psyntaxe ("SYNT_DEPLPARTIEL");
// pour faire plaisir à gcc qui veut une fonction main de type int
return (0);
}
/* vérifie si le champ nomchamp du mail de numéro numes
contient la chaine passée en 2ème paramètre */
int testchamp (char *nomchamp, char *chainetest, int numes)
{
char bufw [120]; // buffer d'envoi d'une requête
char valchamp [120]; // contenu du champ à tester
int poschamp; // positionnement dans valchamp
int i; // positionnement dans chainetest
// initialisation
valchamp [0] = '\0';
// message de suivi de déroulement
// "\rAnalyse du mail n° %d "
printf (message ("ANALYSE_MAIL_BL"), numes);
fflush (stdout);
// demande de lecture de l'entête du message
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)
{
// Erreur serveur pour l'accès au mail
aff_err_argnum ("ERREUR_SERVEUR", numes);
return 0;
}
// lecture et mémorisation des caractéristiques du message
do
{
// si elle contient le champ recherché
if (start (nomchamp))
{
// convertir les caractères spéciaux
majlignentete ();
// et mémoriser ce champ
membuf (valchamp);
}
// lire la ligne suivante de l'entête du message
lire_pop ();
}
// lecture terminée si ligne limitée à un .
while (buf_lect [0] != '.' || buf_lect [1] != '\0');
// on se positionne au début du champ à tester
poschamp = 0;
// vérifier si la chaine chainetest se trouve dans valchamp
do
{
i = 0;
while (valchamp [poschamp+i] == chainetest [i])
{
// terminé si tous les caractères de chainetest trouvés
if (chainetest [++i] == 0)
return 1;
}
}
// sinon recherche dans la suite de valchamp
while (valchamp [poschamp++]);
// aucune des chaines de la liste n'a été trouvée dans valchamp
return (0);
}