2013-09-29 73 views
2

我嘗試在本地網絡的java發送郵件,使用Microsoft Exchange ServerJAVAMAIL:AUTH NTLM失敗

有我的代碼:

import java.io.UnsupportedEncodingException; 
import java.util.Properties; 

import javax.mail.Message; 
import javax.mail.MessagingException; 
import javax.mail.PasswordAuthentication; 
import javax.mail.Session; 
import javax.mail.Transport; 
import javax.mail.internet.AddressException; 
import javax.mail.internet.InternetAddress; 
import javax.mail.internet.MimeMessage; 


public class Main { 


     public static void main(String[] args) { 

      final String username = "[email protected]"; 
      final String password = "password"; 

      Properties props = new Properties(); 
      props.put("mail.smtp.auth", "true"); 
      props.put("mail.debug", "true"); 
      props.put("mail.smtp.host", "exchange_host.MyDomain.com"); 
      props.put("mail.smtp.port", "25"); 
      props.put("mail.smtp.auth.mechanisms","NTLM"); 
      props.put("mail.smtp.auth.ntlm.domain","MyDomain"); 


      Session session = Session.getInstance(props,new MyAuthenticator(username,password)); 

      try { 

       Message message = new MimeMessage(session); 
       message.setFrom(new InternetAddress("[email protected]")); 
       message.setRecipients(Message.RecipientType.TO, 
        InternetAddress.parse("recipent_adresse")); 
       message.setSubject("Testing Subject"); 
       message.setText("Dear Mail Crawler," 
        + "\n\n No spam to my email, please!"); 

       Transport.send(message); 

       System.out.println("Done"); 

      } catch (MessagingException e) { 
       throw new RuntimeException(e); 
      } 
     } 
    } 

,這是我authentificator類:

import javax.mail.Authenticator; 
import javax.mail.PasswordAuthentication; 

public class MyAuthenticator extends Authenticator { 

    String user; 
    String pw; 
    public MyAuthenticator (String username, String password) 
    { 
     super(); 
     this.user = username; 
     this.pw = password; 
    } 
    public PasswordAuthentication getPasswordAuthentication() 
    { 
     return new PasswordAuthentication(user, pw); 
    } 

} 

我使用NTLM機制,但我得到這個錯誤:

DEBUG: JavaMail version 1.4.7 
DEBUG: successfully loaded resource: /META-INF/javamail.default.providers 
DEBUG: Tables of loaded providers 
DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle]} 
DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]} 
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map 
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle] 
DEBUG SMTP: useEhlo true, useAuth true 
DEBUG SMTP: useEhlo true, useAuth true 
DEBUG SMTP: trying to connect to host "echange_server.MyDomain.com", port 25, isSSL false 
220 echange_server.MyDomain.com Microsoft ESMTP MAIL Service ready at Mon, 30 Sep 2013 09:01:08 +0100 
DEBUG SMTP: connected to host "echange_server.MyDomain.com", port: 25 

EHLO host.MyDomain.com 
250-echange_server.MyDomain.com Hello [xx.xx.xx.xx] 
250-SIZE 
250-PIPELINING 
250-DSN 
250-ENHANCEDSTATUSCODES 
250-STARTTLS 
250-X-ANONYMOUSTLS 
250-AUTH NTLM 
250-X-EXPS GSSAPI NTLM 
250-8BITMIME 
250-BINARYMIME 
250-CHUNKING 
250-XEXCH50 
250-XRDST 
250 XSHADOW 
DEBUG SMTP: Found extension "SIZE", arg "" 
DEBUG SMTP: Found extension "PIPELINING", arg "" 
DEBUG SMTP: Found extension "DSN", arg "" 
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg "" 
DEBUG SMTP: Found extension "STARTTLS", arg "" 
DEBUG SMTP: Found extension "X-ANONYMOUSTLS", arg "" 
DEBUG SMTP: Found extension "AUTH", arg "NTLM" 
DEBUG SMTP: Found extension "X-EXPS", arg "GSSAPI NTLM" 
DEBUG SMTP: Found extension "8BITMIME", arg "" 
DEBUG SMTP: Found extension "BINARYMIME", arg "" 
DEBUG SMTP: Found extension "CHUNKING", arg "" 
DEBUG SMTP: Found extension "XEXCH50", arg "" 
DEBUG SMTP: Found extension "XRDST", arg "" 
DEBUG SMTP: Found extension "XSHADOW", arg "" 
DEBUG SMTP: Attempt to authenticate using mechanisms: NTLM 
DEBUG SMTP: AUTH NTLM failed 

Exception in thread "main" java.lang.RuntimeException: javax.mail.AuthenticationFailedException: 250-exchange_host.MyDomain.com Hello [xx.xx.xx.xx] 

    at testPakcage.Main.main(Main.java:51) 
Caused by: javax.mail.AuthenticationFailedException: 250-exchange_host.MyDomain.com Hello [xx.xx.xx.xx] 

請幫我,我過去幾天搜索解決方案,但我什麼也沒找到

+0

你檢查了這個問題嗎? http://stackoverflow.com/questions/4337812/javamail-ntlm-authentication-failure – epoch

+0

@epoch:是的,我做了,它沒有相同的東西,在這個例子中我使用smtp協議,在另一個他使用imap協議和LOGIN機制:「DEBUG SMTP:檢查機制:LOGIN PLAIN DIGEST-MD5 NTLM AUTH LOGIN」 –

+0

根據交換配置,可能需要在DOMAIN \ username表格中指定用戶名 – Jk1

回答

5

我有這個工作連接到我們的Exchange 2010服務器通過NTLM。

NTLM使用您的Windows登錄名和密碼進行身份驗證,而不是使用您的電子郵件地址和密碼。

我做了以下修改:

