PodoBulge
31 уровень
Минск

Как отправить письмо из Java-приложения (с примером)

Пост из группы Архив info.javarush.ru
3710 участников
Перевод статьи: How to Send Email from Java Program with Example Отправка электронного сообщения из Java-приложения это распространенное требование. Не имеет значения работаешь ли ты над core Java-приложением, веб-приложением или enterprise Java - приложением, тебе может понадобится отправить письмо для оповещения персонала из тех.поддержки об ошибках, или просто отправить письмо пользователям при регистрации, восстановить пароль или попросить их подтвердить адрес электронной почты после регистрации. Есть очень много сценариев(случаев), когда тебе нужна возможность отправить электронные письма из Java-приложения. В готовых приложениях у тебя уже есть модуль или библиотека, работающая со всеми функциями для отправки электронных писем, например, возможность отправлять вложения, изображения, включая подписи и форматированный текст в электронных письмах, НО если тебе нужно написать что-то с нуля, тогда Java Mail API это прекрасный вариант. В этой статье мы научимся как отправлять электронные письма из Java-приложения, используя почтовый API(javax.mail). Перед написанием кода ты должен знать некоторые основы работы электронной почты, например, тебе нужен SMTP(простой протокол передачи почты) сервер. Если ты запускаешь свое Java-приложение под Linux, тогда ты должен знать, что SMTP демон(прим. "компьютерная программа в системах класса UNIX, запускаемая самой системой и работающая в фоновом режиме без прямого взаимодействия с пользователем") использует порт 25. Ты можешь использовать любой почтовый сервер для отправки сообщений применяя Java, включая общедоступные почтовые сервера, такие как GMail, Yahoo или любой другой поставщик услуг, все что тебе нужно это детали их SMTP сервера, например, имя хоста, порт, параметры соединения и т.д. Так же ты можешь использовать SSL(англ. secure sockets layer — уровень защищённых сокетов), TLS(англ. Transport Layer Security — безопасность транспортного уровня) для безопасного соединения и отправки писем, но этот пример мы сделали простым и cфокусировались на минимальной логике для отправки письма из Java-приложения. В дальнейших статьях мы научимся как отправлять письмо используя вложения, как отправлять форматированное с помощью HTML письмо, как прикрепить изображения в письмо, как использовать SSL аутентификацию для соединения с сервером GMail и отправки писем и т.д. А сейчас, давай поймем(разберем) этот простой пример Java Mail API.

Пример Java-кода для отправки электронного сообщения

Для отправки письма из Java-программы тебе потребуются Java Mail API и Java Activation Framework(JAF); если более точно, то тебе понадобятся mail-1.4.5.jar, smtp-1.4.4.jar, и activation-1.1.jar. Тебе нужно скачать эти JAR файлы и включить их в твой Classpath для запуска этой программы. В качестве альтернативы ты можешь использовать Maven для управления зависимостями и включить все зависимости там. Как только у тебя будут все эти JAR файлы, просто следуй шагам ниже для создания и отправки электронного письма c помощью Java.
  1. Создай объект Session вызывая Session.getDefaultInstance(properties), где properties - содержит все важные свойства, например, имя хоста SMTP сервера.
  2. Создай объект MimeMessage передавая ему объект Session, полученный на предыдущем шаге. У нас есть набор различных свойств в этом объекте, таких как получатель письма, тема, тело сообщения, вложения и т.д.
  3. Используй javax.mail.Transport для отправки письма вызывая статический метод send(email), где email может быть объект MimeMessage.
