Looking for Computer Science & Information Technology online
courses ?
Check my new web site: https://www.yesik.it !
Dans cet article, nous allons voir comment envoyer un courrier électronique à partir d'un programme Java SE en utilisant l'API JavaMail.
Sommaire
JavaMail
JavaMail est une extension standard de Java SE. C'est à dire que les spécifications de l'API (Application Programming Interface – L'ensemble des spécifications de classes, méthodes, fonctions, constantes, etc. qui permettent d'utiliser une technologie dans un programme.) sont définies, mais elle n'est pas fournie avec le JRE, ce qui offre la possibilité pour de tierces parties de fournir leur propre implémentation. Ceci dit, Sun fournit aussi une mise en oeuvre de référence de JavaMail, qu'il est possible de télécharger à partir de l'adresse http://java.sun.com/products/javamail. C'est cette version que je vais utiliser.
Après avoir téléchargé – et décompressé l'archive de JavaMail, il convient de copier le JAR (Java ARchive – Un format d'archive utilisé dans le monde Java pour regrouper des fichiers (classes compilées, méta-données, etc.).) mail.jar à l'emplacement de votre choix (l'idéal étant de ne pas le perdre...). Pour ma part, je vais installer le tout dans /usr/local/lib:
sh# cd /usr/local/lib sh# unzip /path/to/javamail-1.4.2.zip sh# ln -s javamail-1.4.2 javamail
Java 1.4 et Java 5.0
Si vous utilisez une version de Java antérieure à la version 6, vous aurez aussi besoin d'une autre extension appelée JavaBeans™ Activation Framework. Ici encore, Sun fournit une mise en oeuvre de référence, disponible à l'adresse http://java.sun.com/beans/glasgow/jaf.html. Vous devrez l'installer de manière similaire à JavaMail:
sh# cd /usr/local/lib sh# unzip /media/disk/jaf-1_1_1.zip sh# ln -s jaf-1_1_1.zip jaf
Premier message
Envoyer un message avec JavaMail n'est pas très compliqué. Néanmoins, il est nécessaire de comprendre un certain nombre de concepts clés. Nous allons donc détailler au fur et à mesure le code.
Session
Tout d'abord, toute application utilisant l'API JavaMail doit commencer par ouvrir une session. Dans JavaMail, la session gére les informations de configuration (nom d'utilisateur, mot de passe, hôte) nécessaires pour utiliser les fonctionnalités de JavaMail. Il ne s'agit pas d'une session au sens de connexion avec un serveur!
/* ... */ Properties props = new Properties(); Session session = Session.getInstance(props);
Remarque:
Les propriétés passées en argument (props) contiennent les informations nécessaires à l'API pour fonctionner. Ici, je laisse les valeurs par défaut. Notamment, cela veut dire:
- Que le serveur de courrier (propriété mail.host) sera localhost;
- Que le nom d'utilisateur pour accéder au serveur (propriété mail.user) sera l'utilisateur courant
- que l'adresse de l'expéditeur (propriété mail.from) sera mail.user@mail.host.
Vous pouvez bien sûr changer ces valeurs. Par exemple, pour modifier l'adresse de l'émetteur du message, il faudrait modifier le code ainsi:
/* ... */ Properties props = new Properties(); props.setProperty("mail.from", "contact@chicoree.fr"); Session session = Session.getInstance(props);
Message
La seconde étape va être de créer le message. Ici encore, il s'agit d'un objet passif essentiellement chargé d'encapsuler des informations: sujet, destinataire, contenu, etc.
/* ... */ Message message = new MimeMessage(session); InternetAddress recipient = new InternetAddress("sylvain@localhost"); message.setRecipient(Message.RecipientType.TO, recipient); message.setSubject("Hello JavaMail"); message.setText("JavaMail vous dit bonjour!");
Remarque:
Ici, j'utilise un message MimeMessage. Comme vous vous en doutez, cela représente un message MIME compatible avec la RFC822.
C'est le seul format de message définit par les spécifications de JavaMail. Néanmoins, chaque mise en oeuvre de JavaMail est susceptible de fournir des formats de messages spécialisés. Ainsi, la mise en oeuvre de référence fournie par Sun offre par exemple la classe com.sun.mail.smtp.SMTPMessage qui permet de régler certaines options liées à la transmission de ce message par SMTP.
Mais, dans la plupart des cas, MimeMessage est très largement suffisant. Donc autant rester dans le cadre des spécifications...
Transport
Enfin, le code le plus intéressant – et le plus actif: celui chargé de transmettre le message. Code le plus intéressant, mais aussi le plus court:
/* ... */ Transport.send(message);
L'appel à la méthode Transport.send ouvre une connexion avec le serveur SMTP, transmet le message, puis ferme la connexion avec le serveur.
Remarque:
Tous les paramètres de connexion sont extraits du message et de l'objet session associé.
Code complet
Voici maintenant le code complet nécessaire pour envoyer un message. En plus de ce qui a été décrit plus haut, celui-ci contient les imports nécessaires et la gestion des exceptions qui peuvent se produire:
import java.util.Properties; import javax.mail.Session; import javax.mail.Message; import javax.mail.internet.MimeMessage; import javax.mail.internet.InternetAddress; import javax.mail.Transport; import javax.mail.internet.AddressException; import javax.mail.NoSuchProviderException; import javax.mail.MessagingException; public class SendTextMessage { public static void main(String[] args) { try { Properties props = new Properties(); // props.setProperty("mail.from", "contact@chicoree.fr"); Session session = Session.getInstance(props); Message message = new MimeMessage(session); InternetAddress recipient = new InternetAddress("sylvain@localhost"); message.setRecipient(Message.RecipientType.TO, recipient); message.setSubject("Hello JavaMail"); message.setText("JavaMail vous dit bonjour!"); Transport.send(message); } catch(NoSuchProviderException e) { System.err.println("Pas de transport disponible pour ce protocole"); System.err.println(e); } catch(AddressException e) { System.err.println("Adresse invalide"); System.err.println(e); } catch(MessagingException e) { System.err.println("Erreur dans le message"); System.err.println(e); } } }
Reste à compiler et exécuter ce code. Bien entendu, il ne faut pas oublier de modifier le CLASSPATH pour utiliser JavaMail:
sh$ export CLASSPATH=".:/usr/local/lib/javamail/mail.jar" sh$ javac SendTextMessage.java sh$ java SendTextMessage
Enfin, vous pouvez utiliser votre client de messagerie préféré pour vérifier que le message a bien été envoyé. Pour ma part, comme j'utilise exim comme serveur mail – et qu'il est configuré pour délivrer les messages dans ma boite mail locale, je peux utiliser mail:
sh$ mail Mail version 8.1.2 01/15/2001. Type ? for help. "/var/mail/sylvain": 1 message 1 new >N 1 sylvain@mobal Fri Aug 14 01:24 20/640 Hello JavaMail & 1 Message 1: From sylvain@mobal Fri Aug 14 01:24:43 2009 Envelope-to: sylvain@localhost Delivery-date: Fri, 14 Aug 2009 01:24:43 +0200 To: sylvain@localhost Subject: Hello JavaMail MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit From: sylvain@mobal Date: Fri, 14 Aug 2009 01:24:43 +0200 JavaMail vous dit bonjour!
Message multipart
Bien envoyer un message texte seul c'est très bien, mais comment transférer une pièce jointe? C'est exactement à cela que servent les messages multipart.
Code initial
Et c'est vrai que là, JavaMail simplifie largement notre travail – puisque le code va beaucoup ressembler au code précédent:
/* ... */ Properties props = new Properties(); // props.setProperty("mail.from", "contact@chicoree.fr"); Session session = Session.getInstance(props); Message message = new MimeMessage(session); InternetAddress recipient = new InternetAddress("sylvain@localhost"); message.setRecipient(Message.RecipientType.TO, recipient); message.setSubject("Hello JavaMail"); // XXX Ici inserer le contenu ''multipart'' du message Transport.send(message);
Et oui! C'est exactement le code de la première partie de cet article, à ceci près que j'ai enlevé la ligne qui définissait le contenu du message. C'est tout ce qui va changer. Et c'est sur quoi nous allons travailler.
Créer les parties
Donc, pour cet exemple, je veux transférer un message contenant deux parties:
- Du texte
- et une image PNG
Créer la partie texte ressemble fortement à ce que nous avions fait dans le message non multipart:
/* ... */ MimeBodyPart mbp1 = new MimeBodyPart(); mbp1.setText("JavaMail vous dit bonjour!");
Quand à l'image PNG, nous allons utiliser une variante qui permet de lire un fichier:
/* ... */ MimeBodyPart mbp2 = new MimeBodyPart(); String file = "/home/sylvain/HelloJavaMail.png"; mbp2.attachFile(file);
Enfin, reste à rassembler ces deux parties, et à attacher l'ensemble au message:
/* ... */ MimeMultipart mp = new MimeMultipart(); mp.addBodyPart(mbp1); mp.addBodyPart(mbp2); message.setContent(mp);
Code complet
Pour terminer voici le code complet du programme:
import java.util.Properties; import javax.mail.Session; import javax.mail.Message; import javax.mail.internet.MimeMessage; import javax.mail.internet.InternetAddress; import javax.mail.Transport; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMultipart; import javax.mail.internet.AddressException; import javax.mail.NoSuchProviderException; import javax.mail.MessagingException; import java.io.IOException; public class SendMultipartMessage { public static void main(String[] args) { try { Properties props = new Properties(); // props.setProperty("mail.from", "contact@chicoree.fr"); Session session = Session.getInstance(props); Message message = new MimeMessage(session); InternetAddress recipient = new InternetAddress("sylvain@localhost"); message.setRecipient(Message.RecipientType.TO, recipient); message.setSubject("Hello JavaMail"); // Partie 1: Le texte MimeBodyPart mbp1 = new MimeBodyPart(); mbp1.setText("JavaMail vous dit bonjour!"); // Partie 2: Le fichier joint MimeBodyPart mbp2 = new MimeBodyPart(); String file = "/home/sylvain/HelloJavaMail.png"; mbp2.attachFile(file); // On regroupe les deux dans le message MimeMultipart mp = new MimeMultipart(); mp.addBodyPart(mbp1); mp.addBodyPart(mbp2); message.setContent(mp); Transport.send(message); } catch(IOException e) { System.err.println("Impossible de lire le fichier joint"); System.err.println(e); } catch(NoSuchProviderException e) { System.err.println("Pas de transport disponible pour ce protocole"); System.err.println(e); } catch(AddressException e) { System.err.println("Adresse invalide"); System.err.println(e); } catch(MessagingException e) { System.err.println("Erreur dans le message"); System.err.println(e); } } }
Conclusion
Nous en avons maintenant terminé de ce tour d'horizon de JavaMail. Vous l'avez constaté, l'API est facile à appréhender – et aucune configuration fastidieuse n'est requise avant de pouvoir transmettre un message. Bref, il s'agit là d'un API comme on souhaiterait en voir plus.
Un dernier mot cependant: nous avons ici utilisé JavaMail pour transmettre un message. Mais cet API ne se réduit pas à cette fonctionnalité. En effet, il est tout aussi possible de consulter sa messagerie avec JavaMail. Mais ce sera pour une autre fois...