1)用戶名應該是Windows登錄,而不是電子郵件地址。 NTLM使用您的Windows憑據進行身份驗證。

2)mail.smtp.auth.ntlm.domain應該是您的Windows域 - 即斜槓前面的部分,如果您通常以「MYDOMAIN \ id12345」作爲用戶名登錄Windows機器。

更新下面的代碼:

public class Main { 
    public static void main(String[] args) { 

    // *** CHANGED *** 
    final String username = "id12345"; // ID you log into Windows with 
    final String password = "MyWindowsPassword"; 

    Properties props = new Properties(); 
    props.put("mail.smtp.auth", "true"); 
    props.put("mail.debug", "true"); 

    props.put("mail.smtp.host", "exchangeserver.mydomain.com"); 
    props.put("mail.smtp.port", "25"); 
    props.put("mail.smtp.auth.mechanisms","NTLM"); 

    // *** CHANGED *** 
    props.put("mail.smtp.auth.ntlm.domain","WINDOMAIN"); // Domain you log into Windows with 


    Session session = Session.getInstance(props,new MyAuthenticator(username,password)); 

    try { 

     Message message = new MimeMessage(session); 
     message.setFrom(new InternetAddress("[email protected]")); 
     message.setRecipients(Message.RecipientType.TO, 
       InternetAddress.parse("[email protected]")); 
     message.setSubject("Test email"); 
     message.setText("TEST EMAIL"); 

     Transport.send(message); 

     System.out.println("Done"); 

    } catch (MessagingException e) { 
     e.printStackTrace(); 
    } 
    } 


    public static class MyAuthenticator extends Authenticator { 

    String user; 
    String pw; 
    public MyAuthenticator (String username, String password) 
    { 
     super(); 
     this.user = username; 
     this.pw = password; 
    } 
    public PasswordAuthentication getPasswordAuthentication() 
    { 
     return new PasswordAuthentication(user, pw); 
    } 
    } 
} 

對於它的價值,你的原帖幫助我解決我已經連接了已持續了好幾天的問題。

最後一點,你可能需要禁用/更改防病毒設置允許訪問了25端口

0

我有同樣的問題,並找出該JavaMail的不支持NTLMv2身份認證後,我的工作出了一個需要JCIFS庫的解決方法。

我將javamail api源代碼(https://java.net/projects/javamail/pages/Home)下載並編輯了com.sun.mail.auth.Ntlm類,以使用JCIFS庫支持(http://jcifs.samba.org)添加對NTLMv2的缺失支持。

文件Ntlm.java第一次修改是在方法init0,以及包括添加缺少標誌NTLMSSP_NEGOTIATE_NTLM2的:

private void init0() { 
// ANDREA LUCIANO: 
// turn on the NTLMv2 negotiation flag in TYPE1 messages: 
// NTLMSSP_NEGOTIATE_NTLM2 (0x00080000) 
// See also http://davenport.sourceforge.net/ntlm.html#type1MessageExample 

    type1 = new byte[256]; 
    type3 = new byte[256]; 
    System.arraycopy(new byte[] {'N','T','L','M','S','S','P',0,1}, 0, 
      type1, 0, 9); 
    type1[12] = (byte) 3; 
    type1[13] = (byte) 0xb2; 
    type1[14] = (byte) 0x08; // ANDREA LUCIANO - added 

... }

的第二變形例是代替本方法generateType3Msg:

public String generateType3Msg(String challenge) { 
    /* First decode the type2 message */ 
    byte[] type2 = null; 
    try { 
     type2 = BASE64DecoderStream.decode(challenge.getBytes("us-ascii")); 
     logger.fine("type 2 message: " + toHex(type2)); // ANDREA LUCIANO - added 
    } catch (UnsupportedEncodingException ex) { 
     // should never happen 
     assert false; 
    } 
    jcifs.ntlmssp.Type2Message t2m; 
    try { 
      t2m = new jcifs.ntlmssp.Type2Message(type2); 
    } catch (IOException ex) { 
      logger.log(Level.FINE, "Invalid Type 2 message", ex); 
      return ""; // will fail later 
    } 

    final int type2Flags = t2m.getFlags(); 
    final int type3Flags = type2Flags & (0xffffffff^(jcifs.ntlmssp.NtlmFlags.NTLMSSP_TARGET_TYPE_DOMAIN | jcifs.ntlmssp.NtlmFlags.NTLMSSP_TARGET_TYPE_SERVER)); 

    jcifs.ntlmssp.Type3Message t3m = new jcifs.ntlmssp.Type3Message(t2m, password, ntdomain, username, hostname, type3Flags); 
     return jcifs.util.Base64.encode(t3m.toByteArray()); 
} 

我發現修補庫simpest方法是編譯的類,並更新庫jar文件:

"c:\Program Files\Java\jdk1.5.0_22\bin\javac.exe" -cp jcifs-1.3.17.jar;javax.mail-1.5.2.jar -d . Ntlm.java 
jar uvf javax.mail-1.5.2.jar com\sun\mail\auth\Ntlm.class 

要儘可能地進行調試,我在我的測試類的主要方法中使用了以下代碼:

final InputStream inputStream = Main.class.getResourceAsStream("/logging.properties"); 
    LogManager.getLogManager().readConfiguration(inputStream); 

    Properties props = new Properties(); 

    props.put("mail.debug", "true"); 
    props.put("mail.debug.auth", "true"); 

與此logging.properties:

# Logging 
    handlers = java.util.logging.ConsoleHandler 

    .level = INFO 

    # Console Logging 
    java.util.logging.ConsoleHandler.level = INFO 

之前使用此補丁測試發送類型1消息後卡住了,因爲我的Exchange服務器所需的NTLMv2身份驗證。 補丁完成後,認證成功完成。

相關問題