PSR SE2a4 2022/2023 G4 : Différence entre versions

De Wiki d'activités IMA
(Séance 3:)
(DS partie Simon)
 
(68 révisions intermédiaires par 2 utilisateurs non affichées)
Ligne 2 : Ligne 2 :
 
Rayane et Simon'''
 
Rayane et Simon'''
  
 +
 +
= '''Archive code source''' =
 +
[[File:SMTPcode_source.zip]]
  
 
= '''À faire:''' =
 
= '''À faire:''' =
Ligne 28 : Ligne 31 :
 
*Allumer la VM => capbreton.plil.info => xen create /etc/xen/VMALAD.cfg  
 
*Allumer la VM => capbreton.plil.info => xen create /etc/xen/VMALAD.cfg  
 
*Se connecter => ssh root@193.48.57.166 => mdp : glopglopglop  
 
*Se connecter => ssh root@193.48.57.166 => mdp : glopglopglop  
 +
*Utilisation de la commande SCP pour déplacer nos fichiers sur la VM
  
 
''
 
''
 +
 
== Modif code: ==
 
== Modif code: ==
 
''
 
''
Ligne 50 : Ligne 55 :
 
     if(resultat<0) ecritureJournal(JOURNIV_DEVERMINE,JOURNAL_MXHS,*p);
 
     if(resultat<0) ecritureJournal(JOURNIV_DEVERMINE,JOURNAL_MXHS,*p);
 
     // Logguer l'erreur
 
     // Logguer l'erreur
     else { break; }
+
     '''else { break; }'''
 
     p++;
 
     p++;
 
     }
 
     }
 
   }
 
   }
 
 
  
 
= '''Séance 2:''' =
 
= '''Séance 2:''' =
Ligne 165 : Ligne 168 :
 
     }
 
     }
  
 +
== Test solution: ==
  
== Test solution: ==
+
*Commande pour lancer SMTPin sur la VM avec la séléction de l'interface local du port 25: '''root@VMALAD:~/SMTP/PSR-ReX-v6/src/SMTPin# ./SMTPin -l'''
 +
*Commande pour lancer SMTPin sur la VM avec la séléction de l'interface eth0 du port 25: '''root@VMALAD:~/SMTP/PSR-ReX-v6/src/SMTPout# ./SMTPout -i eth0'''
 +
*On utilise la commande suivante pour s'assurer que les 2 applications se trouvent sur les bons interfaces: '''root@VMALAD:~# ss -tlpn'''
  
*Commande pour lancer SMTPin sur la VM avec la séléction de l'interface local du port 25: root@VMALAD:~/SMTP/PSR-ReX-v6/src/SMTPin# ./SMTPin -l
+
[[File:2023_g4_commandess.png|thumb|800px|center]]
*Commande pour lancer SMTPin sur la VM avec la séléction de l'interface eth0 du port 25: root@VMALAD:~/SMTP/PSR-ReX-v6/src/SMTPout# ./SMTPout -i eth0
 
  
 
= '''Séance 4:''' =
 
= '''Séance 4:''' =
 +
 +
*Test du serveur SMTP avec l'envoi de mail grâce à l'outil Telnet => le process d'envoi de mail fonctionne 
 +
 +
*A faire => relancer les applications en mode debug pour observer la sortie => Makedebug
 +
 +
== Test: ==
 +
 +
*On lance dans un premier temps les 2 process SMTPin & SMTPout sur la VM
 +
*Utilisation de Telnet, exemple:
 +
 +
[[File:2023_g4_telnet.png|thumb|800px|center]]
 +
 +
== Problèmes: ==
 +
 +
*Problème lors de l'envoi de mail car l'outil Telnet a été utilisé sur un pc externe, or SMTPin est sur l'interface locale
 +
*Problème de MX lors de l'envoi du mail
 +
 +
 +
== A faire lors de la prochaine séance: ==
 +
 +
*Refaire le test d'envoi de mail en utilisant Telnet directement sur la VM
 +
*Modification du code pour résoudre le problème de MX lors de l'envoi du mail
 +
 +
 +
= '''Séance 5:''' =
 +
 +
*Refaire le test d'envoi de mail en utilisant Telnet directement sur la VM
 +
*Modification du code pour résoudre le problème de MX lors de l'envoi du mail
 +
 +
 +
== Test d'envoi de mail: ==
 +
 +
