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 reçus en copie cachée.
Il permet d'éliminer de nombreux spams.
Par contre, il convient de récupérer auparavant les mails
issus de mailing lists qui utilisent ce mode d'envoi.
Un message est généré à l'intention de l'expéditeur du mail
non récupéré.
Un fichier de configuration est utilisé pour se connecter à la
boite aux lettres et pour sélectionner le serveur SMTP servant
à l'envoi des messages.
*/
#define appli // pour la déclaration de variables globales à l'application
/* variables globales au source
(pour éviter des tonnes de passages de paramètres) */
char adr_util [120]; // adresse mail de l'utilisateur
char nom_util [120]; // nom (et prénom) de l'utilisateur
char **listexped; // liste des expéditeurs de mails en copie cachée autorisés
int nb_exped; // nombre d'expéditeurs mémorisés dans listexped
char pref_adr [120]; // préfixe vraie adresse mail pour la masquer aux
// robots qui traitent les réponses aux spams
FILE *ftrace; // fichier contenant les adresses d'expéditeurs refusés
char datecour [10]; // date courante (pour le fichier d'expéditeurs refusés)
int opts; // option -s (mails refusés non signalés aux expéditeurs)
int etat_smtp = 0; // état de la connexion smtp
char serv_smtp [120]; // nom du serveur smtp utilisé
char *ficmailrep; // fichier comptenant un mail pour réponse spécifique
/* compteurs */
int conserves = 0;
int supprimes = 0;
int avertis = 0;
int non_avertis = 0;
/* programme principal */
int main (int nbarg, char *varg[])
{
// fichier contenant les adresses d'expéditeurs à tester
char ficadr_OK [szchemin + 11];
char *car_ficadr_OK; // pointeur sur un caractère de ce fichier
FILE *fconf; // descripteur du fichier de configuration
int numes, nbmes; // numéro du mail courant et nombre de mails
int i, j; // compteurs pour chaines de caractères
// récupération du nom de l'exécutable
memcom (*varg);
// se positionner sur le premier argument de supbcc
nbarg --;
varg ++;
// initialisation des options de supbcc
*pref_adr = '\0';
ftrace = NULL;
ficmailrep = NULL;
opts = 0;
// prise en compte des options de supbcc
while (nbarg > 1 && **varg == '-')
{
// option -m (utilisation d'un mail de réponse spécifique)
if (varg [0][1] == 'm')
{
// mémoriser le nom du fichier contenant le mail de réponse
ficmailrep = varg [1];
// si ce fichier n'existe pas
if (access (ficmailrep, 0) != 0)
errfatale ("MANQUE_FICMAILREP", ficmailrep);
// option -s (pas de mail d'avertissement lorsque
// mail reçu en copie cachée détruit)
else if (strcmp (*varg, "-s") == 0)
{
opts = 1;
// sauter l'argument traité
nbarg --;
varg ++;
}
// option -t (utilisation d'un fichier trace)
else if (strcmp (*varg, "-t") == 0)
{
// 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;
}
// option incorrecte
else
{
// "Option %s incorrecte"
aff_err_arg ("ERR_OPTION", *varg);
nbarg = 0; // on terminera en affichant la syntaxe de la commande
}
}
// aucun traitement si option -m et -s utilisées simultanément
if (ficmailrep && opts)
// "Option -m et -s incompatibles"
affiche_err ("COMPAT_OPT_MS");
// aucun traitement si option -p et -s utilisées simultanément
else if (*pref_adr && opts)
// "Option -p et -s incompatibles"
affiche_err ("COMPAT_OPT_PS");
// sinon, controle du nombre d'arguments restants
else 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ération du nombre de mails
nbmes = nbmails ();
// s'il y a des mails à tester
if (nbmes > 0)
{
// récupérer le nom du répertoire racine de la messagerie
fgets (ficadr_OK, szchemin, fconf);
// fabriquer le chemin d'accès au fichier contenant les
// adresses d'expéditeurs de mails en copie cachée autorisés
// <racine>/accept_bcc
car_ficadr_OK = ficadr_OK + strlen (ficadr_OK);
*(car_ficadr_OK - 1) = '/';
strcpy (car_ficadr_OK, ficdir ("FIC_ACCEPT_BCC"));
// si ce fichier existe
if (access (ficadr_OK, 0) == 0)
// charger en mémoire la liste de ces expéditeurs
listexped = charge_valchamp (ficadr_OK, &nb_exped);
else
// sinon liste vide
nb_exped = 0;
// rechercher le @
while (buf_lect [i] != '@')
if (! buf_lect [i++])
{
// "Adresse Email erronée dans le fichier de configuration"
affiche_err ("ERR_ADR_MAIL");
exit (0);
}
// se positionner au début de l'adresse Email
while (i >= 0 && buf_lect [i] != '<'
&& buf_lect [i] != ' ' && buf_lect [i] != '\t')
i--;
if (supprimes && (opts == 0))
// "%d expéditeurs avertis, %d non avertis\n"
printf (message ("BILAN_AVERTIS"), avertis,
non_avertis);
// fermeture de la connexion smtp si elle a été ouverte
if (etat_smtp)
deconnect_smtp ();
}
// 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 [-pd|-p préfixe|-s] [-m fichier_mail_réponse]"
// " [-t fichier_trace] fichier_configuration"
psyntaxe2 ("SYNT_SUPBCC1", "SYNT_SUPBCC2");
}
// pour faire plaisir à gcc qui veut une fonction main de type int
return (0);
}
/* vérifie si le message choisi est en copie cachée, et
le détruit dans ce cas en avertissant l'expéditeur */
void filtremail (int numes)
{
char bufw [120]; // buffer d'envoi d'une requête
int adr_trouvee; // mémorise si l'adresse du destinataire
// est dans l'entête du mail
// message de suivi de déroulement
// "\rAnalyse du mail n° %d "
printf (message ("ANALYSE_MAIL"), numes);
fflush (stdout);
// demande de lecture de l'entête du message
sprintf (bufw, "TOP %d 1", numes);
env_pop (bufw);
// lire une ligne de l'entête du message
lire_pop ();
// lecture et mémorisation des caractéristiques du message
do
{
// convertir les caractères spéciaux
majlignentete ();
// chercher si on est destinataire principal du mail
if (start ("To"))
{
// mémoriser la première ligne du champ analysé
membuf (bufTo);
// si on n'a pas trouvé l'adresse du destinataire dans le champ Cc:
// (pour le cas où il apparaitrait avant le champ To: dans l'entête)
if (! adr_trouvee)
// vérifier si elle figure dans le champ To:
adr_trouvee = testdest ();
// sinon
else
// passer à la ligne suivante
lire_pop ();
}
// chercher si on est destinataire en copie du mail
else if (start ("Cc"))
{
// mémoriser la première ligne du champ analysé
membuf (bufCc);
// si on n'a pas trouvé l'adresse du destinataire dans le champ To:
if (! adr_trouvee)
// vérifier si elle figure dans le champ Cc:
adr_trouvee = testdest ();
// sinon
else
// passer à la ligne suivante
lire_pop ();
}
// mémorisation des autres champs importants de l'entête du mail
else
{
if (start ("Date"))
membuf (bufDate);
else if (start ("From"))
membuf (bufFrom);
else if (start ("Reply-To"))
membuf (bufReply);
else if (start ("Subject"))
membuf (bufSubject);
else if (start ("Return-Path"))
membuf (bufRetPath);
// 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');
// si on a reçu le mail en copie cachée et qu'il
// ne provient pas d'un expéditeur autorisé
if ((! adr_trouvee) && (! trouve_valchamp (bufFrom, listexped, nb_exped))
&& (! trouve_valchamp (bufReply, listexped, nb_exped)))
{
// demande de destruction du message
sprintf (bufw, "DELE %d", numes);
env_pop (bufw);
lire_pop ();
supprimes ++;
// si utilisation d'un fichier trace
if (ftrace)
// mémoriser l'adresse de l'expéditeur dans ce fichier
fprintf (ftrace, "%s%s\n", datecour, bufFrom + 5);
// envoyer un mail à l'expéditeur, sauf si option -s
if (! opts && (bufFrom [0] || bufRetPath [0]))
{
// si la connexion smtp n'a pas encore été ouverte
if (! etat_smtp)
{
// ouvrir cette connexion et mémoriser son ouverture
if (connect_smtp (serv_smtp))
etat_smtp = 1;
else
etat_smtp = -1;
}
// avertir si possible l'expéditeur et mémorise l'avertissement
if ((etat_smtp > 0) && avertir ())
avertis ++;
else
non_avertis ++;
}
}
else
conserves ++;
}
/* vérifie si le champ To: ou Cc: sur lequel on est
positionné contient l'adresse email de l'utilisateur */
int testdest ()
{
int trouve; // mémorise le résultat de l'analyse
int i, j; // pour parcourir les chaines de caractères à comparer
// initialisation
trouve = 0;
do
{
// on se positionne au début du champ à tester
i = 0;
// vérifier si la chaine adr_util se trouve dans buf_lect
do
{
j = 0;
while (tolower (buf_lect [i + j]) == adr_util [j])
// terminé si tous les caractères de adr_util trouvés
if (adr_util [++j] == 0)
trouve = 1;
}
// sinon recherche dans la suite de buf_lect
while (buf_lect [i++]);
// lire la ligne suivante de l'entête du message
lire_pop ();
}
// on continue jusqu'à ce qu'on trouve l'adresse
// ou qu'on ait traité toute l'entête
while ((*buf_lect == ' ' || *buf_lect == '\t') && ! trouve);
// retourner le résultat de l'analyse
return (trouve);
}
/* avertit l'expéditeur d'un mail en copie cachée que son message est refusé */
int avertir ()
{
char bufw [120]; // buffer d'envoi d'une ligne ou d'une requête smtp
// l'envoi du mail d'avertissement suppose l'accès à un fichier de données
if (! acces_mailrep (NULL, "supbcc"))
return (0);
// destinataire du message
strcpy (bufw, "RCPT TO: <");
// on envoie en priorité à l'adresse du Return_Path
if (bufRetPath [0])
ajout_adr (bufw, bufRetPath + 12);
// sinon à l'expéditeur déclaré
else
ajout_adr (bufw, bufFrom + 5);
// si destinataire refusé, on le signale
if (buf_lect [0] != '2')
{
// Affichage de l'adresse à problème
// "Destinataire %s refusé\n"
putchar ('\n');
printf (message ("REFUS_DEST"), bufw + 9);
puts (buf_lect);
// on n'envoie pas de mail
envoie_smtp ("RSET");
lire_smtp ();
return 0; // mail non envoyé
}
// préparation de l'envoi du message
envoie_smtp ("DATA");
lire_smtp ();
// génération de l'entête du message
// Champ date
gen_champ_date (bufw);
envoie_smtp (bufw);
// si préfixe, l'adresse expéditeur est modifiée dans
// l'entête du message pour tromper les robots de spam
if (*pref_adr)
sprintf (bufw, "From: <%s-%s>", pref_adr, adr_util);
else
sprintf (bufw, "From: <%s>", adr_util);
// chercher le @
while (source [orig] != '@' && source [orig])
orig ++;
// remonter au debut de l'adresse
while (orig > 0 && source [orig] != ' ' && source [orig] != '<')
orig--;
// l'adresse commence sur un caractère significatif
if (source [orig] == '<' || source [orig] == ' ')
debut = orig + 1;
else
debut = orig;
// copie de l'adresse
posdest = strlen (dest);
// on s'arrête si l'on rencontre un > , un blanc ou une fin de chaine
while (source [debut] != '>' && source [debut] & 0xDF)
dest [posdest++] = source [debut++];
// terminer l'expression de l'adresse
dest [posdest] = '\0';
}
/* copie dans le mail à envoyer d'une ligne du mail reçu */
void transf_ligne (char *message)
{
char bufw [82]; // buffer contenant la ligne à envoyer