欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[分享]利用邮箱实现bug提交和自动检查更新

[分享]利用邮箱实现bug提交和自动检查更新

看了下邮件的发送与接收,了解了这方面知识,写一个帖子。
1、设置捕获


int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE h0, LPTSTR lpCmdLine, int nCmdShow)

 {

     BOOL bRet;

     MSG msg;

     HWND hwndFrame;

  [B][COLOR="Red"]   g_previousFilter = SetUnhandledExceptionFilter(TopLevelExceptionFilter);[/COLOR][/B]

     //_CrtSetBreakAlloc(58);

     InitCommonControls();

     g_hInst = hInst;

     //hModUxTheme = LoadLibrary(L"uxtheme.dll");

     //注册框架窗口类

   //创建框架窗口   

   //消息泵

     //if (hModUxTheme)

     //FreeLibrary(hModUxTheme);

     _CrtDumpMemoryLeaks();

     return (int) bRet;

 } 


2、捕获处理

LONG WINAPI TopLevelExceptionFilter(struct _EXCEPTION_POINTERS *pExceptionInfo)

 {

     SYSTEMTIME time;

     LONG lRet = EXCEPTION_CONTINUE_SEARCH;

     //HRESULT hr ;

     int end;

     GetLocalTime(&time);

     char acBuf[MAX_PATH] = {0};

     // Build a string showing the date and time.

     //Returns the number of characters written to the buffer, excluding any terminating NULL characters. A negative value is returned if an error occurs.

     end = wnsprintfA(acBuf, MAX_PATH, "%d%02d%02d%02d%02d%02d.dmp",time.wYear,

         time.wMonth, time.wDay,time.wHour, time.wMinute,time.wSecond);

     if(end > 0)

     {

         HANDLE hFile;

         char szBugFile[MAX_PATH+1] = {0};

         GetModuleFileNameA(NULL,szBugFile,MAX_PATH + 1);

         PathRemoveFileSpecA(szBugFile);

         PathAppendA(szBugFile,acBuf);

         hFile = CreateFileA(szBugFile,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL); 

         if(hFile == INVALID_HANDLE_VALUE) 

         { 

             ;

             //WriteLog(_T("ExceptionInfo"),_T("CreateFile"),_T("-1"));

         }else{

             BOOL (__stdcall *fnMiniDumpWriteDump)(HANDLE,DWORD,HANDLE,MINIDUMP_TYPE,

                 PMINIDUMP_EXCEPTION_INFORMATION, PMINIDUMP_USER_STREAM_INFORMATION,PMINIDUMP_CALLBACK_INFORMATION); 

             //typedef BOOL (__stdcall *MiniDumpWriteDumpProc)(HANDLE,DWORD,HANDLE,MINIDUMP_TYPE,

             //PMINIDUMP_EXCEPTION_INFORMATION, PMINIDUMP_USER_STREAM_INFORMATION,PMINIDUMP_CALLBACK_INFORMATION);

             HINSTANCE hinstLib; 

             //BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; 

             //MiniDumpWriteDumpProc fnMiniDumpWriteDump;

             hinstLib = LoadLibrary(TEXT("DbgHelp.dll")); 

             if(hinstLib)

             {

                 (FARPROC&)fnMiniDumpWriteDump = ::GetProcAddress(hinstLib, "MiniDumpWriteDump");

                 //fnMiniDumpWriteDump = ( MiniDumpWriteDumpProc)::GetProcAddress(hinstLib, _T("MiniDumpWriteDump"));

                 if(fnMiniDumpWriteDump )

                 {

                     MINIDUMP_EXCEPTION_INFORMATION info;

                     info.ThreadId = ::GetCurrentThreadId();

                     info.ExceptionPointers = pExceptionInfo;

                     info.ClientPointers = FALSE;

                     BOOL bOk = fnMiniDumpWriteDump(::GetCurrentProcess,::GetCurrentProcessId(),hFile,MiniDumpNormal,&info,NULL,NULL);

                     if(bOk == FALSE) 

                         WriteLog(_T("ExceptionInfo"),_T("MiniDumpWriteDump"),_T("error(0x%x)"),GetLastError());

                     HWND hBug = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_BUGDLG), NULL, (DLGPROC)BugDlgProc,(LPARAM)&info);

                     SetWindowLong(hBug,GWL_USERDATA,(LONG)szBugFile);

                     ShowWindow(hBug,SW_NORMAL);

                     BOOL bRet;

                     MSG msg;

                     while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) 

                     { 

                         if (bRet == -1)

                         {

                             // Handle the error and possibly exit

                             break;

                         }

                         else if (!IsWindow(hBug) || !IsDialogMessage(hBug, &msg)) 

                         { 

                             TranslateMessage(&msg); 

                             DispatchMessage(&msg); 

                         } 

                     }

                     lRet = EXCEPTION_EXECUTE_HANDLER;

                 }else

                     WriteLog(_T("ExceptionInfo"),_T("MiniDumpWriteDump"),_T("Failed to get"));

                 FreeLibrary(hinstLib); 

             }else

                 WriteLog(_T("ExceptionInfo"),_T("DbgHelp.dll"),_T("Failed to load"));

         }

         CloseHandle(hFile);

         //SAFE_DELETE(g_pszBugFile);

     }

     //if(g_previousFilter)

     //    return g_previousFilter(pExceptionInfo);

     //else

         return lRet;

 }


3、捕获后用户窗口界面消息处理

INT_PTR CALLBACK BugDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

 {

     switch(uMsg)

     {

     case CTLCOLOR_STATIC:

         {

             if(IDC_LINK == GetDlgCtrlID((HWND)lParam))

             {

                 HBRUSH br = CreateSolidBrush( RGB(255,255,255) );

                 return (INT_PTR)br;

             }

         }

         break;

     case WM_COMMAND:

         switch(LOWORD(wParam))

         {

         case IDC_BTNATTACH:

                 OnBugAddFiles(hWnd);

                 return 0;        

         case IDOK:

             {

                 if(BST_CHECKED == IsDlgButtonChecked(hWnd,IDC_SUBMIT))

                 {

                     BugSendMail(hWnd);

                 }

                 if(BST_CHECKED == IsDlgButtonChecked(hWnd,IDC_REBOOT))

                 {

                     TCHAR pszAppPath[MAX_PATH + 1];

                     GetModuleFileName(NULL,pszAppPath,MAX_PATH + 1);

                     ShellExecute(NULL, NULL,pszAppPath, NULL, NULL, SW_SHOWNORMAL);

                 }

             }

             break;

         case IDCANCEL:

                 DestroyWindow(hWnd);

         }

         break;

     case WM_INITDIALOG:

         {

             CenterWindow(hWnd,NULL);

             MINIDUMP_EXCEPTION_INFORMATION *pInfo = (MINIDUMP_EXCEPTION_INFORMATION*)lParam;

         }

         return TRUE;

     case WM_DESTROY:

         //SAFE_DELETE(g_pszAppPath);

         PostQuitMessage(0); 

         break;

     }

     return FALSE;

 } 

 //这里直接2个附件,多个附件需要改下Smtp类

void BugSendMail(HWND hWnd)

 {

     char acBugFile[MAX_PATH + 1] = {0};

     GetDlgItemTextA(hWnd,IDC_ATTACHFILE,acBugFile,MAX_PATH + 1);

     char* pMoreFile = (char*)GetWindowLong(hWnd,GWL_USERDATA);

     SetCursor( LoadCursor(NULL, IDC_WAIT) );

     Smtp smtp;

     char acount[] = "";

     DWORD dwSize;

     char  sName[MAX_COMPUTERNAME_LENGTH + 1];

     dwSize = MAX_COMPUTERNAME_LENGTH + 1;

     GetComputerNameA(sName, &dwSize);

     if(smtp.Connect("smtp.163.com") && smtp.Login(acount,"...")\

         && smtp.Send(acount,"...@qq.com",sName,"f","...",pData,acBugFile,pMoreFile,0))

         ;

     else MessageBox(NULL,_T("send failed."),_T("bug"),MB_OK|MB_ICONERROR);

     SetCursor( LoadCursor(NULL, IDC_ARROW) );

 }

 void CenterWindow(HWND hWnd,HWND hParent)

 {

     if(hParent == NULL)

         hParent = GetDesktopWindow(); 

     RECT rcParent,rc;

     GetWindowRect(hParent, &rcParent); 

     GetWindowRect(hWnd, &rc); 

     int w = rc.right-rc.left,

         h = rc.bottom-rc.top,

         x = rcParent.right - rcParent.left -w,

         y=rcParent.bottom - rcParent.top -h;

     x = rcParent.left + (long)(x/2.0 + 0.5);

     y = rcParent.top + (long)(y/2.0+0.5);

     SetWindowPos(hWnd, HWND_TOP, x, y, 0, 0,SWP_NOSIZE); 

 } 


5、检查更新