*Il n'y a plus d'erreur lorque l'on envoi un mail sur une adresse Polytech (1 seul MX), mais il n'y a pas de réception du message dans la boite mail.
 +
*Le problème persiste lorsqu'il y'a plusieurs MX (exemple avec Google)
 +
 +
== Modif code (à completer): ==
 +
 +
== A faire la prochaine fois: ==
 +
 +
*Modifier le code SMTP.C de 250 à 220
 +
*Checker le multiMX
 +
 +
 +
 +
= '''Séance 6:''' =
 +
 +
 +
== Problèmes: ==
 +
 +
*Nous avons essayé d'envoyer un mail de notre serveur SMTP vers un autre serveur (polytech), cependant les clées de notre domaine minable.site ont expirées, de nouvelles clés ont été créer mais nous devons attendre que ces changements soient pris en compte => Nous passons donc sur la réception de mail.
 +
 +
*Après un nouveau test, il y a toujours un problème => Notre serveur n'a pas de MX => nous en avons créer un => il faut du temps afin que la modification soient prise en compte
 +
 +
== Modifications: ==
 +
 +
*La fonction connexionserveur
 +
 +
 +
= '''Séance 7:''' =
 +
 +
== Problèmes: ==
 +
 +
#Il n'est actuellement pas possible d'effectuer l'envoi d'un mail vers une adresse gmail, car les serveurs de l'école n'autorise pas les adresses l'IPV6 (uniquement IPV4), or notre programme priorise la connexion IPV6.<br>
 +
#Les services Gmail sont très stricts en terme d'envoi et réception de mail, il nous faut un certain message ID, s'il n'y en a pas google refuse la réception du mail.
 +
#Lorsque le serveur mail Polytech nous envoie un mail il utilise la commande EHLO, or notre serveur SMTP utilise la commande HELO
 +
 +
== Modifications: ==
 +
 +
1. Modification de la fonction "connexionServeur" L97, dans le chemin suivant: libs/Reseau/reseau.c <br>
 +
'''Avant'''
 +
 +
if((ipv6==0 && p->ai_family==AF_INET6) || (ipv6==1 && ipv4==0 && p->ai_family==AF_INET))
 +
 
 +
'''Après'''
 +
 +
if((ipv4==0 && p->ai_family==AF_INET) || (ipv4==1 && ipv6==0 && p->ai_family==AF_INET6))
 +
 +
Nous avons modifier la priorité, c'est désormais l'IPV4 qui est recherché en premier.
 +
 +
