• 电子邮件发送的原理以及简易实现


        在代码開始之前,我们先手工模拟一遍发送电子邮件的过程。那么接下来的代码你就easy懂多了!

        以下以163邮箱为例!

        

         先键入telnet命令。然后连接到网易的smtpserver,使用25号port.

         

         接着看下图:

    <<<<<<

                  从如今開始。我们能够模拟发送信件的过程了!

         发送命令:EHLO hello  (hello能够随意替换)

         

         然后我们请求登陆!

         发送命令: AUTH LOGIN

         

         然后发送自己账户的username的base64编码(不要@XXX.com)过去!我用的一个測试邮箱it_is_just_a_test@163.com,it_is_just_a_test的base64编码是aXRfaXNfanVzdF9hX3Rlc3Q=

         

          然后将自己的password的base64编码发过去!我的password的base64编码是MTk5MzA3MTRseWg=

         

         server告诉你认证成功了!我们如今就能够发送邮件了!

         先发送邮件说明:MAIL FROM: <it_is_just_a_test@163.com>

         然后发送目的邮箱说明:RCPT TO: <it_is_just_a_test@126.com>

         然后请求发送邮件:DATA     

            然后发送邮件头和邮件体,发送数据:

         From: it_is_just_a_test@163.com

         To: it_is_just_a_test@126.com

         Subject: 測试一下

         MIME-Version: 1.0



         这是一封測试邮件!!! .

         (在正文输入结束时回车输入一个 . (英文输入法下的句号)然后再回车。表示正文部分的结束。这时将显示邮件成功发送的信息。)<CR><LF>表示的是回车

                   

                    当信件发送完毕了之后。我们能够利用quit命令关闭与server的连接!

                    基本原理就是这样了:然后我们来看代码吧!(利用程序发送的时候无非就是把回车换成" "!)

         

    #include <iostream>
    #include <WinSock2.h>
    #include <windows.h>
    #include <string.h>
    using namespace std;
    #pragma  comment(lib, "ws2_32.lib")	/*链接ws2_32.lib动态链接库*/
    const int MAXSIZE = 1024;
    
    int srvPort = 25;
    char srvDomain[256] = "smtp.163.com";
    char userName[256] = "it_is_just_a_test@163.com"; //自己的邮箱名称
    char password[256] = "19930714lyh"; //自己邮箱的密码
    char targetEmail[256] = "it_is_just_a_test@126.com"; //要发送的邮件地址
    char emailTitle[256] = "你好!我是李树花开!

    "; //邮件主题 char content[256] = "这是一封測试邮件!

    非常高兴我的第一个邮件client制作成功了!

    ";//邮件正文 SOCKET CreateConn(char* pWebsite,int port) { //为建立socket对象做准备。初始化环境 SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0); //建立socket对象 SOCKADDR_IN addrSrv; HOSTENT* pHostent; pHostent = gethostbyname(pWebsite); //得到有关于域名的信息 addrSrv.sin_addr.S_un.S_addr = *((DWORD *)pHostent->h_addr_list[0]); //得到smtpserver的网络字节序的ip地址 addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(port); int tf = connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //向server发送请求 if(tf!=0) { return 0; //printf("链接失败 "); } return sockClient; } //int DoWhat是否接受数据 void SendAndRecvMsg( SOCKET sockClient, //client的套接字 char* pMessage, //要发送的消息 int Messagelen, //消息的长度 int DoWhat, //造作的类型 char* recvBuf, //接收的缓冲区 int recvBufLen //缓冲区长度 ) { char lpMessage[256] = {0}; memcpy(lpMessage, pMessage, Messagelen); printf(" %s ", lpMessage); if (DoWhat == 0) { send(sockClient, lpMessage, Messagelen, 0); memset(recvBuf , 0, recvBufLen); DWORD num = recv(sockClient, recvBuf, recvBufLen, 0); //接收数据 printf("%s ", recvBuf); int i = 0; while(i != num) { printf("%02X ", recvBuf[i++]); if((i)%16 == 0) { printf(" "); } } printf(" "); } else if (DoWhat == 1) { send(sockClient, lpMessage, Messagelen, 0); } else if (DoWhat == 2) //不过接收数据 { memset(recvBuf, 0, recvBufLen); DWORD num=recv(sockClient,recvBuf,recvBufLen,0); //接收数据 cout << recvBuf << endl; int i = 0; while(i < num) { printf("%02X ", (byte)recvBuf[i++]); if((i)%16 == 0) { printf(" "); } } printf(" "); } } int GetStrLen(char* pString) //得到字符串的长度 { int i = 0; while(pString[i++] != 0); return i-1; } void StringToBase64(const char *src,char *dst) {/*将字符串变为base64编码*/ int i = 0; char *p = dst; int d= strlen(src) - 3; static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; //for(i=0;i<strlen(src)-3;i+=3) ;if (strlen(src)-3)<0 there is a buf for(i=0;i<=d;i+=3) { *p++ = Base64[((*(src + i)) >> 2) & 0x3f]; *p++ = Base64[(((*(src + i)) & 0x3) << 4) + ((*(src + i + 1)) >> 4)]; *p++ = Base64[((*(src + i + 1) & 0xf) << 2) + ((*(src + i + 2)) >> 6)]; *p++ = Base64[(*(src + i + 2)) & 0x3f]; } if((strlen(src) - i) == 1) { *p++ = Base64[((*(src + i)) >> 2) & 0x3f]; *p++ = Base64[((*(src + i)) & 0x3) << 4]; *p++ = '='; *p++ = '='; } if((strlen(src) - i) == 2) { *p++ = Base64[((*(src + i)) >> 2) & 0x3f]; *p++ = Base64[(((*(src + i)) & 0x3) << 4) + ((*(src + i + 1)) >> 4)]; *p++ = Base64[((*(src + i + 1) & 0xf) << 2)]; *p++ = '='; } *p = ''; } bool FormatEmail(char* pFrom, char* pTo, char* pSubject, char* pMessage, char* Email) {/*格式化要发送的内容*/ lstrcat(Email, "From: "); lstrcat(Email, pFrom); lstrcat(Email, " "); lstrcat(Email, "To: "); lstrcat(Email, pTo); lstrcat(Email, " "); lstrcat(Email, "Subject: "); lstrcat(Email, pSubject); lstrcat(Email, " "); lstrcat(Email, "MIME-Version: 1.0"); lstrcat(Email, " "); lstrcat(Email, " "); lstrcat(Email, pMessage); lstrcat(Email, " . "); return TRUE; } void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2, 1); err = WSAStartup(wVersionRequested, &wsaData); SOCKET sockClient = CreateConn(srvDomain, srvPort); //网易smtp邮箱。25号端口 char buff[MAXSIZE]; memset(buff, 0, sizeof(char) * MAXSIZE); //清零 SendAndRecvMsg(sockClient, 0, 0, 2, buff, MAXSIZE); //接收数据 char UserNameToSendEmail[256] = {0}; sprintf(UserNameToSendEmail, "EHLO %s", "it_is_just_a_test@163.com"); lstrcat(UserNameToSendEmail, " "); SendAndRecvMsg(sockClient, UserNameToSendEmail, GetStrLen(UserNameToSendEmail), 0, buff, MAXSIZE); //既接收也发送 SendAndRecvMsg(sockClient, "AUTH LOGIN ", strlen("AUTH LOGIN "), 0, buff, MAXSIZE); //请求登陆 char pUerName[256] = {0}; //strstr函数搜索一个字符串在还有一个字符串中的第一次出现,并返回第一次出现位置的指针 DWORD p = strstr(userName,"@") - userName; memcpy(pUerName, userName, p); //得到username,如从"13203200199@163.com"得到"13203200199" char base[256]; StringToBase64(pUerName, base); //得到username的base64编码 char str[MAXSIZE]; memset(str, 0, MAXSIZE); sprintf(str, "%s ", base/*"MTMyMDMyMDAxOTk="*/); SendAndRecvMsg(sockClient, str, lstrlen(str), 0, buff, MAXSIZE); //发送username,并接收server的返回 StringToBase64(password, base); memset(str, 0, 1024); sprintf(str, "%s ", base); SendAndRecvMsg(sockClient, str, lstrlen(str),0, buff, MAXSIZE); //发送用户密码。并接收server的返回 char MailFrom[256] = {0}; sprintf(MailFrom, "MAIL FROM: <%s> ", userName); SendAndRecvMsg(sockClient, MailFrom, lstrlen(MailFrom), 0, buff, MAXSIZE); char RcptTo[256] = {0}; sprintf(RcptTo, "RCPT TO: <%s> ", targetEmail); SendAndRecvMsg(sockClient, RcptTo, lstrlen(RcptTo), 0, buff, MAXSIZE); SendAndRecvMsg(sockClient, "DATA ", lstrlen("DATA "), 0, buff, MAXSIZE); char Email[1024] = {0}; FormatEmail(userName, targetEmail, emailTitle, content, Email); SendAndRecvMsg(sockClient,Email,lstrlen(Email), 0, buff, MAXSIZE); SendAndRecvMsg(sockClient,"QUIT ", lstrlen("QUIT "), 0, buff, MAXSIZE); closesocket(sockClient); WSACleanup(); }


  • 相关阅读:
    K短路 (A*算法) [Usaco2008 Mar]牛跑步&[Sdoi2010]魔法猪学院
    [Noi2015]软件包管理器 BZOJ4196
    [SDOI2011]染色 BZOJ2243 树链剖分+线段树
    序列操作 BZOJ2962 线段树
    斜率优化入门学习+总结 Apio2011特别行动队&Apio2014序列分割&HZOI2008玩具装箱&ZJOI2007仓库建设&小P的牧场&防御准备&Sdoi2016征途
    BZOJ1854: [Scoi2010]游戏 二分图
    BZOJ3613: [Heoi2014]南园满地堆轻絮
    BZOJ4590: [Shoi2015]自动刷题机
    [JSOI2008]星球大战starwar BZOJ1015
    Rmq Problem/mex BZOJ3339 BZOJ3585
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/6763887.html
Copyright © 2020-2023  润新知