一、首先瞭解一下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.comSOCKET 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 ) ; //--------------------------NAMErecv(httpsock , recvbuf , MAXBUF , 0);cout<<"Client : send name \nServer : "<<recvbuf<<endl;memset(recvbuf , 0 ,MAXBUF);send( httpsock , pass , strlen(pass) , 0 ) ; //----------------------------PASSWORDrecv(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數組中的賬戶和密碼可以根據自己實際情況修改)