- Java – Send Emails using Gmail SMTP using TLS/SSL
- Работа с сообщениями JavaMail
- Протоколы JavaMail API
- Отправка сообщения по протоколу SMTP
- Конструктор класса SendEmail.java, настройка SMTP SSL
- Листинг аутентификатора EmailAuthenticator.java
- Вложение файла в сообщение, MimeBodyPart
- Отправка сообщения, Multipart
- Пример отправки сообщения
- Чтение сообщений по протоколу IMAP
- Листинг примера чтения почтовых сообщений
- Скачать примеры использования JavaMail
Java – Send Emails using Gmail SMTP using TLS/SSL
Learn to send emails using the Jakarta Mail API and using the Gmail SMTP Server. We will see the Java examples to send plain text emails as well as emails with attachments.
1. Gmail SMTP Server Details
Google has provided free access to one of its SMTP servers and we can use its Java code to send emails.
- Gmail SMTP server: smtp.gmail.com
- Port: 465 (SSL required) / 587 (TLS required)
- Username: Gmail id
- Password: The app password
We must create the app password as described in this guide. We cannot use the Gmail password (used to signin in the browser) if we have enabled the 2-factor authentication for the account.
In absense of App password, you will get the “AuthenticationFailedException: 534-5.7.9 Application-specific password required.” error in runtime.
For a typical client application, we need to perform the following steps to send an email:
- Create a mail message containing the message header and body
- Create a Session object, which authenticates the user using the Authenticator , and controls access to the message store and transport.
- Send the message to its recipient list.
Start with adding the following dependencies to the project. Note that the Angus Mail implementation of Jakarta Mail Specification 2.1+ providing a platform-independent and protocol-independent framework to build mail and messaging applications.
jakarta.mail jakarta.mail-api 2.1.2 org.eclipse.angus jakarta.mail 2.0.1
The EmailSender is a utility class that accepts the message parameters and sends the email to recipients.
import jakarta.mail.Authenticator; import jakarta.mail.Message; import jakarta.mail.MessagingException; import jakarta.mail.Multipart; import jakarta.mail.PasswordAuthentication; import jakarta.mail.Session; import jakarta.mail.Transport; import jakarta.mail.internet.InternetAddress; import jakarta.mail.internet.MimeBodyPart; import jakarta.mail.internet.MimeMessage; import jakarta.mail.internet.MimeMultipart; import java.util.Date; import java.util.List; import java.util.Properties; public class EmailSender < private static final Properties PROPERTIES = new Properties(); private static final String USERNAME = "admin@gmail.in"; //change it private static final String PASSWORD = "password"; //change it private static final String HOST = "smtp.gmail.com"; static < PROPERTIES.put("mail.smtp.host", "smtp.gmail.com"); PROPERTIES.put("mail.smtp.port", "587"); PROPERTIES.put("mail.smtp.auth", "true"); PROPERTIES.put("mail.smtp.starttls.enable", "true"); >public static void sendPlainTextEmail(String from, String to, String subject, List messages, boolean debug) < Authenticator authenticator = new Authenticator() < protected PasswordAuthentication getPasswordAuthentication() < return new PasswordAuthentication(USERNAME, PASSWORD); >>; Session session = Session.getInstance(PROPERTIES, authenticator); session.setDebug(debug); try < // create a message with headers MimeMessage msg = new MimeMessage(session); msg.setFrom(new InternetAddress(from)); InternetAddress[] address = ; msg.setRecipients(Message.RecipientType.TO, address); msg.setSubject(subject); msg.setSentDate(new Date()); // create message body Multipart mp = new MimeMultipart(); for (String message : messages) < MimeBodyPart mbp = new MimeBodyPart(); mbp.setText(message, "us-ascii"); mp.addBodyPart(mbp); >msg.setContent(mp); // send the message Transport.send(msg); > catch (MessagingException mex) < mex.printStackTrace(); Exception ex = null; if ((ex = mex.getNextException()) != null) < ex.printStackTrace(); >> > >
To test the above class, we can invoke the sendPlainTextEmail() method as follows:
import java.util.List; public class MailTest < public static void main(String[] args) < EmailSender.sendPlainTextEmail("sender@gmail.com", "reciever@gmail.com", "Test Email", List.of("Hello", "World"), true); >>
Check the email. You should be able to see the email in your Gmail inbox as follows:
If we do not have TLS support on the server, we can use the SSL support provided in the API. To use SSL, follow these steps:
- Remove the mail.smtp.starttls.enable property
- Use port number 465
- Add SSL support in the properties
The modified properties will be:
Now we can run the above program with modified properties, and we will again get the email in our inbox.
6. Adding Email Attachments
If we want to add the attachments to the email body, we can use the MimeBodyPart.attachFile() method to attach a file.
MimeBodyPart attachmentBodyPart = new MimeBodyPart(); attachmentBodyPart.attachFile(new File("path/to/file"));
In this example, we saw the Java programs to send emails using the Gmail SMTP server to multiple recipients. Drop me your questions in the comments.
Работа с сообщениями JavaMail
Свободно распространяемая библиотека JavaMail предназначена для подключения к почтовым серверам с целью получения и отправки электронной почты с использованием протоколов SMTP, POP3 и IMAP. Библиотека позволяет отправлять сообщения с вложениями и удалять их на почтовом сервере.
Протоколы JavaMail API
- SMTP (Simple Mail Transfer Protocol простой протокол передачи почты) — это широко используемый сетевой протокол для передачи электронной почты в сетях TCP/IP. Электронные почтовые серверы используют протокол SMTP для отправки и получения почтовых сообщений. Клиентские почтовые приложения обычно используют SMTP только для отправки сообщений на почтовый сервер и для ретрансляции с использованием порта 25 (465 для SSL). Т.е. протокол SMTP применяют для передачи исходящей почты.
- IMAP (Internet Message Access Protocol) — протокол прикладного уровня для доступа к электронной почте. Протокол IMAP предоставляет пользователю широкие возможности для работы с почтовыми ящиками, расположенными на удаленном сервере. Почтовая программа, использующая данный протокол, получает доступ к хранилищу корреспонденции на сервере так, как будто эта корреспонденция расположена на компьютере получателя. Электронными письмами можно управлять с компьютера пользователя без пересылки файлов по сети. Протокол IMAP использует транспортный протокол TCP и прослушивает порт 143.
- POP3 (Post Office Protocol Version 3 протокол почтового отделения 3-ей версии) — это стандартный сетевой протокол прикладного уровня, используемый клиентами электронной почты для получения почты с удаленного сервера по TCP/IP-соединению. Протокол POP3 поддерживает простые требования «загрузи-и-удали» для доступа к удаленным почтовым ящикам. Сервер POP3 прослушивает порт 110.
Отправка сообщения по протоколу SMTP
Создадим класс подготовки и отправки сообщения SendEmail.java. В классе определим поля сервера SMTP, поля авторизации на сервере и дополнительные поля вложения файла FILE_PATH и адресата для ответа REPLY_TO.
Конструктор класса SendEmail.java, настройка SMTP SSL
public class SendEmail < private Message message = null; protected static String SMTP_SERVER = null; protected static String SMTP_Port = null; protected static String SMTP_AUTH_USER = null; protected static String SMTP_AUTH_PWD = null; protected static String EMAIL_FROM = null; protected static String FILE_PATH = null; protected static String REPLY_TO = null; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public SendEmail(final String emailTo, final String thema) < // Настройка SMTP SSL Properties properties = new Properties(); properties.put("mail.smtp.host" , SMTP_SERVER); properties.put("mail.smtp.port" , SMTP_Port ); properties.put("mail.smtp.auth" , "true" ); properties.put("mail.smtp.ssl.enable" , "true" ); properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); try < Authenticator auth = new EmailAuthenticator(SMTP_AUTH_USER, SMTP_AUTH_PWD); Session session = Session.getDefaultInstance(properties,auth); session.setDebug(false); InternetAddress email_from = new InternetAddress(EMAIL_FROM); InternetAddress email_to = new InternetAddress(emailTo ); InternetAddress reply_to = (REPLY_TO != null) ? new InternetAddress(REPLY_TO) : null; message = new MimeMessage(session); message.setFrom(email_from); message.setRecipient(Message.RecipientType.TO, email_to); message.setSubject(thema); if (reply_to != null) message.setReplyTo (new Address[] ); > catch (AddressException e) < System.err.println(e.getMessage()); >catch (MessagingException e) < System.err.println(e.getMessage()); >> >
Конструктор класса SendEmail.java включает два параметра : email получателя и тему сообщения. Первоначально в конструкторе определяются свойства сервера; подключение к серверу будет выполняться по защищенному каналу SSL с авторизацией пользователя. Для этого создается класс авторизации auth типа Authenticator и формируется сессия класса javax.mail.Session, которой в качестве параметров передаются свойства properties и auth.
На следующем шаге формируется сообщение для отправки. Предварительно создаются адресаты (тип InternetAddress) email_from, email_to, reply_to . Адресат сообщения reply_to используется для случая, когда получатель должен отвечать не непосредственно отправителю email_from, который играет роль сервера перессылки. Данную опцию должен поддерживать сервер получателя, чтобы при нажатии на кнопку «Ответить» пользователю открывалось новое письмо с подстановкой в поле адресата «Кому» значения reply_to, а не email_from.
Конструктор объекта сообщения message типа MimeMessage в качестве параметра получает значение созданной защищенной с сервером SMTP сессии session.
Листинг аутентификатора EmailAuthenticator.java
Класс Authenticator обеспечивает доступ к защищенным почтовым ресурсам на сервере. В примерах этот класс используется для установления сессии с сервером. Когда потребуется авторизация, библиотека JavaMail будет вызывать метод getPasswordAuthentication.
public class EmailAuthenticator extends javax.mail.Authenticator < private String login ; private String password; public EmailAuthenticator (final String login, final String password) < this.login = login; this.password = password; >public PasswordAuthentication getPasswordAuthentication() < return new PasswordAuthentication(login, password); >>
Вложение файла в сообщение, MimeBodyPart
Для вложения файла в сообщение необходимо создать объект типа MimeBodyPart, в котором в качестве параметров указать путь к файлу и наименование файла. Следующий листинг представляет функцию формирования объекта MimeBodyPart с содержимом файла, который можно вкладывать в сообщение.
private MimeBodyPart createFileAttachment(String filepath) throws MessagingException < // Создание MimeBodyPart MimeBodyPart mbp = new MimeBodyPart(); // Определение файла в качестве контента FileDataSource fds = new FileDataSource(filepath); mbp.setDataHandler(new DataHandler(fds)); mbp.setFileName(fds.getName()); return mbp; >
Отправка сообщения, Multipart
Функция sendMessage завершает оформление сообщения. Для этого создается объект mmp типа MimeMultipart, в который можно вложить другие объекты типа MimeBodyPart (текст, файл). Метод сообщения setContent, которому в качестве параметра передается объект MimeMultipart, определяет содержимое сообщения.
public boolean sendMessage (final String text) < boolean result = false; try < // Содержимое сообщения Multipart mmp = new MimeMultipart(); // Текст сообщения MimeBodyPart bodyPart = new MimeBodyPart(); bodyPart.setContent(text, "text/plain; charset=utf-8"); mmp.addBodyPart(bodyPart); // Вложение файла в сообщение if (FILE_PATH != null) < MimeBodyPart mbr = createFileAttachment(FILE_PATH); mmp.addBodyPart(mbr); >// Определение контента сообщения message.setContent(mmp); // Отправка сообщения Transport.send(message); result = true; > catch (MessagingException e) < // Ошибка отправки сообщения System.err.println(e.getMessage()); >return result; >
Для отправки сообщения используется метод send класса Transport, который имеет следующие перегруженные методы send :
static void send(Message message) throws MessagingException static void send(Message message, Address[] addresses) throws MessagingException
Первый метод send отправит сообщение получателям, указанным в сообщении. Второй метод отправит сообщение всем получателям, определенным в массиве addresses за исключением тех, которые определены в сообщении.
Пример отправки сообщения
Для отправки сообщения создадим файл свойств email.properties, в котором определим все необходимые параметры сервера SMTP и параметры подключения. В примере используем почтовый сервер Yandex, хотя настройки позволяют использовать и другие известные почтовые сервера.
# # Параметры сервера SMTP # server=smtp.yandex.ru port=465 # # email отправителя # from=. @yandex.ru user=. pass=. # # email получателя # to=. @yandex.ru # # email для ответа # replyto=java-online@mail.ru # # Сообщение : тема и текст # thema=Пересылка сообщения text=Тестовое сообщение для перессылки
В файле свойств необходимо заполнить 4 поля, значения которых определены в виде многоточий. Если, к примеру, почтовый адрес в Yandex’e имеет вид qwerty@yandex.ru, то пользователь user будет иметь значение qwerty.
Следующий класс EmailTest используется для отправки сообщения. Сначала из файла свойств читаются параметры почтового сервера и параметры подключения. Для чтения файла используется класс InputStream, более подробно о котором сказано на странице Потоки ввода. После этого создается объект SendEmail и выполняется отправка сообщения.
public class EmailTest < private final static String PROPS_FILE = "email.properties"; public static void main(String[] args) < try < InputStream is = new FileInputStream(PROPS_FILE); if (is != null) < Reader reader = new InputStreamReader(is, "UTF-8"); Properties pr = new Properties(); pr.load(reader); SendEmail.SMTP_SERVER = pr.getProperty ("server" ); SendEmail.SMTP_Port = pr.getProperty ("port" ); SendEmail.EMAIL_FROM = pr.getProperty ("from" ); SendEmail.SMTP_AUTH_USER = pr.getProperty ("user" ); SendEmail.SMTP_AUTH_PWD = pr.getProperty ("pass" ); SendEmail.REPLY_TO = pr.getProperty ("replyto"); SendEmail.FILE_PATH = PROPS_FILE; String emailTo = pr.getProperty ("to" ); String thema = pr.getProperty ("thema"); String text = pr.getProperty ("text" ); is.close(); SendEmail se = new SendEmail(emailTo, thema); se.sendMessage(text); System.out.println ("Сообщение отправлено"); >> catch (IOException e) < e.printStackTrace(); >> >
Представленный пример с небольшими изменениями можно использовать для рассылки сообщений.
Чтение сообщений по протоколу IMAP
Как было отмечено выше протокол IMAP следует использовать для чтения почтовых сообщений. При использовании протокола IMAP программа должна подключиться к серверу и получить доступ к папке INBOX. Для настройки сессии подключения по протоколу IMAP необходимо указать следующие данные :
- адрес почтового сервера (в следующем примере мы используем imap.yandex.ru);
- порт подключения — 993;
- защита соединения — SSL.
Для доступа к почтовому серверу также необходимо указать логин и пароль пользователя. Если для получение почты (подключения к почтовому серверу) используется ящик вида «login@yandex.ru», то логином является часть адреса до знака «@».
Листинг примера чтения почтовых сообщений
В следующем примере сначала настраивается сессия с почтовым сервером для работы по «закрытому» каналу связи. После этого выполняется чтение последнего сообщения папки «INBOX», которое было отправлено в предыдущем примере. В консоль выводится информация этого последнего сообщения.
Чтобы пример сработал необходимо вместо многоточий подставить реальные логин и пароль.
public class ReadEmail < String IMAP_AUTH_EMAIL = ". @yandex.ru" ; String IMAP_AUTH_PWD = ". " ; String IMAP_Server = "imap.yandex.ru"; String IMAP_Port = "993" ; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public ReadEmail() < Properties properties = new Properties(); properties.put("mail.debug" , "false" ); properties.put("mail.store.protocol" , "imaps" ); properties.put("mail.imap.ssl.enable", "true" ); properties.put("mail.imap.port" , IMAP_Port); Authenticator auth = new EmailAuthenticator(IMAP_AUTH_EMAIL, IMAP_AUTH_PWD); Session session = Session.getDefaultInstance(properties, auth); session.setDebug(false); try < Store store = session.getStore(); // Подключение к почтовому серверу store.connect(IMAP_Server, IMAP_AUTH_EMAIL, IMAP_AUTH_PWD); // Папка входящих сообщений Folder inbox = store.getFolder("INBOX"); // Открываем папку в режиме только для чтения inbox.open(Folder.READ_ONLY); System.out.println("Количество сообщений : " + String.valueOf(inbox.getMessageCount())); if (inbox.getMessageCount() == 0) return; // Последнее сообщение; первое сообщение под номером 1 Message message = inbox.getMessage(inbox.getMessageCount()); Multipart mp = (Multipart) message.getContent(); // Вывод содержимого в консоль for (int i = 0; i < mp.getCount(); i++)< BodyPart bp = mp.getBodyPart(i); if (bp.getFileName() == null) System.out.println(" " + i + ". сообщение : '" + bp.getContent() + "'"); else System.out.println(" " + i + ". файл : '" + bp.getFileName() + "'"); >> catch (NoSuchProviderException e) < System.err.println(e.getMessage()); >catch (MessagingException e) < System.err.println(e.getMessage()); >catch (IOException e) < System.err.println(e.getMessage()); >> //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public static void main(String[] args) < new ReadEmail(); System.exit(0); >//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >
В примере используются абстрактные классы
- Store — представляет собой хранилище сообщений, поддерживаемых почтовым сервером и сгруппированных по владельцу,
- Folder — предоставляет возможность иерархически организовывать сообщения. Папки могут содержать сообщения и поддиректории.
В консоль будет выведено следующее сообщение. Конечно, количество сообщений в почтовом ящике «INBOX» будет другим.
Количество сообщений : 30 0. сообщение : 'Тестовое сообщение для перессылки' 1. файл : 'email.properties'
Скачать примеры использования JavaMail
Исходные коды рассмотренных примеров использования библиотеки JavaMail в виде проекта Eclipse можно скачать здесь (930 Кб).