2. Pour ajouter un ID à notre message, on ajoute un enregistrement SPF ==> ne fonctionne pas (le message ID n'est pas valide) malgré l'enregistrement SPF. Vérifiacation de la bonne utilisation du SPF avec la commande <code> host -t txt minable.site </code> <br>
 +
 +
3. On ajoute dans la lib SMTP ==> si on reçois une commande inconnue du serveur SMTP, on renvois un code non implémenté "500" ==> lorsque l'on retourne ce code, le serveur mail Polytech va réessayer de nous envoyer le mail avec la commande HELO. <br>
 +
 +
== Ajout: ==
 +
 +
*Création d'une arborescence dans "tmp" avec chaque utilisateur, comprenant chacun un dossier "tmp"
 +
 +
[[Fichier:2022-PSR-arbre.PNG|thumb|800px|center]]
 +
 +
= '''Séance 8:''' =
 +
Nous abandonnons l'envoi de mail vers les serveurs Google, car nous n'avons pas d'adresse IPV6 à notre nom de domaine
 +
== Objectifs: ==
 +
#Stocker le mail reçu dans le bon répertoire (correspondant au user ayant reçu le mail)
 +
#Réaliser des tests de surcharges sur notre serveur
 +
 +
== Réalisation : ==
 +
 +
#Pour stocker les mails reçus dans les bons répertoires pour obtenir le résultat ci-dessous:
 +
[[Fichier:2022-PSR-arbre-2.PNG|thumb|800px|center]]
 +
Pour chaque utilisateur de notre map, un répertoire new va stocker les mails reçu. Pour lire nos mail il suffit d'utiliser la commande cat ou vim suivi du n° de mail à lire.<br>
 +
Nous modifions 2 choses dans out.c  :
 +
*Dans le fonction <code>*adresseVersUtilisateur(char *destinataire)</code> la conditions de la boucle for est à modifier <code>for(i=0;i<strlen(destinataire);i++)</code> au lieu de <code>for(i=0;i<strlen(adresse);i++)</code>, car on veut parcourir notre adresse mail destinataire caractère par caractère.
 +
*Dans le fonction <code>*scanCarteUtilisateur(char *courriel)</code> la condition du if est à modifier <code>if(strcasecmp(adresse[i].adresse,courriel)==0)</code> au lieu de <code>if(strcasecmp(adresse[i].adresse,courriel))</code>, car strcasecmp renvoie 0 lorsque nos 2 chaines de caractères sont égales. La condition précédente ne nous permettais pas  de rentrer dans notre if.
 +
#Pour réaliser notre test de charge, nous avons au préalable créer un fichier de test "test1" comportant toutes nos commandes nc
 +
[[Fichier:2022-fichier-test1.PNG|thumb|800px|center]]
 +
Nous l'utilisons grâce à la commande <code>nc -C -i1 -q0 localhost 25 < ~SimonRayane/PSR-Rex-v6/test1</code>
 +
Pour surcharger le serveur nous allons utiliser une boucle pour envoyer 50 mails, dans le fichier bash "chargeTest.sh" suivant:
 +
[[Fichier:2022-fichier-chargetest.PNG|thumb|800px|center]]
 +
Le test de surcharge est un succès, nous recevons bien les 50 mails sur l'adresse mail Polytech.
 +
 +
 +
= '''DS partie Simon''' =
 +
 +
Pour le DS on m'a demander de enlever les "..." répétitif présent dans la console du SMTPOut afin de délimiter le corps et les en-tête lorsque on reçoit un mail sur notre serveur SMTP
 +
 +
Voici le code modifié qui est présent dans <code> ~/SimonRayaneDS/PSR-ReX-v6/libs/SMTP/smtp.c </code>
 +
 
 +
else{
 +
    int c=0,cpt=0,ct=0;
 +
    while(donnees->corps[c]!='\0'){ if(donnees->corps[c]=='\n') cpt++; c++; }
 +
    int cpt2=0;
 +
    c=0;
 +
    while(donnees->corps[c]!='\0'){
 +
      if(cpt2<AFFICHE_COURRIEL_DEBUT || cpt2>cpt-AFFICHE_COURRIEL_FIN) fwrite(donnees->corps+c,sizeof(char),1,sortie);
 +
      if(donnees->corps[c]=='\n') cpt2++;
 +
      c++;
 +
      if(cpt2==AFFICHE_COURRIEL_DEBUT && cpt2<=cpt-AFFICHE_COURRIEL_FIN && ct==0) {        
 +
        fprintf(sortie,"...\n");
 +
      ct=1;
 +
      }
 +
      }
 +
    }
 +
  }
 +
 +
J'ai ajouté une variable c pour que l'affichage se fasse uniquement une fois. Cette variable se mettra à 1 dès qu'on l'écris une fois et donc ne repassera plus jamais dans la condition qui attend un ct==0

Version actuelle datée du 14 juin 2023 à 17:08

Groupe Numéro 4 Rayane et Simon


Archive code source

Fichier:SMTPcode source.zip

À faire:

  • Un système doit être réalisé permettant au serveur SMTP sortant de mettre en file d’attente les messages non remis à destination pour cause d’erreur transitoire du serveur SMTP cible
  • Les communications peuvent être chiffrées par TLS, les communication chiffrées peuvent être négociées directement sur le port 465
  • Il doit être possible de basculer sur une communication chiffrée à partir du port 25 en utilisant les commandes EHLO et STARTTLS
  • Les serveurs SMTP doivent gérer les enregistrements MX permettant d’associer un nom de domaine à un serveur de messagerie, le recours aux enregistrements AAAA et A est à utiliser en cas d’absence de MX => Partiellement
  • Pour la transmission vers les serveurs SMTP cibles, une communication chiffrée doit être préférée => SMTP dialogue à modifier => commande EHLO => permet de connaitre les fonctions du serveur
  • Le processus de remise stocke le message dans le sous-répertoire Maildir/tmp puis le déplace dans le sous-répertoire Maildir/new, déplacement doit être fait par la primitive rename => Partiellement fait, ajout du move dans la fonction gestionCourriel du fichier out.c


