воскресенье, 9 августа 2009 г.

Несколько мгновений JavaMail + Gmail

И вот пришло время Java. Первой моей задачей было написать модуль обрабатывающий входящие письма из нужного почтового ящика, и по необходимости отправлял ответ. Погуглив пару минут сразу было найдено основа для моего модуля - JavaMail. Немного магии присутствует и в этой сборке.

Через некоторое время у меня были методы для работы с почтой.

Для отправки почты:
String SMTP_AUTH_USER = "<почтовый адрес в почте Gmail>"; 
String SMTP_AUTH_PWD = "<пароль>";

Properties props = new Properties();

props.put("mail.transport.protocol", "smtps");
props.put("mail.smtps.host", SMTP_AUTH_USER);
props.put("mail.smtps.auth", "true");
props.put("mail.smtp.sendpartial", "true");

Session session = Session.getDefaultInstance(props);
session.setDebug(true);
Transport transport = session.getTransport();
transport.connect("smtp.gmail.com", 465, SMTP_AUTH_USER, SMTP_AUTH_PWD);

MimeMessage message = new MimeMessage(session);
message.setSubject("тестовое письмо!");
message.setText("Тестирование JavaMail c Gmail почтой прошло успешно!");
message.addRecipient(Message.RecipientType.TO, new InternetAddress("<получатель>"));
message.setSentDate(new Date());

transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO));

Для получения почты:
String POP_AUTH_USER = "<почтовый адрес в почте Gmail>";
String POP_AUTH_PWD = "<пароль>";

String FOLDER_INDOX = "INBOX"; // имя папки "Входящие"
String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";

Properties pop3Props = new Properties();

pop3Props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);
pop3Props.setProperty("mail.pop3.socketFactory.fallback", "false");
pop3Props.setProperty("mail.pop3.port", "995");
pop3Props.setProperty("mail.pop3.socketFactory.port", "995");

URLName url = new URLName("pop3", "pop.gmail.com", 955, "", POP_AUTH_USER, POP_AUTH_PWD);

Session session = Session.getInstance(pop3Props, null);
Store store = session.getStore(url);
store.connect();

Folder folder = store.getFolder(FOLDER_INDOX);
try {
folder.open(Folder.READ_WRITE);
} catch (MessagingException ex) {
folder.open(Folder.READ_ONLY);
}
Message[] messages = folder.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));
// обработка сообщений
folder.close(false);
store.close();

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

Как ответить на письмо?


Почитав FAQ по JavaMail стало понятно что рекомендуют воспользоваться методов Message.reply(). И вот тут начала проявляться магия JavaMail.
Message[] mes = folder.getMessages();
for(int i = 0; i < mes.length; i++) {
Message message = mes[i];
Message reply = message.reply(false);
reply.setText("Ответ на ваш запрос! :)");
// отправить его нужно по протоколу SMTP! Делаем финт ушами.
Transport transport = pop.getSession().getTransport("smtps");
transport.connect("smtp.gmail.com", 465, "<почтовый адрес в почте Gmail>", "<пароль>");
transport.sendMessage(reply, reply.getRecipients(Message.RecipientType.TO));
transport.close();
break;
}

Как удалить сообщение используя POP протокол?


После получения письма иногда возникает необходимость удалить его, отметить как не прочитанное, и т.д. Что бы сохранить эти изменения нужно воспользоваться очередным магическим функционалом, а именно закрыть папку с параметром true.
message.setFlag(Flag.DELETED, true);
// ......
folder.close(true);


Как получить доступ к папкам "Все письма", "Спам", и т.д.


Тут возникло некое разочарование, т.к. Gmail не дает доступ через smtp протокол к таким папкам. Для доступа в такие папки необходимо воспользоваться протоколом imap (провайдер "imaps") и получить папку с указанием нужного имени. Например:
store.getFolder("[Gmail]/All"); //Вся почта
store.getFolder("[Gmail]/Spam"); //Спам
store.getFolder("[Gmail]/Starred"); //Помеченные
store.getFolder("[Gmail]/Sent"); //Отправленные
store.getFolder("[Gmail]/Drafts"); //Черновики
store.getFolder("[Gmail]/Trash"); //Корзина


Радует в работе с JavaMail то, что FAQ написан очень хорошо и качественно. В 80% случаев решение мелких проблем можно было найти в нем.
Модуль написан, задание выполнено :).

5 коммент.:

  1. Спасибо большое!
    Долго искала работающий код и вот у вас нашла!!!

    ОтветитьУдалить
  2. Полезная статья, тоже искал хороший пример по JavaMail. Спасибо

    ОтветитьУдалить
  3. Пользуйтесь на здоровье!

    ОтветитьУдалить
  4. с чем связана ошибка:
    javax.mail.MessagingException: can't determine local email address

    ОтветитьУдалить
  5. >javax.mail.MessagingException: can't determine local email address

    Возникает в случае если не задан отправитель! Если проблема не в этом (или не получится разобраться), то код в студию.

    ОтветитьУдалить