如何使用Socket实现SMTP协议?代码举例讲解

SMTP(Simple Mail Transfer Protocol)协议用于电子邮件传输。实现SMTP协议主要包含:

  1. 连接SMTP服务器:默认端口25。
  2. 鉴权:使用用户名和密码登录,若服务器支持TLS,需要先建立TLS连接。
  3. 邮件内容构建:根据RFC 5321规范构建邮件内容,包含发件人、收件人、主题、正文等。
  4. 发送邮件:使用MAIL FROM和RCPT TO命令指定发件人和收件人,使用DATA命令发送邮件内容。
  5. 断开连接:使用QUIT命令断开SMTP连接。
    实现一个简单的SMTP客户端可以如下:
public class SMTPClient {
    private Socket socket;
    private OutputStream out;
    private String server;
    private int port = 25;

    public SMTPClient(String server, int port) throws IOException {
        this.server = server;
        this.port = port;
        connect();
    }

    private void connect() throws IOException {
        socket = new Socket(server, port);
        out = socket.getOutputStream();
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        String welcomeMsg = in.readLine();      // 220 Welcome message
        sendCommand("EHLO localhost");          // 250 Success
        sendCommand("STARTTLS");                // 220 Ready to start TLS
        startTLS();                             // Reconnect with TLS
        sendCommand("EHLO localhost");          // 250 Success 
        sendCommand("AUTH LOGIN");              // 334 Username
        sendCommand(Base64.encode("username")); // 334 Password
        sendCommand(Base64.encode("password")); // 235 Success
    }  

    private void startTLS() throws IOException {
        SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
        SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket, server, port, true);
        socket = sslSocket;
        out = socket.getOutputStream();
    }  

    private void sendCommand(String cmd) throws IOException {
        out.write((cmd + "\r\n").getBytes());
        String response = socket.getInputStream().readLine();
    }  

    public void sendEmail(String from, String to, String subject, String content) throws IOException {
        sendCommand("MAIL FROM: <" + from + ">");         // 250 OK
        sendCommand("RCPT TO: <" + to + ">");             // 250 OK
        sendCommand("DATA");                              // 354 Start mail input; end with <CR><LF>.<CR><LF> 
        out.write(("Subject: " + subject + "\r\n").getBytes());
        out.write(content.getBytes());
        sendCommand("\r\n.\r\n");                         // 250 OK  
        sendCommand("QUIT");                              // 221 Bye
    }
}

我们可以这样使用SMTPClient发送邮件:

SMTPClient client = new SMTPClient("smtp.example.com");
client.sendEmail("from@example.com", "to@example.com", "Subject", "Content");