当地址正确时,使用javax.mail时出现“无效地址”问题

7

我正在使用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已经呈现了我的身份验证信息,但实际上没有。谢谢你提供提示,促使我查看邮件服务器方面的问题。

知道一些被报告为无效的电子邮件地址的示例会有所帮助。或者至少知道它们的格式。 - matt b
请提供一个无效电子邮件列表。 - johnstok
你可能想把你的更新发布为一个答案并接受它。 - matt b
嗯...我把我的更新发布为答案了。这样做起作用了。但是系统不允许我接受它。我猜你不能回答自己的问题并将其标记为正确答案。这很有道理。否则,你可以操纵系统使其更有利于你。 - Steven M. Cherry
5个回答

7

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

好的,这是我发现的情况。在接收电子邮件时,上面的代码正确设置了身份验证,并且实际上调用了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身份验证信息时,它并没有呈现。感谢提示我查看邮件服务器方面的线索。

2
我建议将InternetAddress的调用更改为使用“严格”解释,看看是否会在你遇到问题的地址上出现进一步的错误。
message.addRecipient(Message.RecipientType.TO, 
        new InternetAddress(vcea.get(i).emailaddr, true ));
//                                                 ^^^^ turns on strict interpretation

InternetAddress构造函数的Javadoc

如果失败,它将抛出一个名为AddressException的异常,其中有一个名为getPos()的方法,该方法返回失败的位置(Javadoc


0

试试这个:

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

抱歉我的英语不太好。


0
对于在 SMTP 配置中使用 SSL 加密的人来说,一个好的提示是应该通过指定属性 mail.smtp.ssl.enable 来启用它,如下所示:
props.put("mail.smtp.ssl.enable", "true");

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

-1

这似乎是我在工作中遇到的一个问题。如果您展示的代码是并发的,那么直接使用System.getProperties可能会有问题,因为您放在它们上面的主机值可能会被下一个请求覆盖,同时仍然保留被覆盖主机的用户和密码。

在我们的情况下,通过使用System.getProperties()哈希表的克隆来解决了这个问题。

希望能帮到您(这个问题确实很难追踪)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接