/*
Fichier chargepartiel.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 télécharge 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.
Un fichier de configuration est utilisé pour se connecter à la
boite aux lettres et pour fixer le répertoire racine du système
de messagerie.
Les mail entrants sont stockés dans le sous répertoire "entree"
de ce répertoire racine et se distinguent par leur numéro.
*/
#define appli // pour la déclaration de variables globales à l'application
/* constantes pour indiquer si l'on efface le(s) mail(s) téléchargé(s) */
#define OPTDEFAUT 0
#define EFFACE 1
#define CONSERVE 2
/* prototypes */
int testchamp (char *nomchamp, char *chainetest, int numes);
void chargemail (int numes, long numail, int effacement);
/* variable globale au source
(pour éviter des tonnes de passages de paramètres) */
char dirmails [szchemin]; // répertoire de destination des messages
// chaines de caractères mémorisées pour éviter appels répétitifs à message ()
char mess_analys [50]; // message signalant l'analyse d'un mail
char mess_telech [50]; // message signalant le téléchargement d'un mail
/* 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 nbrecup = 0; // nombre de mails téléchargés
long numail; // numéro du mail dans le fichier téléchargé
int option; // option : détermine si on conserve les mails récupérés
int optn; // option : mail récupéré si la chaine n'est pas
// trouvée dans le champ ou si champ absent
char *ncom; // nom de la commande que l'on exécute (chargepartiel)
// récupération du nom de l'exécutable
memcom (*varg);
// se positionner sur le premier argument de chargepartiel
varg ++;
nbarg --;
// options de fonctionnement par défaut
option = OPTDEFAUT;
optn = 0;
// récupération de l'option de fonctionnement éventuelle
while (nbarg > 0 && **varg == '-')
{
switch (varg [0][1])
{
// option effacement du serveur des mails récupérés
case 'd': if (option == CONSERVE)
{
// "Options -d et -k incompatibles"
affiche_err ("COMPAT_OPT_DK");
return (-1);
}
else
option = EFFACE;
break;
// option conservation sur le serveur des mails récupérés
case 'k': if (option == EFFACE)
{
// "Options -d et -k incompatibles"
affiche_err ("COMPAT_OPT_DK");
return (-1);
}
else
option = CONSERVE;
break;
// option récupération 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
if (nbarg == 3)
{
// ouvrir le fichier de configuration
fconf = ouvre_ficonf (varg [2]);
if (fconf)
{
// connexion sur le compte mail du serveur pop
if (connect_pop (fconf))
{
// récupérer le répertoire racine de la messagerie
fgets (dirmails, sizeof (dirmails) - 7, fconf);
dirmails [strlen (dirmails) - 1] = '\0';
// si ce répertoire existe
if (access (dirmails, 0) == 0)
{
// créer si nécessaire le sous repertoire d'entrée
strcat (dirmails, "/");
strcat (dirmails, ficdir ("DIR_ENTREE"));
mkdir (dirmails, 0755);
// récupération du nombre de mails
nbmes = nbmails ();
// si des mails peuvent être récupérés
if (nbmes)
{
// récupération du numéro du dernier fichier mail
numail = num_dermail (dirmails);
// Initialisation des messages à afficher à chaque
// analyse ou téléchargement de mail
// "\rAnalyse du mail n° %d "
strcpy (mess_analys, message ("ANALYSE_MAIL_BL"));
// "\rTéléchargement du mail n° %d"
strcpy (mess_telech, message ("TELECH_MAIL"));
// pour chaque fichier mail du serveur
for (numes = 1; numes <= nbmes; numes++)
{
// si le champ à tester contient la chaine
// ou ne la contient pas si option -n
if (testchamp (varg [0], varg [1], numes) != optn)
{
// télécharger le mail correspondant
chargemail (numes, ++numail, option);
// on compte les mails téléchargés
nbrecup ++;
}
}
// édition d'un récapitulatif
// "\n%d mails téléchargés sur %d\n"
printf (message ("TOTAL_TELECH"), nbrecup, nbmes);
// sauvegarde du numéro du dernier fichier mail
sauv_num_dermail (dirmails, numail);
}
}
else
// "répertoire de messagerie %s inexistant"
aff_err_arg ("REP_RACINE_ABSENT", dirmails);
// se déconnecter proprement du serveur pop
deconnect_pop ();
}
// on n'a plus besoin du fichier de configuration
fclose (fconf);
}
}
else
// "Syntaxe : %s [(-k|d)] [-n] nom_champ chaine_champ fichier_configuration"
psyntaxe ("SYNT_CHARGEPARTIEL");
// 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 (mess_analys, 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);
}
/* télécharge le message choisi et l'enlève du serveur si c'est demandé */
void chargemail (int numes, long numail, int effacement)
{
char bufw [120]; // buffer d'envoi d'une requête
char ficmail [sizeof (dirmails) + 9];
FILE *fmail;
// création du fichier mail
sprintf (ficmail, "%s/r%07ld.n", dirmails, numail);
fmail = fopen (ficmail, "w");
if (fmail)
{
// message de suivi du déroulement
// "\rTéléchargement du mail n° %d"
printf (mess_telech, numes);
fflush (stdout);
// demande de lecture du message et réception de l'acquittement
sprintf (bufw, "RETR %d", numes);
env_pop (bufw);
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);
fclose (fmail);
unlink (ficmail);
return;
}
// lire la première ligne de l'entête du mail
lire_pop ();
// lecture et copie du message jusqu'à une ligne limitée a un .
while (buf_lect [0] != '.' || buf_lect [1] != '\0')
{
// copie de la ligne lue dans le fichier mail
fputs (buf_lect, fmail);
fputc ('\n', fmail); // nécessaire car supprimé de buf_lect
// et lecture de la suivante
lire_pop ();
}
// fermer le fichier contenant le mail
fclose (fmail);
// et supprimer si nécessaire le mail du serveur
if (effacement != CONSERVE)
{
sprintf (bufw, "DELE %d", numes);
env_pop (bufw);
lire_pop ();
}
}
else
// "Impossible d'écrire dans le fichier %s"
aff_err_arg ("IMPOS_ECR_FICH", ficmail);
}