Сегодня мы рассмотрим пример использования JavaMail для отправки электронной почты в программах на Java. Отправка электронных писем – одна из обычных задач в реальных приложениях, и поэтому Java предоставляет надежный API JavaMail, который мы можем использовать для отправки электронных писем с использованием SMTP-сервера. API JavaMail поддерживает аутентификацию как по TLS, так и по SSL для отправки электронных писем.
Пример JavaMail
Сегодня мы узнаем, как использовать API JavaMail для отправки электронных писем с использованием SMTP-сервера без аутентификации, с аутентификацией TLS и SSL, а также как отправлять вложения и прикреплять и использовать изображения в теле электронного письма. Для аутентификации TLS и SSL я использую SMTP-сервер GMail, потому что он поддерживает оба из них. Вы также можете выбрать почтовый сервер Java в зависимости от потребностей вашего проекта. API JavaMail не является частью стандартного JDK, поэтому вам придется загрузить его с официального веб-сайта, т.е. домашняя страница JavaMail. Загрузите последнюю версию эталонной реализации JavaMail и включите ее в путь сборки вашего проекта. Имя файла JAR будет javax.mail.jar. Если вы используете проект на базе Maven, просто добавьте зависимость ниже в ваш проект.
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.5.5</version>
</dependency>
Программа на Java для отправки электронной почты содержит следующие шаги:
- Создание объекта
javax.mail.Session
- Создание объекта
javax.mail.internet.MimeMessage
, необходимо установить различные свойства в этом объекте, такие как адрес электронной почты получателя, тема электронного письма, адрес электронной почты для ответа, тело электронного письма, вложения и т. д. - Использование
javax.mail.Transport
для отправки электронного сообщения.
Логика создания сеанса отличается в зависимости от типа сервера SMTP, например, если сервер SMTP не требует аутентификации, мы можем создать объект Session с некоторыми простыми свойствами, тогда как если требуется аутентификация TLS или SSL, то логика создания будет отличаться. Поэтому я создам утилитарный класс с некоторыми утилитарными методами для отправки электронных писем, а затем буду использовать этот утилитарный метод с разными серверами SMTP.
Пример программы JavaMail
Наш класс EmailUtil, который имеет единственный метод для отправки электронной почты, выглядит следующим образом, он требует javax.mail.Session и некоторые другие обязательные поля в качестве аргументов. Для упрощения некоторые аргументы захардкожены, но вы можете расширить этот метод, чтобы передавать их или читать из каких-либо конфигурационных файлов.
package com.journaldev.mail;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
public class EmailUtil {
/**
* Utility method to send simple HTML email
* @param session
* @param toEmail
* @param subject
* @param body
*/
public static void sendEmail(Session session, String toEmail, String subject, String body){
try
{
MimeMessage msg = new MimeMessage(session);
// установка заголовков сообщения
msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
msg.addHeader("format", "flowed");
msg.addHeader("Content-Transfer-Encoding", "8bit");
msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD"));
msg.setReplyTo(InternetAddress.parse("[email protected]", false));
msg.setSubject(subject, "UTF-8");
msg.setText(body, "UTF-8");
msg.setSentDate(new Date());
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
System.out.println("Message is ready");
Transport.send(msg);
System.out.println("EMail Sent Successfully!!");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Обратите внимание, что я устанавливаю некоторые свойства заголовка в MimeMessage, они используются электронными клиентами для правильного отображения и отображения электронного сообщения. Остальная часть программы проста и понятна. Теперь давайте создадим нашу программу для отправки электронной почты без аутентификации.
Отправка почты в Java с использованием SMTP без аутентификации
package com.journaldev.mail;
import java.util.Properties;
import javax.mail.Session;
public class SimpleEmail {
public static void main(String[] args) {
System.out.println("SimpleEmail Start");
String smtpHostServer = "smtp.example.com";
String emailID = "[email protected]";
Properties props = System.getProperties();
props.put("mail.smtp.host", smtpHostServer);
Session session = Session.getInstance(props, null);
EmailUtil.sendEmail(session, emailID,"SimpleEmail Testing Subject", "SimpleEmail Testing Body");
}
}
Обратите внимание, что я использую Session.getInstance() для получения объекта Session, передавая объект Properties. Нам нужно установить свойство mail.smtp.host с хостом SMTP-сервера. Если SMTP-сервер не работает на порте по умолчанию (25), то также нужно установить свойство mail.smtp.port. Просто запустите эту программу с вашим SMTP-сервером без аутентификации и установите идентификатор электронной почты получателя как ваш собственный, и вы получите электронное письмо в кратчайшие сроки. Программа проста в понимании и хорошо работает, но в реальной жизни большинство SMTP-серверов используют некоторый вид аутентификации, такой как аутентификация TLS или SSL. Теперь мы увидим, как создать объект Session для этих протоколов аутентификации.
Отправка электронной почты в Java SMTP с аутентификацией TLS
package com.journaldev.mail;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
public class TLSEmail {
/**
Outgoing Mail (SMTP) Server
requires TLS or SSL: smtp.gmail.com (use authentication)
Use Authentication: Yes
Port for TLS/STARTTLS: 587
*/
public static void main(String[] args) {
final String fromEmail = "[email protected]"; //requires valid gmail id
final String password = "mypassword"; // correct password for gmail id
final String toEmail = "[email protected]"; // can be any email id
System.out.println("TLSEmail Start");
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com"); //SMTP Host
props.put("mail.smtp.port", "587"); //TLS Port
props.put("mail.smtp.auth", "true"); //enable authentication
props.put("mail.smtp.starttls.enable", "true"); //enable STARTTLS
//создание объекта Authenticator для передачи в аргумент Session.getInstance
Authenticator auth = new Authenticator() {
//переопределение метода getPasswordAuthentication
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(fromEmail, password);
}
};
Session session = Session.getInstance(props, auth);
EmailUtil.sendEmail(session, toEmail,"TLSEmail Testing Subject", "TLSEmail Testing Body");
}
}
Поскольку я использую SMTP-сервер GMail, который доступен всем, вы можете установить правильные переменные в указанной выше программе и запустить ее самостоятельно. Поверьте, это работает!! 🙂
Пример Java SMTP с аутентификацией SSL
package com.journaldev.mail;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
public class SSLEmail {
/**
Outgoing Mail (SMTP) Server
requires TLS or SSL: smtp.gmail.com (use authentication)
Use Authentication: Yes
Port for SSL: 465
*/
public static void main(String[] args) {
final String fromEmail = "[email protected]"; //requires valid gmail id
final String password = "mypassword"; // correct password for gmail id
final String toEmail = "[email protected]"; // can be any email id
System.out.println("SSLEmail Start");
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com"); //SMTP Host
props.put("mail.smtp.socketFactory.port", "465"); //SSL Port
props.put("mail.smtp.socketFactory.class",
"javax.net.ssl.SSLSocketFactory"); //SSL Factory Class
props.put("mail.smtp.auth", "true"); //Enabling SMTP Authentication
props.put("mail.smtp.port", "465"); //SMTP Port
Authenticator auth = new Authenticator() {
//переопределение метода getPasswordAuthentication
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(fromEmail, password);
}
};
Session session = Session.getDefaultInstance(props, auth);
System.out.println("Session created");
EmailUtil.sendEmail(session, toEmail,"SSLEmail Testing Subject", "SSLEmail Testing Body");
EmailUtil.sendAttachmentEmail(session, toEmail,"SSLEmail Testing Subject with Attachment", "SSLEmail Testing Body with Attachment");
EmailUtil.sendImageEmail(session, toEmail,"SSLEmail Testing Subject with Image", "SSLEmail Testing Body with Image");
}
}
Программа практически такая же, как при аутентификации через TLS, только некоторые свойства отличаются. Как вы можете видеть, я вызываю некоторые другие методы из класса EmailUtil для отправки вложения и изображения по электронной почте, но я их еще не определил. Фактически, я оставил их для показа позже и чтобы начать учебное пособие с простого.
Пример JavaMail – отправка почты в Java с вложением
Для отправки файла в качестве вложения нам необходимо создать объекты javax.mail.internet.MimeBodyPart
и javax.mail.internet.MimeMultipart
. Сначала добавьте часть тела для текстового сообщения в электронное письмо, а затем используйте FileDataSource, чтобы прикрепить файл ко второй части многочастного тела. Метод выглядит следующим образом.
/**
* Utility method to send email with attachment
* @param session
* @param toEmail
* @param subject
* @param body
*/
public static void sendAttachmentEmail(Session session, String toEmail, String subject, String body){
try{
MimeMessage msg = new MimeMessage(session);
msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
msg.addHeader("format", "flowed");
msg.addHeader("Content-Transfer-Encoding", "8bit");
msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD"));
msg.setReplyTo(InternetAddress.parse("[email protected]", false));
msg.setSubject(subject, "UTF-8");
msg.setSentDate(new Date());
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
// Создание части тела сообщения
BodyPart messageBodyPart = new MimeBodyPart();
// Заполнение сообщения
messageBodyPart.setText(body);
// Создание многочастного сообщения для вложения
Multipart multipart = new MimeMultipart();
// Установка текстовой части сообщения
multipart.addBodyPart(messageBodyPart);
// Вторая часть - вложение
messageBodyPart = new MimeBodyPart();
String filename = "abc.txt";
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
// Отправка полных частей сообщения
msg.setContent(multipart);
// Отправка сообщения
Transport.send(msg);
System.out.println("EMail Sent Successfully with attachment!!");
}catch (MessagingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
Программа может показаться сложной на первый взгляд, но на самом деле проста: просто создайте часть тела для текстового сообщения и другую часть тела для вложения, а затем добавьте их в мультипарт. Вы также можете расширить этот метод для прикрепления нескольких файлов.
Пример JavaMail – отправка почты в Java с изображением
Поскольку мы можем создавать HTML-текст сообщения, если файл с изображением находится в каком-то месте на сервере, мы можем использовать элемент img для его отображения в сообщении. Но иногда мы хотим прикрепить изображение к электронной почте и затем использовать его в самом сообщении. Вы наверняка видели множество писем с приложенными изображениями, которые также используются в тексте письма. Хитрость заключается в том, чтобы прикрепить файл изображения как любое другое вложение, а затем установить заголовок Content-ID для файла изображения, а затем использовать тот же идентификатор содержимого в теле электронного сообщения с помощью <img src='cid:image_id'>
.
/**
* Utility method to send image in email body
* @param session
* @param toEmail
* @param subject
* @param body
*/
public static void sendImageEmail(Session session, String toEmail, String subject, String body){
try{
MimeMessage msg = new MimeMessage(session);
msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
msg.addHeader("format", "flowed");
msg.addHeader("Content-Transfer-Encoding", "8bit");
msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD"));
msg.setReplyTo(InternetAddress.parse("[email protected]", false));
msg.setSubject(subject, "UTF-8");
msg.setSentDate(new Date());
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
// Создание части тела сообщения
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(body);
// Создание мультипартового сообщения для вложения
Multipart multipart = new MimeMultipart();
// Установка части текстового сообщения
multipart.addBodyPart(messageBodyPart);
// Вторая часть - вложение изображения
messageBodyPart = new MimeBodyPart();
String filename = "image.png";
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
// Хитрость заключается в добавлении сюда заголовка content-id
messageBodyPart.setHeader("Content-ID", "image_id");
multipart.addBodyPart(messageBodyPart);
// Третья часть для отображения изображения в теле электронного сообщения
messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent("Attached Image
" +
"
", "text/html");
multipart.addBodyPart(messageBodyPart);
// Установить мультипартовое сообщение в сообщение электронной почты
msg.setContent(multipart);
// Отправить сообщение
Transport.send(msg);
System.out.println("EMail Sent Successfully with image!!");
}catch (MessagingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
Советы по устранению неполадок в JavaMail API
-
java.net.UnknownHostException
возникает, когда ваша система не может разрешить IP-адрес SMTP-сервера, возможно, он неверен или недоступен из вашей сети. Например, SMTP-сервер GMail – smtp.gmail.com, и если я использую smtp.google.com, я получу это исключение. Если имя хоста верное, попробуйте выполнить пинг сервера через командную строку, чтобы убедиться, что он доступен из вашей системы.pankaj@Pankaj:~/CODE$ ping smtp.gmail.com PING gmail-smtp-msa.l.google.com (74.125.129.108): 56 data bytes 64 bytes from 74.125.129.108: icmp_seq=0 ttl=46 time=38.308 ms 64 bytes from 74.125.129.108: icmp_seq=1 ttl=46 time=42.247 ms 64 bytes from 74.125.129.108: icmp_seq=2 ttl=46 time=38.164 ms 64 bytes from 74.125.129.108: icmp_seq=3 ttl=46 time=53.153 ms
-
Если ваша программа застряла в вызове метода send() транспорта, проверьте, что порт SMTP указан правильно. Если он правильный, то используйте telnet для проверки доступности с вашего компьютера, вы получите вывод, подобный следующему.
pankaj@Pankaj:~/CODE$ telnet smtp.gmail.com 587 Trying 2607:f8b0:400e:c02::6d... Connected to gmail-smtp-msa.l.google.com. Escape character is '^]'. 220 mx.google.com ESMTP sx8sm78485186pab.5 - gsmtp HELO 250 mx.google.com at your service
Это все для примера JavaMail для отправки почты в Java с использованием SMTP-сервера с различными протоколами аутентификации, вложениями и изображениями. Надеюсь, это решит все ваши потребности в отправке электронной почты в программах на Java.
Source:
https://www.digitalocean.com/community/tutorials/javamail-example-send-mail-in-java-smtp