使用此Java程序了解SMTP工作原理的socket(不允许使用JavaMail)
我不确定如何将编码的base64凭据传递到邮件服务器。有没有办法不用JavaMail就可以做到这一点?我一直遇到authentication 530 authentication required错误,我知道这是由于未正确发送凭据造成的,但我无法找出这一点
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.util.Base64;
import java.util.Base64.Encoder;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.net.*;
public class EmailClient
{
public static void main(String[] args) throws Exception
{
// Establish a TCP connection with the mail server.
SSLSocket socket = (SSLSocket) ((SSLSocketFactory)
SSLSocketFactory.getDefault()).
createSocket(InetAddress.getByName("smtp.gmail.com"), 465);
/* encoding the username and password in Base64 for SMTP */
Encoder base64Encoder = Base64.getEncoder();
String smtpUser =
base64Encoder.encodeToString("username".getBytes());
String smtpPass =
base64Encoder.encodeToString("password".getBytes());
// Create a BufferedReader to read a line at a time.
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
// Read greeting from the server.
String response = br.readLine();
System.out.println(response);
if (!response.startsWith("220")) {
throw new Exception("220 reply not received from server.");
}
// Get a reference to the socket's output stream.
OutputStream os = socket.getOutputStream();
// Send HELO command and get server response.
String command = "HELO alice\r\n";
System.out.print(command);
os.write(command.getBytes("US-ASCII"));
response = br.readLine();
System.out.println(response);
if (!response.startsWith("250")) {
throw new Exception("250 reply not received from server.");
}
// Authentication
String cmmd authMsg = "AUTH LOGIN\r\n"
// How do I send my encoded credentials to the server?
// Send MAIL FROM command.
String mailFrom = "MAIL FROM: <xxxxxxxx@gmail.com>\r\n";
System.out.print(mailFrom);
os.write(mailFrom.getBytes("US-ASCII"));
response = br.readLine();
System.out.println(response);
if (!response.startsWith("250")) {
socket.close();
throw new Exception("250 reply not received from server.");
}
// Send RCPT TO command.
String commandRCPT = "RCPT TO:<xxxxxxxxxx.com>\r\n";
System.out.print(commandRCPT);
os.write(commandRCPT.getBytes("US-ASCII"));
response = br.readLine();
System.out.println(response);
if (!response.startsWith("250")) {
socket.close();
throw new Exception("250 reply not received from server.");
}
// Send DATA command.
String commandDATA = "DATA\r\n";
System.out.print(commandDATA);
os.write(commandDATA.getBytes("US-ASCII"));
response = br.readLine();
System.out.println(response);
if (!response.startsWith("354")) {
socket.close();
throw new Exception("354 reply not received from server.");
}
// Send message data.
String msgLine1 = "email sent\r\n";
System.out.print(msgLine1);
os.write(msgLine1.getBytes("US-ASCII"));
// End with line with a single period.
String msgLine2 = ".\r\n";
System.out.print(msgLine2);
os.write(msgLine2.getBytes("US-ASCII"));
response = br.readLine();
System.out.println(response);
if (!response.startsWith("250")) {
socket.close();
throw new Exception("250 reply not received from server.");
}
// Send QUIT command.
String commandQUIT = "QUIT\r\n";
System.out.print(commandQUIT);
os.write(commandQUIT.getBytes("US-ASCII"));
response = br.readLine();
System.out.println(response);
if (!response.startsWith("221")) {
socket.close();
throw new Exception("221 reply not received from server.");
}
socket.close();
}
}
# 1 楼答案
在您展示的代码中没有发生SMTP authentication,这就是
RCPT TO
命令失败的原因。见What is the need of SMTP AUTH?SMTP客户端需要在连接到服务器、识别自身之后,以及在发送任何
MAIL FROM
/RCPT TO
/DATA
命令之前,成功发送AUTH
命令。您需要使用EHLO
而不是HELO
来确定服务器实际支持哪些AUTH
方案(LOGIN
,PLAIN
,GSSAPI
,DIGEST-MD5
,CRAM-MD5
,OAUTHBEARER
,等等),然后对其中一个方案进行相应的身份验证1:FYI,} 、^{} 和^{} 身份验证方案。请参阅this reference,其中对它们进行了更详细的描述
mail.smtp2go.com
支持^{有关更多详细信息,请参阅RFC 4422: Simple Authentication and Security Layer (SASL)、RFC 4954: SMTP Service Extension for Authentication和其他相关RFC
我还建议您阅读RFC 5321: Simple Mail Transfer Protocol以了解SMTP协议的一般工作原理,因为您现在掌握的代码在如何处理协议方面并不完整,尤其是在如何读取服务器的响应方面(请参见section 4.2: SMTP Replies)
试着做些类似的事情: