java - Java 中的 IMAP 客户端(仅限套接字)在接收时挂起

标签 java sockets imap

我想实现一个简单的 IMAP 客户端。我可以连接到服务器,接收其问候语,但似乎在 login 命令后接收响应时遇到问题。

我知道在 IMAP 行中以 \r\n.\r\n 结尾,但似乎一次读取一个字节在这里不起作用,我不知道为什么。

我的代码:

class NewClass {

    public static String readAll(Socket socket, String end) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String line;

        while (!sb.toString().endsWith(end))
        {
            char c = (char)reader.read();
            sb.append(c);
        }
        return sb.toString();
    }

    public static void main(String[] args) throws IOException {
        String host = "x.x.x.x";
        int port = 143;

        Socket socket = new Socket(host, port);

        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);

        // server's greeting
        String initreply = readAll(socket, "\r\n");
        System.out.println(initreply);

        // log me in
        String login_cmd = "A1 LOGIN user pass\r\n";
        writer.print(login_cmd);
        writer.flush();
        String loginreply = readAll(socket, "\r\n");
        System.out.println(loginreply);

    }
}

最佳答案

IMAP 没有什么简单,它是一个非常复杂的协议(protocol),需要从头开始实现。考虑寻找预先存在的 IMAP 库。

话虽如此,很明显您没有阅读 IMAP 规范,RFC 3501 (特别是 section 2.2 "Commands and Responses" ),否则您就会知道代码失败的原因。您的代码不符合规范。

特别是:

  1. 您没有在 LOGIN 命令末尾发送尾随 \r\n,因此服务器不会发送任何响应。 PrintWriter.print() 不打印换行符。 PrintWriter.println() 可以,但它只打印 LF,但 IMAP 使用 CRLF。因此,您需要在发送到服务器的每个命令的末尾包含 \r\n

  2. 您根本没有正确读取服务器响应。您必须读取行,同时考虑 *+ 标记,直到您收到以相同 A1 开头的行 标签,用于标记 LOGIN 命令。如果您使用 BufferedReader.readLine() 而不是将字符单独读取到 StringBuilder 中,则逻辑会更容易实现。从技术上讲,您应该异步进行读取,例如在后台线程中,因为 IMAP 是异步协议(protocol)。一次可以有多个命令在运行,并且服务器可以在命令响应之间发送未经请求的数据。响应中的标签告诉您正在响应哪些命令(如果有)。以 * 标记为前缀的未标记响应应按原样处理,无论哪个命令生成它们。

关于java - Java 中的 IMAP 客户端(仅限套接字)在接收时挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43350870/

相关文章:

java - 如何根据多个参数过滤Web服务结果?

java - 显示 JFrame 时获取另一个 JFrame 的数据

c++ - 使用 MsDev 将 linux 套接字应用程序移植到 windows

IMAP - 编辑草稿或现有消息?

delphi - 如何下载消息、存储它并在不同的文件夹中重新创建它?

java - 在 Wicket 中为下载链接设置超时?

java - 如何部署tomcat7-maven-plugin?

python - 在Python中使用ZMQ在客户端/服务器配置中进行嗅探器/监视

sockets - Python 3.x socket.error : [Errno 10013] An attempt was made to access a socket in a way forbidden by its access permissions

java - 无法使用 javax.mail 从 google 获取草稿、垃圾邮件和垃圾文件夹中的电子邮件