Dans le langage Java, il existe une API (au sens littéral du terme) qui permet d'envoyer un mail depuis une application développée avec Java. Ce tutoriel a pour but de vous indiquer pas à pas comment envoyer un mail en java d'une part, mais aussi vous structurera le code de sorte qu'il soit réutilisable et extensible facilement selon vos besoins.
1. Description de notre exemple
Il s'agit ici de construire une application (console) qui enverra un mail à différents destinataires. le type de mail, le ou les destinataires et les éventuels fichiers à attacher au mail envoyé seront indiqués à la console de manière interactive, à l'application.
2. Les dépendances nécessaires pour l'envoie de mail
Bien que la dépendance vers Java Mail API (désormais Jakarta Mail API) existe, il est préférable d'indiquer la dépendance de l'implémentation de cette API qui vous intéresse. Dans ce tutoriel, nous utiliserons l'implémentation de référence de cette API (Jakarta Mail) désormais dénommée: Eclipse Angus
2.1 Dépendances Gradle
implementation('org.eclipse.angus:angus-mail:2.0.3')
2.2 Dépendances Maven
<dependencies>
<groupId>org.eclipse.angus</groupId>
<artifactId>angus-mail</artifactId>
<version>2.0.3</version>
</dependencies>
3. Les étapes pour envoyer un mail en Java
3.1 Définir les propriétés (properties) nécessaires
- mail.smtp.host: le nom réseau ou l'ip du serveur SMTP. Un serveur SMTP est un serveur qui se charge de l'envoie du mail. Exemple: smtp.gmail.com
- mail.smtp.port: Le port sur lequel écoute le serveur SMTP. Exemple: 465
- mail.smtp.auth: une valeur qui indique que le serveur SMTP a besoin d'une authentification lorsqu'on y accède pour l'envoie de mail. Exemple: true
- mail.smtp.socketFactory.port: Le port sur lequel écoute le serveur SMTP pour les envois cryptés (SSL). Exemple: 465
- mail.smtp.socketFactory.class: La factory qui sera utilisée par l'API Java Mail pour encrypter les envois SSL. Exemple: javax.net.ssl.SSLSocketFactory
Properties prop = new Properties();
prop.put("mail.smtp.host", "smtp.gmail.com");
prop.put("mail.smtp.port", "465");
prop.put("mail.smtp.auth", "true");
prop.put("mail.smtp.socketFactory.port", "465");
prop.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
3.2 Créer la session mail
Si votre serveur SMTP n'a pas besoin d'autentification et que vous l'avez indiqué avec la propriété mail.smtp.auth comme suit: prop.put("mail.smtp.auth", "false"), alors la création de la session mail sera:
Session session = Session.getInstance(prop);
Dans le cas contraire, il faudra créer la session en indiquant l'authentification:
String username = "javatutorialshub@gmail.com";
String password = "xxxxxxxxx";
Session session = Session.getInstance(prop,
new jakarta.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
3.3 Composer le mail
Deux éléments sont très importants dans la composition du mail. Il faut nécessairement indiquer l'adresse email qui est à la source de l'envoie de mail: message.setFrom(...) et ensuite la liste des destinataires du mail: message. setRecipients(...)
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("myUserFrom@gmail.com"));
message.setRecipients(
Message.RecipientType.TO,
InternetAddress.parse("user1@gmail.com, user2@yahoo.com")
);
message.setSubject("Proverbe Chinois du jour");
String msg = "Celui qui sait qu'il ne sait pas, éduque-le. Celui qui sait qu'il sait, " +
"écoute-le. Celui qui ne sait pas qu'il sait, éveille-le. Celui qui ne sait pas " +
"qu'il ne sait pas, fuis-le.";
MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.setContent(msg, "text/html; charset=utf-8");
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(mimeBodyPart);
message.setContent(multipart);
Pour indiquer des emails en copie du mail que vous envoyez via Java Mail, vous devez utiliser message.setRecipients(...) avec:
- Message.RecipientType.CC: Copie Conforme
- Message.RecipientType.BCC: Copie Cachée
3.4 Envoyer le mail
L'envoie de mail se fait via une seule méthode:
3.5 Le code tout en un
try {
Properties prop = new Properties();
prop.put("mail.smtp.host", "smtp.gmail.com");
prop.put("mail.smtp.port", "465");
prop.put("mail.smtp.auth", "true");
prop.put("mail.smtp.socketFactory.port", "465");
prop.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
String username = "javatutorialshub@gmail.com";
String password = "xxxxxxxxx";
Session session = Session.getInstance(prop,
new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("myUserFrom@gmail.com"));
message.setRecipients(
Message.RecipientType.TO,
InternetAddress.parse("user1@gmail.com, user2@yahoo.com")
);
message.setSubject("Proverbe Chinois du jour");
String msg = "Celui qui sait qu'il ne sait pas, éduque-le. Celui qui sait qu'il sait, " +
"écoute-le. Celui qui ne sait pas qu'il sait, éveille-le. Celui qui ne sait pas " +
"qu'il ne sait pas, fuis-le.";
MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.setContent(msg, "text/html; charset=utf-8");
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(mimeBodyPart);
message.setContent(multipart);
Transport.send(message);
} catch (MessagingException e) {
log.log(Level.SEVERE, e.getMessage(), e);
}
Comme vous pouvez le voir, mettre tout le code en un pour l'envoie de mail, n'est pas une bonne idée, et n'est à aucun moment une bone pratique. Raison pour laquelle dans application ci dessous, nous allons désigner différemment afin de rendre plus modulaire les différents composants.
4. Le design de notre application d'envoi de mail
Notre application a été structurée de sorte que chaque classe/interface n'ai qu'un seul role (une seule responsabilité), bien défini, conformément aux règles de développement SOLID (nous y reviendrons dans un autre tutoriel)
MailComposer: Classe abstraite qui se charge de composer le mail en collectant des informations sur les adresses de destination, le sujet du mail et son contenu.
public Message compose(Session session) throws MailComposerException {
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(fromEmail));
message.setRecipients(
Message.RecipientType.TO,
toEmails.stream().map(t -> {
try {
return new InternetAddress(t);
} catch (AddressException e) {
logger.log(Level.SEVERE, "Error occurred when converting '" +
t + "' email");
throw new RuntimeException(e);
}
}).toList().toArray(new InternetAddress[0])
);
return doCompleteCompose(message);
} catch (MessagingException e) {
logger.log(Level.SEVERE, "Error convert email to internet addresses");
throw new MailComposerException(e);
}
}
TextMailComposer: il s'agit d'une implémentation basique du MailComposer qui se charge de positionner le contenu du mail en tant que texte dans l'objet Message de l'API Jakarta Mail.
public Message doCompleteCompose(Message message) throws MailComposerException {
try {
message.setSubject(subject);
message.setText(content);
return message;
} catch (MessagingException e) {
logger.log(Level.SEVERE, "Error occurred when composing the text message");
throw new MailComposerException(e);
}
}
HtmlMailComposer: Cette implémentation du MailComposer, quant à elle se charge de positionner le contenu du mail en tant que contenu html afin que le message soit formatté et affiché comme une page web(html)
public Message doCompleteCompose(Message message) throws MailComposerException {
try {
Multipart multipart = new MimeMultipart();
addBodyPart(multipart);
message.setSubject(subject);
message.setContent(multipart);
return message;
} catch (MessagingException e) {
logger.log(Level.SEVERE, "Error occurred when composing the text message");
throw new MailComposerException(e);
}
}
protected void addBodyPart(Multipart multipart) throws MessagingException {
MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.setContent(content, TEXT_HTML_CHARSET_UTF_8);
multipart.addBodyPart(mimeBodyPart);
}
MultiPartMailComposer: quant à cette dernière implémentation étend (hérite) HtmlMailComposer et permet d'attacher plusieurs fichiers au mail.
protected void addBodyPart(Multipart multipart) throws MessagingException {
super.addBodyPart(multipart);
if(filePaths != null && !filePaths.isEmpty()) {
filePaths.forEach(filePath -> {
MimeBodyPart attachmentBodyPart = new MimeBodyPart();
try {
attachmentBodyPart.attachFile(new File(filePath));
multipart.addBodyPart(attachmentBodyPart);
} catch (IOException | MessagingException e) {
logger.log(Level.SEVERE, "Error occurred when attaching file to
mail body: '" + filePath);
throw new RuntimeException(e);
}
});
}
}
Ensuite dans la partie gauche de notre design apparait la classe qui se chargera de faire l'envoie, rien que l'envoie.
L'interface MailSender est implémentée par MailSenderImpl qui au final se charge d'invoquer la méthode compose du MailComposer puis utilise le message produit dans l'invocation de Transport.send()
public void send(MailComposer mailComposer) throws MailSenderException {
try {
Message message = mailComposer.compose(session);
Transport.send(message);
} catch (MailComposerException e) {
throw new MailSenderException(e);
} catch (MessagingException e) {
logger.log(Level.SEVERE, "Error occurred when send the mail message to
the recipients");
throw new MailSenderException(e);
}
}
Et enfin l'application principale(main) ne manipulera que le MailSender d'un côté et collectera des données de saisie de l'utilisateur au sein d'un MailComposer qu'elle passera ensuite au MailSender pour action.
Vous remarquerez aussi que des exceptions spécifiques ont été à chaque fois créées afin de donner du sens et spécialisées les exceptions et erreurs. Et tout ceci en suivant notre tutoriel sur la gestion des exceptions que vous trouverez en cliquant sur ce lien
Le code source de ce tutoriel et de notre application est présent sur github à cette adresse: simple-mail-sender
Ne pas hésiter à commenter ou à poser une question ou à demander de l'aide autour de java et des technologies connexes. Nous nous ferons un plaisir de vous répondre.
Commentaires
Enregistrer un commentaire