主题:求高手帮解决下判断新邮件的问题。
moonblade
[专家分:120] 发布于 2008-04-12 13:23:00
我写了个小东西,用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个回复)
沙发
orangelegend [专家分:860] 发布于 2008-04-14 00:17:00
我记得pop3协议里面有个stat.
可以查看邮件的信息。
板凳
orangelegend [专家分:860] 发布于 2008-04-14 00:22:00
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 楼
orangelegend [专家分:860] 发布于 2008-04-14 00:23:00
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 楼
moonblade [专家分:120] 发布于 2008-04-14 13:58:00
UIDL [Msg#] 处理 返回邮件的唯一标识符,POP3会话的每个标识符都将是唯一的
这一条看得我很激动~~~
加完了分才看到“楼主加分啊”是这家伙的签名。。。
5 楼
moonblade [专家分:120] 发布于 2008-04-15 08:46:00
oye,解决了。谢谢楼上的大力支持。
做出了一个监测邮件的小东西,当发现新邮件时会有Agent精灵跑出来
6 楼
fxf568 [专家分:0] 发布于 2008-05-08 16:05:00
楼主我也在做相同的东西,我现在一个是遇到你说的不能判断新邮件的问题,还有就是怎么样取得他的附件信息,希望楼主能告诉一下啊
7 楼
moonblade [专家分:120] 发布于 2008-05-09 14:40:00
关于解决检测新邮件的问题,使用的是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 楼
fxf568 [专家分:0] 发布于 2008-05-09 16:57:00
用楼主的办法,新邮件的问题解决了,但是我读取的时候遇到大邮件,或者邮件数量比较多的时候,总是出现“无法从传输连接中读取数据: 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。”这个错误, 不知道有没有解决办法,还有就是邮件解码的问题了,解码太麻烦了
9 楼
moonblade [专家分:120] 发布于 2008-05-09 17:09:00
我也是遇到过这个问题。不知道如何解决。
解码不知道怎么整。因为不止有一种编码。
如果你想做一个可以收发邮件的软件,你可以找一下jmail的内容。
据说很多NB的邮件客户端都是这个做的,里面对于编码解码什么的很强大
10 楼
fxf568 [专家分:0] 发布于 2008-05-10 10:02:00
解码到是还好办,我做的只是在公司内部使用的,专门接受公司邮件服务器上的邮件,所以解码可以固定,现在就是怎么解决连接超时的问题,还有就是怎么取得附件的数量啊,这个上次忽略了,楼主你是怎么解决的啊
我来回复