Séance 1:

  • Lecture du Sujet
  • On examine le code:- fonction in.c => fonction chercheMX (fct de résolution) => Permet d'obtenir le MX (nom d'un MTA) et donc le MTA (agent de transfert)
  • Compilation du code
  • Il faut determiner les tâches à effectuer


Prise en main de la VM (VMALAD):

  • Allumer la VM => capbreton.plil.info => xen create /etc/xen/VMALAD.cfg
  • Se connecter => ssh root@193.48.57.166 => mdp : glopglopglop
  • Utilisation de la commande SCP pour déplacer nos fichiers sur la VM

Modif code:

  • Changement dans gestionCourriel() -> in.c / changement pour éviter d'envoyer le message sur tout les mx mais sur celui qui marche


while(*p!=NULL){
 #ifdef DEVERMINE
   printf("Serveur : %s\n",*p);
 #endif
   int ss=connexionServeur(*p,SMTP_PORT_DEFAULT);
   FILE *dialogue=fdopen(ss,"a+");
   if(dialogue==NULL){
     perror("gestionCourriel.fdopen");
     exit(EXIT_FAILURE);
   }
   char erreur[MAX_ERREUR];
   int resultat=SMTP_dialogue(dialogue,donnees,erreur,MAX_ERREUR);
   fclose(dialogue);
   if(resultat<0) ecritureJournal(JOURNIV_DEVERMINE,JOURNAL_MXHS,*p);
   // Logguer l'erreur
   else { break; }
   p++;
    }
 }

Séance 2:

  • Explication du code en salle de cours (1h)



Modif code:

  • Dans Mutex.c => ajout d'un free(mutexes) | Car le threads est détruit mais pas l'allocation mémoire des mutexes
  • Dans out.c => fonction gestionCourriel => ajout d'un rename (move) du fichier TMP vers le fichier NEW
char new_fichier[MAX_CHEMIN];
sprintf(new_fichier, "%s/%s/%s/%ld_%010d_%010ld",dossier,id,MAILDIR_NEW,time_save,pid,messages);
rename(fichier, new_fichier);
}


Taches restantes:

En cours:

  • Un système doit être réalisé permettant au serveur SMTP sortant de mettre en file d’attente les messages non remis à destination pour cause d’erreur transitoire du serveur SMTP cible
  • Les communications peuvent être chiffrées par TLS, les communication chiffrées peuvent être négociées directement sur le port 465
  • Il doit être possible de basculer sur une communication chiffrée à partir du port 25 en utilisant les commandes EHLO et STARTTLS
  • Les serveurs SMTP doivent gérer les enregistrements MX permettant d’associer un nom de domaine à un serveur de messagerie, le recours aux enregistrements AAAA et A est à utiliser en cas d’absence de MX => Partiellement
  • Pour la transmission vers les serveurs SMTP cibles, une communication chiffrée doit être préférée => SMTP dialogue à modifier => commande EHLO => permet de connaitre les fonctions du serveur


Terminé:

  • Le processus de remise stocke le message dans le sous-répertoire Maildir/tmp puis le déplace dans le sous-répertoire Maildir/new, déplacement doit être fait par la primitive rename => ajout du move dans la fonction gestionCourriel du fichier out.c


Séance 3:

  • Remise en forme du Wiki
  • Tester la communication de notre application et debuguer
  • Problème: SMTPin & SMTPout sur la même interface du port 25 ==> Il faut trouver un moyen de déplacer l'un des 2 sur une autre interface
  • Solution: Créer un argument a notre apllication pour pouvoir modifier l'interface, (précision de l'interface pour SMTPin & SMTPout)

Modif code:

  • Dans SMTPout ==> args.h => ajout d'une variable "interface" à la structure "stmp_config
struct smtp_config
 {
   char journal[CONFIG_MAX_JOURNAL];
   int niveau;
   char port[CONFIG_MAX_PORT];
   char dossier[CONFIG_MAX_CHEMIN];
   char carte[CONFIG_MAX_CHEMIN];
   unsigned char local;
   char interface[CONFIG_MAX_INTERFACE];
 };
  • Dans SMTPout ==> args.c => ajout d'un case i "interface" dans le switch


