Introduction
L’objectif de cet article est de créer un serveur SMTP (serveur de courriel) avec NodeJS.
L’utilité de ce projet est de permettre de faire des tests rapidement avec les courriels dans un environnement de développement.
De plus, cette technique permet de recevoir des courriels, de les analyser et de les traiter de plusieurs manières et le tout en JavaScript.
Le package NPM utilisé pour atteindre cet objectif est celui de nodemailer soit smtp-server
Matériel requis
- NodeJS
- NPM
- Connaissance en serveur SMTP / ce qui se rapporte aux courriels
Étape 1 - Création du Projet
mkdir smtp && cd smtp
npm init
npm install --save smtp-server
Étape 2 - Création du fichier serveur
À la racine du projet, créer un fichier nommé server.js
Ajouter ceci dans le fichier (proviens directement de l’exemple disponible sur Github)
// smtp.js
const { SMTPServer } = require("smtp-server");
const server = new SMTPServer({
// disable STARTTLS to allow authentication in clear text mode
disabledCommands: ["STARTTLS", "AUTH"],
logger: true,
onData(stream, session, callback) {
stream.pipe(process.stdout); // print message to console
stream.on("end", callback);
},
});
server.listen(2525);
Le port 2525 a été utilisé pour faire les tests, car le port 25 était déjà utilisé par le service postfix.
Le port 2525 et NodeJS
Source: issue Github
Pour autoriser le port 2525 dans NodeJS, il faut exécuter la commande node
en sudo, ce qui n’est pas du tout recommandé.
ou faire comme suit pour utiliser le port 25:
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/node
sudo kill -9 `sudo lsof -t -i:25`
Étape 3 - Envoyer un courriel
Ouvrir un autre terminal (Sur la même machine)
Puis lancez cette commande :
Vous devez avoir netcat sur votre machine
nc localhost 2525
Puis vous pouvez utiliser les commandes suivantes:
helo localhost
mail from: <test@localhost>
rcpt to: <test@localhost>
data
Subject: Un test
Du contenu
^M
.^M
quit
Sur le MacBook, afficher les caractères <CR><LF>
ou ^M
, il faut faire control+v, ENTER, ENTER
Pour terminer d’écrire le corps du message (body),
^M
.^M
La sortie sur la console obtenue:
someuser@MacBook ~ % nc localhost 2525
220 MacBook.local ESMTP
helo localhost
250 MacBook.local Nice to meet you, mail.local
mail from: <test@localhost>
250 Accepted
rcpt to: <test@localhost>
250 Accepted
data
354 End data with <CR><LF>.<CR><LF>
Subject: Testing email with nodejs
Some content
^M
.^M
250 OK: message queued
quit
221 Bye
Étape 4 - Sur la console du serveur
someuser@MacBook Tools % sudo node index.js
Password:
[2020-04-02 02:28:35] INFO SMTP Server listening on [::]:2525
[2020-04-02 02:28:50] INFO [#tdl2lpomj6hycbca] Connection from mail.local
[2020-04-02 02:28:50] DEBUG [#tdl2lpomj6hycbca] S: 220 MacBook ESMTP
[2020-04-02 02:28:55] DEBUG [#tdl2lpomj6hycbca] C: helo localhost
[2020-04-02 02:28:55] DEBUG [#tdl2lpomj6hycbca] S: 250 MacBook Nice to meet you, mail.local
[2020-04-02 02:29:14] DEBUG [#tdl2lpomj6hycbca] C: mail from: <test@localhost>
[2020-04-02 02:29:14] DEBUG [#tdl2lpomj6hycbca] S: 250 Accepted
[2020-04-02 02:29:23] DEBUG [#tdl2lpomj6hycbca] C: rcpt to: <test@localhost>
[2020-04-02 02:29:23] DEBUG [#tdl2lpomj6hycbca] S: 250 Accepted
[2020-04-02 02:29:25] DEBUG [#tdl2lpomj6hycbca] C: data
[2020-04-02 02:29:25] DEBUG [#tdl2lpomj6hycbca] S: 354 End data with <CR><LF>.<CR><LF>
Subject: Testing email with nodejs
Some content
.
[2020-04-02 02:30:26] DEBUG [#tdl2lpomj6hycbca] C: <73 bytes of DATA>
[2020-04-02 02:30:26] DEBUG [#tdl2lpomj6hycbca] S: 250 OK: message queued
2020-04-02 02:30:59] DEBUG [#tdl2lpomj6hycbca] C: quit
[2020-04-02 02:30:59] DEBUG [#tdl2lpomj6hycbca] S: 221 Bye
[2020-04-02 02:30:59] INFO [#tdl2lpomj6hycbca] Connection closed to mail.local
Vous devriez avoir obtenu quelque chose semblable.
Étape 5 - Autres trucs et intégrations
Nodemailer offre un outil en NodeJS pour envoyer les courriels,
Voici un exemple:
npm install nodemailer --save
Créer un fichier nommé client.js
const SMTPConnection = require("nodemailer/lib/smtp-connection");
let connection = new SMTPConnection({
port: 2525,
host: "127.0.0.1",
secure: false,
debug: true,
});
connection.connect(() => {
console.log("Connection is established");
});
connection.on("connect", () => {
console.log("Client Connected");
connection.send(
{ from: "test@location.com", to: "testing@somewhere.com" },
"Subject: This is the subject\nThis is my message for you, HELLO !",
(err, info) => {
console.error(err);
console.log(info);
}
);
});
connection.on("error", (err) => {
console.error(err);
});
Lancer la commande comme suit : node client.js
La sortie sur la console du fichier client.js
Connection is established
Client Connected
null
{ accepted: [ 'testing@somewhere.com' ],
rejected: [],
envelopeTime: 4,
messageTime: 5,
messageSize: 70,
response: '250 OK: message queued' }
La sortie du serveur
2020-04-02 02:49:55] INFO [#hmfejvebjflwu4ep] Connection from mail.local
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] S: 220 MacBook.local ESMTP
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] C: EHLO MacBook.local
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] S: 250-MacBook.local Nice to meet you, mail.local
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] 250-PIPELINING
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] 250-8BITMIME
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] 250 SMTPUTF8
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] C: MAIL FROM:<test@location.com>
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] S: 250 Accepted
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] C: RCPT TO:<testing@somewhere.com>
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] S: 250 Accepted
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] C: DATA
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] S: 354 End data with <CR><LF>.<CR><LF>
Subject: This is the subject
This is my message for you, HELLO !
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] C: <67 bytes of DATA>
[2020-04-02 02:49:55] DEBUG [#hmfejvebjflwu4ep] S: 250 OK: message queued
[2020-04-02 02:50:55] DEBUG [#hmfejvebjflwu4ep] S: 421 Timeout - closing connection
[2020-04-02 02:50:55] INFO [#hmfejvebjflwu4ep] Connection closed to mail.local
Conclusion
Ce petit projet m’a permis d’apprendre les commandes pour envoyer un serveur et ce type de serveur m’a permis de faire une démo pour mon module @studiowebux/mailer
La démo est disponible : mailer
Problèmes survenus
501 Bad sender address syntax
Il me manquait les <
et >
mail from: <test@something.com>
rcpt to: <test@somewhere.com>
Port déjà utilisé
Vérifier que votre port 25 est disponible (j’utilise le port 2525 pour éviter les conflits)
Aucun email n’est envoyé
C’est normal, vous devez gérer cette partie pour envoyer le email. C’est-à-dire que vous devez renvoyer le courriel sur un “vrai” serveur de courriel.
421 Timeout - closing connection
Il faut utiliser la commande quit
pour terminer la connexion avant le timeout.