回 帖 发 新 帖 刷新版面

主题:求高手帮解决下判断新邮件的问题。

我写了个小东西,用C#访问我的邮箱,能够检测到邮箱里有多少邮件,并且能够访问邮件的内容。 
但是有两个问题: 
1、我无法区分那些邮件是新邮件,比如说,我的程序第一次访问,发现有10份邮件,第二次访问,发现有11分,但是我无法区分那一封是新来的。 
2、我想用邮件到来的日期来区分,但是现在的方法是通过检查整个邮件的内容来获取想要的信息,如果赶上个邮件带个大附件,就很慢很慢,有没有一个只获取邮件到来日期的方法。 
3、如果有更好的方法请告诉我,目的是检测有没有“新”邮件。就是上次检测时没检测到的邮件。 

下面附部分代码: 
      public TcpClient Server;        //用以和服务器建立TCP连接 
        public NetworkStream NetStrm;   //客户机和服务器会话使用的数据流 
        public StreamReader RdStrm;     //用以操作数据流,从数据流中获取从服务器反馈的数据 
        public string Data; 
        public byte[] szData; 
        public string CRLF = "\r\n"; 

 private void RetrieveBtn_Click(object sender, EventArgs e) 
        { 
            Cursor cr = Cursor.Current; 
            Cursor.Current = Cursors.WaitCursor; 
            string szTemp; 
            String[] arrTemp; 
            bool strBody = false; 
            String[] arrRet = new String[10]; 
        //    MessageBox.Show(arrRet[1]); 
            Message.Clear(); 
            //清除邮件内容显示区 
            try 
            { 
                Data = "RETR " + numericUpDown1.Value.ToString() + CRLF; 
                // 定义接收邮箱中的第几封邮件的命令 
                szData = System.Text.Encoding.GetEncoding("gb2312").GetBytes(Data.ToCharArray()); 
                NetStrm.Write(szData, 0, szData.Length); 
                //向服务器发送接收邮件命令 
                szTemp = RdStrm.ReadLine(); 
             //   MessageBox.Show(szTemp); 
                Message.Text=szTemp; 

               if (szTemp[0] != '-') 
                { 
                    //解析接收的邮件内容,并按条目不同显示 
                     
                  while (szTemp != ".") 
                    { 
                        arrTemp = szTemp.Split(":".ToCharArray()); 
                        if (szTemp == "") 
                            strBody = true; 
                        if (arrTemp[0] == "Date") 
                        { arrRet[1] = arrTemp[1]; Message.Text = "发送时间:" + arrRet[1] + CRLF; MessageBox.Show(arrRet[1]); } 
                      //   if (arrTemp[0] == "From")//break; 
                      //      arrRet[2] = arrTemp[1]; 
                     //   if (arrTemp[0] == "To") 
                     //       arrRet[3] = arrTemp[1]; 
                     //   if (arrTemp[0] == "Subject") 
                      //   arrRet[4] = arrTemp[1]; 
                    //    if (strBody) 
                    //       arrRet[5] = arrRet[5] + szTemp; 
                       
                      //     //显示邮件发送时间信息 
                  //    Message.Text = Message.Text + "发送者:" + arrRet[2] + CRLF; 
                       //显示发信人 
                    //     Message.Text = Message.Text + "接收者:" + arrRet[3] + CRLF; 
                         //显示目的地址 
                   //   Message.Text = Message.Text + "主题:" + arrRet[4] + CRLF; 
                         //显示邮件主题 
                     //  Message.Text = Message.Text + "内容:" + arrRet[5] + CRLF; 
                        //显示邮件内容 
                       // 
                        szTemp = RdStrm.ReadLine();  
                    } 
                } /**/ 
                Cursor.Current = cr; 
             //  RdStrm.Close(); 
                //回复光标 
            } 
            catch (InvalidOperationException err) 
            { 
                statusBar1.Text = "错误: " + err.ToString(); 
            } 
        }

回复列表 (共11个回复)

沙发

我记得pop3协议里面有个stat.
可以查看邮件的信息。

板凳

POP3还支持另外两个命令。这两个命令是:LIST和NOOP。LIST命令可用来列出邮件的信息。就象下面所显示的一样:

Client:LIST
Server:+OK2messages(320octets)
Server:1120
Server:2200
Server:.

通过对LIST命令提供邮件索引号,可列出特定邮件的信息,如下例:

Client:LIST2
Server:+OK2200

NOOP命令具体的事情不做,只是用来检查同服务器的连接。

UPDATE状态

当你处于UPDATE状态时,你只有一个命令可用,那就是:QUIT。用这个命令来确认你所做的所有改变,删除被标上删除标记的邮件以及关闭连接。


这里写的是list,我记得是stat,stat是获取单个邮件的具体信息。

3 楼

