/*
Fichier chargepartaille.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 les mail en attente sur un serveur.
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.
Cette version de chargemail charge en premier les mails les plus
petits, puis les mails de plus en plus gros.
Contrairement à chargemail, les mails téléchargés sont détruits du
serveur sans attendre la fin du téléchargement. Ainsi, s'il y a
une rupture de connexion pendant l'utilisation de chargepartaille,
il ne sera pas nécessaire de télécharger une autre fois la plupart
des mails déjà récupérés.
*/
#define appli // pour la déclaration de variables globales à l'application
/* constantes */
#define nb_sec 20 // durée entre 2 validations d'effacement des mails
#define taille_dep 5000 // taille maximale des mails chargés en premier
#define szmaxliste 100 // longueur max de la liste des tailles de mail
/* variables globales au source
(pour éviter des tonnes de passages de paramètres) */
char dirmails [szchemin]; // répertoire de destination des messages
FILE *fconf; // descripteur du fichier de configuration
// chaine de caractères mémorisée pour éviter un appel répétitif à message ()
char mess_telech [50]; // message signalant le téléchargement d'un mail
/* programme principal */
int main (int nbarg, char *varg[])
{
// récupération du nom de l'exécutable
memcom (*varg);
// controle du nombre d'arguments
if (--nbarg == 1)
{
// ouvrir le fichier de configuration
fconf = ouvre_ficonf (varg [1]);
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);
// Initialisation du message à
// afficher à chaque téléchargement
// "\rTéléchargement du mail n° %d"
strcpy (mess_telech, message ("TELECH_MAIL"));
// télécharger les mails par taille croissante
chargepartaille ();
}
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 fichier_configuration"
psyntaxe ("SYNT_CHARGEPARTAIL");
// pour faire plaisir à gcc qui veut une fonction main de type int
return (0);
}
/* télécharge les mails par taille croissante en validant
périodiquement leur destruction sur le serveur */
void chargepartaille ()
{
long listetaille [szmaxliste]; // nombre d'octets des différents mails
int posliste, szliste; // position et nombre d'éléments dans listetaille
long numail; // numéro du mail dans le fichier téléchargé
long taillemax; // taille maximale mails téléchargés à cette étape
int etape; // numéro d'étape
unsigned long heurefin; // pour décider de changer d'étape
long tampon; // variable de travail
// initialisation
taillemax = taille_dep;
etape = 1;
// récupération du numéro du dernier fichier mail déjà téléchargé
numail = num_dermail (dirmails);
// récupération du nombre de mails
szliste = nbmails ();
// tant qu'il y a des mails à télécharger
while (szliste > 0)
{
// "%d mails en attente de téléchargement\n"
printf (message ("A_TELECHARGER"), szliste);
// limiter si nécessaire le nombre de mails traités à cette étape
if (szliste > szmaxliste)
szliste = szmaxliste;
// calcul de l'heure du changement d'étape
heurefin = time (0) + nb_sec;
// mémoriser les tailles des mails
env_pop ("LIST");
posliste = 0;
// sauter le message d'entête de la liste
lire_pop ();
do
{
// lire la taille d'un mail
lire_pop ();
// s'ils sont trop nombreux, on ne mémorise que les premiers
if (posliste < szliste)
sscanf (buf_lect, "%ld%ld", &tampon, &listetaille [posliste++]);
}
while (buf_lect [0] != '.');
// se positionner en début de liste
posliste = 0;
// rechercher le premier mail dont la taille convient
while (listetaille [posliste] > taillemax)
{
// tant qu'on n'en trouve pas, on avance dans la liste
if (++posliste == szliste)
{
// si pas trouvé en fin de liste, essayer avec taille supérieure
taillemax = taillemax * 2;
posliste = 0;
}
}
// téléchargement des mails dont la taille convient
do
{
if (listetaille [posliste] <= taillemax)
// attention à la numérotation des mails
chargemail (posliste + 1, ++numail);
}
while (++posliste < szliste && heurefin > time (0));
// pour l'affichage
putchar ('\n');
// valider la destruction des mails téléchargés
deconnect_pop ();
// et recommencer une étape similaire
rewind (fconf);
connect_pop (fconf);
szliste = nbmails ();
}
// sauvegarde du numéro du dernier fichier mail
sauv_num_dermail (dirmails, numail);
}
/* télécharge le mail choisi et l'enlève du serveur */
// 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
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);
}