Журнал LinuxFormat - перейти на главную

LXF97:Java EE

Материал из Linuxformat
(Различия между версиями)
Перейти к: навигация, поиск
(Почтовый сервис)
Строка 1: Строка 1:
{{Цикл/Java EE}}
+
http://www.textervart.com
[[Категория:Учебники]]
+
{{Цикл/Java EE}}
==Почтовый сервис==
+
[[Категория:Учебники]]
 +
==Почтовый сервис==
  
[[Media:JavaEE_LXF97.tar.gz‎|Скачать исходный код примера]]
+
[[Media:JavaEE_LXF97.tar.gz‎|Скачать исходный код примера]]
  
: '''ЧАСТЬ 9''' Хотите оснастить свою программу возможностью писать «на деревню дедушке»? '''Александр Бабаев''' знает подходящее средство.
+
: '''ЧАСТЬ 9''' Хотите оснастить свою программу возможностью писать «на деревню дедушке»? '''Александр Бабаев''' знает подходящее средство.
  
  
Несмотря на засилье браузера в серии, JEE им не ограничивается. Давайте попробуем посылать письма из Java (ведь каждая хорошая программа должна уметь сообщать разработчикам об ошибках), и сделаем это приложение не браузерным, а «обычным».
+
Несмотря на засилье браузера в серии, JEE им не ограничивается. Давайте попробуем посылать письма из Java (ведь каждая хорошая программа должна уметь сообщать разработчикам об ошибках), и сделаем это приложение не браузерным, а «обычным».
  
===Коротко о почте===
+
===Коротко о почте===
  
Чтобы работать с почтой, нужно уметь её отправлять и получать. При попытке разобраться в этом вы наткнетесь на следующие буквосочетания (с разными вариациями): '''SMTP, POP, IMAP'''. Рассмотрим кратко, что это такое и как этим пользоваться (а также где почитать поподробнее).
+
Чтобы работать с почтой, нужно уметь её отправлять и получать. При попытке разобраться в этом вы наткнетесь на следующие буквосочетания (с разными вариациями): '''SMTP, POP, IMAP'''. Рассмотрим кратко, что это такое и как этим пользоваться (а также где почитать поподробнее).
  
 
* '''SMTP'''
 
* '''SMTP'''
При помощи Simple Mail Transfer Protocol (простого протокола передачи почты) почта передается с клиента на сервер. Отправляется то есть. Протокол текстовый, и если есть желание, можно отправлять письма прямо из telnet’а.
+
При помощи Simple Mail Transfer Protocol (простого протокола передачи почты) почта передается с клиента на сервер. Отправляется то есть. Протокол текстовый, и если есть желание, можно отправлять письма прямо из telnet’а.
  
 
* '''POP'''
 
* '''POP'''
Тоже текстовый протокол, но уже не для передачи, а для приема сообщений. Может выдать информацию по почтовому ящику (сколько
+
Тоже текстовый протокол, но уже не для передачи, а для приема сообщений. Может выдать информацию по почтовому ящику (сколько
сообщений, какой их размер), загрузить сообщение по номеру и так далее.
+
сообщений, какой их размер), загрузить сообщение по номеру и так далее.
  
 
* '''IMAP'''
 
* '''IMAP'''
'''POP''' предполагает, что почта скачивается на клиент и там уже раскладывается по папкам, обрабатывается, группируется. При этом с сервера сообщения стираются. Это не всегда удобно. Как раз для хранения почты на сервере создан протокол '''IMAP'''. Как и предыдущие два, он текстовый. Но с его помощью можно не только получить сообщения, но и создать на сервере папку, переместить письмо куда-нибудь, подписаться на получение изменений (новых писем) в папке, и так далее.
+
'''POP''' предполагает, что почта скачивается на клиент и там уже раскладывается по папкам, обрабатывается, группируется. При этом с сервера сообщения стираются. Это не всегда удобно. Как раз для хранения почты на сервере создан протокол '''IMAP'''. Как и предыдущие два, он текстовый. Но с его помощью можно не только получить сообщения, но и создать на сервере папку, переместить письмо куда-нибудь, подписаться на получение изменений (новых писем) в папке, и так далее.
  
* '''GoogleMail/HotMail/'''
+
* '''GoogleMail/HotMail/…'''
Но и это не всё. Протоколы протоколами, но некоторые сервисы работают «по-своему». И если '''GoogleMail''' предоставляет '''POP'''-интерфейс, то '''Hotmail''', например, нет. В таком случае обычно есть какой-то свой, нестандартный протокол.
+
Но и это не всё. Протоколы протоколами, но некоторые сервисы работают «по-своему». И если '''GoogleMail''' предоставляет '''POP'''-интерфейс, то '''Hotmail''', например, нет. В таком случае обычно есть какой-то свой, нестандартный протокол.
  
===Итого===
+
===Итого===
  
