简体   繁体   English

在没有 Java Mail API 或任何第三方 API 的情况下用 Java 编写 SMTP 客户端

[英]Writing SMTP Client in Java without Java Mail API or any third party API

I am asking this and I am terribly embarrassed.我问这个,我非常尴尬。 I am implementing an SMTP client without using Java MAIL API or any other third party encryption library, open source or not as I am not fond of third party APIs and wish to do stuff my way on my terms.我正在实现一个 SMTP 客户端,而不使用 Java MAIL API 或任何其他第三方加密库,无论是否开源,因为我不喜欢第三方 API 并希望按照我的方式做事。 I know it is arrogant but it is the way I am.我知道这很傲慢,但这就是我的方式。 So, far I have this: -所以,到目前为止我有这个: -

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);
    }
}

This gets stuck at STARTTLS and although I am encoding with base64 the user-name and pass-word but it remains stuck there.这会卡在 STARTTLS 上,虽然我用 base64 编码用户名和密码,但它仍然卡在那里。 What wrong am I doing?我做错了什么? Please, help me out.请帮帮我。 Thank you!谢谢! PS: - I am new to Java. PS: - 我是 Java 新手。

I would suggest to rely on the inputStream::available() method for reading the content.我建议依靠inputStream::available()方法来读取内容。 In that way, you may create a helper method like这样,您可以创建一个辅助方法,如

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();
}

Then replace code block然后替换代码块

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

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

In that way you would proceed to the STARTTLS command, but I'm not sure you should send it because own implementation of TLS using plain Sockets is not something you would like to do as a home task.通过这种方式,您将继续执行STARTTLS命令,但我不确定您是否应该发送它,因为使用普通 Sockets 自己实现的 TLS 不是您想要作为家庭任务做的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM