【问题标题】:Getting Invalid Address with javax.mail when the addresses are fine当地址正常时使用 javax.mail 获取无效地址
【发布时间】:2010-09-19 09:40:54
【问题描述】:

我正在使用 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");

这将强制 javax.mail API 进行登录验证。然后使用实际的 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){

在不强制认证的情况下,邮件服务器将我视为未经授权的中继,然后将我关闭。 “有效”的地址和无效的地址之间的区别在于,“有效”的地址都是邮件服务器的本地地址。因此,它只是接受了他们。但是对于任何非本地“中继”地址,它会拒绝该消息,因为我认为 javax.mail API 没有提供我的身份验证信息。

感谢您提供线索,提示我也查看邮件服务器端。

【问题讨论】:

  • 了解报告为无效的电子邮件地址的一些示例会有所帮助。或者至少是他们的格式。
  • 请提供无效邮件列表。
  • 您可能希望发布您的更新作为答案并接受它。
  • 嗯...发布了我的更新作为答案。那行得通。但是系统不让我接受。我猜您无法回答自己的问题并将其标记为正确答案。说得通。否则,您可以对系统有利。

标签: java email


【解决方案1】:

试试这个:

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);

对不起我的英语。这不好。

【讨论】:

    【解决方案2】:

    对于那些在 smtp 配置中使用 ssl 加密的人来说,一个很好的提示,你应该通过指定属性mail.smtp.ssl.enable 来启用它,如下所示:

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

    否则可能会导致与上述类似的问题。

    【讨论】:

      【解决方案3】:

      在我看来,这就像我工作中发生的一个问题。 如果您显示的代码是并发的,那么直接使用 System.getProperties 可能是个问题,因为您放置在它们上的主机值可能会被下一个请求覆盖,同时仍保留被覆盖主机的用户名和密码。

      在我们的例子中,我们使用 System.getProperties() 哈希表的克隆解决了这个问题。

      希望有所帮助(这个问题真的很难追踪)。

      【讨论】:

        【解决方案4】:

        --更新:身份验证问题。

        好的,这就是我发现的情况。收到邮件时,上面的代码正确设置了身份验证,并实际调用了 Authenticator.getPasswordAuthentication() 回调。

        发送电子邮件时并非如此。你必须做更多的事情。添加这个:

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

        这将强制 javax.mail API 进行登录验证。然后使用实际的 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){
        

        没有强制验证,邮件服务器将我视为未经授权的中继,然后将我关闭。 “有效”的地址和无效的地址之间的区别在于,“有效”的地址都是邮件服务器的本地地址。因此,它只是接受了他们。但是对于任何非本地“中继”地址,它会拒绝该消息,因为我认为 javax.mail API 没有提供我的身份验证信息。

        感谢您提供线索,提示我也查看邮件服务器端。

        【讨论】:

          【解决方案5】:

          我会更改对 InternetAddress 的调用以使用“严格”解释,看看您是否在遇到问题的地址上遇到更多错误。

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

          Javadoc for InternetAddress constructor

          如果失败,它会抛出一个AddressException,它有一个名为getPos()的方法,它返回失败的位置(Javadoc

          【讨论】:

            猜你喜欢
            • 2017-12-25
            • 2013-11-16
            • 1970-01-01
            • 1970-01-01
            • 2020-09-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多