3

簡単なGmailクライアントを作成しようとしています。問題は、私がかなり奇妙な応答を受け取っていることです。実際、私はまったく応答を得ていませんSslStream.read。最初にクライアントとしてGmailサーバーに接続すると、完全に機能します(Connect()メソッド)が、メールから数を取得しようとすると、再びメソッドを使用SslStream.readするとleerMensaje()、奇妙になり、実行が停止し、Webページがスタックします読み込み中。

これが私が取り組んでいるクラスです:

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

そして、これがメソッドを呼び出すaspxWebページです。

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によってメッセージの終わりも推測しているように見えますが、sslStream.Read(...)このメソッドはストリームが閉じられるまで0を返しません。読み取られるのを待っているデータがこれ以上ない場合は、Read()ブロックされ、さ​​らにデータが到着するのを待ちます。これは、表示されているハングを説明しています。

POP3プロトコルの仕様によると、単一行の応答の場合、応答の終了を示す「\ r \ n」シーケンスと、複数行の応答をもたらすコマンド(メッセージデータの取得など)を待つ必要があります。 )、応答は単一の「。」で終了します。行自体(つまり、行は「。\ r \ n」で始まります)。この終了シーケンスを含むメッセージを処理するための追加のルールがあるため、プロトコル仕様を自分で読むことをお勧めします。

于 2012-04-25T07:19:43.123 に答える