3

我正在尝试做一个简单的 Gmail 客户端。问题是我得到了一个非常奇怪的回应。实际上我根本没有得到回应SslStream.read。首先,当我作为客户端连接到 gmail 服务器时,它可以正常工作(Connect()方法),但是当我尝试从电子邮件中获取号码时,再次使用SslStream.readwithleerMensaje()方法时,它变得很奇怪并且停止运行,并且网页卡住了加载。

这是我正在学习的课程:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Text;
using System.Net.Mail;

namespace GmailClient
{
    public class GmailPop
    {
        private SslStream sslStream;
        private String user;
        private String pass;

        public GmailPop(String user, String pass)
        {
            this.user = user;
            this.pass = pass;
        }

        public bool Connect()
        {
            String response;
            byte[] buffer = new byte[2048];
            int bytes = -1;
            TcpClient server = new TcpClient("pop.gmail.com", 995);
            sslStream = new SslStream(server.GetStream());
            sslStream.AuthenticateAsClient("pop.gmail.com");
            bytes = sslStream.Read(buffer, 0, buffer.Length);
            response = Encoding.ASCII.GetString(buffer,0,bytes);
            sslStream.Write(Encoding.ASCII.GetBytes("USER recent:" + user+"\r\n"));
            bytes = sslStream.Read(buffer, 0, buffer.Length);
            response = Encoding.ASCII.GetString(buffer,0,bytes);
            if(response.StartsWith("+OK")){
                sslStream.Write(Encoding.ASCII.GetBytes("PASS "+pass+"\r\n"));
                bytes = sslStream.Read(buffer,0,buffer.Length);
                response = Encoding.ASCII.GetString(buffer, 0, bytes);
                return response.StartsWith("+OK");
            }
            return false;
        }
        public int numCorreos()
        {
            String res = escribirLeer("STAT");
            String[] resA = res.Split(' ');
            int num = Int32.Parse(resA[1]);
            return num;
        }
        public String leerMensaje()
        {
            int bytes = -1;
            byte[] buffer = new byte[2048];
            String msg = "";
            do
            {
                bytes = sslStream.Read(buffer, 0, buffer.Length);
                msg += Encoding.ASCII.GetString(buffer, 0, bytes);
            } while (bytes != 0);
            return msg;
        }
        public void escribirMsg(String msg)
        {
            byte[] buffer = Encoding.ASCII.GetBytes(msg);
            sslStream.Write(buffer);
            sslStream.Flush();
        }
        public String escribirLeer(String msg)
        {
            escribirMsg(msg);
            String respuesta = leerMensaje();
            return respuesta;
        }
    }
}

这是调用该方法的aspx网页:

GmailPop client;
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Session["user"] != null && Session["pass"] != null)
            {
                String user = Session["user"].ToString();
                String pass = Session["pass"].ToString();

                client = new GmailPop(user, pass);

                if (client.Connect())
                {                    
                    Session["active"] = true;
                    Response.Write(numCorreos());
                }
                else
                {
                    Session.Remove("pass");
                    Response.Redirect("login.aspx?error=login");
                }
            }
            else
            {
                Response.Redirect("login.aspx");
            }
        }
    }
4

1 回答 1

2

第一个问题是您将“STAT”作为命令发送,但所有命令都必须以“\r\n”结尾,因此您需要发送“STAT\r\n”。

看来您还通过 0 from 的返回码推断消息的结尾sslStream.Read(...),但是在流关闭之前,此方法不会返回 0。在没有更多数据等待读取的情况下,Read()将阻塞,等待更多数据到达,这解释了您所看到的挂起。

根据POP3 协议规范,对于单行响应,您应该等待一个“\r\n”序列来指示响应的结束,以及那些导致多行响应的命令(例如检索消息数据),响应由单个“。”终止。单独一行(即该行以“.\r\n”开头)。处理包含此终止序列的消息还有其他规则,因此我建议您自己阅读协议规范。

于 2012-04-25T07:19:43.123 回答