2016-01-08 23 views
5

Buon anno!Impossibile inviare posta tramite SSL o TLS utilizzando SMTP utilizzando Javamail

Sto lavorando a un'applicazione in cui l'utente riceve un'email ogni volta che si verifica un particolare trigger.

Questa è la funzione che sto usando per inviare e-mail:

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

abbastanza strano, ogni volta che provo per eseguire il codice precedente con il metodo principale che sarebbe inviare l'e-mail sia per protocolli SSL e TLS con successo.

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

Ma fallisce ogni volta che provo a eseguire lo stesso codice tramite la mia applicazione web.

inviandola tramite SSL getta questo errore:

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) 

inviandola tramite TLS getta questo errore:

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) 

Qualsiasi tipo di aiuto è apprezzato.

Edit1:

Ecco il file tpl da parte anteriore

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

I valori viene salvato in un file di configurazione che assomiglia a questo:

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()) 
    } 

Questa è la classe che imposta e ottiene le proprietà:

https://codeshare.io/5G8ki

Grazie.

+0

Ciò che mi sorprende è che dici che funziona nel test della riga di comando. Dovresti impostare 'mail.smtp.socketFactory.class' su' javax.net.ssl.SSLSocketFactory' anche con TLS, non solo SSL. Ma non correlato a questo, ti suggerirei di utilizzare le condizioni Yoda per verificare costanti di stringa come '" true ".equals (sslStr)'. È sicuro e ha meno confusione. – coladict

risposta

1

Stiamo avendo qualche proprietà impostate per 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"); 

Per uso Auth SMTPS invece di smtp

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

Mentre Ottenere il trasporto

session.getTransport("smtps"); 

Anche in questo caso passare l'e-mail di accoglienza e password durante il collegamento

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

Per il debugging

session.setDebug(true); 
2

Benche il codice sia ok, c'è almeno un grosso problema. Si sta tentando di utilizzare la stessa porta (587) per TLS e SSL. Non sono sicuro di TLS, ma il codice SSL dovrebbe funzionare SE si invia la richiesta alla porta 465.Come scritto here (google FAQ):

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

Hanno le proprie porte specifiche. L'errore che si ottiene per SSL:

Unrecognized SSL message, plaintext connection? 

è il client non capire il fatto che ha ricevuto una risposta codificata non SSL (a causa della porta di TLS non implementare SSL).

+0

Non sto utilizzando la stessa porta per entrambi i protocolli. Sto usando 465 per SSL e 587 per TLS. –

+0

Puoi mostrarci il codice web che sta effettivamente producendo l'errore? Hai incluso la versione del metodo principale, ma ciò funziona già. In base al messaggio errato * si * sta tentando di avviare la connessione SSL su una porta TLS. Potrebbe esserci qualcosa di sbagliato nel tuo elenco di parametri nella tua webapp? –

+0

Controllare il post modificato –

0

Provare il seguente codice funziona per me.

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

Recentemente, c'è una sicurezza di aggiornamento in gmail. È necessario consentire l'opzione "Consenti accesso meno sicuro alle applicazioni" nella pagina https://myaccount.google.com/security?pli=1. Quindi è possibile inviare mail dal proprio account senza problemi

0

simple-java-mail ha un enum semplice che è possibile utilizzare per indicare SSL o TLS. Non è necessario preoccuparsi delle proprietà corrette in questo modo:

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

Se si dispone di due fattori login attivata, è necessario generare un application specific password dal tuo account Google per rendere questo esempio il lavoro.