6. POP3命令码如下: 
命令 参数 状态 描述 
------------------------------------------ 
USER username 认可 此命令与下面的pass命令若成功,将导致状态转换 
PASS password 认可 
APOP Name,Digest 认可 Digest是MD5消息摘要 
------------------------------------------ 
STAT None 处理 请求服务器发回关于邮箱的统计资料,如邮件总数和总字节数 
UIDL [Msg#] 处理 返回邮件的唯一标识符,POP3会话的每个标识符都将是唯一的 
LIST [Msg#] 处理 返回邮件数量和每个邮件的大小 
RETR [Msg#] 处理 返回由参数标识的邮件的全部文本 
DELE [Msg#] 处理 服务器将由参数标识的邮件标记为删除,由quit命令执行 
RSET None 处理 服务器将重置所有标记为删除的邮件,用于撤消DELE命令 
TOP [Msg#] 处理 服务器将返回由参数标识的邮件前n行内容,n必须是正整数 
NOOP None 处理 服务器返回一个肯定的响应


保存UIDL链表或数组,逐一比较。

4 楼

UIDL [Msg#] 处理 返回邮件的唯一标识符,POP3会话的每个标识符都将是唯一的 
这一条看得我很激动~~~
加完了分才看到“楼主加分啊”是这家伙的签名。。。

5 楼

oye,解决了。谢谢楼上的大力支持。
做出了一个监测邮件的小东西,当发现新邮件时会有Agent精灵跑出来

6 楼

楼主我也在做相同的东西,我现在一个是遇到你说的不能判断新邮件的问题,还有就是怎么样取得他的附件信息,希望楼主能告诉一下啊

7 楼


关于解决检测新邮件的问题,使用的是orangelegend的回帖中提到的UIDL [Msg#] 处理 返回邮件的唯一标识符,POP3会话的每个标识符都将是唯一的 这一条。检测邮件时逐个的访问每个邮件的msg属性。返回的值是“+OK 编号 XXXXXXXXX”,其中前面一块都是固定的,后面的是唯一标识符。我是把这个记录到一个ini里,如果ini里有这个标识符的纪录,那么就说明这是一个老邮件了。

        private void CheckMail()
        {
            if (!CKMail)
                return;
            bool AgTip = false;
            time1 = System.DateTime.Now;
            int NowMails = usermail.Connect(UserData);
            if (NowMails > 0)
            {
                for (int MNum = 1; MNum <= NowMails;MNum++ )
                {
                    //获取唯一值
                    string MKey = usermail.GetKey(MNum);
                    //判断,如果是新邮件就记录
                    if ((MKey != "Error") && (UMSG.OldNew(MKey) == ""))
                    {
                        //记录
                        UMSG.AddNew(MKey);
                        AgTip = true;
                    }
                }
            } 
            if (NowMails != -255)
            {
                usermail.Disconnec(); 
            }

            if (AgTip)
                Agform.AgTips();
        }


       /// <summary>
        /// 获取指定邮件的唯一POP3标识
        /// </summary>
        /// <param name="MNum">邮件序号</param>
        /// <returns></returns>
        public string GetKey(int MNum)
        {
            string szTemp;
            String[] arrTemp;;
            String[] arrRet = new String[10];
            int cut = MNum / 10 + 6;
            try
            {
                string Get = "UIDL " + MNum + CRLF;
                // 定义接收邮箱中的第几封邮件的命令
                szData = System.Text.Encoding.GetEncoding("gb2312").GetBytes(Get.ToCharArray());
                NetStrm.Write(szData, 0, szData.Length);
                //向服务器发送接收邮件命令
                szTemp = RdStrm.ReadLine();
                //Key
                arrTemp = szTemp.Split(":".ToCharArray());
                //处理字符 err
                return arrTemp[0].Remove(0,cut);
            }
            catch (InvalidOperationException)
            {
                return "Error";
            }

        }

至于附件,我没考虑这个。因为我是配合livemail使用来弥补livemail邮件提示不明显的缺点,因此就只用来提示有没有新邮件。毕竟现在成熟的邮件收发程序太多了,有好用的干嘛不用呢。

8 楼

用楼主的办法,新邮件的问题解决了,但是我读取的时候遇到大邮件,或者邮件数量比较多的时候,总是出现“无法从传输连接中读取数据: 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。”这个错误, 不知道有没有解决办法,还有就是邮件解码的问题了,解码太麻烦了

9 楼

我也是遇到过这个问题。不知道如何解决。
解码不知道怎么整。因为不止有一种编码。
如果你想做一个可以收发邮件的软件,你可以找一下jmail的内容。
据说很多NB的邮件客户端都是这个做的,里面对于编码解码什么的很强大

10 楼

解码到是还好办,我做的只是在公司内部使用的,专门接受公司邮件服务器上的邮件,所以解码可以固定,现在就是怎么解决连接超时的问题,还有就是怎么取得附件的数量啊,这个上次忽略了,楼主你是怎么解决的啊

我来回复

您尚未登录,请登录后再回复。点此登录或注册