static struct option long_options[] = {
   {"local",no_argument,0,'l'},
   {"port",required_argument,0,'p'},
   {"journal",required_argument,0,'j'},
   {"niveau",required_argument,0,'n'},
   {"dossier",required_argument,0,'d'},
   {"utilisateurs",required_argument,0,'u'},
   {"interfaces", required_argument,0, 'i'},
   {0,0,0,0}
   };
 while(1){
   int c=getopt_long(argc,argv,"lp:j:n:d:u:i:",long_options,NULL);
   if(c<0) break;
   switch(c){
     case 'l':
       config->local=1;
       break;
     case 'i':
     strncpy(config->interface,optarg,sizeof(config->interface)-1);
     break;
     case 'p':
       strncpy(config->port,optarg,sizeof(config->port)-1);
       break;
     case 'j':
       strncpy(config->journal,optarg,sizeof(config->journal)-1);
       break;
     case 'd':
       strncpy(config->dossier,optarg,sizeof(config->dossier)-1);
       break;
     case 'u':
       strncpy(config->carte,optarg,sizeof(config->carte)-1);
       break;
     case 'n':
       config->niveau=atoi(optarg);
       break;
     default:
       afficheSyntaxe(argv[0]);
       break;
     }
   }

Test solution:

  • Commande pour lancer SMTPin sur la VM avec la séléction de l'interface local du port 25: root@VMALAD:~/SMTP/PSR-ReX-v6/src/SMTPin# ./SMTPin -l
  • Commande pour lancer SMTPin sur la VM avec la séléction de l'interface eth0 du port 25: root@VMALAD:~/SMTP/PSR-ReX-v6/src/SMTPout# ./SMTPout -i eth0
  • On utilise la commande suivante pour s'assurer que les 2 applications se trouvent sur les bons interfaces: root@VMALAD:~# ss -tlpn
2023 g4 commandess.png

Séance 4:

  • Test du serveur SMTP avec l'envoi de mail grâce à l'outil Telnet => le process d'envoi de mail fonctionne
  • A faire => relancer les applications en mode debug pour observer la sortie => Makedebug

Test:

  • On lance dans un premier temps les 2 process SMTPin & SMTPout sur la VM
  • Utilisation de Telnet, exemple:
2023 g4 telnet.png

Problèmes:

  • Problème lors de l'envoi de mail car l'outil Telnet a été utilisé sur un pc externe, or SMTPin est sur l'interface locale
  • Problème de MX lors de l'envoi du mail


A faire lors de la prochaine séance:

  • Refaire le test d'envoi de mail en utilisant Telnet directement sur la VM
  • Modification du code pour résoudre le problème de MX lors de l'envoi du mail


Séance 5:

  • Refaire le test d'envoi de mail en utilisant Telnet directement sur la VM
  • Modification du code pour résoudre le problème de MX lors de l'envoi du mail


Test d'envoi de mail:

  • Il n'y a plus d'erreur lorque l'on envoi un mail sur une adresse Polytech (1 seul MX), mais il n'y a pas de réception du message dans la boite mail.
  • Le problème persiste lorsqu'il y'a plusieurs MX (exemple avec Google)

Modif code (à completer):

A faire la prochaine fois:

  • Modifier le code SMTP.C de 250 à 220
  • Checker le multiMX


Séance 6:

Problèmes:

  • Nous avons essayé d'envoyer un mail de notre serveur SMTP vers un autre serveur (polytech), cependant les clées de notre domaine minable.site ont expirées, de nouvelles clés ont été créer mais nous devons attendre que ces changements soient pris en compte => Nous passons donc sur la réception de mail.
  • Après un nouveau test, il y a toujours un problème => Notre serveur n'a pas de MX => nous en avons créer un => il faut du temps afin que la modification soient prise en compte

Modifications:

  • La fonction connexionserveur


Séance 7:

Problèmes:

  1. Il n'est actuellement pas possible d'effectuer l'envoi d'un mail vers une adresse gmail, car les serveurs de l'école n'autorise pas les adresses l'IPV6 (uniquement IPV4), or notre programme priorise la connexion IPV6.
  2. Les services Gmail sont très stricts en terme d'envoi et réception de mail, il nous faut un certain message ID, s'il n'y en a pas google refuse la réception du mail.
  3. Lorsque le serveur mail Polytech nous envoie un mail il utilise la commande EHLO, or notre serveur SMTP utilise la commande HELO

Modifications:

1. Modification de la fonction "connexionServeur" L97, dans le chemin suivant: libs/Reseau/reseau.c
Avant

if((ipv6==0 && p->ai_family==AF_INET6) || (ipv6==1 && ipv4==0 && p->ai_family==AF_INET))
  