В итоге получается, что разных протоколов много-много (это не считая вариантов и нюансов, комбинаций которых сотни). И чтобы по-человечески все это обрабатывать, пришлось писать бы огромное количество кода. А потом его отлаживать… Поэтому обычно, рассматривая сетевые приложения, отправку/получение писем обходят стороной. Действительно, зачем? Кому нужно, и так разберется.
+
В итоге получается, что разных протоколов много-много (это не считая вариантов и нюансов, комбинаций которых сотни). И чтобы по-человечески все это обрабатывать, пришлось писать бы огромное количество кода. А потом его отлаживать… Поэтому обычно, рассматривая сетевые приложения, отправку/получение писем обходят стороной. Действительно, зачем? Кому нужно, и так разберется.
  
Но в Java, как всегда, уже позаботились о том, чтобы упростить жизнь человеку, которому нужно рассылать письма – позаботились на самом высшем уровне (в Sun Microsystems) и достаточно качественно.
+
Но в Java, как всегда, уже позаботились о том, чтобы упростить жизнь человеку, которому нужно рассылать письма – позаботились на самом высшем уровне (в Sun Microsystems) и достаточно качественно.
  
===И где волшебная кнопка?===
+
===И где волшебная кнопка?===
  
Есть такая замечательная библиотека, '''JavaMail'''. Она достаточно крупная (224 килобайта только JAR-файл), зато и умеет очень много. А чего не умеет – можно научить, благо архитектура настраиваемая. Давайте посмотрим, как с ней работать.
+
Есть такая замечательная библиотека, '''JavaMail'''. Она достаточно крупная (224 килобайта только JAR-файл), зато и умеет очень много. А чего не умеет – можно научить, благо архитектура настраиваемая. Давайте посмотрим, как с ней работать.
  
===Подготовка===
+
===Подготовка===
  
Для начала скачаем саму библиотеку. Страничка продукта находится по адресу http://java.sun.com/products/javamail/; скачивать нужно, как водится, последний релиз (1.4). Также понадобится JavaBeans Activation Framework (JAF), которую можно загрузить со странички рядом: http://java.sun.com/products/javabeans/jaf/index.jsp.
+
Для начала скачаем саму библиотеку. Страничка продукта находится по адресу http://java.sun.com/products/javamail/; скачивать нужно, как водится, последний релиз (1.4). Также понадобится JavaBeans Activation Framework (JAF), которую можно загрузить со странички рядом: http://java.sun.com/products/javabeans/jaf/index.jsp.
  
После загрузки и разархивирования, получаем две библиотеки: '''mail.jar''' и '''activation.jar'''. Первая из них поддерживает все возможные протоколы, поэтому размер имеет достаточно внушительный. Если что-то из этого многообразия вам не нужно, можно воспользоваться урезанными версиями, они также содержатся в '''mail.jar'''.
+
После загрузки и разархивирования, получаем две библиотеки: '''mail.jar''' и '''activation.jar'''. Первая из них поддерживает все возможные протоколы, поэтому размер имеет достаточно внушительный. Если что-то из этого многообразия вам не нужно, можно воспользоваться урезанными версиями, они также содержатся в '''mail.jar'''.
  
Создадим каталог для проекта ('''QuickMailer'''), в нем заведем подкаталог '''libs''' и положим туда эти два jar-файла. Потом заведем другой подкаталог ('''src'''), для записи исходных текстов.
+
Создадим каталог для проекта ('''QuickMailer'''), в нем заведем подкаталог '''libs''' и положим туда эти два jar-файла. Потом заведем другой подкаталог ('''src'''), для записи исходных текстов.
  
===Окошки===
+
===Окошки===
  
Сделаем окошко для отправки сообщения. Оно будет простое, как на рис. 1.
+
Сделаем окошко для отправки сообщения. Оно будет простое, как на рис. 1.
[[Изображение:LXF97_JAVA1.jpg|Рис. 1. Окно создания и отправки сообщений.]]
+
[[Изображение:LXF97_JAVA1.jpg|Рис. 1. Окно создания и отправки сообщений.]]
  
Подробно рассказать про то, как создаются формы, не хватит места. Но привести код, создающий такое окошко – запросто.
+
Подробно рассказать про то, как создаются формы, не хватит места. Но привести код, создающий такое окошко – запросто.
  
 
<source lang="java">
 
