现在的位置: 首页 > 综合 > 正文

利用 POP3 协议和套接字编写接收邮件的程序

2013年01月29日 ⁄ 综合 ⁄ 共 3682字 ⁄ 字号 评论关闭

一、首先了解一下POP3协议:

POP3(Post Office Protocol 3)即邮局协议的第3个版本,它是规定个人计算机如何连接到互联网上的邮件服务器进行收发邮件的协议。它是因特网电子邮件的第一个离线协议标准,POP3协议允许用户从服务器上把邮件存储到本地主机(即自己的计算机)上,同时根据客户端的操作删除或保存在邮件服务器上的邮件,而POP3服务器则是遵循POP3协议的接收邮件服务器,用来接收电子邮件的。POP3协议是TCP/IP协议族中的一员,,由RFC
1939 定义。POP3协议默认端口:110

POP3客户向POP3服务器发送命令并等待响应,POP3命令采用命令行形式,用ASCII码表示。服务器响应是由一个单独的命令行组成或多个命令行组成,响应第一行以ASCII文本+OK或-ERR(OK指成功,-ERR指失败)指出相应的操作状态是成功还是失败。

二、POP3命令码

   命令参数状态描述

  USER username认可此命令与下面的pass命令若成功,将导致状态转换

  PASS password认可

  APOPName,Digest认可Digest是MD5消息摘要

  ------------------------------------------

  STATNone处理请求服务器发回关于邮箱的统计资料,如邮件总数和总字节数

  UIDL[Msg#]处理返回邮件的唯一标识符,POP3会话的每个标识符都将是唯一的

  LIST[Msg#]处理返回邮件数量和每个邮件的大小

  RETR[Msg#]处理返回由参数标识的邮件的全部文本

  DELE[Msg#]处理服务器将由参数标识的邮件标记为删除,由quit命令执行

  RSETNone处理服务器将重置所有标记为删除的邮件,用于撤消DELE命令

  TOP[Msg#]处理服务器将返回由参数标识的邮件前n行内容,n必须是正整数

  NOOPNone处理服务器返回一个肯定的响应

  ------------------------------------------

  QUITNone更新

  a.客户机希望结束这次会话

  b.如果服务器处于‘处理’状态,那么将进入‘更新’状态以删除任何标记为删除的邮件

  c.导致由处理状态到更新状态,又重返认可状态的转变

  d.如果这个命令发出时服务器处于‘认可’状态,则结束会话,不进行‘更新’状态。

三、编程实现:

代码如下:

//================================================================= 
#include <iostream.h> 
#include <winsock2.h>
#define MAXBUF  2048

#pragma comment(lib,"ws2_32.lib")
//================================================
bool InitSock();
char sendbuf[MAXBUF] = { 0 } ;
char name[] = "user abcde@163.com\t\n" ; // pop3 请求头
char pass[] = "pass 123456\t\n" ;
char ret[]  = "retr 1\t\n";
char quit[] = "quit\t\n";  //  
char recvbuf[MAXBUF] = { 0 } ;
int  num = 0;
//=================================================================
void main() 
{
	InitSock();

	struct hostent *phost = gethostbyname("pop3.163.com"); 
	//struct hostent *phost = gethostbyname("pop.qq.com"); 
	// 注意163等的邮件服务器是: pop3.163.com 或者 pop.163.com 都可以,ping的结果看出都一样
	//-----qq邮件 --------------- pop.qq.com

	SOCKET httpsock = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
	if (INVALID_SOCKET == httpsock)
	{
		cout<<"socket error !"<<endl;
		WSACleanup( );
	}
	
	SOCKADDR_IN sock_addr = { 0 } ;
	sock_addr.sin_family  = AF_INET ;
	sock_addr.sin_port    = htons(110) ;
	// sock_addr.sin_addr.S_un.S_addr = inet_addr("119.75.217.109");   //获得的IP地址

        memcpy(&sock_addr.sin_addr.S_un.S_addr , phost->h_addr_list[0] , phost->h_length );
	cout<< "POP3 server IP: " <<inet_ntoa( sock_addr.sin_addr)<<endl;

	int res = connect(httpsock , (sockaddr *)&sock_addr , sizeof(sockaddr));
	if (res == SOCKET_ERROR)
	{
		cout<<"connect error !"<<endl;
		closesocket(httpsock);
		WSACleanup( );
		return ;
	}
	recv(httpsock , recvbuf , MAXBUF , 0);
	cout<<"Client : connect successfully!\nServer : "<<recvbuf<<endl;
	memset(recvbuf , 0 ,MAXBUF);
	


	send( httpsock , name , strlen(name) , 0 ) ;  //--------------------------NAME
	recv(httpsock , recvbuf , MAXBUF , 0);
	cout<<"Client : send name \nServer : "<<recvbuf<<endl;
	memset(recvbuf , 0 ,MAXBUF);

	send( httpsock , pass , strlen(pass) , 0 ) ; //----------------------------PASSWORD
	recv(httpsock , recvbuf , MAXBUF , 0);
	cout<<"Client : send password\nServer : "<<recvbuf<<endl;
    memset(recvbuf , 0 ,MAXBUF);


	send( httpsock , "stat\r\n" , strlen("stat\r\n") , 0 ) ;
	recv(httpsock , recvbuf , MAXBUF , 0);
	cout<<"Client : send stat \nServer : "<<recvbuf<<endl;
	memset(recvbuf , 0 ,MAXBUF);
	// Sleep(20);

	send( httpsock , ret , strlen(ret) , 0 ) ;
	cout<<"Client : send retr 1 \n";
	while (1)
	{		
		num = recv(httpsock , recvbuf , MAXBUF , 0);
		cout<<"Server : "<<recvbuf<<endl;
		memset(recvbuf , 0 ,MAXBUF);
		if (num<=0) 
		{
			break;
		}
	}

	// send( httpsock , "dele 1" , strlen("dele 1") , 0 ) ;

	send( httpsock , quit , strlen(quit) , 0 ) ;
	num = recv(httpsock , recvbuf , MAXBUF , 0);
	cout<<"Client : send quit  \nServer : "<<recvbuf<<endl;
	memset(recvbuf , 0 ,MAXBUF);
	// Sleep(20);

	closesocket(httpsock);

	system("pause");
	
	WSACleanup( );
	
}

//==================================================================
bool InitSock()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	
	wVersionRequested = MAKEWORD( 2, 2 );
	
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {
		
		return false;
	}	
	
	if ( LOBYTE( wsaData.wVersion ) != 2 ||
		HIBYTE( wsaData.wVersion ) != 2 ) {
		WSACleanup( );
		return false;
	}
	return true;		
}

(name和pass数组中的账户和密码可以根据自己实际情况修改)

抱歉!评论已关闭.