2008-10-27 61 views
4

我正在使用javax.mail系統,並遇到「無效地址」異常的問題。這裏的代碼的基礎知識:當地址正常時,使用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 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提供的身份驗證信息。

感謝您的線索,以提示我也看看郵件服務器的一面。

+0

這將有助於瞭解報告爲無效的電子郵件地址的一些示例。或者至少是他們的格式。 – 2008-10-27 15:08:59

回答

5

--update的位置:問題認證。

好的,這是我發現的事情。在接收電子郵件時,上面的代碼正確設置了身份驗證,並且實際調用了Authenticator.getPasswordAuthentication()回調。

發送電子郵件時並非如此。你必須做更多。加入:

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

這將強制javax.mail API執行登錄驗證。然後用一個實際的交通情況,而不是靜態的。發送()方法:

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提供的身份驗證信息。

感謝您的線索,以提示我也看看郵件服務器的一面。

0

試試這個:

String to="[email protected]"; 
String cc="[email protected],[email protected]"; //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

我會改變對InternetAddress的調用,以使用「嚴格」的解釋,看看你是否遇到問題的地址進一步錯誤。

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

Javadoc for InternetAddress constructor

如果失敗,它會拋出AddressException,其具有稱爲getPos()方法,該方法返回失敗(Javadoc

0

在我看來,這似乎是我工作中發生的問題。 如果您顯示的代碼是併發的,那麼直接使用System.getProperties 可能會造成問題,因爲您放在它們上的主機值可能會被下一個請求覆蓋,同時仍然保留覆蓋主機的用戶和密碼。

在我們的例子中,我們解決了使用System.getProperties()哈希表的克隆。

希望有幫助(這個問題真的很難追蹤)。

1

一個好線索使用SSL加密在SMTP配置那些,應該通過指定屬性mail.smtp.ssl.enable啓用,如下圖所示:

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

否則如上所述它可以導致類似的問題。