首页 > 解决方案 > 在没有 Java Mail API 或任何第三方 API 的情况下用 Java 编写 SMTP 客户端

问题描述

我在问这个问题,我感到非常尴尬。我在不使用 Java MAIL API 或任何其他第三方加密库的情况下实现 SMTP 客户端,无论是否开源,因为我不喜欢第三方 API 并希望按照我的方式做事。我知道这很傲慢,但我就是这样。所以,到目前为止我有这个: -

import java.net.Socket;
import java.util.Scanner;
import java.util.Base64;

public class SocketSample
{
    public static void main(String[] args) throws Exception
    {
        Socket socket = null;
        InputStream in = null;
        OutputStream out = null;
        String uid = Base64.getEncoder().encodeToString("xyz@gmail.com".getBytes());
        String pwd = Base64.getEncoder().encodeToString("abc123".getBytes());
        System.out.println(uid);
        System.out.println(pwd);
        //char ans = '\0';
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter host: ");
        String host = scanner.nextLine();
        System.out.print("Enter port: ");
        int port = Integer.parseInt(scanner.nextLine());
        socket = new Socket();
        socket.connect(new InetSocketAddress(host, port));
        if (socket.isConnected())
        {

            System.out.println("Socket connected.");
            out = socket.getOutputStream();
            String command = "HELO " + host + "\r\n";
            byte[] data = command.getBytes();
            out.write(data);
            out.flush();
            //
            in = socket.getInputStream();
            int c = '\0';
            while (c != -1)
            {
                c = in.read();
                System.out.print((char) c);
            }
            //
            command = "STARTTLS\r\n";
            data = command.getBytes();
            out.write(data);
            out.flush();
            c = '\0';
            while(c != -1)
            {
                c = in.read();
                System.out.print((char) c);
            }
            /*
            command = "HELO " + host + "\r\n";
            data = Base64.getEncoder().encodeToString(command.getBytes()).getBytes();
            out.write(data);
            out.flush();
            c = '\0';
            while(c != -1)
            {
                c = in.read();
                System.out.print((char) c);
            }
            */
            System.out.println(uid);
            System.out.println(pwd);
            command = "AUTH PLAIN " + uid + "\r\n";
            data = command.getBytes();
            out.write(data);
            out.flush();
            c = '\0';
            while(c != -1)
            {
                c = in.read();
                System.out.print((char) c);
            }
            //
            command = pwd + "\r\n";
            data = command.getBytes();
            out.write(data);
            out.flush();
            c = '\0';
            while (c != -1)
            {
                c = in.read();
                System.out.print((char) c);
            }
        }
        out.close();
        in.close();
        socket.close();
        System.exit(0);
    }
}

这卡在 STARTTLS 上,虽然我使用 base64 编码用户名和密码,但它仍然卡在那里。我在做什么错?请帮帮我。谢谢!PS:-我是Java新手。

标签: javaauthenticationsmtpgmail

解决方案


我建议依靠inputStream::available()阅读内容的方法。这样,您可以创建一个辅助方法,例如

private static String readResponse(InputStream inputStream) throws IOException {
    int c;
    StringBuilder raw = new StringBuilder();
    do {
        c = inputStream.read();
        raw.append((char) c);
    } while (inputStream.available() > 0);
    return raw.toString();
}

然后替换代码块

int c = '\0';
while (c != -1) {
    c = in.read();
    System.out.print((char) c);
}

System.out.println(readResponse(in));

这样,您将继续执行STARTTLS命令,但我不确定您是否应该发送它,因为您自己使用普通 Sockets 实现的 TLS 不是您想做的家庭任务。


推荐阅读