DWORD WINAPI UpdataThreadFunc( LPVOID lpParam )

{

	Pop3 pop;

	g_style |= UPDATA;

	if(pop.Connect("pop.163.com") && pop.Login("xxx@163.com","xxx"))

	{

		int nSize,k = 0,nBufSize = 0;

		int iCount = pop.Stat();

		char *pSubject,*pSubjectEnd,*pUpdataVersion,*szBuf=0;

		const char acUpdataFile[] = "Updataxx";

		const char acVer[] = "Ver=";

		const char acAddr[] = "Addr=";

		const char acSub[] = "\r\nSUBJECT: ";

		for(;iCount > 0 && (g_style & UPDATA);iCount--)

		{

			pSubject=pSubjectEnd=pUpdataVersion = 0;

			nSize = pop.List(iCount);

			if(nSize <= 0) 

				continue;

			if(nBufSize < nSize)

			{

				SAFE_DELETE_ARRAY(szBuf);

				nBufSize = nSize+1;

				szBuf = new char[nBufSize];

			}

			nSize = pop.Retr(iCount,szBuf,nSize);

			if(0 >= nSize)

				continue;

			szBuf[nSize] = 0;

                                                   //里面要放更新的内容,需要自己发邮件到此邮箱,简单的信息写在标题里就可以了然后解析,如xxx|ver=2.00|addr=xxx|xxx

		}

end:

		pop.Disconnect();

		SAFE_DELETE_ARRAY(szBuf);

	}

	g_style &= ~UPDATA;

	OutputDebugString(_T("UpdataThreadFunc return\n"));

	return 0;

}


6、邮件类

#include "Base64.h"

#include <string> 

using namespace std; 

#include <winsock2.h>

#pragma comment(lib,"ws2_32.lib")

extern WORD g_style;

SOCKET InitSocket(WORD wVersionRequired = MAKEWORD(2,2));    // 创建

void ReleaseSocket(SOCKET  hSOCKET);    // 释放Socket

#define BOUNDARY "fang"                // 边界字符串

#define for if(0); else for                        // 变量作用域

//缓冲区大小,这个值必须是57的整数倍!

#define BUFFER_READ 11400

class Smtp  

{

public:

     Smtp();

     virtual ~Smtp();

private:

     SOCKET m_SOCKET;

     LPHOSTENT m_HOSTENT;

     SOCKADDR_IN m_SOCKADDR_IN;

private:

     /*

     功能:

         验证从服务器返回的前三位代码和传递进来的参数是否一样

    备注:

         211 帮助返回系统状态

        214 帮助信息

        220 服务准备就绪

        221 关闭连接

        235 用户验证成功

        250 请求操作就绪

        251 用户不在本地,转寄到其他路径

        334 等待用户输入验证信息

        354 开始邮件输入

        421 服务不可用

        450 操作未执行,邮箱忙

        451 操作中止,本地错误

        452 操作未执行,存储空间不足

        500 命令不可识别或语言错误

        501 参数语法错误

        502 命令不支技

        503 命令顺序错误

        504 命令参数不支持

        550 操作未执行,邮箱不可用

        551 非本地用户

        552 中止存储空间不足

        553 操作未执行,邮箱名不正确

        554 传输失败

    */

     BOOL CheckResponse(const char* RecvCode);

     BOOL SendFile(const char *szFile);

public:

     //接smtp服务器

    BOOL Connect(const char* SmtpAddr);//,const int Port

     //验证用户名和密码

    BOOL Login(const char* Username,const char* Password);

     //发送数据

    BOOL Send(const char* SendFrom,            // 发送地址

                  const char* SendToList,    // 目地地址列表

                  const char* SenderName,            // 发送者姓名

                  const char* ReceiverName,        // 接收者姓名

                  const char* Subject,                // 邮件主题

                  const char* Content,                // 邮件内容

                  const char* File1,        // 附件1

                   const char* File2,        // 附件2

                   BOOL IsHtml);                        // 是否以HTML格式发送

};

#endif

 class Pop3

{

public:

     Pop3();

     virtual ~Pop3();

private:

     BOOL m_bConnected;

     SOCKET m_SOCKET;

     LPHOSTENT m_HOSTENT;

     SOCKADDR_IN m_SOCKADDR_IN;

public:

     BOOL Connect(const char*  ServerAddr,const int Port = 110);

     BOOL CheckResponse(const char* Action, char *pBuf = NULL, int cSize = 0);

     BOOL Login(const char *Username,const char *Password);

     BOOL Disconnect();

     /*(STAT)

     该命令请求服务器返回信箱大小的信息,但是不包过标记为删除的邮件

    Client:STAT

     Server:+OK 2 4065

     服务器的应答包含信箱的数量以及所有邮件的大小。stat命令仅在事务状态时可用的

    */

     int Stat(DWORD *dwTotalSize = NULL);

     BOOL Dele( UINT iIndex );

     int Retr(UINT iIndex,char *Msg, int cMsg);

     /*  列表(LIST) 参数0全部,返回数量=STAT;其他返回大小,否则-1错误

    该命令请求服务器返回一个信箱中特定邮件的大小信息或者没有删除标记的所有邮件的大小信息

    Client: LIST 1

     Server:+OK 1 1046

     该命令有两种使用情形,带参和不带参。List后面如果指定邮件,则返回邮件大小信息,如上所示。  List指定的邮件如果被标识为删除或者不存在,则出错,如下所示:

    Client:LIST 5

     Server:-ERR no such message ,only message 1 thru 1 are present in your inbox

     如果List不带参数,如下所示:

     Client:LIST

     Server将返回多行应答。

    +OK

     1 1045

     2 2204

     .

     应答成功先是相应+OK,接着每一行含有一个邮件号和邮件的大小(字节数),最后是以句点"."作为结束  行。

    */

     int List(int iIndex = 0);

 }; 

#include "mail.h"

#include "..\header.h"

SOCKET InitSocket(WORD wVersionRequired)

 {

     WSADATA WSAData;

     SOCKET  hServer;

     if(WSAStartup(wVersionRequired,&WSAData) == SOCKET_ERROR)

         return SOCKET_ERROR;

     // Create a TCP/IP socket, no specific protocol.

     hServer = socket(AF_INET,SOCK_STREAM,0);

     return hServer;

 }

void ReleaseSocket(SOCKET  hSOCKET)

 {

     if(hSOCKET != SOCKET_ERROR) 

     {

         shutdown( hSOCKET,SD_BOTH);

         closesocket( hSOCKET);

     }

     WSACleanup();

 }

Smtp::Smtp()

 {

 }

Smtp::~Smtp()

 {

     ReleaseSocket(m_SOCKET);

 }

BOOL Smtp::CheckResponse(const char* RecvCode)

 {

     try

     {

         char Buf[1024]={0};

         if(recv(m_SOCKET,Buf,1024,0) == SOCKET_ERROR) 

         {

             WriteLog(_T("bugsend"),_T("CheckRecv"),_T("error:%ld"),WSAGetLastError());

             return false;

         }

         if(RecvCode[0] == Buf[0] && RecvCode[1] == Buf[1] && RecvCode[2] == Buf[2])

             return TRUE;

         WriteLogA("bugsend","CheckRecv",Buf);

         return  false;

     }

     catch(...)

     {

         return false;

     }

 }

BOOL Smtp::Connect(const char*  ServerAddr)//,const int Port

{

     LPSERVENT lpServEntry;

     int  iProtocolPort;

     if((m_SOCKET =InitSocket(MAKEWORD(2,2))) == SOCKET_ERROR)

         return false;

     // Lookup email server's IP address.

     if((m_HOSTENT = gethostbyname(ServerAddr))==NULL)

     {

         return false;

     }

     if(m_HOSTENT->h_addr_list[0] == NULL)

     {

         return false;

     }

     // Get the mail service port.

     lpServEntry = getservbyname( "mail" , 0);

     // Use the SMTP default port if no other port is specified.

     if (lpServEntry == NULL)

         iProtocolPort = htons(IPPORT_SMTP);

     else

         iProtocolPort = lpServEntry->s_port;

     // Setup a Socket Address structure.

     memset(&m_SOCKADDR_IN,0,sizeof(m_SOCKADDR_IN));

     m_SOCKADDR_IN.sin_family = AF_INET;

     m_SOCKADDR_IN.sin_port   = iProtocolPort;//htons(Port)

     m_SOCKADDR_IN.sin_addr.S_un.S_addr = *(ULONG *)m_HOSTENT->h_addr_list[0];

     //连接服务器

    if(connect(m_SOCKET,(sockaddr *)&m_SOCKADDR_IN,sizeof(m_SOCKADDR_IN)) == SOCKET_ERROR)

     {

         return false;

     }

     if(!CheckResponse("220")) return false;

     char szBuf[1024];

     //向服务器发送"HELO "+服务器名

    wnsprintfA(szBuf,1024,"HELO %s\r\n",ServerAddr);

     if(send(m_SOCKET,szBuf,lstrlenA(szBuf),0) == SOCKET_ERROR)    

     {

         return false;

     }

     if(!CheckResponse("250")) return false;

     return true;

 }

BOOL Smtp::Login(const char *Username,const char *Password)

 {

     Base64 base64;

     int iRet;

     //发送"AUTH LOGIN"

     if(send(m_SOCKET,"AUTH LOGIN\r\n",lstrlenA("AUTH LOGIN\r\n"),0) == SOCKET_ERROR)

     {

         return false;

     }

     if(!CheckResponse("334")) return false;

     int iLength = lstrlenA(Username);

     char *szEncode = new char[base64.GetEncodedLength(iLength) + 5];

     char *pEnd = 0;

     //发送经base64编码的用户名

    pEnd = (char*)base64.Encode((unsigned char *)Username,iLength,(unsigned char*)szEncode,0);

     lstrcpyA(pEnd,"\r\n");

     iRet = send(m_SOCKET,szEncode,lstrlenA(szEncode),0);

     SAFE_DELETE_ARRAY(szEncode);

     if(iRet == SOCKET_ERROR)

         return false;

     if(!CheckResponse("334")) return false;

     //发送经base64编码的密码

    iLength = lstrlenA(Password);

     szEncode = new char[base64.GetEncodedLength(iLength) + 5];

     pEnd = (char*)base64.Encode((unsigned char *)Password,iLength,(unsigned char*)szEncode,0);

     lstrcpyA(pEnd,"\r\n");

     iRet = send(m_SOCKET,szEncode,lstrlenA(szEncode),0);

     SAFE_DELETE_ARRAY(szEncode);

     if(iRet == SOCKET_ERROR)

         return false;

     if(!CheckResponse("235")) return false;

     return true;

 }