<source lang="java">
Строка 64: Строка 65:
 
     private JButton _buttonSend;
 
     private JButton _buttonSend;
 
     public QuickMailerForm() throws HeadlessException {
 
     public QuickMailerForm() throws HeadlessException {
       setTitle(“Быстро Мэйлер”);
+
       setTitle(“Быстро Мэйлер”);
 
       setDefaultCloseOperation(EXIT_ON_CLOSE);
 
       setDefaultCloseOperation(EXIT_ON_CLOSE);
 
       createLayout();
 
       createLayout();
Строка 76: Строка 77:
 
</source>
 
</source>
  
Как видно, класс наследуется от '''JFrame''', это окно приложения. Имеется конструктор, где окну присваивается заголовок, устанавливается размер и положение в середине экрана. Также есть две функции: первая создает компоненты ('''createLayout'''), вторая «вешает» на кнопку Отправить обработчик события, который собирает информацию и вызывает метод отправки почты.
+
Как видно, класс наследуется от '''JFrame''', это окно приложения. Имеется конструктор, где окну присваивается заголовок, устанавливается размер и положение в середине экрана. Также есть две функции: первая создает компоненты ('''createLayout'''), вторая «вешает» на кнопку Отправить обработчик события, который собирает информацию и вызывает метод отправки почты.
  
Вот как создаются компоненты формы:
+
Вот как создаются компоненты формы:
  
 
<source lang="java">
 
<source lang="java">
 
  private void createLayout() {
 
  private void createLayout() {
 
       JPanel labelsPanel = new JPanel(new GridLayout(2, 1));
 
       JPanel labelsPanel = new JPanel(new GridLayout(2, 1));
       labelsPanel.add(new JLabel(“EMail получателя:, JLabel.RIGHT));
+
       labelsPanel.add(new JLabel(“EMail получателя:”, JLabel.RIGHT));
       labelsPanel.add(new JLabel(“Тема письма:, JLabel.RIGHT));
+
       labelsPanel.add(new JLabel(“Тема письма:”, JLabel.RIGHT));
 
       JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
 
       JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
       _buttonSend = new JButton(“Отправить”);
+
       _buttonSend = new JButton(“Отправить”);
 
       buttonsPanel.add(_buttonSend);
 
       buttonsPanel.add(_buttonSend);
 
       JPanel fieldsPanel = new JPanel(new GridLayout(2, 1));
 
       JPanel fieldsPanel = new JPanel(new GridLayout(2, 1));
Строка 97: Строка 98:
 
       controlsPanel.add(fieldsPanel, BorderLayout.CENTER);
 
       controlsPanel.add(fieldsPanel, BorderLayout.CENTER);
 
         JPanel mainPanel = new JPanel(new BorderLayout(5, 5));
 
         JPanel mainPanel = new JPanel(new BorderLayout(5, 5));
         _message = new JEditorPane(“text/rtf”, “”);
+
         _message = new JEditorPane(“text/rtf”, “”);
 
         mainPanel.add(controlsPanel, BorderLayout.NORTH);
 
         mainPanel.add(controlsPanel, BorderLayout.NORTH);
 
         mainPanel.add(new JScrollPane(_message), BorderLayout.CENTER);
 
         mainPanel.add(new JScrollPane(_message), BorderLayout.CENTER);
Строка 106: Строка 107:
 
</source>
 
</source>
  
Вкратце, здесь создается несколько панелей, вложенных друг в друга. Чтобы выглядело получше, задаются отступы и межкомпонентные расстояния.
+
Вкратце, здесь создается несколько панелей, вложенных друг в друга. Чтобы выглядело получше, задаются отступы и межкомпонентные расстояния.
  
Последний метод – создание обработчика события нажатия на кнопку:
+
Последний метод – создание обработчика события нажатия на кнопку:
  
 
<source lang="java">
 
<source lang="java">
Строка 115: Строка 116:
 
             public void actionPerformed(ActionEvent e) {
 
             public void actionPerformed(ActionEvent e) {
 
               try {
 
               try {
                 QuickMailer.sendMessage(“alex@jdnevnik.com”, _fieldTo.getText(), _fieldSubject.getText(),
+
                 QuickMailer.sendMessage(“alex@jdnevnik.com”, _fieldTo.getText(), _fieldSubject.getText(),
 
                     _message.getDocument().getText(0, _message.getDocument().getLength()));
 
                     _message.getDocument().getText(0, _message.getDocument().getLength()));
 
               } catch (Exception e1) {
 
               } catch (Exception e1) {
Строка 125: Строка 126:
 
</source>
 
</source>
  
Тут все достаточно просто. Вытаскиваются параметры письма из полей, после чего вызывается некий метод '''sendMessage''', который мы сейчас и рассмотрим подробнее.
+
Тут все достаточно просто. Вытаскиваются параметры письма из полей, после чего вызывается некий метод '''sendMessage''', который мы сейчас и рассмотрим подробнее.
  
===Собственно отправка сообщения===
+
===Собственно отправка сообщения===
  
Предполагается, что у вас на localhost’е настроен smtp-сервер (у меня стоит ''postfix''), либо есть доступ к какому-то другому (который не требует авторизации: с ней разбираться пока не будем).
+
Предполагается, что у вас на localhost’е настроен smtp-сервер (у меня стоит ''postfix''), либо есть доступ к какому-то другому (который не требует авторизации: с ней разбираться пока не будем).
  
Для начала создадим адреса отправителя и получателя:
+
Для начала создадим адреса отправителя и получателя:
  
 
<source lang="java">
 
<source lang="java">
 
  public static void sendMessage(String aFrom, String aTo, String aSubject,
 
  public static void sendMessage(String aFrom, String aTo, String aSubject,
 
  String aMessageText) throws Exception {
 
  String aMessageText) throws Exception {
     InternetAddress from = new InternetAddress(aFrom, “From”);
+
     InternetAddress from = new InternetAddress(aFrom, “From”);
     InternetAddress to = new InternetAddress(aTo, “To”);
+
     InternetAddress to = new InternetAddress(aTo, “To”);
 
</source>
 
</source>
  
Теперь нужно настроить так называемый транспорт, который будет заниматься отправкой сообщения.
+
Теперь нужно настроить так называемый транспорт, который будет заниматься отправкой сообщения.
  
 
<source lang="java">
 
<source lang="java">
 
     Properties props = new Properties();
 
     Properties props = new Properties();
     props.put(“mail.transport.protocol”, “smtp”);
+
     props.put(“mail.transport.protocol”, “smtp”);
     props.put(“mail.smtp.host”, “localhost”);
+
     props.put(“mail.smtp.host”, “localhost”);
     props.put(“mail.smtp.port”, “25”);
+
     props.put(“mail.smtp.port”, “25”);
 
     Session session = Session.getDefaultInstance(props);
 
     Session session = Session.getDefaultInstance(props);
 
     Transport transport = session.getTransport();
 
     Transport transport = session.getTransport();
 
</source>
 
</source>
  
Теперь – создадим само сообщение.
+
Теперь – создадим само сообщение.
  
 
<source lang="java">
 
<source lang="java">
Строка 157: Строка 158:
 
     message.setFrom(from);
 
     message.setFrom(from);
 
     message.setRecipient(Message.RecipientType.TO, to);
 
     message.setRecipient(Message.RecipientType.TO, to);
     message.setSubject(aSubject, “utf-8”);
+
     message.setSubject(aSubject, “utf-8”);
     message.setContent(aMessageText, “text/plain; charset=utf-8”);
+
     message.setContent(aMessageText, “text/plain; charset=utf-8”);
 
</source>
 
</source>
  
И, наконец, отошлем письмо.
+
И, наконец, отошлем письмо.
  
 
<source lang="java">
 
<source lang="java">
Строка 170: Строка 171:
 
</source>
 
</source>
  
Как можно заметить, все предельно просто и понятно – но исключительно потому, что сам пример простой. Система достаточно мощная, чтобы справиться и с авторизацией, и с сообщениями на разныхязыках, и с вложениями файлов.
+
Как можно заметить, все предельно просто и понятно – но исключительно потому, что сам пример простой. Система достаточно мощная, чтобы справиться и с авторизацией, и с сообщениями на разныхязыках, и с вложениями файлов.
  
===Собираем все вместе===
+
===Собираем все вместе===
  
Осталось только написать метод, который будет все это запускать.
+
Осталось только написать метод, который будет все это запускать.
  
 
<source lang="java">
 
<source lang="java">
Строка 183: Строка 184:
 
</source>
 
</source>
  
У меня после написания кода получилось два файла, '''QuickMailer.java''' и '''QuickMailerForm.java'''. Скомпилируем их (выполнив, находясь в каталоге, в котором находится '''src''' и '''libs'''):
+
У меня после написания кода получилось два файла, '''QuickMailer.java''' и '''QuickMailerForm.java'''. Скомпилируем их (выполнив, находясь в каталоге, в котором находится '''src''' и '''libs'''):
  
 
<code>
 
<code>
Строка 189: Строка 190:
 
</code>
 
</code>
  
Обратите внимание на часть команды после '''-cp'''. Это указание компилятору, где искать используемые в коде классы, кроме стандартных. Часть команды после '''-d''' определяет каталог, куда будут складываться скомпилированные классы. И, наконец, так как мы создавали файлы в кодировке UTF-8 (в ней представлены исходные тексты на диске), то и в командной строке это нужно указать, иначе будет выбрана кодировка по умолчанию, а это не всегда верно.
+
Обратите внимание на часть команды после '''-cp'''. Это указание компилятору, где искать используемые в коде классы, кроме стандартных. Часть команды после '''-d''' определяет каталог, куда будут складываться скомпилированные классы. И, наконец, так как мы создавали файлы в кодировке UTF-8 (в ней представлены исходные тексты на диске), то и в командной строке это нужно указать, иначе будет выбрана кодировка по умолчанию, а это не всегда верно.
  
Запустим:
+
Запустим:
  
 
<code>
 
<code>
Строка 199: Строка 200:
 
</code>
 
</code>
  
Можно отправлять письма.
+
Можно отправлять письма.
  
===А получить?===
+
===А получить?===
  
На новое окошко места уже не хватит. Ограничимся просмотром кода, который нужно написать для того, чтобы получить письмо, например, по протоколу '''POP'''.
+
На новое окошко места уже не хватит. Ограничимся просмотром кода, который нужно написать для того, чтобы получить письмо, например, по протоколу '''POP'''.
  
 
<source lang="java">
 
<source lang="java">
 
  Properties props = new Properties();
 
  Properties props = new Properties();
 
  Session session = Session.getDefaultInstance(props, null);
 
  Session session = Session.getDefaultInstance(props, null);
  Store store = session.getStore(“pop3”);
+
  Store store = session.getStore(“pop3”);
 
  store.connect(aHost, aUserName, aPassword);
 
  store.connect(aHost, aUserName, aPassword);
  Folder folder = store.getFolder(“INBOX”);
+
  Folder folder = store.getFolder(“INBOX”);
 
  folder.open(Folder.READ_ONLY);
 
  folder.open(Folder.READ_ONLY);
 
  Message message[] = folder.getMessages();
 
  Message message[] = folder.getMessages();
 
  for (int i = 0, n = message.length; i < n; i++) {
 
  for (int i = 0, n = message.length; i < n; i++) {
   System.out.println(i + : + message[i].getFrom()[0] + \t” + message[i].
+
   System.out.println(i + “: “ + message[i].getFrom()[0] + “\t” + message[i].
 
  getSubject());
 
  getSubject());
 
  }
 
  }
Строка 221: Строка 222:
 
</source>
 
</source>
  
Данный кусок кода просто выведет список всех писем на сервере.
+
Данный кусок кода просто выведет список всех писем на сервере.
  
===Ну, а если не мудрить…===
+
===Ну, а если не мудрить…===
  
Есть вариант и попроще. Если программа работает с почтой активно, можно использовать библиотеку наших постоянных друзей из ''apache-commons''. Называется она '''commons-email''', и ее страничка располагается по адресу http://commons.apache.org/email/. Скачав библиотеку, положим её в '''libs''', к '''mail.jar''' и компании. Теперь попробуем отправить письмо с ее помощью:
+
Есть вариант и попроще. Если программа работает с почтой активно, можно использовать библиотеку наших постоянных друзей из ''apache-commons''. Называется она '''commons-email''', и ее страничка располагается по адресу http://commons.apache.org/email/. Скачав библиотеку, положим её в '''libs''', к '''mail.jar''' и компании. Теперь попробуем отправить письмо с ее помощью:
  
 
<source lang="java">
 
<source lang="java">
Строка 231: Строка 232:
 
  String aSubject, String aMessageText) throws EmailException {
 
  String aSubject, String aMessageText) throws EmailException {
 
     SimpleEmail email = new SimpleEmail();
 
     SimpleEmail email = new SimpleEmail();
     email.setHostName(“localhost”);
+
     email.setHostName(“localhost”);
     email.setFrom(aFrom, “From”);
+
     email.setFrom(aFrom, “From”);
     email.addTo(aTo, “To”);
+
     email.addTo(aTo, “To”);
 
     email.setSubject(aSubject);
 
     email.setSubject(aSubject);
 
     email.setMsg(aMessageText);
 
     email.setMsg(aMessageText);
Строка 240: Строка 241:
 
</source>
 
</source>
  
Насколько все проще и понятнее сразу стало! А если нужно файл приложить? Да пожалуйста:
+
Насколько все проще и понятнее сразу стало! А если нужно файл приложить? Да пожалуйста:
  
 
<source lang="java">
 
<source lang="java">
Строка 246: Строка 247:
 
  String aSubject, String aMessageText) throws EmailException {
 
  String aSubject, String aMessageText) throws EmailException {
 
     EmailAttachment attachment = new EmailAttachment();
 
     EmailAttachment attachment = new EmailAttachment();
     attachment.setPath(“attachments/attachment.zip”);
+
     attachment.setPath(“attachments/attachment.zip”);
 
     attachment.setDisposition(EmailAttachment.ATTACHMENT);
 
     attachment.setDisposition(EmailAttachment.ATTACHMENT);
     attachment.setDescription(“Файл-приложение к письму”);
+
     attachment.setDescription(“Файл-приложение к письму”);
     attachment.setName(“attachment.zip”);
+
     attachment.setName(“attachment.zip”);
 
     MultiPartEmail email = new MultiPartEmail();
 
     MultiPartEmail email = new MultiPartEmail();
     email.setHostName(“localhost”);
+
     email.setHostName(“localhost”);
     email.setFrom(aFrom, “From”);
+
     email.setFrom(aFrom, “From”);
     email.addTo(aTo, “To”);
+
     email.addTo(aTo, “To”);
 
     email.setSubject(aSubject);
 
     email.setSubject(aSubject);
 
     email.setMsg(aMessageText);
 
     email.setMsg(aMessageText);
Строка 261: Строка 262:
 
</source>
 
</source>
  
Здесь тоже ничего сложного нет. Создать приложение в письме можно и используя только '''JavaMail''', но там это получается достаточно непросто, и длиннее раза в три-четыре.
+
Здесь тоже ничего сложного нет. Создать приложение в письме можно и используя только '''JavaMail''', но там это получается достаточно непросто, и длиннее раза в три-четыре.
  
===Про спам===
+
===Про спам===
  
Конечно, работа с почтой не так проста, как это отражено в статье. Есть и проблема спама (а для программно отправляемых сообщений – проблема того, что оно с большой вероятностью посчитается именно спамом), и проблема корректности. SMTP-протокол, в частности, достаточно старый, и там много неточностей, неявных правил и так далее. В общем, то, что есть '''JavaMail''' – это отлично, и она очень сильно помогает при работе с почтовыми сообщениями, но панацеей тем не менее не является. Все равно нужно представлять себе, как работает протокол, какие заголовки нужно ставить, как обрабатывают сообщения разные почтовые клиенты (чтобы письмо нормально там показывалось, а не крякозябрами) и много чего еще.
+
Конечно, работа с почтой не так проста, как это отражено в статье. Есть и проблема спама (а для программно отправляемых сообщений – проблема того, что оно с большой вероятностью посчитается именно спамом), и проблема корректности. SMTP-протокол, в частности, достаточно старый, и там много неточностей, неявных правил и так далее. В общем, то, что есть '''JavaMail''' – это отлично, и она очень сильно помогает при работе с почтовыми сообщениями, но панацеей тем не менее не является. Все равно нужно представлять себе, как работает протокол, какие заголовки нужно ставить, как обрабатывают сообщения разные почтовые клиенты (чтобы письмо нормально там показывалось, а не крякозябрами) и много чего еще.
  
Но все же, надеюсь, теперь можно не бояться страшных буквенных сочетаний, связанных с почтой, и спокойно встраивать в прорамму еще одно удобнейшее средство коммуникации: электронные письма. '''LXF'''
+
Но все же, надеюсь, теперь можно не бояться страшных буквенных сочетаний, связанных с почтой, и спокойно встраивать в прорамму еще одно удобнейшее средство коммуникации: электронные письма. '''LXF'''

Версия 01:09, 22 мая 2009

http://www.textervart.com Шаблон:Цикл/Java EE Категория:Учебники

Содержание

Почтовый сервис

Скачать исходный код примера

ЧАСТЬ 9 Хотите оснастить свою программу возможностью писать «на деревню дедушке»? Александр Бабаев знает подходящее средство.


Несмотря на засилье браузера в серии, JEE им не ограничивается. Давайте попробуем посылать письма из Java (ведь каждая хорошая программа должна уметь сообщать разработчикам об ошибках), и сделаем это приложение не браузерным, а «обычным».

Коротко о почте

Чтобы работать с почтой, нужно уметь её отправлять и получать. При попытке разобраться в этом вы наткнетесь на следующие буквосочетания (с разными вариациями): SMTP, POP, IMAP. Рассмотрим кратко, что это такое и как этим пользоваться (а также где почитать поподробнее).

  • SMTP

При помощи Simple Mail Transfer Protocol (простого протокола передачи почты) почта передается с клиента на сервер. Отправляется то есть. Протокол текстовый, и если есть желание, можно отправлять письма прямо из telnet’а.

  • POP

Тоже текстовый протокол, но уже не для передачи, а для приема сообщений. Может выдать информацию по почтовому ящику (сколько сообщений, какой их размер), загрузить сообщение по номеру и так далее.

  • IMAP

POP предполагает, что почта скачивается на клиент и там уже раскладывается по папкам, обрабатывается, группируется. При этом с сервера сообщения стираются. Это не всегда удобно. Как раз для хранения почты на сервере создан протокол IMAP. Как и предыдущие два, он текстовый. Но с его помощью можно не только получить сообщения, но и создать на сервере папку, переместить письмо куда-нибудь, подписаться на получение изменений (новых писем) в папке, и так далее.

  • GoogleMail/HotMail/…

Но и это не всё. Протоколы протоколами, но некоторые сервисы работают «по-своему». И если GoogleMail предоставляет POP-интерфейс, то Hotmail, например, нет. В таком случае обычно есть какой-то свой, нестандартный протокол.

Итого

В итоге получается, что разных протоколов много-много (это не считая вариантов и нюансов, комбинаций которых сотни). И чтобы по-человечески все это обрабатывать, пришлось писать бы огромное количество кода. А потом его отлаживать… Поэтому обычно, рассматривая сетевые приложения, отправку/получение писем обходят стороной. Действительно, зачем? Кому нужно, и так разберется.

Но в Java, как всегда, уже позаботились о том, чтобы упростить жизнь человеку, которому нужно рассылать письма – позаботились на самом высшем уровне (в Sun Microsystems) и достаточно качественно.

И где волшебная кнопка?

Есть такая замечательная библиотека, JavaMail. Она достаточно крупная (224 килобайта только JAR-файл), зато и умеет очень много. А чего не умеет – можно научить, благо архитектура настраиваемая. Давайте посмотрим, как с ней работать.

Подготовка

Для начала скачаем саму библиотеку. Страничка продукта находится по адресу http://java.sun.com/products/javamail/; скачивать нужно, как водится, последний релиз (1.4). Также понадобится JavaBeans Activation Framework (JAF), которую можно загрузить со странички рядом: http://java.sun.com/products/javabeans/jaf/index.jsp.

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

Создадим каталог для проекта (QuickMailer), в нем заведем подкаталог libs и положим туда эти два jar-файла. Потом заведем другой подкаталог (src), для записи исходных текстов.

Окошки

Сделаем окошко для отправки сообщения. Оно будет простое, как на рис. 1. Рис. 1. Окно создания и отправки сообщений.

Подробно рассказать про то, как создаются формы, не хватит места. Но привести код, создающий такое окошко – запросто.

 import javax.swing.*;
 import javax.swing.border.EmptyBorder;
 import java.awt.*;
 import java.awt.event.ActionListener;
 import java.awt.event.ActionEvent;
 public class QuickMailerForm extends JFrame {
    private JTextField _fieldTo;
    private JTextField _fieldSubject;
    private JEditorPane _message;
    private JButton _buttonSend;
    public QuickMailerForm() throws HeadlessException {
       setTitle(“Быстро Мэйлер”);
       setDefaultCloseOperation(EXIT_ON_CLOSE);
       createLayout();
       createActions();
       pack();
       setSize(700, 560);
       Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
       setLocation((int) (screenSize.getWidth() - 700)/2, (int) ((screenSize.getHeight() - 560)/2));
    }
 }

Как видно, класс наследуется от JFrame, это окно приложения. Имеется конструктор, где окну присваивается заголовок, устанавливается размер и положение в середине экрана. Также есть две функции: первая создает компоненты (createLayout), вторая «вешает» на кнопку Отправить обработчик события, который собирает информацию и вызывает метод отправки почты.

Вот как создаются компоненты формы:

 private void createLayout() {
       JPanel labelsPanel = new JPanel(new GridLayout(2, 1));
       labelsPanel.add(new JLabel(“EMail получателя:”, JLabel.RIGHT));
       labelsPanel.add(new JLabel(“Тема письма:”, JLabel.RIGHT));
       JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
       _buttonSend = new JButton(“Отправить”);
       buttonsPanel.add(_buttonSend);
       JPanel fieldsPanel = new JPanel(new GridLayout(2, 1));
       _fieldTo = new JTextField();
       _fieldSubject = new JTextField();
       fieldsPanel.add(_fieldTo);
       fieldsPanel.add(_fieldSubject);
       JPanel controlsPanel = new JPanel(new BorderLayout(5, 5));
       controlsPanel.add(labelsPanel, BorderLayout.WEST);
       controlsPanel.add(fieldsPanel, BorderLayout.CENTER);
        JPanel mainPanel = new JPanel(new BorderLayout(5, 5));
        _message = new JEditorPane(“text/rtf”, “”);
        mainPanel.add(controlsPanel, BorderLayout.NORTH);
        mainPanel.add(new JScrollPane(_message), BorderLayout.CENTER);
        mainPanel.add(buttonsPanel, BorderLayout.SOUTH);
        mainPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(mainPanel);
  }

Вкратце, здесь создается несколько панелей, вложенных друг в друга. Чтобы выглядело получше, задаются отступы и межкомпонентные расстояния.

Последний метод – создание обработчика события нажатия на кнопку:

  private void createActions() {
        _buttonSend.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
              try {
                QuickMailer.sendMessage(“alex@jdnevnik.com”, _fieldTo.getText(), _fieldSubject.getText(),
                     _message.getDocument().getText(0, _message.getDocument().getLength()));
              } catch (Exception e1) {
                  e1.printStackTrace();
              }
            }
        });
  }

Тут все достаточно просто. Вытаскиваются параметры письма из полей, после чего вызывается некий метод sendMessage, который мы сейчас и рассмотрим подробнее.

Собственно отправка сообщения

Предполагается, что у вас на localhost’е настроен smtp-сервер (у меня стоит postfix), либо есть доступ к какому-то другому (который не требует авторизации: с ней разбираться пока не будем).

Для начала создадим адреса отправителя и получателя:

 public static void sendMessage(String aFrom, String aTo, String aSubject,
 String aMessageText) throws Exception {
    InternetAddress from = new InternetAddress(aFrom, “From”);
    InternetAddress to = new InternetAddress(aTo, “To”);

Теперь нужно настроить так называемый транспорт, который будет заниматься отправкой сообщения.

    Properties props = new Properties();
    props.put(“mail.transport.protocol”, “smtp”);
    props.put(“mail.smtp.host”, “localhost”);
    props.put(“mail.smtp.port”, “25”);
    Session session = Session.getDefaultInstance(props);
    Transport transport = session.getTransport();

Теперь – создадим само сообщение.

    MimeMessage message = new MimeMessage(session);
    message.setFrom(from);
    message.setRecipient(Message.RecipientType.TO, to);
    message.setSubject(aSubject, “utf-8”);
    message.setContent(aMessageText, “text/plain; charset=utf-8”);

И, наконец, отошлем письмо.

   transport.connect();
   transport.sendMessage(message, new Address[]{to});
   transport.close();
 }

Как можно заметить, все предельно просто и понятно – но исключительно потому, что сам пример простой. Система достаточно мощная, чтобы справиться и с авторизацией, и с сообщениями на разныхязыках, и с вложениями файлов.

Собираем все вместе

Осталось только написать метод, который будет все это запускать.

 public static void main(String[] args) {
   QuickMailerForm form = new QuickMailerForm();
   form.setVisible(true);
 }

У меня после написания кода получилось два файла, QuickMailer.java и QuickMailerForm.java. Скомпилируем их (выполнив, находясь в каталоге, в котором находится src и libs):

javac -cp libs/activation.jar:libs/commons-email-1.0.jar:libs/mail.jar -encoding utf-8 -d out src/*.java

Обратите внимание на часть команды после -cp. Это указание компилятору, где искать используемые в коде классы, кроме стандартных. Часть команды после -d определяет каталог, куда будут складываться скомпилированные классы. И, наконец, так как мы создавали файлы в кодировке UTF-8 (в ней представлены исходные тексты на диске), то и в командной строке это нужно указать, иначе будет выбрана кодировка по умолчанию, а это не всегда верно.

Запустим:

cd out
java -cp .:../libs/activation.jar:../libs/commons-email-1.0.jar:../libs/mail.jar
QuickMailer

Можно отправлять письма.

А получить?

На новое окошко места уже не хватит. Ограничимся просмотром кода, который нужно написать для того, чтобы получить письмо, например, по протоколу POP.

 Properties props = new Properties();
 Session session = Session.getDefaultInstance(props, null);
 Store store = session.getStore(“pop3”);
 store.connect(aHost, aUserName, aPassword);
 Folder folder = store.getFolder(“INBOX”);
 folder.open(Folder.READ_ONLY);
 Message message[] = folder.getMessages();
 for (int i = 0, n = message.length; i < n; i++) {
   System.out.println(i + “: “ + message[i].getFrom()[0] + “\t” + message[i].
 getSubject());
 }
 folder.close(false);
 store.close();

Данный кусок кода просто выведет список всех писем на сервере.

Ну, а если не мудрить…

Есть вариант и попроще. Если программа работает с почтой активно, можно использовать библиотеку наших постоянных друзей из apache-commons. Называется она commons-email, и ее страничка располагается по адресу http://commons.apache.org/email/. Скачав библиотеку, положим её в libs, к mail.jar и компании. Теперь попробуем отправить письмо с ее помощью:

 public static void sendMessageCommonsEMail(String aFrom, String aTo,
 String aSubject, String aMessageText) throws EmailException {
    SimpleEmail email = new SimpleEmail();
    email.setHostName(“localhost”);
    email.setFrom(aFrom, “From”);
    email.addTo(aTo, “To”);
    email.setSubject(aSubject);
    email.setMsg(aMessageText);
    email.send();
 }

Насколько все проще и понятнее сразу стало! А если нужно файл приложить? Да пожалуйста:

 public static void sendMessageWithAttachment(String aFrom, String aTo,
 String aSubject, String aMessageText) throws EmailException {
    EmailAttachment attachment = new EmailAttachment();
    attachment.setPath(“attachments/attachment.zip”);
    attachment.setDisposition(EmailAttachment.ATTACHMENT);
    attachment.setDescription(“Файл-приложение к письму”);
    attachment.setName(“attachment.zip”);
    MultiPartEmail email = new MultiPartEmail();
    email.setHostName(“localhost”);
    email.setFrom(aFrom, “From”);
    email.addTo(aTo, “To”);
    email.setSubject(aSubject);
    email.setMsg(aMessageText);
    email.attach(attachment);
    email.send();
 }

Здесь тоже ничего сложного нет. Создать приложение в письме можно и используя только JavaMail, но там это получается достаточно непросто, и длиннее раза в три-четыре.

Про спам

Конечно, работа с почтой не так проста, как это отражено в статье. Есть и проблема спама (а для программно отправляемых сообщений – проблема того, что оно с большой вероятностью посчитается именно спамом), и проблема корректности. SMTP-протокол, в частности, достаточно старый, и там много неточностей, неявных правил и так далее. В общем, то, что есть JavaMail – это отлично, и она очень сильно помогает при работе с почтовыми сообщениями, но панацеей тем не менее не является. Все равно нужно представлять себе, как работает протокол, какие заголовки нужно ставить, как обрабатывают сообщения разные почтовые клиенты (чтобы письмо нормально там показывалось, а не крякозябрами) и много чего еще.

Но все же, надеюсь, теперь можно не бояться страшных буквенных сочетаний, связанных с почтой, и спокойно встраивать в прорамму еще одно удобнейшее средство коммуникации: электронные письма. LXF

Персональные инструменты
купить
подписаться
Яндекс.Метрика