Количество свойств, которые ты передаешь для создания объекта Session отличается в зависимости от типа SMTP сервера, например, если ты используешь SMTP сервер, который не требует никакой аутентификации, ты можешь создать объект Session только с одним свойством, например, smtp.mail.host, и тебе не нужно указывать порт, потому что он имеет порт 25 по умолчанию. С другой стороны, если ты подключаешься к SMTP серверу, который требует TLS или SSL аутентификацию, например, GMail's SMTP Host, тогда тебе нужно предоставить немного больше свойств, например, mail.smtp.port=547 для TLS и mail.smtp.port=457 для SSL. Это законченная Java-программа, которая соединяется с стандартным SMTP сервером без аутентификации и отправляет текстовое письмо используя Java Mail API. import java.util.Properties; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; /** * Java Program to send text mail using default SMTP server and without authentication. * You need mail.jar, smtp.jar and activation.jar to run this program. * * @author Javin Paul */ public class EmailSender{ public static void main(String args[]){ String to = "receive@abc.om"; // sender email String from = "sender@abc.com"; // receiver email String host = "127.0.0.1"; // mail server host Properties properties = System.getProperties(); properties.setProperty("mail.smtp.host", host); Session session = Session.getDefaultInstance(properties); // default session try { MimeMessage message = new MimeMessage(session); // email message message.setFrom(new InternetAddress(from)); // setting header fields message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); message.setSubject("Test Mail from Java Program"); // subject line // actual mail body message.setText("You can send mail from Java program by using mail API, but you need" + "couple of more JAR files e.g. smtp.jar and activation.jar"); // Send message Transport.send(message); System.out.println("Email Sent successfully...."); } catch (MessagingException mex){ mex.printStackTrace(); } } } На выходе : Ты можешь скомпилировать и запустить эту программу для отправки простого электронного письма из Java-программы: $ javac EmailSender.java $ java EmailSender Sent email successfully.... Как ты можешь видеть, очень просто отправлять письма из Java-программы. Как только ты создал объект MimeMessage, тебе нужно добавить получателей, которые могут указываться в полях TO, CC, BCC. Завершив с получателями нам нужно указать тему письма, и, наконец, само содержание письма вызвав метод message.setText(); Если ты хочешь сделать множественную рассылку, тогда следующие метод может быть использован для указания получателей: void addRecipients(Message.RecipientType type, Address[] addresses) throws MessagingException Ты можешь добавить людей в поле TO используя Message.RecipientType.TO, в поле CC используя Message.RecipientType.CC, и в BCC - Message.RecipientType.BCC.

Ошибки и исключения

Когда многие Java-программисты впервые начинают писать программу для отправки электронного письма, они натыкаются на ошибку, потому что большинство из них думает, что mail.jar и activation.jar будет достаточно для отправки письма из Java-приложения, что не так, особенно если ты отправляешь имейл через локальный SMTP сервер в Linux. Если ты запускаешь эту программу только с mail.jar и activation.jar в твоем CLASSPATH, ты вероятнее всего получишь эту ошибку.

Exception 1:

com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1; nested exception is: java.net.ConnectException: Connection refused: connect at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1984) at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:656) at javax.mail.Service.connect(Service.java:345) at javax.mail.Service.connect(Service.java:226) at javax.mail.Service.connect(Service.java:175) at javax.mail.Transport.send0(Transport.java:253) at javax.mail.Transport.send(Transport.java:124) at Testing.main(Testing.java:62) Caused by: java.net.ConnectException: Connection refused: connect at java.net.DualStackPlainSocketImpl.connect0(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:579) at java.net.Socket.connect(Socket.java:528) at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:301) at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:229) at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1950) ... 7 more Хотя решение этой ошибки очень простое, она может вас запутать. java.net.ConnectException: Connection refused: connect обычно вылетает, когда не работает сервер или неверно указанный порт, по которому ты соединяешься. Решение: кроме mail-1.4.5.jar, тебе так же нужны smtp-1.4.4.jar и activation-1.1.jar.

Exception 2:

