我正在尝试使用STARTTLS命令发送电子邮件。我在Gmail中设置了一个测试帐户,并将其设置为只接受带有TLS连接的入站电子邮件。用STARTTLS发送电子邮件
由于我不想进入的原因,我不能使用JavaMail或其他电子邮件库。
我已经能够使用openssl将电子邮件发送到此测试帐户。所以我知道该帐户已正确设置。
例子工作:OpenSSL的的s_client.First -starttls SMTP -crlf -connect aspmx.l.google.com:25
我也已经能够发送电子邮件,使用TLS结合.Net应用程序此电子邮件帐户。
我知道我的示例(下面)不是发送电子邮件的正确方式,因为我没有对服务器的响应做出反应,但我认为这是一个很好的/简短的方式来创建示例来演示问题。
我一直在尝试一段时间才能使其工作。我曾尝试连接不同的端口(465,587,25),结果相似。我得到的错误是在命令“AUTH LOGIN”上,但是我之前的命令“EHLO aspmx.l.google.com”中没有收到来自服务器的响应。
我得到的错误是:“错误:软件导致连接中止:套接字写入错误”。
我在正确的道路上谈判TLS连接传输电子邮件或我是否错过了明显的东西?
任何帮助将不胜感激。
例子:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.xml.bind.DatatypeConverter;
public class SendEmailWithTLSConnectionTest {
private static DataOutputStream dos;
private static BufferedReader out = null;
public static void main(String[] args) throws Exception
{
try
{
int delay = 1000;
String username = DatatypeConverter.printBase64Binary("[email protected]".getBytes());
String password = DatatypeConverter.printBase64Binary("2wsxZAQ!".getBytes());
Socket sock = new Socket("aspmx.l.google.com", 25);
out = new BufferedReader(new InputStreamReader(sock.getInputStream()));
(new Thread(new Runnable()
{
public void run()
{
while(true)
{
try
{
if(out != null)
{
String line;
while((line = out.readLine()) != null)
{
System.out.println("SERVER: "+line);
}
}
}
catch (IOException e)
{
System.out.println("IOException SERVER! Error: " + e);
try {
Thread.sleep(1000 * 5);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
})).start();
dos = new DataOutputStream(sock.getOutputStream());
send("EHLO aspmx.l.google.com\r\n");
Thread.sleep(delay * 5);
send("STARTTLS\r\n");
Thread.sleep(delay * 5);
SSLSocket sslSocket = (SSLSocket) ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(
sock,
sock.getInetAddress().getHostAddress(),
587,
true);
sslSocket.setUseClientMode(true);
sslSocket.setEnableSessionCreation(true);
// Thread.sleep(delay * 5);
// sslSocket.startHandshake();
send("EHLO aspmx.l.google.com\r\n");
Thread.sleep(delay * 5);
send("AUTH LOGIN\r\n");
Thread.sleep(delay * 5);
send(username + "\r\n");
Thread.sleep(delay * 5);
send(password + "\r\n");
Thread.sleep(delay * 5);
send("MAIL FROM: <[email protected]>\r\n");
Thread.sleep(delay * 5);
send("RCPT TO: <[email protected]>\r\n");
Thread.sleep(delay * 5);
send("DATA\r\n");
Thread.sleep(delay * 5);
send("Test 1 2 3");
Thread.sleep(delay * 5);
send("\r\n.\r\n");
Thread.sleep(delay * 5);
send("QUIT\r\n");
}
catch(Exception ex)
{
System.out.println("Exception when sending out test. Error: " + ex.getMessage());
}
}
private static void send(String s) throws Exception
{
dos.writeBytes(s);
System.out.println("CLIENT: "+s);
}
}
输出:
SERVER: 220 mx.google.com ESMTP on10si24036122pac.132 - gsmtp
CLIENT: EHLO aspmx.l.google.com
SERVER: 250-mx.google.com at your service, [103.23.17.19]
SERVER: 250-SIZE 35882577
SERVER: 250-8BITMIME
SERVER: 250-STARTTLS
SERVER: 250-ENHANCEDSTATUSCODES
SERVER: 250-PIPELINING
SERVER: 250-CHUNKING
SERVER: 250 SMTPUTF8
CLIENT: STARTTLS
SERVER: 220 2.0.0 Ready to start TLS
CLIENT: EHLO aspmx.l.google.com
Exception when sending out test. Error: Software caused connection abort: socket write error
感谢您的反馈。对于域“aspmx.l.google.com”端口587不起作用,所以不得不使用端口25.然后,startHandshake()命令给了我一个错误,但第二次它工作正常。我不得不改变你的示例代码,以便在我们发送下一个命令之前允许完成服务器的响应。但它现在正在完美工作。非常感谢你! – Leo
为什么您使用'aspmx.l.google.com'而不是'smtp.gmail.com'?为什么在EHLO命令中指定'aspmx.l.google.com'?您应该发送自己的客户端主机名。无论如何,我给你的代码已经等待一个完整的响应到达,然后才允许发送下一个命令。 'sendCmd()'发送一个命令行,然后读取响应,直到到达最终响应终止符,然后它将响应代码返回给调用者。 –
我并非试图将电子邮件转交给Gmail来转发邮件。我正在尝试将其他邮件服务器的电子邮件发送到Gmail用户的邮箱。如果您执行tls.calcium.co.nz的mxlookup,您将获得gmail域名“aspmx.l.google.com”而不是smtp域名“smtp.gmail.com”。 – Leo