JavaMail问题:无法向SMTP主机发送命令

9

我正在尝试使用Java Mail,但是出现了“无法将命令发送到SMTP主机”的错误。如果可以的话,请提供任何帮助以及未来问题的解决方案。

确切的异常信息为:

javax.mail.MessagingException: Can't send command to SMTP host;
  nested exception is:
    java.net.SocketException: Connection closed by remote host
    at com.sun.mail.smtp.SMTPTransport.sendCommand(SMTPTransport.java:2106)
    at com.sun.mail.smtp.SMTPTransport.sendCommand(SMTPTransport.java:2093)
    at com.sun.mail.smtp.SMTPTransport.close(SMTPTransport.java:1184)
    at javax.mail.Transport.send0(Transport.java:197)
    at javax.mail.Transport.send(Transport.java:124)
    at TestEmail.main(TestEmail.java:45)
    at __SHELL17.run(__SHELL17.java:6)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at bluej.runtime.ExecServer$3.run(ExecServer.java:774)
Caused by: java.net.SocketException: Connection closed by remote host
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkWrite(SSLSocketImpl.java:1186)
    at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:43)
    at com.sun.mail.util.TraceOutputStream.write(TraceOutputStream.java:114)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
    at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
    at com.sun.mail.smtp.SMTPTransport.sendCommand(SMTPTransport.java:2104)
    ... 11 more

我的代码如下:

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

// Send a simple, single part, text/plain e-mail
public class TestEmail {

    public static void main(String[] args) {

        // SUBSTITUTE YOUR EMAIL ADDRESSES HERE!!!
        String to = "my gmail account whose name i removed for publicity";
        String from = "my hotmail account whose name i removed for publicity";
        // SUBSTITUTE YOUR ISP'S MAIL SERVER HERE!!!
        String host = "smtp.live.com";

        // Create properties, get Session
        Properties props = new Properties();

        // If using static Transport.send(),
        // need to specify which host to send it to
        props.put("mail.smtp.host", host);
        props.put("mail.smtp.starttls.enable", "true");
        // To see what is going on behind the scene
        props.put("mail.debug", "true");
        Session session = Session.getInstance(props);

        try {
            // Instantiatee a message
            Message msg = new MimeMessage(session);

            //Set message attributes
            msg.setFrom(new InternetAddress(from));
            InternetAddress[] address = {new InternetAddress(to)};
            msg.setRecipients(Message.RecipientType.TO, address);
            msg.setSubject("Test E-Mail through Java");
            msg.setSentDate(new Date());

            // Set message content
            msg.setText("This is a test of sending a " +
                        "plain text e-mail through Java.\n" +
                        "Here is line 2.");

            //Send the message
            Transport.send(msg);
        }
        catch (MessagingException mex) {
            // Prints all nested (chained) exceptions as well
            mex.printStackTrace();
        }
    }
}

1
"而且如果可能的话,任何未来问题的解决方案" - 真的吗? - Jim Garrison
我的意思是,我之前输入了“mail.smtp.auth”,然后出现了用户名和密码错误,这就是我的意思。 - Globmont
堆栈跟踪显示“远程主机关闭连接”。您需要使用Wireshark捕获流量并找出确切的事件序列。如果手动telnet到邮件服务器并尝试邮件会话,会发生什么? - Jim Garrison
抱歉,我对SMTP和邮件不太熟悉,所以我没有完全理解你刚才说的话。你能否请用通俗易懂的语言再解释一下呢? :) - Globmont
我在下面发布了一个答案。但是,除非你对SMTP和TLS有更多的了解,否则你将无法取得进展。 - Jim Garrison
显示剩余2条评论
6个回答

13

今天我也遇到了同样的问题。但是对我来说问题所在是,smtp服务器没有启用TLS。因此我更改了邮件属性如下。


mail.smtp.starttls.enable=false

现在一切都很顺利。


1
你能告诉我在 Jenkins 中设置这个的位置吗? - Utsav Gupta
我真的不确定Jenkins。但作为一名常规电脑用户,我建议搜索包含文本mail.smtp.starttls的文件。如果我对你错了,请忽略我的建议。 - vissu
我也很困惑这个应该在哪里设置。我是因为在Jenkins遇到了同样的问题才找到了这个问题。 - Tim
您可以在 Jenkins -> 配置 -> 全局属性 中进行设置。 - Ε Г И І И О

3

在我的情况下,启用邮件调试后,我成功找到了根本问题。

启用邮件调试的不同方法:

java -Dmail.debug=true ...

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

Jenkins配置文件(/etc/default/jenkins):

JAVA_ARGS="-Dmail.smtp.starttls.enable=true -Dmail.debug=true"

更多信息: http://www.oracle.com/technetwork/java/faq-135477.html

我的具体错误是创建电子邮件时"from:"行中的地址不正确。Google "G Suite" (google apps for business)要求发件人地址与账户所有者在同一域中。例如mycompanyname.com

邮件发送器调试显示:

MAIL FROM:<jenkins-pipeline@bogusdomain.com> 550-5.7.1无法使用中继[192.168.42.42]的凭据。您在 G Suite SMTP Relay 服务中注册的 IP 地址与发送此电子邮件的帐户所属的域不匹配。如果您正在尝试中继来自未在您的 G Suite 帐户下注册的域的邮件


你是怎么解决它的? - Alberto Acuña
我在发件人行中使用了我的 GSuite 域名来修复它。 - Donn Lee

1

服务器需要 STARTTLS。如果我使用 telnet 进行手动 SMTP 会话,这是我得到的:

220 BLU0-SMTP122.phx.gbl Microsoft ESMTP MAIL Service, Version: 6.0.3790.4675 ready at  Mon, 18 Jul 2011 17:08:14 -0700
HELO jhmg.net
250 BLU0-SMTP122.phx.gbl Hello [70.123.155.64]
MAIL FROM:<zzz@zzz.com>
530 5.7.0 Must issue a STARTTLS command first

该服务器不接受未加密的连接


好的,你是说我需要加密我的连接? - Globmont
我应该如何开始呢?如果我听起来有些愚蠢,对不起,我只是新手,对邮件之类的东西不太熟悉。 - Globmont
2
@JimGarrison,链接已经失效了,你能找到它吗?谢谢! - Alberto Acuña
2
@Globmont,你找到如何加密连接的方法了吗? - Alberto Acuña

0

尝试添加发件人地址

mail.setFromAddress("姓名 ");


0

您需要将 SSL 信任设置为 smtp.gmail.com

properties.put("mail.smtp.ssl.trust", "smtp.gmail.com");

并将 Authenticator 作为会话参数


        Session session = Session.getDefaultInstance(properties,new javax.mail.Authenticator(){
            protected PasswordAuthentication getPasswordAuthentication() {

                return new PasswordAuthentication(
                        sender, senderPassword);// Specify the Username and the PassWord
            }
        });

-1

为了O365添加了这行代码。现在运行良好。

sslMailProps.put("mail.smtp.ssl.enable", "true");


请提供有关您所提供解决方案的更多信息。 - Burhan Khanzada

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