了解POP3协议,使用简单的代码监控pop3邮箱,或者不用代码,直接使用telnet

POP3协议要点 ,更详细的信息可以查看 RFC1939

(1) POP3命令由一个命令和一些参数组成。 所有命令以一个CRLF对结束
(2) 命令和参数由可打印的ASCII字符组成, 它们之间由空格间隔
(3) POP3响应由一个状态码和一个可能跟有附加信息的命令组成。所有响应也是由CRLF对结束
(4) 有两种状态码,"确定" ("+OK")和"失败" ("-ERR")。
(5) 当所有信息发送结束时,发送最后一行,包括一个结束字符(十进制码46,也就是".")和一个CRLF对。
(6) 在POP3协议中有三种状态, 认可状态,处理状态,和更新状态
当客户机与服务器建立联系时,一旦客户机提供了自己身份并成功确认,即由认可状态转入处理状态,在完成相应的操作后客户机发出QUIT命令,则进入更新状态,更新之后最后重返认可状态。如下图

等待连接 身份确认 QUIT命令
—— |认可|————— |处理|——————|更新|
|__________________________________|
重返认可状态

一个最小的,成功的Client-Server会话过程

POP3 Client POP3 Server
Socket() listen()

Connect() -------------------------------> accept()
<------------------------------ +OK 发送确认消息 (进入"确认"状态)

发送USER命令------------------------------>
<----------------------------- +OK 发送确认消息
发送PASS命令------------------------------>
<----------------------------- +OK 发送确认消息 (进入"操作"状态)

发送QUIT命令------------------------------>
<----------------------------- +OK 发送确认消息 (进入"更新"状态)
如果客户在"确认"状态下发送QUIT后,会话并不进入"更新"状态

可以在命令行(cmd.exe)里测试一下:
c:\telnet pop3.163.com 110 //连接网易的邮件服务器
+OK coremail .... //服务器返回+OK
USER 'yourusername' //客户端发出用户名,可能在yourusername上需要一对单引号
PASS 'yourpassword' //客户端发出密码,可能在yourpassword上需要一对单引号
+OK mm nn // 返回邮件数和大小
STAT //得到邮箱的状态
+OK xxx xxx // 返回邮件数和大小

客户可以发出的命令列表以及含义,源自 ChinaUnix

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

Foxmail 和 Outlook 使用 pop3时的异同 源自 LinuxForum.net
假定服务器上有三封邮件等待客户机接收。用foxmail与OE的不同之处在于foxmail每收一封标记删除一封,而Outlook则等全部接收完后再全部标记为删除最后执行quit命令。
Foxmail OutLook
-------------------------------------------
RETR 1 RETR 1
DELE 1 RETR 2
RETR 2 RETR 3
DELE 2 DELE 1
RETR 3 DELE 2
DELE 3 DELE 3
QUIT QUIT
-------------------------------------------
简单的C#代码就可以实现pop3邮箱的监控
namespace Sky.MailMonitor
{

public class Pop3
{
private const int bufsize = 1024 ; // default 1kbytes buffers

// 服务器确认消息的状态码,必须是大写的
private const string OKFlag = " +OK " ;
private const string ERRFlag = " -ERR " ;
private int _port = 110 ;
public int Port
{
get
{
return _port;
}

set
{
_port = value;
}
}
private int mailCount = 0 ;
public int MailCount
{
get
{
return mailCount;
}
set
{
mailCount = value;
}
}

private int mailSpace = 0 ;
public int MailSpace
{
get
{
return mailSpace;
}
set
{
mailSpace = value;
}
}

private Socket socket = null ;
public int port
{
get { return Port; }
}

// step 1: 连接一个POP3服务器,希望得到+OK的确认消息
public void Connect( string hostname)
{
// 建立一个套接字
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

IPHostEntry hostInfo = Dns.GetHostByName(hostname);
IPEndPoint endPoint = new IPEndPoint(hostInfo.AddressList[ 0 ], Port);

socket.Connect(endPoint);
string tmp = RecvLine(); // blocking,wait for '+OK'
Console.WriteLine(tmp);
}
// step 2:发送命令字USER和PASS
public void Login( string username, string password)
{

SendCommand( " USER " + username);
string tmp = RecvLine();
Console.WriteLine( " Server say: {0} " , tmp);

SendCommand( " PASS " + password);
string tmp1 = RecvLine();
Console.WriteLine( " Server say: {0} " , tmp1);
}
// step 3:发送命令字STAT,请求服务器发回关于邮箱的统计资料,如邮件总数和总字节数
// C:STAT
// S:+OK nn mm
// nn是邮件数量,mm是大小
public void Stat()
{
SendCommand( " STAT " );
string tmp = RecvLine();
tmp = tmp.Substring(tmp.IndexOf( " " ) + 1 ); // 在+OK和一个空格之后得到邮件数量,字节数
string tmp1 = tmp.Substring( 0 , tmp.IndexOf( " " )).Trim();
MailCount = Int32.Parse(tmp.Substring( 0 , tmp.IndexOf( " " )).Trim());
Console.WriteLine( " Server say: {0} " , tmp);
// MailSpace = Int32.Parse(tmp1.Substring(0, tmp1.IndexOf(" ")).Trim());
}
// LIST [msg] ,msg参数是可选的, 返回邮件数量和每个邮件的大小,如果没有msg参数,服务器将返回所有的邮件信息
// C:LIST
// S:+OK 187 9703827
// 1 31502
// 2 1168
// 3 1826
// . .
public void List()
{
SendCommand( " LIST " );
string tmp = RecvLine();
Console.WriteLine( " Server say: {0} " , tmp);
}


public void Dele( string mailNumber)
{
SendCommand( " DELE " + mailNumber);
string tmp = RecvLine();
Console.WriteLine( " Server say: {0} " , tmp);
}

public void Quit()
{
SendCommand( " QUIT " );
string tmp = RecvLine();
Console.WriteLine( " Server say: {0} " , tmp);
}

//
// 关闭打开的连接并且发送QUIT命令字,QUIT命令没有参数
public void Close()
{
if (socket == null )
return ;
try
<IMG id=Codehighlighter1_3509_3574_Open_Image onclick="this.style.display='none'; Codehighlighter1_3509_3574_Open_Text.style.display='none'; Codehighlighter1_3509_3574_Closed_Image.style.display='inline'; Codehighlighter1_3509_3574_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockSta

Published At
Categories with Web编程
Tagged with
comments powered by Disqus