Пример JavaMail – Отправка почты в Java с использованием SMTP

Сегодня мы рассмотрим пример использования 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 для отправки электронной почты содержит следующие шаги:

  1. Создание объекта javax.mail.Session
  2. Создание объекта javax.mail.internet.MimeMessage, необходимо установить различные свойства в этом объекте, такие как адрес электронной почты получателя, тема электронного письма, адрес электронной почты для ответа, тело электронного письма, вложения и т. д.
  3. Использование 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

  1. 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
    
  2. Если ваша программа застряла в вызове метода 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