简易电子邮件收信的原理以及实现

来源:互联网 发布:自动弹钢琴的软件 编辑:程序博客网 时间:2024/06/05 08:01

          上面一篇已经讲到如何发信了,今天索性来个结尾谈一谈如何发信!

      和前面的流程差不多,我们也手工模拟一次发信流程!

      其实和前面的发信流程差不太多!一样的,我们以网易的邮箱为例!

     我们先要连接到网易的pop邮箱!

     命令为: telnet pop.163.com 110

     意思很明显,要求连接到网易的pop服务器的110号端口.

     

     然后就可以登陆了!

     输入命令:user xxxxx (你的用户名,不用加密)

      如果没有出错的话,系统一般会返回+OK之类的东西.

    然后输入:pass xxxxxx(你邮箱的密码,不加密)

      一样的,如果没有出错的话,系统一般会返回+OK之类的东西.

      

     现在我们就可以操作了!

     虽然可以使用的命令很多,不过最常用的命令只有两个!

      第一个是list命令,用来列出邮件的条目!我们看一下!

      

       表示有19封邮件,右边是邮件大小。

       还有一个命令自然是retr命令了!它用来获取邮件!看我演示:

       

      retr使用规则是 retr + 你要获取的邮件的编号!

      好吧!既然已经说到这份上了,我顺便提一句!服务器发送的大部分内容是用base64加密了的,所以我们看到满屏幕的字母!那么怎么读取出内容呢?这不是这篇文章的重点,所以我们代码采取的方式是直接将服务器发送过来的邮件内容写到文件里,存成.eml文件,然后邮件客户端可以打开这种文件,推荐采用foxmail来打开这种文件!

      最后,不要忘了quit命令,关闭与服务器的连接,这里就不再演示!

      看代码吧!

           pop3.cpp

