TP Noté 2015 : SMTP

Dans ce sujet, nous vous demandons de réaliser un client puis un serveur SMTP en utilisant la bibliothèque Java NIO.

Commencez par créer un nouveau projet Java dans votre environnement que vous appellez tpnote-VotreNom. Créez aussi dans cette arborescence du projet un fichier readme.txt dans lequel vous mettez vos notes. Créez un paquetage smtp dans votre project Eclipse.

Le barème est donné à titre d'indication.

En fin de TP :

  1. si ce n'est pas déjà fait, créez un fichier readme.txt dans lequel vous mettez vos notes à destination des correcteurs ;
  2. exportez votre projet Eclipse sous la forme d'une archive :
  3. déposez le fichier sur moodle comme devoir ;
  4. vérifiez avec l'enseignant présent dans la salle que le fichier téléchargé est correct.

1 Présentation du sujet

Objectif : réaliser des classes qui permettent de réaliser un client puis un serveur SMTP.

Le serveur SMTP que vous devez réaliser doit avoir un comportement identique à celui décrit dans le RFC821. Nous ne vous demandons pas de comprendre l'ensemble du document RFC, mais vous pouvez vous en servir pour lever les ambiguïtés si nécessaire.

Les requêtes SMTP sont décrites plus loin.

2. Partie Client SMTP (10pts)

Dans cette partie, vous devez écrire un client qui interagit avec le serveur associé au port 2025 sur une machine, par exemple la vôtre.

Récupérez l'archive smtp.jar

Vous pourrez alors lancer le serveur dans une fenêtre console en tapant la ligne de commande suivante :
java -jar smtp.jar -v 2025

Cette ligne de commande lance un serveur SMTP minimal sur le port 2025.

En attendant d'avoir votre client, vous pouvez tester ce serveur minimal en exécutant par exemple la commande :

telnet localhost 2025

2.1 Handshake SMTP (5pts)

La transmission de messages entre le client et le serveur commence par un échange d'identité qui est décrit dans la section 3.5 du RFC :

  1. lorsque le client se connecte, le serveur lui transmet la chaîne de caractères :
    220 Smtp service ready<CRLF>
  2. le client doit alors envoyer la chaîne de caractères suivante :
    HELO client.telecom-sudparis.eu<CRLF>
  3. le serveur répond alors par :

Écrivez la classe SmtpHandshake se connectant au serveur et obtenant le message d'acceptation de connexion du serveur.

2.2 Envoi d'un message d'une ligne (5pts)

Une fois le handshake réussit, les messages sont transmis du client vers le serveur en respectant la séquence décrite dans la section 3.1 du RFC :

  1. le client transmet la chaîne de caractères décrivant l'émetteur :
    MAIL from : user@telecom-sudparis.eu<CRLF>
  2. le client envoie ensuite une chaîne de caractères décrivant le récepteur  :
    RCPT to : user@telecom-sudparis.eu<CRLF>
  3. lorsque le serveur a accepté une adresse de destinataire, le client peut envoyer le contenu du message. Dans notre prototype, nous nous contenterons d'une ligne de texte :
    1. il transmet la chaîne de caractères :
      DATA<CRLF>
    2. le serveur répond par la chaîne de caractères :
      354 Start mail input; end with <CRLF>.<CRLF>
    3. le client peut alors transmettre la ligne ;
    4. le serveur termine la transaction lorsqu'il a reçu le message, et enfin, coupe la connexion.

Écrivez la classe SmtpSendOneMessage se connectant au serveur et obtenant le message d'acceptation de connexion du serveur puis transmettant un message en respectant ce protocole.

3. Partie Serveur (10pts)

3.1. Handshake coté serveur (5pts)

Écrivez une classe SmtpServerHandShake qui :

  1. écoute sur le port passé en argument ;
  2. lorsqu'un client se connecte à ce port :
    1. répond en envoyant la chaîne de caractères :
      220 Smtp service ready<CRLF>
    2. puis, attend de recevoir la chaîne de type HELO ;
    3. et enfin, répond en envoyant la chaîne de caractères :
      250 Nice to meet you

3.2. Réception du message côté serveur (2pts)

À partir de la classe précédente, écrivez une classe SmtpServerOneMail qui :

  1. réalise le handshake comme précédemment ;
  2. puis attend de recevoir :
    MAIL from: 
    et répond si c'est ok par :
    250 ok
    sinon par :
    501
  3. puis, attend de recevoir :
    RCPT to:
    et répond si c'est ok par :
    250 ok
    sinon par :
    501
  4. puis, attend de recevoir :
    DATA
    et répond si c'est ok par :
    354 Start mail input; end with <CRLF>.<CRLF>
    sinon par :
    503
  5. ensuite, attend de recevoir le contenu du message (une ligne de texte) et répond par :
    250 ok
  6. et enfin, termine la conversation en quittant.

3.3. Connections multiples côté serveur (3pts)

À partir de la classe précédente, écrivez une classe SmtpServerMultiClient qui réalise le même travail que précédemment mais avec plusieurs clients simultanément.

Vous pouvez soit utiliser des Threads soit utiliser un Selector.