Получение неверного адреса с javax.mail, когда адреса в порядке - PullRequest
5 голосов
/ 27 октября 2008

Я использую систему javax.mail и у меня проблемы с исключениями "Неверный адрес". Вот основы кода:

    // Get system properties
    Properties props = System.getProperties();

    // Setup mail server
    props.put("mail.smtp.host", m_sending_host);

    // Get session
    Session session = Session.getDefaultInstance(props, new Authenticator(){
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(m_sending_user, m_sending_pass);
        }
    });


    // Define message
    MimeMessage message = new MimeMessage(session);
    message.setFrom(new InternetAddress(m_sending_from));
    message.addRecipient(Message.RecipientType.TO, 
        new InternetAddress(vcea.get(i).emailaddr));
    message.setSubject( replaceEnvVars(subject) );
    message.setText(replaceEnvVars(body));

    // Send message
    try {
        Transport.send(message);
    } catch (Exception e){
        Log.Error("Error sending e-mail to addr (%s): %s",
                vcea.get(i).emailaddr, e.getLocalizedMessage() );

    }

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

Любые подсказки или подсказки будут с благодарностью.

- Обновление: проблема с аутентификацией.

Хорошо, вот что я обнаружил. При получении электронной почты приведенный выше код корректно устанавливает аутентификацию, и фактически вызывается обратный вызов Authenticator.getPasswordAuthentication ().

Не так при отправке электронной почты. Вы должны сделать немного больше. Добавьте это:

    // Setup mail server
    props.put("mail.smtp.host", m_sending_host);
    props.put("mail.smtp.auth", "true");

, который заставит API javax.mail выполнить аутентификацию при входе. А затем используйте фактический экземпляр Transport вместо статического метода .send ():

    Transport t = session.getTransport(m_sending_protocol);
    t.connect(m_sending_user, m_sending_pass);

...

        // Send message
        try {
            t.sendMessage(message, message.getAllRecipients());
        } catch (Exception e){

Не форсируя аутентификацию, почтовый сервер увидел меня как несанкционированный ретранслятор и просто отключил меня. Разница между «работающими» адресами и адресами, которые не работали, заключалась в том, что «работающие» адреса были локальными для почтового сервера. Поэтому он просто принял их. Но для любых нелокальных «ретранслируемых» адресов оно отклонило бы сообщение, потому что моя информация для аутентификации не была представлена ​​API javax.mail, когда я думал, что это будет.

Спасибо за подсказки, побуждающие меня взглянуть и на сторону почтового сервера.

Ответы [ 5 ]

6 голосов
/ 27 октября 2008

- Обновление: проблема с аутентификацией.

Хорошо, вот что я обнаружил. При получении электронной почты приведенный выше код правильно устанавливает аутентификацию, и фактически вызывается обратный вызов Authenticator.getPasswordAuthentication ().

Не так при отправке электронной почты. Вы должны сделать немного больше. Добавьте это:

// Setup mail server
props.put("mail.smtp.host", m_sending_host);
props.put("mail.smtp.auth", "true");

, что заставит API javax.mail выполнить аутентификацию при входе. А затем используйте фактический экземпляр Transport вместо статического метода .send ():

Transport t = session.getTransport(m_sending_protocol);
t.connect(m_sending_user, m_sending_pass);

...

    // Send message
    try {
        t.sendMessage(message, message.getAllRecipients());
    } catch (Exception e){

Не форсируя аутентификацию, почтовый сервер увидел меня как несанкционированный ретранслятор и просто отключил меня. Разница между «работающими» адресами и адресами, которые не работали, заключалась в том, что «работающие» адреса были локальными для почтового сервера. Поэтому он просто принял их. Но для любых нелокальных «ретранслируемых» адресов он отклонил бы сообщение, потому что моя информация для аутентификации не была представлена ​​API javax.mail, когда я думал, что это произойдет.

Спасибо за подсказки, побуждающие меня взглянуть и на сторону почтового сервера.

2 голосов
/ 27 октября 2008

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

message.addRecipient(Message.RecipientType.TO, 
        new InternetAddress(vcea.get(i).emailaddr, true ));
//                                                 ^^^^ turns on strict interpretation

Javadoc для InternetAddress конструктор

Если это не удастся, он выдаст AddressException, который имеет метод с именем getPos(), который возвращает позицию сбоя ( Javadoc )

1 голос
/ 29 июля 2011

Хороший совет для тех, кто использует ssl-шифрование в конфигурации smtp, вы должны включить его, указав свойство mail.smtp.ssl.enable, как показано ниже:

props.put("mail.smtp.ssl.enable", "true");

В противном случае это может привести к проблемам, аналогичным описанным выше.

0 голосов
/ 28 октября 2008

Мне кажется, это проблема, которая произошла на моей работе. Если код, который вы показываете, является параллельным, то используйте непосредственно System.getProperties Это может быть проблемой, потому что значение хоста, которое вы им указали, может быть перезаписано при следующем запросе, при этом сохраняя имя пользователя и пароль от перезаписанного хоста.

В нашем случае мы решили, что используем клон хеш-таблицы System.getProperties ().

Надеюсь, это поможет (эту проблему было действительно трудно отследить).

0 голосов
/ 27 октября 2008

Попробуйте это:

String to="stackoverflow@so.com";
String cc="one@mail.com,two@mail.com"; //The separator ',' works good

message.setRecipients(Message.RecipientType.TO,new InternetAddress[] { 
new InternetAddress(to) }); // This is only one mail

InternetAddress[] addr = parseAddressList(cc); //Here add all the rest of the mails
message.setRecipients(Message.RecipientType.CC,addr);

Извините за мой английский. Это не хорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...