通过JavaMail发送邮件到Gmail时的TLS问题

9

事实证明,JavaMail 比我想象的更令人沮丧。我查看了几个在线示例,以了解如何通过 Gmail 服务器(但不通过 SSL)发送简单的 SMTP 电子邮件。尝试了几个不同的代码示例后,每当我调用 transport.connect() 时,都会得到相同的异常堆栈跟踪:

Exception in thread "main" com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.0 Must issue a STARTTLS command first. l10sm302158wfk.21
     at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:2057)
     at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:1580)
     at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1097)
     at SendEmail.main(SendEmail.java:47)

请问我应该添加或做些什么来解决这个问题?
以下是我的代码:
    Properties props = new Properties();
    props.put("mail.transport.protocol", "smtp");
    props.put("mail.host", "smtp.gmail.com");
    props.put("mail.user", "blahblah@gmail.com");
    props.put("mail.password", "blah");
    props.put("mail.port", "587");

    Session mailSession = Session.getDefaultInstance(props, null);
    Transport transport = mailSession.getTransport();

    MimeMessage message = new MimeMessage(mailSession);
    message.setSubject("This is a test");
    message.setContent("This is a test", "text/plain");
    message.addRecipient(Message.RecipientType.TO, new InternetAddress("blahblah2@gmail.com"));

    transport.connect();
    transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO));
    transport.close();
4个回答

15

您需要启用STARTTLS。向配置文件中再添加一个属性:

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

1
谢谢,这解决了STARTTLS的问题,但现在我遇到了这个异常。你能帮我吗?主线程中的异常:"com.sun.mail.smtp.SMTPSendFailedException: 530-5.5.1 需要身份验证。请在以下网址了解更多信息:
530 5.5.1 http://mail.google.com/support/bin/answer.py?answer=14257 g2sm368231pbh.15... 我查看了它包含的网站,但没有找到任何有用的信息。
- Brian
3
没问题,您需要将mail.smtp.auth属性设置为true - Rob Harrop
1
再次感谢!现在我遇到了这个错误...“连接失败,未指定密码?”... 我知道我已经提供了密码,就像你从上面的代码中看到的那样。但是密码的属性标签是否命名为其他我没有正确提供的名称? - Brian
1
好的,也许你应该使用一个“Authenticator”而不是配置凭据。删除“mail.user”和“mail.password”键。然后,不要将null作为第二个参数传递给“Session.getDefaultInstance”,而是创建并传递一个实现“Authenticator”的对象,该对象覆盖“getPasswordAuthentication”方法 - 具体细节很容易实现。 - Rob Harrop
啊,这个程序在我的开发桌面上完美运行。但是当我将它移动到服务器并运行时,出现了以下错误:javax.mail.MessagingException: 无法将套接字转换为TLS;嵌套异常是:java.io.IOException: 使用套接字工厂类 null 启动 TLS 时出现异常:主机、端口:smtp.gmail.com,25;异常:java.security.ProviderException: 无法初始化 NSS com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1880) com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:648)... 有什么想法吗? - Brian
显示剩余3条评论

5
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

public class CopyOfSendMail {

private static String SMPT_HOSTNAME = "my smtp port no";
private static String USERNAME = "root";
private static String PASSWORD = "root";

public static void main(String[] args) {
    Properties props = new Properties();
    props.put("mail.smtp.host", SMPT_HOSTNAME);
    props.put("mail.from","aaa@gmail.com");
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.auth", "true");
    props.put("mail.debug", "true");

    Session session = Session.getInstance(props, new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(USERNAME, PASSWORD);
        }
    });
    try {
        MimeMessage msg = new MimeMessage(session);
        msg.setFrom();
        msg.setRecipients(Message.RecipientType.TO,
                          "bbb@gmail.com");
        msg.setSubject("JavaMail hello world example");
        msg.setSentDate(new Date());
        msg.setText("Hello, world!\n");
        Transport.send(msg);
     } catch (MessagingException mex) {
        System.out.println("send failed, exception: " + mex);
     }
    }
}

谢谢Rob和Brian!在你们的帮助下,我将整个代码放在这里...任何想要创建简单邮件发送器的人都可以使用上面的代码,它会完美地工作。 - pooja

1

这里是使用MSN-SMTP服务的邮件发送器。

我的主机是smtp.live.com,端口是587。

Java Mail官方文档所述,您可以在此处获取有关最佳Java Mail机制以发送和接收邮件的更多信息。

邮件客户端的属性为:

  Properties mailProps = new Properties();
  mailProps.put("mail.smtp.user",mailID);
  mailProps.put("mail.smtp.host",host);
  mailProps.put("mail.smtp.auth", "true");
  mailProps.put("mail.smtp.port",port);
  mailProps.put("mail.smtp.starttls.enable", "true");
  Session mailSession = Session.getInstance(mailProps,null);

发送机制是:
 SMTPTransport t=(SMTPTransport)mailSession.getTransport("smtp");
 System.out.println(" Taking protocol! ");
 t.connect(host, mailID, password);
 System.out.println(" Connection Successfull! ");
 t.sendMessage(mimMessage,mimMessage.getAllRecipients());

注意:
代码在本地印度服务器上运行良好。 但是在Azur Congo无响应:两者都是Linux服务器。
错误为:
 com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.0 Must issue a STARTTLS command first

即使手动设置系统属性:
 java -Dmail.smtp.starttls.enable=true SendAMai

另外,@Rob Harrop和@Brian的观点也得到了确认。

if you're on Linux ensure that you have libnss3 and openssl installed

0
package enviando_email.enviando_email;
import static org.junit.Assert.assertTrue;
import java.util.Properties;
import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.junit.Test;

/**
 * Unit test for simple App.
 */

public class AppTest 
{

    @org.junit.Test
    public void testEmail() {
        
          final String username = "yourusername";
          final String password = "yourpass";
        
        try {
            
            Properties properties = new Properties(); 
            properties.put("mail.smtp.auth", "true"); /*autorizacao*/
            properties.put("mail.smtp.starttls.enable", "true"); /* autenticacação*/
            properties.put("mail.smtp.host", "smtp-mail.outlook.com"); /* servidor do gmail */
            properties.put("mail.smtp.port", "587"); /* porta de saida do servidor */
            properties.put("mail.smtp.socketFactory.port", "587"); /* especifica a porta a ser conectada pelo socket */
            properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); /* classe do socket de conexão SMTP */
            
            //cria sessão - recebe objeto autorizado para se manter na sessão 
            Session session = Session.getInstance(properties, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
            
            Address[] toUser = InternetAddress.parse("recipient1@hotmail.com,recipient2@gmail.com");
            
            Message message = new MimeMessage(session); //pega sessão válida 
            message.setFrom(new InternetAddress(username)); //pega o usuario que iniciou a sessão e envia mensagem por ele
            message.setRecipients(Message.RecipientType.TO, toUser); //para quem enviar email 
            message.setSubject("Chegou assunto do e-mail"); //Assunto do e-mail
            message.setText("Olá esse e-mail está sendo enviado pelo java mail");
            
            Transport.send(message);
            
        }catch (Exception e) {
            e.printStackTrace();
        }
        
    }
}

1
我将我自己使用的内容放在上面,希望对您有所帮助。 - Crystyan S. Santos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接