BOOL Smtp::SendFile(const char *szFile)

 {

     if(szFile == NULL || szFile[0] == '\0') return false;

     Base64 base64;

     char szBuf[1024];

     char *pFileName = PathFindFileNameA(szFile);

     wnsprintfA(szBuf,1024,"--%s\r\n"\

         "Content-Type:application/octet-stream;Name=\"%s\"\r\n"\

         "Content-Disposition:attachment;FileName=\"%s\"\r\n"\

         "Content-Transfer-Encoding:Base64\r\n\r\n"

         ,BOUNDARY,pFileName,pFileName);

     if(SOCKET_ERROR == send(m_SOCKET,szBuf,lstrlenA(szBuf),0))

         return false;

     HANDLE fd;

     fd=CreateFileA(szFile,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

     if(fd == INVALID_HANDLE_VALUE) {

         DisplayError(_T("Create"));

         return FALSE;

     }

     BOOL bRet = FALSE;

     char encode[18000],Buf[BUFFER_READ+1];

     int ccEncode;

     DWORD ReadSize;

     ReadFile(fd,Buf,BUFFER_READ,&ReadSize,0);

     while(ReadSize==BUFFER_READ)

     {

         base64.Encode((unsigned char*)Buf,ReadSize,(unsigned char*)encode,&ccEncode);

         if(send(m_SOCKET,encode,ccEncode,0) == SOCKET_ERROR)

         {

             goto end;

         }

         //memset(Buf,0,BUFFER_READ+1);

         ReadFile(fd,Buf,BUFFER_READ,&ReadSize,0);

     }

     char *pEnd = (char*)base64.Encode((unsigned char*)Buf,ReadSize,(unsigned char*)encode,&ccEncode);

     wnsprintfA(pEnd,5,"\r\n\r\n");

     if(send(m_SOCKET,encode,ccEncode+4,0) == SOCKET_ERROR)

     {

         goto end;

     }

     bRet = TRUE;

end:

     CloseHandle(fd);

     return bRet;

 }

BOOL Smtp::Send(const char* SendFrom,                // 发送地址

                const char* SendTo,    // 目地地址

                const char* SenderName,            // 发送者姓名

                const char* ReceiverName,            // 接收者姓名

                const char* Subject,                // 邮件主题

                const char* Content,                // 邮件内容

                const char* File1,            // 附件1

                 const char* File2,            // 附件2

                 BOOL IsHtml)                        // 是否以HTML格式发送

{

     if(SendFrom == NULL || SendFrom[0] == '\0') return FALSE;

     string strTmp;

     char szBuf[1024];

     //发送MAIL FROM:<abc@xyz.com>

     wnsprintfA(szBuf,1024,"MAIL FROM:<%s>\r\n",SendFrom);

     if(send(m_SOCKET,szBuf,lstrlenA(szBuf),0) == SOCKET_ERROR)

     {

         return false;

     }

     if(!CheckResponse("250")) return false;

     //发送RCPT To:<abc@xyz.com>

     wnsprintfA(szBuf,1024,"RCPT To:<%s>\r\n",SendTo);

     if(send(m_SOCKET,szBuf,lstrlenA(szBuf),0) == SOCKET_ERROR)

     {

         return false;

     }

     if(!CheckResponse("250")) return false;

     //发送"DATA\r\n"

     wnsprintfA(szBuf,1024,"DATA\r\n");

     if(send(m_SOCKET,szBuf,lstrlenA(szBuf),0) == SOCKET_ERROR)

     {

         return false;

     }

     if(!CheckResponse("354")) return false;

     wnsprintfA(szBuf,1024,"From:%s<%s>\r\n"\

         "Subject:%s\r\n"\

         "MIME_Version:1.0\r\n"\

         "X-Mailer:Generator\r\n"\

         "MIME_Version:1.0\r\n"\

         "Content-type:multipart/mixed;Boundary=\"%s\"\r\n\r\n"

         ,SenderName,SendFrom,Subject,BOUNDARY );

     //先将HEADER部分发送过去

    if(send(m_SOCKET,szBuf,lstrlenA(szBuf),0) == SOCKET_ERROR)

     {

         return false;    

     }

     //邮件主体

    wnsprintfA(szBuf,1024,"--%s\r\n"\

         "Content-type:text/%s;Charset=gb2312\r\n"\

         "Content-Transfer-Encoding:8bit\r\n\r\n"

         ,BOUNDARY,IsHtml ? "html" : "plain");

     if(send(m_SOCKET,szBuf,lstrlenA(szBuf),0) == SOCKET_ERROR)

     {

         return false;    

     }

     //将邮件内容发送出去

    if(send(m_SOCKET,Content,lstrlenA(Content),0) == SOCKET_ERROR)

     {

         return false;    

     }

     wnsprintfA(szBuf,1024,"\r\n\r\n");

     if(send(m_SOCKET,szBuf,lstrlenA(szBuf),0) == SOCKET_ERROR)

     {

         return false;    

     }

     /*

     附件处理

    对文件内容分段进行base64编码,编码一小段,传送一小段

    */

     SendFile(File1);

     SendFile(File2);

     //界尾

    wnsprintfA(szBuf,1024,"--"BOUNDARY"--\r\n.\r\n");

     if(send(m_SOCKET,szBuf,lstrlenA(szBuf),0) == SOCKET_ERROR)

     {

         return false;    

     }

     if(!CheckResponse("250")) return false;

     //退出

    wnsprintfA(szBuf,1024,"QUIT\r\n");

     if(send(m_SOCKET,szBuf,lstrlenA(szBuf),0) == SOCKET_ERROR)

     {

         return false;

     }

     if(!CheckResponse("221")) return false;

     return true;

 }

Pop3::Pop3()

 {

     m_bConnected = FALSE;

 }

Pop3::~Pop3()

 {

     if( m_bConnected )

         Disconnect();

     ReleaseSocket(m_SOCKET);

 }

BOOL Pop3::CheckResponse(const char* Action,char* pBuf,int cSize)

 {

     try

     {

         char szBuf[1024];

         int iLength;

         if(pBuf == NULL)

         {

             pBuf = szBuf;

             cSize = 1024;

         }

         iLength = recv(m_SOCKET,pBuf,cSize,0);

         if(iLength == SOCKET_ERROR) 

         {

             WriteLog(_T("updata"),_T("CheckRecv"),_T("error:%ld"),WSAGetLastError());

             return FALSE;

         }

         if (0 == StrCmpNIA(pBuf,"-ERR",4))

         {

             WriteLogA("updata",Action,pBuf);

             return FALSE;     

         }

         return iLength;

     }

     catch(...)

     {

         return false;

     }

 }

BOOL Pop3::Connect(const char*  ServerAddr,const int Port)

 {

     SOCKADDR_IN    SockAddr;

     //SOCKET         hServer;

     //LPSERVENT lpServEntry;

     if((m_SOCKET = InitSocket(MAKEWORD(2,2))) == SOCKET_ERROR)

         return false;

     // Lookup email server's IP address.

     if((m_HOSTENT = gethostbyname(ServerAddr))==NULL)

     {

         return false;

     }

     if(m_HOSTENT->h_addr_list[0] == NULL)

     {

         return false;

     }

     // Setup a Socket Address structure.

     SockAddr.sin_family = AF_INET;

     SockAddr.sin_port = htons(Port);

     SockAddr.sin_addr = *((LPIN_ADDR)*m_HOSTENT->h_addr_list);

     //int nNetTimeout = 30000; //30秒

    //setsockopt(m_SOCKET,SOL_SOCKET,SO_RCVTIMEO,(char* )&nNetTimeout,sizeof(int));

     // Connect the Socket.

     if (connect( m_SOCKET, (PSOCKADDR) &SockAddr, sizeof(SockAddr)) == SOCKET_ERROR)

         return FALSE;

     if(!CheckResponse("connect server")) return false;

     return TRUE;

 }

BOOL Pop3::Login(const char *Username,const char *Password)

 {

     char szBuf[1024];

     wnsprintfA(szBuf,1024,"USER %s\r\n",Username);

     if(send(m_SOCKET,szBuf,lstrlenA(szBuf),0) == SOCKET_ERROR)

         return false;

     if(!CheckResponse("USER")) return FALSE;

         wnsprintfA(szBuf,1024,"PASS %s\r\n",Password);

     if(send(m_SOCKET,szBuf,lstrlenA(szBuf),0) == SOCKET_ERROR)

         return false;

     if(!CheckResponse("PASS")) return FALSE;

     m_bConnected = TRUE;

     return TRUE;

 }

BOOL Pop3::Disconnect()

 {

     //BOOL ret;

     if( !m_bConnected )

         return TRUE;

     // Disconnect gracefully from the server and close the socket

     char szBuf[20];

     lstrcpynA(szBuf,"QUIT\r\n",20);

     send(m_SOCKET,szBuf,lstrlenA(szBuf),0);

     // No need to check return value here.If it fails, the message is available with GetLastError

     m_bConnected = FALSE;

     return CheckResponse("QUIT");

 }

int Pop3::Stat(DWORD *dwTotalSize)

 {

     char szBuf[1024];

     lstrcpynA(szBuf,"STAT\r\n",20);

     send(m_SOCKET,szBuf,lstrlenA(szBuf),0);

     if( !CheckResponse("STAT",szBuf,1024) ) return -1;

     char* pNum =StrPBrkA(szBuf,"0123456789");

     if (pNum == NULL) return -1;

     int sum = strtol(pNum,&pNum,10);

     if(dwTotalSize)

         *dwTotalSize = strtoul(pNum + 1,&pNum,10);

     return sum;

 }

BOOL Pop3::Dele( UINT iIndex )

 {

     char szBuf[1024];

     wnsprintfA(szBuf,20,"DELE %d\r\n",iIndex);

     send(m_SOCKET,szBuf,lstrlenA(szBuf),0);

     return CheckResponse("DELE");

 }

int Pop3::List(int iIndex)

 {

     if(iIndex == 0)

         return Stat();

     char szBuf[1024];

     wnsprintfA(szBuf,20,"LIST %d\r\n",iIndex);

     send(m_SOCKET,szBuf,lstrlenA(szBuf),0);

     if(0 >= CheckResponse("LIST",szBuf,1024) ) return -1;

     int i = 0,size = 0;

     sscanf_s(szBuf,"%*s%d%d",&i, &size);

     return size;

 }

int Pop3::Retr( UINT iIndex,char *Msg, int cMsg)

 {

     if(iIndex <= 0 || Msg == 0 || !(g_style & UPDATA))

         return -1;

     char szBuf[1024];

     int nChars,nHasRev = 0,nDesire = cMsg;

     Msg[0] = '\0';

     wnsprintfA(szBuf,1024,"RETR %d\r\n",iIndex);

     send(m_SOCKET,szBuf,lstrlenA(szBuf),0);

     //Sleep(1000);

     nChars = CheckResponse("RETR",Msg,cMsg);

     while(nDesire > 0 && (g_style & UPDATA))

     {    

         if(nChars < 0){

             // 由于是非阻塞的模式,所以当errno为EAGAIN时,表示当前缓冲区已无数据可读

            // 在这里就当作是该次事件已处理处.

             if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)

                 nDesire = 1;

             else

                 break;

         }

         //else if(nChars == 0)

         //    break;//这里表示对端的socket已正常关闭

        //else if(nChars == nDesire)

         //    nDesire = 1;

         if(nHasRev >= cMsg)//把缓冲区的内容拷完耗尽,免得下次拷到这里的内容

        {

             nChars = recv(m_SOCKET,szBuf,1024,0);

             nDesire = 1024;

         }

         else

         {

             nHasRev += nChars;

             nDesire = cMsg-nHasRev;

             nChars = recv(m_SOCKET,Msg+nHasRev,nDesire,0);        

         }

     }

     return nHasRev;

 }

 #ifndef _BASE64

