2016-01-08 173 views
5

新年快樂!無法通過SSL或TLS使用SMTP郵件發送郵件

我正在處理用戶在發生特定觸發時收到電子郵件的應用程序。

這是我用來發送電子郵件的功能:

public static void sendEmail(String host, String port, String useSSL, String useTLS, String useAuth, String user, String password, String subject, String content, String type, String recipients) 
      throws NoSuchProviderException, AddressException, MessagingException { 
     final Properties props = new Properties(); 
     props.setProperty("mail.transport.protocol", "smtp"); 
     props.setProperty("mail.smtp.host", host); 
     props.setProperty("mail.smtp.port", port);   
     if (useSSL != null && !useSSL.equals("false") && useSSL.equals("true")) { 
      props.setProperty("mail.smtp.ssl.enable", useSSL); 
      props.setProperty("mail.smtp.socketFactory.class", 
        "javax.net.ssl.SSLSocketFactory"); 
      props.setProperty("mail.smtp.socketFactory.port", port); 

     } 
     if (useTLS != null && !useTLS.equals("false") && useTLS.equals("true")) { 
      props.setProperty("mail.smtp.starttls.enable", useTLS); 
      props.setProperty("mail.smtp.socketFactory.fallback", "true"); 
     } 
     props.setProperty("mail.smtp.auth", useAuth); 
     props.setProperty("mail.from", user); 
     props.setProperty("mail.smtp.user", user); 
     props.setProperty("mail.password", password); 

     Session mailSession = Session.getDefaultInstance(props, new Authenticator() { 
      protected PasswordAuthentication getPasswordAuthentication() { 
       return new PasswordAuthentication(props.getProperty("mail.smtp.user"), props 
         .getProperty("mail.password")); 
      } 
     }); 

     Transport transport = mailSession.getTransport(); 

     MimeMessage message = new MimeMessage(mailSession); 
     message.setHeader("Subject", subject); 
     message.setContent(content, type); 

     StringTokenizer tokenizer = new StringTokenizer(recipients, ";"); 
     while (tokenizer.hasMoreTokens()) { 
      String recipient = tokenizer.nextToken(); 
      message.addRecipient(Message.RecipientType.TO, 
        new InternetAddress(recipient)); 
     } 

     transport.connect(); 
     transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO)); 
     transport.close(); 

奇的是,每當我試圖運行與主要方法上面的代碼它會發送電子郵件兩種SSL和TLS協議成功。

public static void main(String args[]) 
    { 
     try { 
      Notifier.sendEmail("smtp.gmail.com", "587", "false", "true", "true","[email protected]", "testpassword", "CHECKING SETTINGS", "CHECKING EMAIL FUNCTIONALITY", "text/html", "[email protected]"); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 

但是,只要我嘗試通過我的web應用程序運行相同的代碼,它就會失敗。

通過SSL發送它拋出這個錯誤:

com.sun.mail.smtp.SMTPSendFailedException: 530-5.5.1 Authentication Required. Learn more at 
jvm 1 | 530 5.5.1 https://support.google.com/mail/answer/14257 f12sm88286300pat.20 - gsmtp 
jvm 1 | 
jvm 1 | at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:2057) 

通過TLS發送它拋出這個錯誤:

javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 587; 
jvm 1 | nested exception is: 
jvm 1 | javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection? 
jvm 1 | at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1934) 

任何形式的幫助表示讚賞。

EDIT1:

下面是從前端TPL文件

<div class="label1"><h3 class="label">Host:</h3></div> 
    <div class="field1"><input type="text" class="input1" name="host" size="20" value="$HOST$"></div> 
     <div class="port"><h3 class="label">Port:</h3></div> 
     <div class="fieldport"><input type="text" class="fieldport" name="port" size="5" value="$PORT$"></div> 
     <div class="ssl"> 
       <input type="radio" name="sslEnable" value="$SSLENABLE$"> 
        Enable SSL? 
     </div> 
     <div class="tls"> 
       <input type="radio" name="tlsEnable" value="$TLSENABLE$"> 
        Enable TLS? 
     </div> 
     <div class="auth"> 
       <input type="checkbox" name="auth"$AUTH$> 
        Enable Authentication? 
     </div>    
    <div class="label2"><h3 class="label">User:</h3></div> 
    <div class="field2"><input type="text" class="input1" name="user" size="20" value="$USER$"></div> 
    <div class="label3"><h3 class="label">Password:</h3></div> 
    <div class="field3"><input type="password" class="input1" name="password" size="20" value="$PASSWORD$"></div> 
    <div class="label4"><h3 class="label">Recipient(s):</h3></div> 
    <div class="field4"><input type="text" class="input1" name="recipients" size="50" value="$RECIPIENTS$"></div> 

的數值會保存在一個配置文件,該文件是這樣的:

host=smtp.gmail.com 
port=587 
ssl=false 
tls=true 
auth=true 
[email protected] 
password=O0UbYboDfVFRaiA= 
[email protected] 
trigger1=false 
attempt=0 
trigger2=false 
percent=5 
anyOrAll=ANY 
trigger3=true 
format=HTML 
trigger4=true 
trigger5=true 

