/*
Fichier filtredest.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étruit les mails du serveur envoyés à des
destinataires particuliers.
Il sert à filtrer les spams envoyés à une adresse Email
alphabétiquement voisines de l'adresse de celui qui reçoit
le mail.
La liste des adresses de destinataires interdites est mémorisée
dans un fichier
Un fichier de configuration est utilisé pour se connecter à la
boite aux lettres.
*/
#define appli // pour la déclaration de variables globales à l'application
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "messages.h"
#include "buflect.h"
#include "ficonf.h"
#include "pop.h"
#include "testchamp.h"
#include "trtentete.h"
#include "datecour.h"
#include "szchemin.h"
/* prototypes */
int testdest (int numes);
/* variables globales au source
(pour éviter des tonnes de passages de paramètres) */
char **listedest; // mémorise les destinataires interdits
int sz_listedest; // nombre de destinataires mémorisés dans listedest
char bufTo [120]; // buffer contenant le destinataire du mail
int opto, optO; // options de traitement
// chaine de caractère mémorisée pour éviter appels répétitifs à message ()
char mess_analys [50]; // message signalant l'analyse d'un mail
/* programme principal */
int main (int nbarg, char *varg[])
{
// fichier contenant la liste des chaines à tester
char fichliste [szchemin + 11];
char *car_fichliste; // pointeur sur un caractère de ce fichier
FILE *fconf; // descripteur du fichier de configuration
FILE *ftrace; // fichier contenant les destinataires des mail refusés
int numes, nbmes; // muméro du mail courant et nombre de mails
char bufw [120]; // buffer d'envoi d'une requête de destruction de mail
char datecour [10]; // date courante (pour le fichier des mails refusés)
int conserves = 0; // nombre de mails conservés
int supprimes = 0; // nombre de mails supprimés
// récupération du nom de l'exécutable
memcom (*varg);
// se positionner sur le premier argument de filtredest
nbarg --;
varg ++;
// initialisations valeur des options
ftrace = NULL;
opto = 0;
optO = 0;
// si le programme a été lancé avec des options
while (nbarg >= 2 && **varg == '-')
{
// traitement des options
switch (varg [0][1])
{
// option trace des mails supprimés
case 't' : // ouvrir le fichier trace en écriture fin de fichier
ftrace = fopen (varg [1], "a");
// si nom de fichier correct
if (ftrace)
// initialiser la date courante
initdatecour (datecour);
else
// sinon, avertir l'utilisateur
// "Impossible d'écrire dans le fichier %s"
aff_err_arg ("IMPOS_ECR_FICH", varg [1]);
// sauter les arguments traités
nbarg -= 2;
varg += 2;
break;
// option test de la ligne d'entête d'origine (avant conversion)
case 'o' : if (! optO)
opto = 1;
else
// "L'option -O est prioritaire sur l'option -o"
affiche_err ("PRIO_OPT_O");
// sauter l'argument traité
nbarg --;
varg ++;
break;
// option test de la ligne d'entête d'origine (avant conversion)
case 'O' : optO = 1;
if (opto)
// "L'option -O est prioritaire sur l'option -o"
affiche_err ("PRIO_OPT_O");
// sauter l'argument traité
nbarg --;
varg ++;
break;
// aucune autre option n'est reconnue
// "Option %s incorrecte"
default : aff_err_arg ("ERR_OPTION", *varg);
nbarg = 0; // pour rappeller la syntaxe
}
}
// controle du nombre d'arguments restants
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 le nom du répertoire racine de la messagerie
fgets (fichliste, szchemin, fconf);
// fabriquer le chemin d'accès au fichier contenant les
// destinataires interdits : <racine>/refus_dest
car_fichliste = fichliste + strlen (fichliste);
*(car_fichliste - 1) = '/';
strcpy (car_fichliste, ficdir ("FIC_REFUS_DEST"));
// charger en mémoire les destinataires interdits
listedest = charge_valchamp (fichliste, &sz_listedest);
// si la liste n'est pas vide
if (sz_listedest)
{
// récupération du nombre de mails
nbmes = nbmails ();
// Initialisation du message à afficher
// à chaque analyse de mail
// "\rAnalyse du mail n° %d"
strcpy (mess_analys, message ("ANALYSE_MAIL"));
// vérification des différents mails
for (numes = 1; numes <= nbmes; numes++)
{
// si le destinataire du mail
// contient une chaine interdite
if (testdest (numes))
{
// demande de destruction du mail
sprintf (bufw, "DELE %d", numes);
env_pop (bufw);
lire_pop ();
supprimes ++;
// si utilisation d'un fichier trace
if (ftrace)
// mémoriser le destinataire de ce mail
fprintf (ftrace, "%s%s\n", datecour, bufTo);
}
else
conserves ++;
}
// édition d'un récapitulatif
// "\n%d messages conservés, %d supprimés\n"
printf (message ("BILAN_FILTRAGE"), conserves, supprimes);
}
// se déconnecter proprement du serveur pop
deconnect_pop ();
// si des mails ont été supprimés
if (supprimes)
// attendre pour enregistrement correct des suppressions
// (évite problème si autre filtre appelé juste après)
sleep (2);
}
// on n'a plus besoin du fichier de configuration
fclose (fconf);
}
}
else
// "Syntaxe : %s [-(o|O)] [-t fichier_trace] fich_configuration"
psyntaxe ("SYNT_FILT-DEST/SUJ");
return (0);
}
/* lit l'entête d'un mail et vérifie si son destinataire est autorisé */
int testdest (int numes)
{
char bufw [120]; // buffer d'envoi d'une requête
char destbrut [120]; // buffer contenant le destinataire du mail non décodé
int debdest; // position premier caractère utile du destinataire
// "\rAnalyse du mail n° %d"
printf (mess_analys, numes);
fflush (stdout);
// initialisation
bufTo [0] = '\0';
destbrut [0] = '\0';
// 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 entête du message et mémorisation du destinataire du mail
do
{
// si on a trouvé le champ destinataire
if (start ("To"))
{
// recherche du premier caractère significatif du destinataire
debdest = 3;
while (buf_lect [debdest] == ' ')
debdest++;
// si option -o ou -O
if (opto || optO)
{
// mémoriser destinataire du mail avant conversion en le
// tronquant si nécessaire pour éviter un débordement de tableau
if (strlen (buf_lect + debdest) >= sizeof (destbrut))
{
memcpy (destbrut, buf_lect + debdest, sizeof (destbrut));
destbrut [sizeof (destbrut) - 1] = '\0';
}
else
strcpy (destbrut, buf_lect + debdest);
}
// si on n'utilise pas l'option -O
if (! optO)
{
// convertir les caractères spéciaux de la ligne
majlignentete ();
// tronquer si nécessaire le destinataire
if (strlen (buf_lect + debdest) >= sizeof (bufTo))
buf_lect [debdest + sizeof (bufTo) - 1] = '\0';
// mémorisation du destinataire converti
strcpy (bufTo, buf_lect + debdest);
}
}
// 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');
// vérifier si le mail contient un des destinataires de la liste interdite
if (optO)
// option -O : test sur le destinataire brut seulement
return trouve_valchamp (destbrut, listedest, sz_listedest);
else if (opto)
{
// option -o (seule) : test sur le destinataire brut et converti
return (trouve_valchamp (destbrut, listedest, sz_listedest)
|| trouve_valchamp (bufTo, listedest, sz_listedest));
}
else
// aucune option : test sur le destinataire converti seulement
return trouve_valchamp (bufTo, listedest, sz_listedest);
}