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 transfère le fichier mail passé en paramètre
Le chemin d'accès au fichier peut être absolu ou relatif.
On peut choisir les destinataires à partir du carnet d'adresses
ou en saisir de nouveaux
Le fichier obtenu est ensuite stoqué dans le répertoire des mails à envoyer
Pour que cela soit possible, il faut :
- soit que la commande trsfmail soit lancée depuis la chaine vmail...
- soit préciser le nom du répertoire de l'arborescence des mails
*/
#define appli // pour la déclaration de variables globales à l'application
/* variable globale au source
(pour éviter des passages de paramètres) */
long numail; // numéro que prendra le mail généré
/* programme principal */
int main (int nbarg, char *varg[])
{
char fictmp [szchemin]; // fichier de travail pour fabriquer le mail
char ficmail [szchemin]; // nom du fichier mail définitif
char *commande = ficmail; // réutilisation tableau pour appel de l'éditeur
char *editeur; // éditeur utilisé pour modifier le mail
// récupération du nom de l'exécutable
memcom (*varg);
// si nombre d'arguments correct
if (--nbarg == 1 || nbarg == 2)
{
// ouvrir le fichier mail auquel on doit répondre
fmail = fopen (varg [1], "r");
// terminé si le fichier n'a pas pu être ouvert
if (! fmail)
{
if (access (varg [1], 0) == 0)
// "Problème d'accès au fichier %s"
errfatale ("ACCES_FICHIER", varg [1]);
else
// "Fichier %s inexistant"
errfatale ("FICH_INEXISTANT", varg [1]);
}
}
// sinon, rappel de la syntaxe de la commande
else
// "Syntaxe : %s nom_fichier_mail [répertoire_emails]"
psyntaxe ("SYNT_REP/TRSF-MAIL");
// on démarre avec la configuration standard du clavier
mode_normal ();
// récupérer le nom du répertoire des mails à envoyer
recupdirenv (nbarg, varg [2]);
// créer un nom de fichier temporaire pour le mail
// il a toujours le même nom pour éviter de polluer le
// répertoire d'envoi en cas de fausse manoeuvre opérateur
sprintf (fictmp, "%s/tmp-mes", direnv);
// charger le carnet d'adresses
charge_carnet_adr ();
// configurer la liaison clavier pour lecture directe avec timeout
mode_raw ();
// fabriquer l'entête du mail de réponse
gene_entete (fictmp);
// retour à la configuration standard du clavier
mode_normal ();
// mémoriser les dates et heure d'envoi du message
ajout_date (fictmp);
// recopier le contenu du mail à transférer
ajout_entete (fictmp);
// modification avant envoi ?
// "Voulez vous modifier le fichier mail avant envoi ? "
affiche_msg_nocr ("MAJ_MAIL_PRET");
if (tolower (getchar ()) != 'n')
{
// si oui, choix de l'éditeur de textes
editeur = getenv ("EDITOR");
if (! editeur)
editeur = "vi";
// et modification du mail
sprintf (commande, "%s %s", editeur, fictmp);
system (commande);
}
// donner au fichier mail son nom définitif
sprintf (ficmail, "%s/e%07ld", direnv, numail);
rename (fictmp, ficmail);
// mettre à jour le fichier numail du répertoire de sortie
sauv_num_dermail (direnv, numail);
// pour faire plaisir à gcc qui veut une fonction main de type int
return (0);
}
/* génère l'entête du mail que l'on transfère */
void gene_entete (char *nomfic)
{
long pos_deblig; // position dans le fichier en début de ligne
// position dans le fichier mail de 2 champs de l'entête
long posSubject, posContent;
// fabriquer et ouvrir en écriture le fichier d'entête
fdest = fopen (nomfic, "w");
if (! fdest)
// "Impossible de créer un fichier d'entête %s"
errfatale ("IMPOS_CRE_ENTETE", nomfic);
// Récupération position du sujet et du type du message initial
do
{
// récupérer la position en début de ligne
pos_deblig = ftell (fmail);
// lire une ligne de l'entête du message
lire_fmail ();
// repérage des champs importants et mémorisation de leur position
if (start ("Subject"))
posSubject = pos_deblig;
else if (start ("Content-Type"))
posContent = pos_deblig;
}
while (buf_lect [0] != '\0'); // lecture entête terminée si ligne vide
// génération du champ Subject
if (posSubject >= 0)
{
// lire la ligne contenant le sujet
fseek (fmail, posSubject, SEEK_SET);
lire_fmail ();
// convertir les caractères spéciaux éventuels
// c'est dans envmail qu'on réencodera éventuellement ce champ
majlignentete ();
// si la ligne du sujet n'est pas vide
if (strlen (buf_lect) > 9)
{
// rajouter Tr: ou remplacer le Fw: dans le sujet si nécessaire
if (buf_lect [11] == ':' && tolower (buf_lect [9]) == 't'
&& tolower (buf_lect [10]) == 'r')
fputs (buf_lect, fdest);
else if (buf_lect [11] == ':' && tolower (buf_lect [9]) == 'f'
&& tolower (buf_lect [10]) == 'w')
fprintf (fdest, "Subject: Tr: %s", buf_lect + 12);
else
fprintf (fdest, "Subject: Tr: %s", buf_lect + 9);
// lire la ligne suivante
lire_fmail ();
}
else
{
// on va vérifier si le sujet est sur la ligne suivante
lire_fmail ();
// si c'est le cas
if (*buf_lect == ' ' || *buf_lect == '\t')
// générer le début du champ sujet
fputs ("Subject: Tr: ", fdest);
else
// sinon, on fera comme si la mot clé Subject n'a pas été trouvé
posSubject = 0;
}
// tantque c'est aussi une ligne du sujet
while (*buf_lect == ' ' || *buf_lect == '\t')
{
// convertir les caractères spéciaux éventuels
majlignentete ();
// rajouter le contenu de la ligne au sujet
fputs (buf_lect + 1, fdest);
// et lire la ligne suivante
lire_fmail ();
}
}
// si champ sujet absent ou trouvé vide lors du test précédent
if (posSubject == 0)
{
// on va en demander un à l'expéditeur
// "Sujet du mail ? "
affiche_msg_nocr ("SUJET_MAIL");
// retour à la configuration standard du clavier
mode_normal ();
// lecture clavier en tenant compte des défauts de la commande fgets
buf_lect [60] = '\0';
fgets (buf_lect, 60, stdin);
// générer la ligne contenant le sujet du mail (elle contient un \n)
fprintf (fdest, "Subject: Tr: %s", buf_lect);
}
// sinon terminer la ligne contenant le sujet
else
fputc ('\n', fdest);
// récupérer le type principal du message et ses caractéristiques
recup_typeorig (posContent);
// si fichier mail de type multipart/mixed
if (ctype == MultipMixed)
{
// générer le champ Content-Type
fprintf (fdest, "Content-Type: multipart/mixed;\n");
fprintf (fdest, "\tboundary=\"%s\"\n", bordure [0]);
}
else
{
// sinon, le mail transféré se limitera à une zone texte
// jeu de caractères du message
fprintf (fdest, "Content-Type: text/plain; charset=");
if (util_utf8 ())
fprintf (fdest, "UTF-8;\n");
else
fprintf (fdest, "ISO-8859-15;\n");
// un copyright qui n'est pas celui d'Outlook ;-))
// "libremail : logiciel libre multilingue"
fprintf (fdest, "User-Agent: libremail : %s\n",
message ("QUALIF_LIBREMAIL"));
// permettra de relire ce fichier
fclose (fdest);
}
/* recopie le contenu du mail à transférer */
void ajout_entete (char *nomfic)
{
long pos_deblig; // position dans le fichier en début de ligne
// position dans le fichier mail des principaux champs de l'entête
long posDate, posFrom, posXorig, posTo, posCc, posReply, posSubject;
char *varenv_xorig; // variable d'environnement libremail_xorig
char xorig; // information utile de libremail_xorig
// fabriquer et ouvrir en écriture le fichier mail
fdest = fopen (nomfic, "a");
if (! fdest)
// "Impossible de compléter le fichier mail %s"
errfatale ("IMPOS_MAJ_FICMAIL", nomfic);
// lecture de l'entête et mémorisation de la position des champs importants
do
{
// récupérer la position en début de ligne
pos_deblig = ftell (fmail);
// lire une ligne de l'entête du message
lire_fmail ();
// repérage des champs importants et mémorisation de leur position
if (start ("X-Mailer") || start ("User-Agent"))
fprintf (fdest, "%s\n", buf_lect); // copie directe
else if (start ("Date"))
posDate = pos_deblig;
else if (start ("From"))
posFrom = pos_deblig;
else if (start ("X-Original-From") && xorig != 'n')
posXorig = pos_deblig;
else if (start ("To"))
posTo = pos_deblig;
else if (start ("Cc"))
posCc = pos_deblig;
else if (start ("Reply-To"))
posReply = pos_deblig;
else if (start ("Subject"))
posSubject = pos_deblig;
// on en profite pour mémoriser le mode d'encodage
else if (start ("Content-Transfer-Encoding"))
mem_encodage ();
}
while (buf_lect [0] != '\0'); // lecture entête terminée si ligne vide
// rappel des caractéristiques du message auquel on répond
if (posDate >= 0)
copchamp (posDate);
if (posFrom >= 0 && (posXorig < 0 || xorig == '2'))
copchamp (posFrom);
if (posXorig >= 0)
copchamp (posXorig);
if (posTo >= 0)
copchamp (posTo);
if (posCc >= 0)
copchamp (posCc);
if (posReply >= 0)
copchamp (posReply);
if (posSubject >= 0)
copchamp (posSubject);
// revenir au début du corps du message
fseek (fmail, pos_deblig, SEEK_SET);
lire_fmail ();
// copie du contenu du mail
if (ctypeorig & Multipart)
// il faudra analyser les sections
ajout_message ();
else
// une simple copie du texte suffit
copie_texte ();
// mémoriser tous les modes multipart imbriqués
do
{
switch (ctype)
{
case MultipMixed : multipmixed = 1;
break;
case MultipAlter : multipalter = 1;
break;
case MultipRep : multiprep = 1;
break;
case MultipRel : multiprel = 1;
}
// passer à la section suivante
prochaine_section ();
// récupérer ses caractéristiques
recup_infos_section ();
}
while ((ctype & Multipart) && lire_fmail ());
// indiquer si le mail peut contenir des pièces jointes
if (multipmixed)
// "Pièce(s) jointes(s) probable(s)"
genligne (message ("PJ_PROBABLE"));
// si une section multipart/alternative a été trouvée, se positionner
// (si l'on n'y est pas) sur la section text/plain du mail
if (multipalter)
posit_texte ();
// générer une ligne de séparation avec l'entête
genligne ("\n");
// si structure du mail non conforme, message d'erreur
if (! lire_fmail ())
// "Pas de zone texte dans ce mail !!!"
genligne (message ("MANQUE_ZONE_TEXTE"));
// lecture et mémorisation du corps du message
do
{
// mise en forme et mémorisation de la dernière ligne lue
majligne ();
// et lecture de la suivante
if (! lire_fmail ())
return; // on sort en fin de fichier
// si mode multipart/report, on saute les entêtes de section
if (multiprep && nbordures && surbordure ())
{
do
lire_fmail ();
while (*buf_lect);
}
}
// on s'arrête en fin de fichier, ou sur la prochaine bordure
while (nbordures == 0 || ! surbordure ());
// si mode multipart mixed on va recopier les pièces jointes
if (ctypeorig == MultipMixed)
{
// on ne conserve que la bordure de premier niveau
// (permet de sauter le texte HTML en mode multipart/alternative)
nbordures = 1;
// se positionner sur la prochaine section si on n'y est pas déjà
while (! surbordure () && lire_fmail ())
;
// recopier les lignes concernant les pièces jointes jusqu'à la fin
do
{
fputs (buf_lect, fdest);
fputc ('\n', fdest);
}
while (lire_fmail ());
}
}
/* lecture et copie d'un mail de type text/plain */
void copie_texte ()
{
// si texte encodé base 64
if (encodage_texte == Base64)
// générer une ligne de séparation avec l'entête
genligne ("\n");
// répéter
do
{
// mise en forme et mémorisation de la dernière ligne lue
majligne ();
// et lecture de la suivante
}
// on s'arrête en fin de fichier
while (lire_fmail ());
}
/* recopie une ligne du texte du mail en
passant à la ligne si elle est trop longue */
void genligne (char *buffer)
{
char * nouvligne;
int taille_ligne;
int i;
// récupérer la longueur de la ligne
taille_ligne = strlen (buffer);
// si ligne longue
if (taille_ligne > 80)
{
// on tente de la tronquer à moins de 80 car
i = 70;
// chercher un blanc pour passer à la ligne
// ou un \n résultant d'un abus de l'encodage Mime
while (i > 0 && buffer [i] != ' ' && buffer [i] != '\n')
i--;
// si pas de blanc trouvé
if (i == 0)
{
// on en cherche un dans l'autre sens
i = 70;
while (i < taille_ligne && buffer [i] != ' ' && buffer [i] != '\n')
i++;
}
// mémoriser la taille de la ligne tronquée
taille_ligne = i;
}
// recopier les données
for (i = 0; i < taille_ligne; i++)
fputc (buffer [i], fdest);
// si la ligne a été tronquée
if (taille_ligne < strlen (buffer))
{
// générer un passage à la ligne
fputc ('\n', fdest);
// et traiter la suite
genligne (buffer + taille_ligne + 1);
}
}