2016-01-08 13 views
5

Szczęśliwego Nowego Roku!Nie można wysyłać poczty za pośrednictwem protokołu SSL lub TLS za pomocą protokołu SMTP przy użyciu Javamail

Pracuję nad aplikacją, w której użytkownik otrzymuje wiadomość e-mail, gdy wystąpi określony problem.

Jest to funkcja, która używam do wysyłania 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(); 

dość dziwne, gdy próbuję uruchomić powyższy kod z metody Main że to wysłać e-mail dla obu protokołów SSL i TLS z powodzeniem.

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

Ale zawiedzie, gdy próbuję uruchomić ten sam kod za pośrednictwem mojej aplikacji internetowej.

wysyłanie go poprzez SSL generuje ten błąd:

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) 

wysłanie go poprzez TLS generuje ten błąd:

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) 

Wszelkiego rodzaju pomoc jest mile widziana.

Edit1:

Oto plik tpl z przodu

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

Wartości zostaje zapisany w pliku konfiguracyjnym, który wygląda tak:

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

Jest to klasa, który wyznacza i pobiera właściwości:

https://codeshare.io/5G8ki

Dziękuję.

+0

To, co zaskakuje mnie, to fakt, że działa w teście wiersza poleceń. Powinieneś ustawić 'mail.smtp.socketFactory.class' na' javax.net.ssl.SSLSocketFactory' nawet z TLS, nie tylko SSL. Ale niezwiązane z tym, proponuję użyć warunków Yoda, aby sprawdzić stałe ciąg znaków, takich jak '" true ".equals (sslStr)'. Jest bezpieczny i ma mniej bałaganu. – coladict

Odpowiedz

1

Jesteśmy o kilka dodatkowych właściwości określone dla 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"); 

Dla Autentyczna użytku SMTPS zamiast SMTP

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

podczas uzyskiwania transportu

session.getTransport("smtps"); 

Ponownie przekazać wiadomość e-mail hosta i hasło podczas łączenia

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

Do debugowania

session.setDebug(true); 
2

Mimo, kod wygląda ok, jest co najmniej jeden duży problem. Próbujesz użyć tego samego portu (587) dla TLS i SSL. Nie jestem pewien co do TLS, ale kod SSL powinien zadziałać, JEŚLI wyślesz swoje żądanie do portu 465.Jak napisane here (google FAQ):

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

Mają własne porty. Błąd masz SSL:

Unrecognized SSL message, plaintext connection? 

Czy Twój klient nie rozumiejąc fakt, że otrzymał zakodowaną odpowiedź non-SSL (ze względu na port TLS nie wykonawczego SSL).

+0

Nie używam tego samego portu dla obu protokołów. Używam 465 dla SSL i 587 dla TLS. –

+0

Czy możesz pokazać nam kod internetowy, który faktycznie generuje błąd? Uwzględniono główną wersję metody, ale to już działa. W oparciu o errormessage * jesteś * próbuje zainicjować połączenie SSL na porcie TLS. Czy może być coś nie tak z twoją listą parametrów w twojej aplikacji internetowej? –

+0

Sprawdź edytowany wpis –

0

Spróbuj użyć następującego kodu, który działa dla mnie.

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

Niedawno w Gmailu jest aktualizacja zabezpieczeń. Musisz zezwolić na opcję "Zezwalaj na mniej bezpieczny dostęp do aplikacji" na stronie https://myaccount.google.com/security?pli=1. Następnie możesz bez problemu wysyłać wiadomości e-mail z konta

0

simple-java-mail ma proste wyliczenie, za pomocą którego możesz wskazać SSL lub TLS. Nie trzeba się martwić o odpowiednich właściwościach w ten sposób:

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

Jeśli masz dwuskładnikowe logowanie włączone, trzeba wygenerować application specific password z konta Google, aby ten przykład pracę.

Powiązane problemy