Это другая ошибка, называющаяся NoClassDefFoundError, которая обычно относится к отсутствующему JAR файлу в Classpath Exception in thread "main" java.lang.NoClassDefFoundError: javax/mail/MessagingException at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2521) at java.lang.Class.getMethod0(Class.java:2764) at java.lang.Class.getMethod(Class.java:1653) at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:494) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:486) Caused by: java.lang.ClassNotFoundException: javax.mail.MessagingException at java.net.URLClassLoader$1.run(URLClassLoader.java:366) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) Решение: Мне удалось решить мою проблему, она произошла из-за некорректного Classpath. Несмотря на то, что у меня были все три требуемых JAR, файл Java класса для программы в одной директории и я запускал программу оттуда, Java не смогла этого понять. Я попытался ввести следующие команды и программа прекрасно заработала: java -cp mail-1.4.5.jar:smtp-1.4.4.jar:activation-1.1.jar:. JavaMailSender Sent email successfully.... Пожалуйста обратите внимание, что текущая директория отмечена точкой в конце аргумента Classpath. Так как я запускал программу в Linux, я использовал двоеточие(:) вместо точки с запятой(;)(как в Windows). Вот и все о том, как отправить имейл из Java-приложения используя почтовое API. Тебе может показаться это очень простым, так как не нужно ничего более, кроме трех JAR файлов. Намного проще, если ты используешь Gradle или Maven для управления зависимостями. В следующих туториалах мы увидим более сложные примеры Java Mail API для отправки писем с вложениями, с картинками и красиво отформатированных писем для отправки отчетов и таблиц.
Комментарии (9)
  • популярные
  • новые
  • старые
Для того, что бы оставить комментарий вы должны авторизоваться
mtechno25 уровень
27 марта 2017, 15:32
Спасибо. Хороший перевод!
ПС прочитал статью, загуглил пример работы с сервером яндекса, все вышло.
djigurda7128 уровень
6 июня 2016, 12:19
Добрый день, помогите, не могу добавить jar-файлы. Скачиваю их, кидаю в папку, добавляю в переменную classpath по полному пути + имя файла, пытаюсь импортировать классы, а они все равно не видны, в чем может быть проблема?? Пытался добавить их через File\Settings\Plugins\Install plugin from disk выдает ошибку «fail to load plugin descriptor from file „
Gashek9 уровень, Минск
13 августа 2015, 15:05
Всем, доброго дня. Для отправки писем хочу использовать корпоративный ящик google, параметры для работы с ним (порты, SSL, TLS), насколько я понимаю, должны прописываться в «properties.setProperty(String key, String value);». Подскажите пожалуйста, как будут выглядеть «String key» для этих параметров(синтаксис) или где можно посмотреть полный перечень возможных параметров. Гуглил по java.util.Properties и javax.mail.Session, но списка параметров так и не нашел. Заранее благодарен.
Gashek9 уровень, Минск
13 августа 2015, 16:24
Нашел! Может кому-нибудь понадобятся:

SSL

(«mail.smtp.host», «smtp.gmail.com»);
(«mail.smtp.socketFactory.port», «465»);
(«mail.smtp.socketFactory.class», «javax.net.ssl.SSLSocketFactory»);
(«mail.smtp.auth», «true»)
(«mail.smtp.port», «465»)

TLS

(«mail.smtp.auth», «true»)
(«mail.smtp.starttls.enable», «true»)
(«mail.smtp.host», «smtp.gmail.com»)
(«mail.smtp.port», «587»)
eniqen32 уровень
1 мая 2015, 13:54
vlad32430 уровень, Минск
30 апреля 2015, 03:27
Для примера который здесь приведён, в Maven достаточно только одной зависимости:
<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>mail</artifactId>
    <version>1.4.7</version>
</dependency>
Olegator337 уровень, Одесса
28 апреля 2015, 08:18
Не хочу ничем обидеть, но когда мне это понадобилось для создания регистратора как тестовое задание, мне выбивало 100500 ошибок безопасности, и ибо сейчас все почтовые ящики борятся со спамом, пришлось изрядно в проперти написать, в том числе и аунтефикацию на свой почтовый ящик…
PodoBulge31 уровень, Минск
28 апреля 2015, 15:22
Все норм:), я ничего от себя не добавлял при переводе статьи, только то, что написал автор)

Можешь кинуть пример своего кода
Gradus27 уровень, Санкт-Петербург
27 апреля 2015, 09:28
Спасибо за статью!