#include <stdio.h>#include <stdlib.h>#include <string.h>#include "pop3.h"CPop3::CPop3(){WSADATA wsaData;WORD version = MAKEWORD(2, 0);WSAStartup(version, &wsaData);}CPop3::~CPop3(){WSACleanup();}int CPop3::Pop3Recv(char* buf, int len, int flags) {/*接收数据*/int rs;int offset = 0;do {if (offset > len - 2)return offset;rs = recv(m_sock, buf + offset, len - offset, flags);if (rs < 0) return -1;offset += rs;buf[offset] = '\0';}while (strstr(buf, "\r\n.\r\n") == (char*)NULL);return offset;}bool CPop3::Create(   const char* username,//用户名   const char* userpwd,//用户密码   const char* svraddr,//服务器地址   unsigned short port//服务端口   ){strcpy(m_username, username);strcpy(m_userpwd, userpwd);strcpy(m_svraddr, svraddr);m_port = port;return true;}bool CPop3::Connect(){//创建套接字m_sock = socket(AF_INET, SOCK_STREAM, 0);//IP地址char ipaddr[16];struct hostent* p;if ((p = gethostbyname(m_svraddr)) == NULL) //如果得不到服务器信息,就说明出错{return FALSE;}sprintf(ipaddr,"%u.%u.%u.%u",(unsigned char)p->h_addr_list[0][0],(unsigned char)p->h_addr_list[0][1],(unsigned char)p->h_addr_list[0][2],(unsigned char)p->h_addr_list[0][3]);//连接pop服务器struct sockaddr_in svraddr;svraddr.sin_family = AF_INET;svraddr.sin_addr.s_addr = inet_addr(ipaddr);svraddr.sin_port = htons(m_port);int ret = connect(m_sock, (struct sockaddr*)&svraddr, sizeof(svraddr));if (ret == SOCKET_ERROR) {return FALSE;}//接收pop3服务器发来的欢迎信息char buf[128];int rs = recv(m_sock, buf, sizeof(buf), 0);buf[rs] = '\0';printf("%s", buf);if (rs <= 0 || strncmp(buf, "+OK", 3) != 0)  /*服务器没有返回OK就出错了*/{return FALSE;}return TRUE;}bool CPop3::Login(){/*登陆*//*发送用户命令*/char sendbuf[128];char recvbuf[128];sprintf(sendbuf, "USER %s\r\n", m_username);printf("%s", sendbuf);send(m_sock, sendbuf, strlen(sendbuf), 0); //发送用户名int rs = recv(m_sock, recvbuf, sizeof(recvbuf), 0);//接收服务器发来的信息    recvbuf[rs] = '\0';if ( rs <= 0 || strncmp(recvbuf, "+OK", 3) != 0 )  //如果没有"+OK"就说明失败了{return FALSE;}printf("%s", recvbuf);/*发送密码信息*/memset(sendbuf, 0, sizeof(sendbuf));sprintf(sendbuf, "PASS %s\r\n", m_userpwd);send(m_sock, sendbuf, strlen(sendbuf), 0);printf("%s", sendbuf);rs = recv(m_sock,recvbuf, sizeof(recvbuf), 0);recvbuf[rs] = '\0';if (rs <= 0 || strncmp(recvbuf, "+OK", 3) != 0) {return FALSE;}printf("%s", recvbuf);return TRUE;}bool CPop3::List(int& sum){/*发送list命令*/char sendbuf[128];char recvbuf[256];sprintf(sendbuf, "LIST \r\n");send(m_sock, sendbuf, strlen(sendbuf), 0);printf("%s", sendbuf);int rs = recv(m_sock, recvbuf, sizeof(recvbuf), 0);if (rs <= 0 || strncmp(recvbuf, "+OK", 3) != 0){return FALSE;}recvbuf[rs] = '\0';printf("%s", recvbuf);sum = GetMailSum(recvbuf); //得到邮件的数目return TRUE;}bool CPop3::FetchEx(int num){int rs;FILE* fp;int flag = 0;unsigned int len;char filename[256];char sendbuf[128];char recvbuf[20480];/* 发送RETR命令*/sprintf(sendbuf, "RETR %d\r\n", num);send(m_sock, sendbuf, strlen(sendbuf), 0);do {rs = Pop3Recv(recvbuf, sizeof(recvbuf), 0); //接收数据if (rs < 0) {return FALSE;}recvbuf[rs] = '\0';printf("Recv RETR Resp: %s", recvbuf); //输出接收的数据if (flag == 0){itoa(num, filename, 10); //按照序号给文件排名strcat(filename, ".eml");flag = 1;fp = fopen(filename, "wb");//准备写文件}len = strlen(recvbuf);fwrite(recvbuf, 1, len, fp);fflush(fp); //刷新}while (strstr(recvbuf, "\r\n.\r\n") == (char*)NULL);fclose(fp);return TRUE;}bool CPop3::Quit(){char sendbuf[128];char recvbuf[128];/*发送QUIT命令*/sprintf(sendbuf, "QUIT\r\n");send(m_sock,sendbuf, strlen(sendbuf), 0);int rs = recv(m_sock, recvbuf, sizeof(recvbuf), 0);if (rs <= 0 || strncmp(recvbuf, "+OK", 3) != 0){return FALSE;}closesocket(m_sock);return TRUE;}int CPop3::GetMailSum(const char* buf){int sum = 0;char* p = strstr(buf, "\r\n"); if (p == NULL)return sum;p = strstr(p + 2, "\r\n");if (p == NULL)return sum;while ((p = strstr(p + 2, "\r\n")) != NULL) {sum++;}return sum;}
    pop3.h

#include <WinSock2.h>#pragma  comment(lib, "ws2_32.lib")/*链接ws2_32.lib动态链接库*/class CPop3 {public:CPop3();~CPop3();//初始化pop3的属性bool Create(const char* username, const char* userpwd, const char* svraddr, unsigned short port = 110);//连接pop3服务器bool Connect();//登陆的服务器bool Login();//利用list命令得到所有的邮件数目bool List(int& sum);//获得序号为num的邮件bool FetchEx(int num = 1);//退出命令bool Quit();protected:int GetMailSum(const char* buf);SOCKET m_sock;char m_username[32];/*用户名*/char m_userpwd[32];/*密码*/char m_svraddr[32];/*服务器域名*/unsigned short m_port;private:int Pop3Recv(char* buf, int len, int flags = 0);};
      然后用一个主程序测试一下:

    main.cpp

#include <stdio.h>#include "pop3.h"int main(){int sum;CPop3 pop3;char userName[256] = "it_is_just_a_test@163.com";char password[256] = "19930714lyh";char srv[256] = "pop.163.com";pop3.Create(userName, password, srv, 110); pop3.Connect(); //连接pop3服务器pop3.Login();pop3.List(sum);if (sum < 0)printf("You have no letter in box !");for (int i = 1; i <= sum; i++) {pop3.FetchEx(i);}         pop3.Quit();return 0;}

         在VC6下面测试完美通过!然后看看你的工程的文件夹下面,是不是出现了很多.eml文件?这些文件可以用foxmail打开,这就是接收到的邮件!赶快尝试一下吧!

     文章写到这里,建议的收信,写信基本上都已经说明白了,其实你稍微包装一下,就可以写出一段MFC的邮件客户端的代码,加个壳而已!


1 0
原创粉丝点击