PSR SE2a4 2022/2023 G6 : Différence entre versions
(→Envoie message) |
(→Envoi message) |
||
Ligne 156 : | Ligne 156 : | ||
Pour pouvoir utiliser les expressions régulières, on utilise la librairie <regex> : #include <regex.h> <br/> | Pour pouvoir utiliser les expressions régulières, on utilise la librairie <regex> : #include <regex.h> <br/> | ||
<pre> | <pre> | ||
− | int | + | int split_email(char* email, char *local_part, char *domain_name, size_t lp_size, size_t dn_size) { |
− | + | char *regexString = "(.+)@(.+)"; | |
− | + | size_t maxGroups = 3; | |
− | + | regex_t regexCompiled; | |
− | + | regmatch_t groupArray[maxGroups]; | |
− | |||
</pre> | </pre> | ||
On commence par créer une fonction d'extraction du nom de domaine qui prend en paramètre le nom du domaine et sa taille.<br/> | On commence par créer une fonction d'extraction du nom de domaine qui prend en paramètre le nom du domaine et sa taille.<br/> | ||
− | La forme <code>char *regexString = "@(.+)";</code> est l'expression régulière nous permettant de récupérer le nom de domaine (tout ce qui ce situe après le "@"). | + | La forme <code>char *regexString = "(.+)@(.+)";</code> est l'expression régulière nous permettant de récupérer le nom d'utilisateur (tout ce qui ce situe avant le "@")et le nom de domaine (tout ce qui ce situe après le "@"). |
Le site https://regex101.com/ nous permet de rentrer notre test string et une expression régulière et d'obtenir le match correspondant, soit, dans notre cas : @(.+).<br/> | Le site https://regex101.com/ nous permet de rentrer notre test string et une expression régulière et d'obtenir le match correspondant, soit, dans notre cas : @(.+).<br/> | ||
+ | Il y a donc 1 match pour 3 groupes (l'ensemble match, l'utilisateur, le destinataire).<br/> | ||
<pre> | <pre> | ||
if(regcomp(®exCompiled, regexString, REG_EXTENDED)){ | if(regcomp(®exCompiled, regexString, REG_EXTENDED)){ | ||
Ligne 182 : | Ligne 182 : | ||
</pre> | </pre> | ||
Ici, on utilise plusieurs fonctions conditionnelles pour informer que l'on n'est pas parvenu à compiler l'expression régulière, qu'il n'y a pas de match (donc de domaine destinataire), qu'il n'y a pas de groupe (dans le domaine destinataire).<br/> | Ici, on utilise plusieurs fonctions conditionnelles pour informer que l'on n'est pas parvenu à compiler l'expression régulière, qu'il n'y a pas de match (donc de domaine destinataire), qu'il n'y a pas de groupe (dans le domaine destinataire).<br/> | ||
− | On | + | <pre> |
+ | memcpy(local_part, email + groupArray[1].rm_so + 1, groupArray[1].rm_eo - groupArray[1].rm_so - 1); | ||
+ | memcpy(domain_name, email + groupArray[2].rm_so, groupArray[2].rm_eo - groupArray[2].rm_so - 1); | ||
+ | </pre> | ||
+ | On utilise la fonction memcpy<br/> | ||
+ | <pre> | ||
+ | int processing_mail(struct smtp_state *state) { | ||
+ | LOG_D("Processing mail..."); | ||
+ | |||
+ | int status = split_email(state->recipient, LOCAL_PART + 0, DOMAIN + 0, sizeof(LOCAL_PART), sizeof(DOMAIN)); | ||
+ | |||
+ | if (status < 0) { | ||
+ | LOG_E("There has been an error during recipient email spliting"); | ||
+ | return -1; | ||
+ | } | ||
+ | |||
+ | LOG_D("local_part: %s", LOCAL_PART); | ||
+ | LOG_D("domain_name: %s", DOMAIN); | ||
+ | |||
+ | return -1; | ||
+ | }; | ||
+ | </pre> |
Version du 5 avril 2023 à 15:19
Sommaire
Infrastructure
Le serveur est disponible sur yamaha.germond.org
(193.48.57.161), le DNS est hébergé sur l'infrastructure de @Bastien.Germond [1]
Architecture
Le projet est sous Meson ; pour compiler, on utilise la commande <meson compile -C build>
Comment récupérer un certificat avec Let's Encrypt ?
TODO
Premier pas
03/02/2023
Création VM : yamaha (IP : 193.48.57.161)
Lancement de la VM
Ouverture du projet beta
Découverte SMTPin
Réception message
10/02/2023
Réécriture du code
Le nouveau code reprend l'architecture globalement du code fourni, ils rassemblent juste les librairies dans une architecture descente sous src et utilise Meson.
Création code root@yamaha:~/SMTP/src# vim MTAext.c
-> réception message (MTAext.c)
Pour générer un identifiant unique, on utilise la librairie <libuuid> : #include <uuid/uuid.h>
https://stackoverflow.com/questions/51053568/generating-a-random-uuid-in-c
int processing_mail(struct smtp_state *state){ LOG_D("Processing mail..."); uuid_t binuuid;// Unique ID in binary uuid_generate_random(binuuid); char *uuid = malloc(37);//Nb of characters for unique id uuid_unparse_lower(binuuid, uuid);//unique id en lettre minuscule
On définit ici un identifiant unique pour pouvoir suivre le mail envoyé (éviter toutes collisions ou perdition de données).
if(fptr == NULL){ LOG_E("Couldn't open Maildir tmp"); exit(1); }
Ici, on utilise une fonction conditionnelle pour informer que l'on n'est pas parvenu à entrer dans le dossier de redirection de mail.
fprintf(fptr, "From: %s\r\n", state->sender); fprintf(fptr, "To: %s\r\n", state->recipient); fprintf(fptr, "%s\r\n", state->body); fclose(fptr);
On transforme les informations stockées dans la structure "state" en format de mail avec la source, le destinataire et le corps.
int server_process(int sfd) { return smtp_process(sfd, processing_mail); }
int main(void) { log_init_default("-", LOG_DEBUG); int sock = init_server("yamaha.germond.org", "8025", NULL); if (sock < 0) { LOG_C("Failed to start server"); return EXIT_FAILURE; } int status = loop_server(sock, server_process); if (status < 0) { LOG_E("MTAext: server closed unexpectedly"); }; return 0; }
La fonction main permet d'initialiser et de lancer notre serveur <yamaha.germond.org> (récupérer l'adresse IPV4/V6) et d'informer des erreurs.
Test code MTAext.c : vérification
Le mail est composé d'une entête et d'un corps de mail
On lance la compilation du code puis l’exécutable ./build/MTAext
La connexion s'établit entre deux terminaux : celui de notre machine virtuelle
root@yamaha:~/SMTP# ./build/MTAext [DEBUG] Server opened on 2001:660:4401:60a0::100:0:8025 [DEBUG] loop_server: waiting for incomming connection [DEBUG] loop_server: waiting for incomming connection [DEBUG] loop_server: waiting for incomming connection
Et celui de la machine PC zabeth19
pifou@zabeth19:~$ telnet yamaha.germond.org 8025 Trying 2001:660:4401:60a0:216:3eff:fe63:515a... Connected to yamaha.germond.org. Escape character is '^]'. 250 Welcome
-> compilation/execution de réception de mails (envoyeur, receveur, corps de mail, UUID)
On envoi un mail depuis la machine zabeth19
pifou@zabeth19:~$ telnet yamaha.germond.org 8025 Trying 2001:660:4401:60a0:216:3eff:fe63:515a... Connected to yamaha.germond.org. Escape character is '^]'. 250 Welcome HELO zabeth19 250 Hi! MAIL FROM:<testreception@yamaha.germond.org> 250 Sender recorded RCPT TO:<receptiontest@yamaha.germond.org> 250 Target recorded DATA Subject: Démonstration du bon fonctionnement de la réception Avec ce mail nous voyons que nous arrivons à communiquer (envoyer d'une machine quelconque et recevoir sur notre serveur.
Et on le reçoit sur notre serveur root@yamaha
[DEBUG] loop_server: waiting for incomming connection [DEBUG] smtp_process: incomming (cmd: HELO): HELO zabeth19 [DEBUG] _thread_main: process done, closing connection. [DEBUG] smtp_process: incomming (cmd: MAIL): MAIL FROM:<testreception@yamaha.germond.org> [DEBUG] smtp_process: incomming (cmd: RCPT): RCPT TO:<receptiontest@yamaha.germond.org> [DEBUG] smtp_process: incomming (cmd: DATA): DATA [DEBUG] Processing mail... [DEBUG] Mail UUID 3a59c1ca-c52a-4af9-8b22-9e9beb1faf53 [DEBUG] Writing mails at /root/Maildir/tmp/3a59c1ca-c52a-4af9-8b22-9e9beb1faf53 [DEBUG] Move mails at /root/Maildir/new/3a59c1ca-c52a-4af9-8b22-9e9beb1faf53 [DEBUG] _thread_main: process done, closing connection.
Avec la commande <mutt>, on peut vérifier que le mail est bien parvenu jusqu'à notre serveur :
1 N Jan 01 testreception@y (0.1K) Démonstration du bon fonctionnement de la réception 2 Jan 01 bastien@yamaha. (0.1K) 3 O Jan 01 bastien@yamaha. (0.1K) Test mail 4 Jan 01 a@b.c (0.1K) 5 Jan 01 a@b.c (0.1K) 6 Jan 01 a@b.c (0.1K)
Envoi message
Création code root@yamaha:~/SMTP/src# vim MTAext.c
-> envoi message (MTAint.c)
Pour pouvoir utiliser les expressions régulières, on utilise la librairie <regex> : #include <regex.h>
int split_email(char* email, char *local_part, char *domain_name, size_t lp_size, size_t dn_size) { char *regexString = "(.+)@(.+)"; size_t maxGroups = 3; regex_t regexCompiled; regmatch_t groupArray[maxGroups];
On commence par créer une fonction d'extraction du nom de domaine qui prend en paramètre le nom du domaine et sa taille.
La forme char *regexString = "(.+)@(.+)";
est l'expression régulière nous permettant de récupérer le nom d'utilisateur (tout ce qui ce situe avant le "@")et le nom de domaine (tout ce qui ce situe après le "@").
Le site https://regex101.com/ nous permet de rentrer notre test string et une expression régulière et d'obtenir le match correspondant, soit, dans notre cas : @(.+).
Il y a donc 1 match pour 3 groupes (l'ensemble match, l'utilisateur, le destinataire).
if(regcomp(®exCompiled, regexString, REG_EXTENDED)){ LOG_D("Fail to compile regular expression."); return -1; } if regexec(®exCompiled, cursor, maxGroups, groupArray, 0)){ LOG_D("There is no recipient domain.") return -1; // No match } if(groupArray[0].rm_so == (size_t)-1){ return -1; // No group in match }
Ici, on utilise plusieurs fonctions conditionnelles pour informer que l'on n'est pas parvenu à compiler l'expression régulière, qu'il n'y a pas de match (donc de domaine destinataire), qu'il n'y a pas de groupe (dans le domaine destinataire).
memcpy(local_part, email + groupArray[1].rm_so + 1, groupArray[1].rm_eo - groupArray[1].rm_so - 1); memcpy(domain_name, email + groupArray[2].rm_so, groupArray[2].rm_eo - groupArray[2].rm_so - 1);
On utilise la fonction memcpy
int processing_mail(struct smtp_state *state) { LOG_D("Processing mail..."); int status = split_email(state->recipient, LOCAL_PART + 0, DOMAIN + 0, sizeof(LOCAL_PART), sizeof(DOMAIN)); if (status < 0) { LOG_E("There has been an error during recipient email spliting"); return -1; } LOG_D("local_part: %s", LOCAL_PART); LOG_D("domain_name: %s", DOMAIN); return -1; };