Après

if((ipv4==0 && p->ai_family==AF_INET) || (ipv4==1 && ipv6==0 && p->ai_family==AF_INET6))

Nous avons modifier la priorité, c'est désormais l'IPV4 qui est recherché en premier.

2. Pour ajouter un ID à notre message, on ajoute un enregistrement SPF ==> ne fonctionne pas (le message ID n'est pas valide) malgré l'enregistrement SPF. Vérifiacation de la bonne utilisation du SPF avec la commande host -t txt minable.site

3. On ajoute dans la lib SMTP ==> si on reçois une commande inconnue du serveur SMTP, on renvois un code non implémenté "500" ==> lorsque l'on retourne ce code, le serveur mail Polytech va réessayer de nous envoyer le mail avec la commande HELO.

Ajout:

  • Création d'une arborescence dans "tmp" avec chaque utilisateur, comprenant chacun un dossier "tmp"
2022-PSR-arbre.PNG

Séance 8:

Nous abandonnons l'envoi de mail vers les serveurs Google, car nous n'avons pas d'adresse IPV6 à notre nom de domaine

Objectifs:

  1. Stocker le mail reçu dans le bon répertoire (correspondant au user ayant reçu le mail)
  2. Réaliser des tests de surcharges sur notre serveur

Réalisation :

  1. Pour stocker les mails reçus dans les bons répertoires pour obtenir le résultat ci-dessous:
2022-PSR-arbre-2.PNG

Pour chaque utilisateur de notre map, un répertoire new va stocker les mails reçu. Pour lire nos mail il suffit d'utiliser la commande cat ou vim suivi du n° de mail à lire.
Nous modifions 2 choses dans out.c  :

  • Dans le fonction *adresseVersUtilisateur(char *destinataire) la conditions de la boucle for est à modifier for(i=0;i<strlen(destinataire);i++) au lieu de for(i=0;i<strlen(adresse);i++), car on veut parcourir notre adresse mail destinataire caractère par caractère.
  • Dans le fonction *scanCarteUtilisateur(char *courriel) la condition du if est à modifier if(strcasecmp(adresse[i].adresse,courriel)==0) au lieu de if(strcasecmp(adresse[i].adresse,courriel)), car strcasecmp renvoie 0 lorsque nos 2 chaines de caractères sont égales. La condition précédente ne nous permettais pas de rentrer dans notre if.
  1. Pour réaliser notre test de charge, nous avons au préalable créer un fichier de test "test1" comportant toutes nos commandes nc
2022-fichier-test1.PNG

Nous l'utilisons grâce à la commande nc -C -i1 -q0 localhost 25 < ~SimonRayane/PSR-Rex-v6/test1 Pour surcharger le serveur nous allons utiliser une boucle pour envoyer 50 mails, dans le fichier bash "chargeTest.sh" suivant:

2022-fichier-chargetest.PNG

Le test de surcharge est un succès, nous recevons bien les 50 mails sur l'adresse mail Polytech.


DS partie Simon

Pour le DS on m'a demander de enlever les "..." répétitif présent dans la console du SMTPOut afin de délimiter le corps et les en-tête lorsque on reçoit un mail sur notre serveur SMTP

Voici le code modifié qui est présent dans ~/SimonRayaneDS/PSR-ReX-v6/libs/SMTP/smtp.c

else{
    int c=0,cpt=0,ct=0;
    while(donnees->corps[c]!='\0'){ if(donnees->corps[c]=='\n') cpt++; c++; }
    int cpt2=0;
    c=0;
    while(donnees->corps[c]!='\0'){
      if(cpt2<AFFICHE_COURRIEL_DEBUT || cpt2>cpt-AFFICHE_COURRIEL_FIN) fwrite(donnees->corps+c,sizeof(char),1,sortie); 
      if(donnees->corps[c]=='\n') cpt2++;
      c++;
      if(cpt2==AFFICHE_COURRIEL_DEBUT && cpt2<=cpt-AFFICHE_COURRIEL_FIN && ct==0) {	        
       fprintf(sortie,"...\n");
     	ct=1;
      }
     }
    }
 } 

J'ai ajouté une variable c pour que l'affichage se fasse uniquement une fois. Cette variable se mettra à 1 dès qu'on l'écris une fois et donc ne repassera plus jamais dans la condition qui attend un ct==0