#define _BASE64

class Base64

{

public:

     /*编码

    DataByte

         [in]输入的数据长度,以字节为单位

    */

     unsigned char* Encode(const unsigned char* Data,int DataByte, unsigned char* strEncode,int *outLength);

     int GetEncodedLength(int iLength);

     /*解码

    DataByte

         [in]输入的数据长度,以字节为单位

    OutByte

         [out]输出的数据长度,以字节为单位,请不要通过返回值计算

        输出数据的长度

    */

     unsigned char* Decode(const char* Data,int DataByte,int& OutByte,unsigned char *strDecode);

 };

#endif #include "Base64.h"

int Base64::GetEncodedLength(const int iLength)

 {

     return ((iLength/3 +1) << 2)+1;

 }

unsigned char* Base64::Encode(const unsigned char* Data,int DataByte,unsigned char* strEncode,int *outLength)

 {

     //编码表

    const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

     unsigned char Tmp[3]={0};

     int LineLength=0,DataByte3 = (int)(DataByte / 3);

     int iLength = 0;

     for(int i=0; i < DataByte3; i++)

     {

         Tmp[0] = *Data++;

         Tmp[1] = *Data++;

         Tmp[2] = *Data++;

         *strEncode++= EncodeTable[Tmp[0] >> 2];

         *strEncode++= EncodeTable[((Tmp[0] << 4) | (Tmp[1] >> 4)) & 0x3F];

         *strEncode++= EncodeTable[((Tmp[1] << 2) | (Tmp[2] >> 6)) & 0x3F];

         *strEncode++= EncodeTable[Tmp[2] & 0x3F];

         iLength += 4;

         if(LineLength+=4,LineLength==76) 

         {

             *strEncode++='\r';

             *strEncode++='\n';

             iLength += 2;

             LineLength=0;

         }

     }

     //对剩余数据进行编码

    int Mod=DataByte % 3;

     if(Mod==1)

     {

         Tmp[0] = *Data++;

         *strEncode++ = EncodeTable[(Tmp[0] & 0xFC) >> 2];

         *strEncode++ = EncodeTable[((Tmp[0] & 0x03) << 4)];

         *strEncode++ = '=';

         *strEncode++ = '=';

         iLength += 4;

     }

     else if(Mod==2)

     {

         Tmp[0] = *Data++;

         Tmp[1] = *Data++;

         *strEncode++ = EncodeTable[(Tmp[0] & 0xFC) >> 2];

         *strEncode++ = EncodeTable[((Tmp[0] & 0x03) << 4) | ((Tmp[1] & 0xF0) >> 4)];

         *strEncode++ = EncodeTable[((Tmp[1] & 0x0F) << 2)];

         *strEncode++ = '=';

         iLength += 4;

     }

     if(outLength) *outLength = iLength;

     return strEncode;

 }

unsigned char* Base64::Decode(const char* Data,int DataByte,int& OutByte, unsigned char* strDecode)

 {

     //解码表

    const char DecodeTable[] =

     {

         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

         62, // '+'

         0, 0, 0,

         63, // '/'

         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'

         0, 0, 0, 0, 0, 0, 0,

         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,

         13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'

         0, 0, 0, 0, 0, 0,

         26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,

         39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'

     };

     int nValue;

     int i= 0;

     while (i < DataByte)

     {

         if (*Data != '\r' && *Data!='\n')

         {

             nValue = DecodeTable[*Data++] << 18;

             nValue += DecodeTable[*Data++] << 12;

             *strDecode++=(nValue & 0x00FF0000) >> 16;

             OutByte++;

             if (*Data != '=')

             {

                 nValue += DecodeTable[*Data++] << 6;

                 *strDecode++=(nValue & 0x0000FF00) >> 8;

                 OutByte++;

                 if (*Data != '=')

                 {

                     nValue += DecodeTable[*Data++];

                     *strDecode++=nValue & 0x000000FF;

                     OutByte++;

                 }

             }

             i += 4;

         }

         else// 回车换行,跳过

        {

             Data++;

             i++;

         }

      }

     return strDecode;

 }

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功