EDIT2:

public static void sendEmail(String message) 
     throws NoSuchProviderException, AddressException, MessagingException 
    { 
    if (message == null || message.trim().equals("")) return; 

    StringBuffer content = new StringBuffer(); 
    content.append(getHeader()); 
    content.append(message); 
    content.append(getFooter()); 
    String format = NotifyProps.getFormat(); 
    String type = "text/plain"; 
    if (format.equals(NotifyProps.HTML)) type = "text/html"; 

    sendEmail(NotifyProps.getHost(), NotifyProps.getPort(), Boolean.toString(NotifyProps.getUseAuth()), Boolean.toString(NotifyProps.getUseSSL()), Boolean.toString(NotifyProps.getUseTLS()),NotifyProps.getUser(), NotifyProps.getPassword(), 
       "Transaction Processor Auto Notification", content.toString(), type, 
       NotifyProps.getRecipients()) 
    } 

這是用於設置和獲取屬性類:

https://codeshare.io/5G8ki

謝謝。

+0

令我驚訝的是,你說它在命令行測試中起作用。即使使用TLS,您應該將'mail.smtp.socketFactory.class'設置爲'javax.net.ssl.SSLSocketFactory',而不僅僅是SSL。 但與此無關,我建議你使用Yoda條件來檢查字符串常量,如'「true」.equals(sslStr)'。它是無效的,並且沒有混亂。 – coladict

回答

1

我們有幾個屬性TLS

props.put("mail.smtp.starttls.enable", "true"); 
props.setProperty("mail.smtp.ssl.enable", "true"); 
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); 
props.put("mail.smtp.socketFactory.fallback", "false"); 

設置在認證使用SMTPS不是SMTP

props.setProperty("mail.smtps.auth", useAuth); 

在獲取交通運輸

session.getTransport("smtps"); 

再次通過主機電子郵件和密碼

transport.connect("smtp.gmail.com", "[email protected]", "password"); 

爲了調試

session.setDebug(true); 
2

Altough你的代碼看起來不錯,至少有一個很大的問題。 您正試圖對TLS和SSL使用相同的端口(587)。我不確定TLS,但如果您將請求發送到端口465,SSL代碼應該可以工作。正如所寫here (google FAQ)

configuring your SMTP server on port 465 (with SSL) and port 587 (with TLS)[...]

他們有自己的特定端口。錯誤您獲得SSL:

Unrecognized SSL message, plaintext connection? 

是您的客戶端不理解,它收到非SSL編碼的響應(因不執行SSL的TLS端口)的事實。

+0

我沒有將兩個協議使用相同的端口。 我使用465 SSL和587 TLS。 –

+0

您能向我們展示實際產生錯誤的網頁代碼嗎?你包括主要的方法版本,但已經有效。根據您正在嘗試在TLS端口上啓動SSL連接的錯誤消息。你的webapp中的參數列表可能有問題嗎? –

+0

請檢查編輯後文章 –

0

請嘗試下面的代碼,它適合我。

public void sendEmail(){ 

     Properties props = new Properties(); 
     props.put("mail.smtp.host", "smtp.gmail.com"); 
     props.put("mail.smtp.socketFactory.port", "465"); 
     props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); 
     props.put("mail.smtp.auth", "true"); 
     props.put("mail.smtp.port", "465"); 

Session session = Session.getDefaultInstance(props, 
      new javax.mail.Authenticator() { 
       protected PasswordAuthentication getPasswordAuthentication() { 
        return new PasswordAuthentication("[email protected]","secret"); 
       } 
      }); 

      try { 
      Message message = new MimeMessage(session); 
      message.setFrom(new InternetAddress("[email protected]")); 
      message.setRecipients(Message.RecipientType.TO, 
        InternetAddress.parse("[email protected]")); 
      message.setSubject("This is testing message"); 
      message.setText("Hi this is testing email....not spam"); 

     Transport.send(message); 
      System.out.println("email successfully sent.."); 

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

最近有一個gmail更新安全。您必須在頁面https://myaccount.google.com/security?pli=1中允許選項「允許安全性較低的應用程序訪問」。然後,您可以從您的帳戶發送郵件沒有問題

0

simple-java-mail有一個簡單的枚舉,您可以用來指示SSL或TLS。您不必擔心正確的屬性這樣:

Email email = new Email(); 

(...) 

new Mailer("smtp.gmail.com", 25, "your user", "your password", TransportStrategy.SMTP_TLS).sendMail(email); 
new Mailer("smtp.gmail.com", 587, "your user", "your password", TransportStrategy.SMTP_TLS).sendMail(email); 
new Mailer("smtp.gmail.com", 465, "your user", "your password", TransportStrategy.SMTP_SSL).sendMail(email); 

如果你有兩個因素登錄後,您需要從您的谷歌帳戶生成application specific password使這個例子工作。