




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第8章郵件接收和發(fā)送客戶端郵件接收和發(fā)送客戶端的作用是在本地計算機和遠程計算機之間傳送電子信件以及接收電子信件。用戶平時所用的Foxmail就是一種郵件接收和發(fā)送客戶端。通常情況下,F(xiàn)oxmail由發(fā)送者將電子信件發(fā)送到郵件效勞器〔SMTP〕中,再由SMTP效勞器將該郵件發(fā)送到POP3〔接收郵件〕效勞器中,郵件接收者通過賬戶和口令再從POP3效勞器中獲取信件。在本章中,將向用戶介紹郵件接收和發(fā)送客戶端的原理以及開發(fā)過程。8.1調(diào)用Windows自帶的郵件發(fā)送程序一般情況下,用戶所使用的Windows操作系統(tǒng)中都帶有默認的郵件發(fā)送程序。通過該郵件發(fā)送程序,用戶可以將郵件發(fā)送到任何目的地址。這種方法比較簡單適用,所以很受大局部用戶歡送。用戶可以在操作系統(tǒng)中,使用操作系統(tǒng)命令翻開郵件程序。如果用戶需要在自己的程序中調(diào)用系統(tǒng)自帶的郵件程序,那么需要使用函數(shù)CreateProcess()或者ShellExecute()進行調(diào)用。下面將分別介紹這兩種方法。8.1.1調(diào)用Windows自帶程序在Windows操作系統(tǒng)中,所有的程序都是以進程為單位運行。本節(jié)中所講述的調(diào)用郵件發(fā)送程序就是通過調(diào)用相應的Windows進程實現(xiàn)的。調(diào)用該Windows進程所使用的命令是“mailto:+string”,其中,string表示郵件發(fā)送的目的地址。例如,用戶需要將郵件發(fā)送到郵件地址為的郵箱中,使用的命令是“”。首先,在Windows系統(tǒng)界面下選擇“開始”|“運行”命令,彈出“運行”對話框,如圖8.1所示。圖8.1“運行”對話框然后,在運行對話框中輸入命令“”,可以翻開Windows自帶的郵件發(fā)送程序進行郵件發(fā)送,如圖8.2所示。圖8.2
Windows郵件收發(fā)器以上過程是用戶通過Windows命令調(diào)用郵件收發(fā)器必須做的。實際上,除了這種方法,用戶還可以在程序中通過函數(shù)調(diào)用Windows郵件收發(fā)器。此種方法將在節(jié)中進行講解。8.1.2CreateProcess()函數(shù)在VC中編程,MFC類庫已經(jīng)提供了幾個庫函數(shù)用于調(diào)用Windows的外部程序,包括郵件收發(fā)程序。在本節(jié)中,將向用戶介紹其中的兩個函數(shù)CreateProcess()和ShellExecute()。1.使用CreateProcess()函數(shù)CreateProcess()函數(shù)可以創(chuàng)立Windows進程,同時也可以調(diào)用已經(jīng)存在的進程。該函數(shù)的原型如下:BOOLCreateProcess(LPCTSTRlpApplicationName,LPTSTRlpCommandLine,LPSECURITY_ATTRIBUTESlpProcessAttributes,LPSECURITY_ATTRIBUTESlpThreadAttributes,BOOLbInheritHandles,DWORDdwCreationFlags,LPVOIDlpEnvironment,LPCTSTRlpCurrentDirectory,LPSTARTUPINFOlpStartupInfo,LPPROCESS_INFORMATIONlpProcessInformation);該函數(shù)創(chuàng)立進程成功那么返回true,否那么返回false。其參數(shù)意義如下:參數(shù)lpApplicationName表示可執(zhí)行文件的名字。用戶指定該參數(shù)后,該函數(shù)會在當前路徑下搜索可執(zhí)行文件,但不會按照系統(tǒng)的搜索路徑進行搜索。注意:使用該參數(shù)時,需要加上擴展名,因為系統(tǒng)不會自動為其添加“.exe”后綴名。參數(shù)lpCommandLine表示將要傳遞到新進程的命令行字符串。使用該參數(shù)時,該函數(shù)會自動為其添加后綴名“.exe”。如果參數(shù)字符串沒有指定所在路徑,那么該函數(shù)那么會按照系統(tǒng)的搜索路徑進行搜索文件。參數(shù)bInheritHandles表示該進程創(chuàng)立的子進程是否能繼承父進程的對象句柄。參數(shù)lpStartupInfo指向結(jié)構(gòu)體STARTUPINFO的指針變量。該結(jié)構(gòu)體的聲明如下:typedefstruct_STARTUPINFO{DWORDcb; //表示該結(jié)構(gòu)體的大小LPTSTRlpReserved; //保存,必須將該參數(shù)初始化為NULLLPTSTRlpDesktop; LPTSTRlpTitle; //設(shè)置控制臺程序的名稱 DWORDdwX; //設(shè)置應用程序窗口的X坐標DWORDdwY; //設(shè)置應用程序窗口的Y坐標DWORDdwXSize; //設(shè)置應用程序窗口的橫向大小DWORDdwYSize; //設(shè)置應用程序窗口的縱向大小DWORDdwXCountChars; //以字符為單位設(shè)置應用程序窗口的X坐標DWORDdwYCountChars; //以字符為單位設(shè)置應用程序窗口的Y坐標DWORDdwFillAttribute; //設(shè)置應用程序窗口所使用的背景色等DWORDdwFlags; //表示創(chuàng)立窗口的標志W(wǎng)ORDwShowWindow; //是否顯示應用程序窗口WORDcbReserved2; //保存,將該參數(shù)必須設(shè)置為0LPBYTElpReserved2; //保存,將該參數(shù)必須設(shè)置為0HANDLEhStdInput; //設(shè)置控制臺程序的輸入輸出緩存句柄HANDLEhStdOutput; HANDLEhStdError; //錯誤輸出句柄}STARTUPINFO,*LPSTARTUPINFO;該結(jié)構(gòu)體主要用于保存新創(chuàng)立進程的窗口信息,如窗口的大小或窗口的顯示方式等。其中,參數(shù)dwFlags標識了窗口創(chuàng)立成功以后,在顯示之前以何種方式進行顯示。其取值如表8.1所示。表8.1程序窗口顯示標志取值注意:在表8.1中所示的程序窗口顯示標志的作用僅僅是為了控制相應的成員變量是否有效而已。例如,用戶在程序中,需要使用到該結(jié)構(gòu)體中的dwFillAttribute成員。那么,用戶必須將參數(shù)dwFlags取值為STARTF_USEFILLATTRIBUTE。否那么,該成員變量將無效。參數(shù)lpProcessInformation是指向結(jié)構(gòu)體PROCESS_INFORMATION的指針變量。該結(jié)構(gòu)體聲明如下:typedefstruct_PROCESS_INFORMATION{HANDLEhProcess; //進程句柄HANDLEhThread; //線程句柄DWORDdwProcessId; //進程IDDWORDdwThreadId; //線程ID}PROCESS_INFORMATION;取
值含
義STARTF_USESIZE使用dwXSize和dwYSize成員STARTF_USESHOWWINDOW使用wShowWindow成員STARTF_USEPOSITION使用dwX和dwY成員STARTF_USECOUNTCHARS使用dwXCountChars和dwYCountChars成員STARTF_USEFILLATTRIBUTE使用dwFillAttribute成員STARTF_USESTDHANDLES使用hStdInput、hStdOutput、hStdError成員STARTF_RUN_FULLSCREEN以全屏方式啟動程序該結(jié)構(gòu)體主要用于保存進程的相關(guān)信息。其他參數(shù)均可以默認設(shè)置為NULL。例如,調(diào)用操作系統(tǒng)的記事本程序。代碼如下:01 ...//省略局部代碼02 STARTUPINFOsi={sizeof(si)}; //定義結(jié)構(gòu)體變量03 PROCESS_INFORMATIONpi; //定義結(jié)構(gòu)體對象04 CString*str="notepad”; //記事本名稱05 CreateProcess(NULL,str,NULL,NULL,false,NULL,NULL,NULL,&si,&pi);06 //調(diào)用函數(shù)翻開記事本程序07 ...//省略局部代碼同樣的道理,用戶在本例中,也可以使用函數(shù)CreateProcess()調(diào)用郵件收發(fā)程序。代碼如下:01 ...//省略局部代碼02 STARTUPINFOsi={sizeof(si)}; //定義結(jié)構(gòu)體變量03 PROCESS_INFORMATIONpi; 04 CString*str="mailto:lymlrl@163"; //翻開郵件程序的系統(tǒng)命令05 CreateProcess(NULL,str,NULL,NULL,false,NULL,NULL,NULL,&si,&pi); 06 //調(diào)用函數(shù)翻開記事本程序07 ...//省略局部代碼2.使用ShellExecute()函數(shù)在MFC編程中,除了函數(shù)CreateProcess()以外,還可以調(diào)用函數(shù)ShellExecute()實現(xiàn)相同的功能。該函數(shù)原型如下:HINSTANCEShellExecute(HWNDhwnd, //父窗口句柄LPCTSTRlpOperation, //將要進行的操作形式LPCTSTRlpFile, //目錄文件名稱或文件路徑LPCTSTRlpParameters, //傳遞的參數(shù)LPCTSTRlpDirectory, //一般為NULLINTnShowCmd //顯示方式);該函數(shù)執(zhí)行成功會返回調(diào)用程序的應用程序指針,否那么返回錯誤代碼。局部錯誤代碼如表8.2所示。表8.2局部錯誤代碼錯誤代碼意
義ERROR_FILE_NOT_FOUND找不到相應文件ERROR_PATH_NOT_FOUND找不到所需路徑ERROR_BAD_FORMAT無效的.exe文件SE_ERR_ASSOCINCOMPLETE無效的文件名0操作系統(tǒng)的內(nèi)存溢出該函數(shù)各個參數(shù)的說明已在函數(shù)原型中標出。使用該函數(shù)調(diào)用操作系統(tǒng)自帶的郵件發(fā)送程序,代碼如下:以上代碼是使用C語言編寫,并且使用命令行窗口界面,目的是為了讓用戶了解整個調(diào)用過程。在隨書光盤的第8章中附有代碼,請用戶自行參考。此段代碼在VC中編譯后的結(jié)果,如圖8.3所示。用戶在運行界面1中輸入字符Y或y,然后按下Enter鍵。程序提示郵件程序正在翻開,當郵件程序翻開以后,實例程序會提示已經(jīng)翻開郵件程序,如圖8.4所示。圖8.3運行界面1圖8.4運行界面2注意:在程序中為了模擬計算機的工作,所以筆者使用了while循環(huán)產(chǎn)生時間差,僅僅是為了讓用戶重復了解該調(diào)用過程。在實際編程中,不提倡使用該方法產(chǎn)生時間差,因為這種方法很危險,容易造成系統(tǒng)的崩潰。通常,使用多線程編程的方法比較平安,也是筆者竭力推薦的一種方法。該類方法將在后面的相關(guān)章節(jié)中講述。8.2SMTP會話過程SMTP是發(fā)送郵件協(xié)議,與前面所講的FTP、HTTP等協(xié)議一樣被用作某種行為的標準標準。本節(jié)的主要內(nèi)容就是向用戶講解郵件客戶端怎么連接SMTP效勞器以及向SMTP效勞器發(fā)送信件等操作。8.2.1怎么連接效勞器在網(wǎng)絡中傳輸郵件信息都是基于TCP/IP協(xié)議的,所以用戶在Windows操作系統(tǒng)中編寫郵件發(fā)送程序時可以使用Windows套接字來完成。一般情況下,客戶端連接效勞器的幾個步驟如下?!?〕客戶端指定IP地址和端口連接效勞器?!?〕效勞器收到連接請求,并同意客戶端連接請求?!?〕客戶端和效勞器互相發(fā)送數(shù)據(jù)?!?〕關(guān)閉效勞器和客戶端的套接字?;谝陨蠋讉€步驟,用戶可以VC中編寫程序?qū)崿F(xiàn)郵件客戶端。1.創(chuàng)立套接字對象該實例與一般網(wǎng)絡程序一樣,需要Windows套接字的支持,所以用戶應該首先初始化套接字庫。代碼如下:01
BOOLCMyEMAIL::OnInitDialog()02
{03
WSADATA
data;04
WORD
ss=MAKEWORD(2,0);
//指定套接字庫版本05
::WSAStartup(ss,&data);
//初始化套接字庫06
}用戶初始化套接字庫以后,還必須記得在程序退出之前釋放該套接字庫。代碼如下:01
voidCMyEMAIL::OnClose()02
{03
::WSACleanup();
//釋放已經(jīng)加載的套接字庫04
}然后,用戶可以調(diào)用API函數(shù)socket()創(chuàng)立連接效勞器的套接字了。代碼如下:在代碼中,函數(shù)socket()創(chuàng)立了基于TCP通信的流式套接字句柄。2.連接效勞器用戶創(chuàng)立好套接字以后,可以調(diào)用API函數(shù)connect()連接效勞器。其原型如下:intconnect(SOCKET s,conststructsockaddrFAR* name,int namelen);該函數(shù)用于連接遠程計算機,如果連接失敗那么返回–1,否那么成功。參數(shù)及其意義如下:參數(shù)s表示將要連接效勞器的套接字句柄,該套接字是用戶之前已經(jīng)創(chuàng)立好的套接字句柄。參數(shù)name是指向套接字地址結(jié)構(gòu)體的指針變量。該套接字結(jié)構(gòu)體聲明如下:structsockaddr_in{
shortsin_family;
u_shortsin_port;
structin_addrsin_addr;
charsin_zero[8];};該結(jié)構(gòu)體是sockaddr結(jié)構(gòu)的擴充結(jié)構(gòu),一般被用在WindowsSocket2中。參數(shù)namelen表示套接字結(jié)構(gòu)對象的大小。使用該函數(shù)在套接字s上連接SMTP效勞器。例如,SMTP效勞器地址為“”,端口為25。代碼如下:通過上面的代碼,用戶已經(jīng)向SMTP效勞器發(fā)送了連接請求。當效勞器接受客戶端的連接請求以后,效勞器會返回相關(guān)響應碼給客戶端。該響應碼的前3位數(shù)字表示效勞器端響應的結(jié)果。局部SMTP響應碼如表8.3所示。表8.3局部SMTP響應碼響
應
碼意
義220服務器就緒221服務器關(guān)閉傳輸通道250客戶端所請求的郵件操作完成450郵件地址不可用421服務器服務不可用,關(guān)閉傳輸通道451由于處理過程中出錯,請求的操作被終止452服務器存儲空間不足500SMTP命令語法錯誤501命令參數(shù)的語法錯誤502命令暫時不可實現(xiàn)503錯誤的命令序列550客戶端請求的操作不能被執(zhí)行或者郵件地址不可用552服務器的存儲不足553郵箱名稱不合法554服務失敗334發(fā)送驗證用戶名235驗證賬號密碼失敗在該實例中,客戶端如果連接效勞器成功那么會返回響應碼220,表示效勞器效勞就緒,否那么返回554??蛻舳私邮枕憫a應該調(diào)用API函數(shù)recv()。代碼如下:本節(jié)中,向用戶講述了連接SMTP效勞器、SMTP響應碼的具體意義以及客戶端接收響應碼,并且配有相關(guān)的代碼實例。8.2.2SMTP命令在客戶端與SMTP效勞器之間進行數(shù)據(jù)傳輸時,雙方都是使用SMTP命令進行交流。因此,SMTP命令在E-mail通信中起著很重要的作用。但是,在向用戶講解SMTP命令之前,用戶必須首先了解一下電子郵件的根本格式。1.E-mail構(gòu)造格式在SMTP協(xié)議中,規(guī)定了E-mail信件的根本格式。該格式與第5章中向用戶所講述的HTTP根本格式一樣,都包含有數(shù)據(jù)頭和數(shù)據(jù)體,并且在兩者之間均使用一個空白行隔開。例如,一封簡單的郵件構(gòu)造格式如下://郵件頭Subject:ThisisaE-mail//空白行Hellolymlrl! //郵件體ThisisaE-mail!在例子中,E-mail的根本格式包括郵件頭和郵件體。郵件頭中的內(nèi)容是關(guān)于該郵件的一些根本信息。例如,發(fā)送者和主題信息。而郵件體中是純文本的郵件內(nèi)容,并且在SMTP協(xié)議中,還規(guī)定在郵件頭和郵件體之間需要使用一個空白行隔開。在郵件頭中,主要是由SMTP標準字段組成,這些字段包含郵件的根本信息。例如://郵件頭Subject:ThisisaE-mail以上字段所包含的信息:郵件發(fā)送者的郵件地址是,郵件主題是ThisisaE-mail。在SMTP協(xié)議中,包含了很多郵件頭標準字段,局部SMTP郵件頭字段如表8.4所示。緊跟著郵件頭的是一個空白行,用于區(qū)分郵件頭和郵件體。在郵件體中,主要是郵件需要發(fā)送的信息內(nèi)容。在郵件體中,不包含任何字段信息,只有文本格式的郵件內(nèi)容而已。表8.4SMTP郵件頭字段字
段意
義From郵件創(chuàng)建者的郵件地址To郵件目的地Sender郵件發(fā)送者Reply-to郵件回復地址Cc郵件抄送人In-Reply-To郵件正被回復Data郵件創(chuàng)建的時間Subject郵件主題Comments郵件的其他說明Keywords郵件的關(guān)鍵字Bcc郵件的密件抄送人郵件地址Message-ID郵件的標識符在表8.4中列出了局部SMTP標準字段。其中,F(xiàn)rom表示郵件的創(chuàng)立者地址,該地址在一般情況下僅有一個。Sender表示郵件的發(fā)送者,該發(fā)送者可能是轉(zhuǎn)發(fā)郵件,該字段可以有多個郵件地址,地址之間使用逗號隔開。同時可以有多個地址的字段是To。例如:01 Data:Tue,04Feb200921:18:03+0800 02 03 ,wexs@163,wen@126,
04 //發(fā)送者為多個地址05 To//接收者也為多個06 Subject:ThisisaE-mail //郵件主題07 //空行08 Hellolymlrl! //郵件數(shù)據(jù)體09 ThisisaE-mail!如果郵件沒有發(fā)送成功,那么客戶端應該將該郵件重新進行發(fā)送。郵件的重發(fā)必須在保證郵件內(nèi)容不發(fā)生改變的情況下進行。實際上,郵件進行重發(fā)只用在原有郵件頭的標題字段前加上字符串“Resent-”。例如,將上述實例中的郵件進行重發(fā),內(nèi)容如下:01 Resent-Data:Tue,04Feb200921:18:03+0800 02 Resent-From03 Resent-Sender04 //發(fā)送者為多個地址05 Resent-To //接收者也為多個06 Resent-Subject:ThisisaE-mail //郵件主題07 08 Hellolymlrl! //郵件數(shù)據(jù)體09 ThisisaE-mail!注意:在連接SMTP效勞器成功以后,客戶端在接收到效勞器返回的DATA命令后,就可以將以上構(gòu)造的郵件內(nèi)容發(fā)送到SMTP效勞器了。2.SMTP命令前面已經(jīng)向用戶介紹過客戶端與SMTP效勞器之間的交流是通過SMTP命令來完成的。常見的SMTP命令如表8.5所示。表8.5常用SMTP命令命
令含
義HELO客戶機向服務器問候MAIL指定郵件的發(fā)送者RCPT指定郵件的接收者DATA指示客戶端或服務器端可以發(fā)送郵件內(nèi)容RSET重新初始化會話狀態(tài)VRFY驗證郵件地址的有效性NOOP空操作QUIT終止會話TURN交換服務器與客戶端下面將參照表8.5中所列舉的局部SMTP命令進行講解。命令HELO是在郵件客戶端連接效勞器成功以后,第一個發(fā)送到效勞器的命令。其作用是向SMTP效勞器問候。例如,客戶端向效勞器問候并說明自己的身份。內(nèi)容如下:HELOlymlrl<crlf>其中,字符<crlf>表示結(jié)束符號。以上內(nèi)容表示客戶端向效勞器問候并且說明自己的身份。例如,在VC中向效勞器發(fā)送該命令,代碼如下:... //省略局部代碼charsendmail[]={"HELOlymlrl\r\n"}; //構(gòu)造命令字符串send(s,sendmail,sizeof(sendmail),0); //發(fā)送命令到效勞器... //省略局部代碼命令MAILFROM/RCPTTO分別表示指定郵件的發(fā)送和接收者。例如:MAILFROM:lymlrl@163<crlf>RCPTTO:lymlrl@126<crlf>上述代碼分別指定了郵件的發(fā)送者和接收者的郵件地址。命令DATA是客戶端發(fā)送到效勞器說明客戶端將要發(fā)送郵件到效勞器。效勞器收到該命令后會返回SMTP響應碼到客戶端,表示效勞器已經(jīng)準備好接收客戶端的郵件數(shù)據(jù)。命令VRFY是被用來驗證某個郵件地址的有效性。例如,用戶用該命令來驗證自己的郵箱地址是否有效,那么可以發(fā)送命令字符串“”到SMTP效勞器。如果該郵箱地址是有效的地址,那么效勞器會返回響應碼250,表示客戶端所請求的操作成功,否那么返回450,表示郵件地址無效。命令QUIT表示終止效勞器和客戶端的會話。例如客戶端向效勞器發(fā)送該命令,代碼如下:...//省略局部代碼charsendmail[]={"QUIT\r\n"}; //構(gòu)造命令字符串send(s,sendmail,sizeof(sendmail),0);//發(fā)送命令到效勞器...//省略局部代碼當效勞器接收到該命令以后,會返回響應碼220到客戶端,表示效勞器已經(jīng)關(guān)閉相關(guān)的數(shù)據(jù)通道。注意:表8.5中的命令在程序中被發(fā)送時必須加上換行符號“\r\n”,或者用戶在構(gòu)造完成整個郵件內(nèi)容后,需要在郵件內(nèi)容后面加上“\0”,表示數(shù)據(jù)內(nèi)容發(fā)送或者接收完畢。8.2.3發(fā)送命令與接收響應在客戶端編程中,通常情況下客戶端都是通過向SMTP效勞器發(fā)送命令表示需要進行的操作。在表8.5中,已經(jīng)列出了局部SMTP常用命令,這些命令都是在客戶端連接效勞器成功以后發(fā)送的??蛻舳税l(fā)送命令以后,效勞器通過向客戶端發(fā)送SMTP響應碼告知其所發(fā)送的命令是否成功或被執(zhí)行。1.與效勞器一問一答客戶端與SMTP效勞器的通信過程是通過問答形式完成的,這個過程是典型的C/S通信模式。下面介紹一下郵件客戶端發(fā)送的命令與效勞器端返回的信息。內(nèi)容如下:01 ... //省略發(fā)送連接請求02 220163Anti-spamGTforCoremailSystem(163com[071018])03 HELO04 250OK05 authlogin06 334dXNlcm5hbWU607 USERbase64 //加密后的用戶名08 334UGFzc3dvcmQ609 PASSbase64 //加密后的密碼10 235Authenticationsuccessful11 MAILFROM12 250MailOK13 RCPTTO14 250MailOK15 DATA //準備發(fā)送信件16 354Enddatawith. //信件以\r\n.\r\n結(jié)束17 ... //省略構(gòu)造信件內(nèi)容并發(fā)送18 QUIT //退出命令19 221bye以上內(nèi)容單數(shù)為客戶端發(fā)送的命令,雙數(shù)為從效勞器端返回的信息。通過上面的內(nèi)容,用戶可以看到這是發(fā)送郵件所要經(jīng)歷的一個典型的C/S〔客戶端/效勞器〕通信過程,通過問答的形式將一封郵件發(fā)送到效勞器。注意:在客戶端發(fā)送DATA命令以后,效勞器會返回是否準備好接收客戶端將要發(fā)送郵件的響應碼,該響應碼是354,表示效勞器已經(jīng)準備好接收郵件。接下來,客戶端可以直接將郵件發(fā)送到效勞器。2.發(fā)送SMTP命令在實例中,客戶端發(fā)送命令是通過API函數(shù)send()進行的。該函數(shù)的作用是向套接字的另一方發(fā)送指定緩沖區(qū)中的內(nèi)容。函數(shù)原型如下:intsend(SOCKETs,constchar*buff,intlen,intflags);該函數(shù)調(diào)用成功返回非0值,否那么失敗。局部參數(shù)意義如下:參數(shù)s表示客戶端所創(chuàng)立的套接字句柄。參數(shù)buff指向緩沖區(qū)的字符指針。參數(shù)len表示緩沖區(qū)的大小,可以使用函數(shù)sizeof()獲得。例如,用戶使用函數(shù)send()將命令DATA發(fā)送到效勞器,代碼如下:CStringstr="DATA\r\n"; //定義命令字符串send(socket_client,str.GetBuffer(1),str.GetLength(),0);3.接收郵件效勞器響應客戶端接收的消息來自于效勞器端返回的響應碼。實現(xiàn)該功能的函數(shù)是recv(),該函數(shù)原型如下:intrecv(SOCKETs,constchar*buff,intlen,intflags);該函數(shù)調(diào)用成功,那么返回實際接收到的字符數(shù),否那么失敗。主要參數(shù)意義如下:參數(shù)s套接字句柄。參數(shù)buff表示接收數(shù)據(jù)的緩沖區(qū)指針,與函數(shù)send()一樣。參數(shù)len表示將接收的數(shù)據(jù)大小。在這里將該參數(shù)設(shè)置為3。charrecv_message[512]="";recv(socket_client,recv_message,512,0);在這里,關(guān)于客戶端接收效勞器響應消息的功能不再進行重復講述,請用戶復習本章前面所講述的相關(guān)內(nèi)容。8.3SMTP客戶端——發(fā)送郵件用戶通過學習前面關(guān)于郵件收發(fā)的根本原理和編程方法,對郵件收發(fā)器的制作已經(jīng)熟悉。在本節(jié)中,將通過編程制作程序?qū)嵗?,向用戶講述在VC環(huán)境下編程的具體方法。通過本節(jié)實例的學習,用戶可以仿照該實例的設(shè)計方法,自行編程實現(xiàn)郵件收發(fā)器。8.3.1準備工作在程序中,窗口界面是最重要的,因為程序界面直接面向用戶。當用戶第一次使用軟件時,其窗口界面決定了用戶對該軟件的第一印象,所以我們先從設(shè)計對話框的界面開始,然后做些編程前的準備工作。1.創(chuàng)立工程創(chuàng)立基于對話框的工程,工程名為sendemil,注意在向?qū)У牡?步選中WindowsSockets復選框,如圖8.5所示。圖8.5
WindowsSockets復選框2.添加控件為對話框添加控件并設(shè)計界面如圖8.6所示:圖8.6程序設(shè)計界面及其關(guān)鍵控件ID號控件的ID以及為控件關(guān)聯(lián)的變量名和類型如圖8.7所示:圖8.7控件關(guān)聯(lián)的變量名及類型3為對話框添加成員變量在類CSendemilDlg中添加成員變量,即與效勞器端交流的套接字。
SMTP登錄身份驗證方式SMTP既可允許匿名登錄也可以要求身份驗證,實際應該中當然是要求身份認證的。身份認證的方式有多種。1.LOGIN方式如下為與SMTP效勞器的對話01 authlogin02 334VXNlcm5hbWU6 ---BASE64編碼“Username:”03 Y29zdGFAYW1heGl0Lm5ldA== ----發(fā)送BASE64編碼的用戶名04 334UGFzc3dvcmQ6 ---BASE64編碼"Password:"05 MTk4MjIxNA== ---客戶端發(fā)送BASE64編碼的密碼06 235authsuccessfully ---登錄成功用戶向效勞器發(fā)送authlogin命令,表示采用此種方式驗證。單號是由客戶端發(fā)送,雙號是由效勞器端返回,對話中提到了BASE64編碼,它是網(wǎng)絡上最常見的用于傳輸8Bit字節(jié)代碼的編碼方式,可用于在HTTP環(huán)境下傳遞較長的標識信息,此種編碼方式不僅比較簡短,同時也具有不可讀性,即所編碼的數(shù)據(jù)不會被人用肉眼所直接看到。相當于對所發(fā)送數(shù)據(jù)進行簡單的加密,有興趣的讀者可以查閱相關(guān)書籍來對它有更多的了解。本章所講的工程實例就是采用此種登錄驗證方式。實例中專門引入了兩個文件Base64.h和Base64.cpp,它們封裝了一個CBase64類,可以用它的成員函數(shù)Encode()對需要進行BASE64編碼的數(shù)據(jù)進行處理。2.PLAIN方式基于明文的SMTP驗證,其向效勞器發(fā)送的用戶名和密碼的格式應該為“<NULL>username<NULL>password”。username是用戶名,后邊的password是口令,NULL是ASCII的0。3.CRAM-MD5方式CRAM-MD5即是一種Keyed-MD5驗證方式,CRAM是“Challenge-ResponseAuthenticationMechanism”的縮寫。所謂Keyed-MD5,是將Client與Server共享的一個Key作為一局部MD5的輸入,正好郵件系統(tǒng)的用戶名和口令可以作為這個Key。SMTP效勞器對以上3種驗證方式并不一定全部支持。連接登錄效勞器為“登錄效勞器”按鈕添加消息響應函數(shù)OnConnect()。1.加載套接字庫WSAStartup()必須是應用程序調(diào)用的第一個WindowsSockets函數(shù)。使用函數(shù)WSAStartup()來加載指定版本的套接字庫。2.創(chuàng)立套接字并獲取SMTP效勞器的IP地址獲取的IP地址會被用在之后的連接效勞器的操作中。m_address是由用戶輸入的SMTP效勞器的網(wǎng)址,通過調(diào)用函數(shù)gethostbyname()來返回一個指向hostent結(jié)構(gòu)的指針,hostent結(jié)構(gòu)的成員h_addr_list包含了SMTP效勞器網(wǎng)絡字節(jié)序的IP地址,通過字節(jié)拷貝函數(shù)memmove()將host->h_addr_list[0]所指向內(nèi)存的4個字節(jié)拷貝到in_addr類型的變量中。3.連接SMTP效勞器需要用默認的端口號25和之前獲得的IP地址填充sockaddr_in結(jié)構(gòu)。代碼通過調(diào)用connect()函數(shù)來連接SMTP效勞器,調(diào)用函數(shù)recv()來接收來自效勞器的響應信息,返回220表示連接成功。4.發(fā)送命令HELO習慣上要問候效勞器一下,就像與熟人第一次見面時的問候一樣。代碼發(fā)送HELOsmtp向效勞器問候,效勞器通常會返回250OK響應。當然也可以不想它問候,如果你不滿意它的“答復”的話。5.登錄驗證選擇一種效勞器支持的驗證方式,通過驗證后才可以進入自己的郵箱。代碼選擇了LOGIN的登錄驗證方式,并先后向效勞器發(fā)送了經(jīng)過Base64處理的用戶名和密碼。代碼中是通過調(diào)用類CBase64的成員函數(shù)Encode()來實現(xiàn)Base64處理的,函數(shù)接收的參數(shù)分別為要處理的數(shù)據(jù)和數(shù)據(jù)的長度。一切正常的話效勞器的響應如下:authlogin334dXNlcm5hbWU6USERbase64 //加密后的用戶名334UGFzc3dvcmQ6PASSbase64 //加密后的密碼235Authenticationsuccessful //成功登錄綜上所述,“登錄效勞器”按鈕的消息響應函數(shù)OnConnect()編寫如下:登錄效勞器的代碼實現(xiàn)效果如圖8.8所示。圖8.8程序連接SMTP效勞器過程構(gòu)造并發(fā)送郵件效勞器端效勞成功啟動以后,客戶端可以將郵件發(fā)送到SMTP效勞器,但是在郵件發(fā)送之前必須對郵件的數(shù)據(jù)進行順序調(diào)整,以符合SMTP協(xié)議的標準。例如,一封正確的郵件數(shù)據(jù)格式應該如下。 //發(fā)件人地址Subject:ThisisaE-Mail //郵件主題//空白行Hellolymlrl! //郵件內(nèi)容ThisisaE-mail!接下來將分別向SMTP效勞器發(fā)送如下命令,正常情況下效勞器的響應如下:MAILFROM250MailOKRCPTTO250MailOKDATA //準備發(fā)送信件354Enddatawith. //信件以\r\n.\r\n結(jié)束... //省略構(gòu)造信件內(nèi)容并發(fā)送QUIT //退出命令221bye1.發(fā)送MAILFROM命令發(fā)送郵件前必須要首先提供的關(guān)鍵信息之——發(fā)件人。m_name是用戶填寫的用戶名信息,代碼首先構(gòu)造了MAILFROM:<發(fā)件人>字符串,然后通過send()函數(shù)發(fā)送到SMTP效勞器,最后用recv()函數(shù)來接收SMTP效勞器的消息響應。2.發(fā)送RCPTTO命令發(fā)送郵件前必須要提供的關(guān)鍵信息之——收件人。m_rely是用戶填寫的收件人信息,代碼首先構(gòu)造了RCPTTO:<收件人>字符串,然后通過send()函數(shù)發(fā)送到SMTP效勞器,最后用recv()函數(shù)來接收SMTP效勞器的消息響應。3.發(fā)送DATA命令發(fā)送DATA提示效勞器:客戶端即將發(fā)送郵件。同時希望得到效勞器“已經(jīng)準備好了”的響應信息。代碼首先構(gòu)造了DATA字符串,然后通過send()函數(shù)發(fā)送到SMTP效勞器,最后用recv()函數(shù)來接收SMTP效勞器的消息響應。4.發(fā)送郵件選擇感興趣的關(guān)鍵字并填充,如主題。按照約定郵件的結(jié)束以“\r\n.\r\n”為標志。m_subject是用戶填寫的主題信息,m_context是用戶填寫的郵件內(nèi)容,代碼將用戶填寫的信息進行了格式化,然后整合在了一起。最后通過send()函數(shù)發(fā)送到SMTP效勞器,最后用recv()函數(shù)來接收SMTP效勞器的消息響應。5.發(fā)送QUIT命令QUIT命令用來通知效勞器結(jié)束會話、斷開連接。代碼首先構(gòu)造了QUIT字符串,然后通過send()函數(shù)發(fā)送到SMTP效勞器,最后用recv()函數(shù)來接收SMTP效勞器的消息響應。綜上所述,添加“郵件發(fā)送”按鈕的消息響應函數(shù)如下:郵件發(fā)送的代碼實現(xiàn)效果如圖8.9所示。圖8.9程序發(fā)送郵件的過程翻開收件人的郵箱查看收到的郵件如圖8.10所示:圖8.10查看郵箱中收到的郵件退出程序雙擊“退出程序”按鈕,添加消息響應函數(shù)OnCancel()。代碼主要調(diào)用函數(shù)closesocket()和WSACleanup()完成關(guān)閉套接字和卸載socket庫的功能。8.4POP3簡介一般,用戶接收郵件是通過向POP3效勞器發(fā)送命令獲取的。具體發(fā)送命令的步驟與SMTP協(xié)議一樣,所以在這里不再贅述,如有不清楚的地方請用戶復習效勞器前面的知識。在本節(jié)中,將向用戶介紹局部POP3命令以及編程實現(xiàn)接收郵件功能。1.POP3命令POP3通信方式與SMTP一樣,使用標準命令與效勞器進行數(shù)據(jù)交換。POP3協(xié)議中還規(guī)定了標準端口為110號端口。POP3標準命令如表8.6所示。表8.6局部POP3標準命令命
令意
義QUIT終止與服務器會話STAT提供信箱大小LIST獲取郵件大小USER客戶端發(fā)送賬號信息到服務器驗證PASS客戶端發(fā)送密碼信息到服務器驗證TOP取出第M封郵件信頭和郵件內(nèi)容的前N行DELE刪除第N封郵件RSET復位POP3會話RETR取出第N封郵件在上表中列出了POP3的相關(guān)命令,下面將對其中的命令進行詳解。命令QUIT的作用是終止與效勞器的會話連接。格式如下:QUIT該命令如果發(fā)送到效勞器執(zhí)行成功,效勞器那么會返回OK,表示效勞器同意客戶端退出對話。命令STAT的作用是請求效勞器信箱的大小信息。命令LIST可以獲取指定郵件的大小信息。如果不帶任何命令參數(shù),那么效勞器會返回所有郵件的大小。格式如下:LIST //客戶端發(fā)送命令LIST11024 //表示第一封郵件的大小22048 //表示第二封郵件的大小...注意:格式中的序號表示郵件的序列號,緊跟后面的數(shù)字表示該郵件的大小信息。使用該命令獲得的郵件列表序號是從1開始的。命令USER將標識客戶端發(fā)送的賬號信息。格式如下:USERlymlrl命令PASS將標識客戶端發(fā)送的密碼信息。格式如下:PASSlwlwlw命令TOP表示將取出指定郵件的信頭和其郵件內(nèi)容的前N行。例如,用戶需要取出第一封郵件的前兩行內(nèi)容,那么發(fā)送TOP命令到效勞器即可。代碼如下:CStringstr("TOP12\r\n"); //構(gòu)造命令字符串send(s,str.GetBuffer(1),sizeof(str),0); //發(fā)送命令到效勞器命令DELE表示對郵件進行刪除操作。如果該命令配合其命令參數(shù)可以刪除第N封郵件。例如,用戶將刪除第N封郵件,格式如下:DELE
N命令RSET的作用是對POP3會話過程進行復位。命令RETR的作用是取出第N封郵件。例如,用戶需要取出第N封郵件。格式如下:RETRN當客戶端發(fā)送該命令以后,效勞器會返回被請求郵件的全部內(nèi)容〔包括郵件頭和郵件內(nèi)容〕。如果效勞器成功接收到POP3命令之后,都會返回相應的請求數(shù)據(jù)到客戶端。返回的數(shù)據(jù)格式如下:+OK效勞器將返回相應的數(shù)據(jù)2.POP3會話POP3會話過程與SMTP一樣,必須首先連接效勞器成功以后才能進行相關(guān)操作。下面簡單介紹一下POP3會話的過程,會話如下:01 //建立連接02 +OKWelcometocoremailMailPop3Server03 user //驗證的用戶名04 +OKcoremail05 passXXXXXX //嘿嘿,這個得保密,實際是明文的06 +OK6message(s)[6689byte(s)]07 list //命令效勞器給出各郵件長度08 +OK6668909 1212510 2203311 353712 457613 558114 683715 . //標識16 stat //查詢客戶郵箱中郵件的總數(shù)和郵件總長度17 +OK66689該會話過程是一個交互式的問答過程。
注意:因為POP3的工作方式與SMTP相似,所以在本章中不再向讀者繼續(xù)講解關(guān)于POP3的其他知識。如果用戶需要具體了解,請參考其他書籍。8.5
POP3客戶端——接收郵件用戶接收郵件是通過POP3〔接收郵件效勞器〕協(xié)議完成的。一般情況下,客戶端通過向效勞器發(fā)送相應的POP3命令獲取郵件。效勞器接收到命令以后,會將數(shù)據(jù)按照E-Mail的數(shù)據(jù)格式整理郵件,然后將郵件發(fā)送到客戶端進行解析、顯示。在本節(jié)中,將向用戶講解POP3命令等相關(guān)知識。準備工作在程序中,窗口界面是最重要的,因為程序界面直接面向用戶。當用戶第一次使用軟件時,其窗口界面決定了用戶對該軟件的第一印象,所以我們先從設(shè)計對話框的界面開始,然后做些編程前的準備工作。1.創(chuàng)立工程創(chuàng)立基于對話框的工程,工程名為recvemil,注意在向?qū)У牡?步選中WindowsSockets復選框,如圖8.11所示。圖8.11WindowsSockets復選框2.添加控件為對話框添加控件并設(shè)計界面如圖8.12所示:
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度債權(quán)債務資產(chǎn)保全執(zhí)行合同
- 2025年度離婚財產(chǎn)分割及子女成長環(huán)境優(yōu)化協(xié)議書
- 二零二五年度美容儀器加盟保證金及售后服務合同
- 2025年度跨境電商平臺員工勞動合同解除書
- 二零二五年度公益歌曲委托創(chuàng)作與宣傳推廣合同
- 二零二五年度特殊工種員工合同解除及職業(yè)康復協(xié)議
- 二零二五年度拆遷補償安置房產(chǎn)分配協(xié)議及租賃權(quán)證辦理
- 2025年度牛羊養(yǎng)殖場動物防疫與疾病防治合同
- 2025年度能源顧問合作協(xié)議
- 工傷賠償協(xié)議書(2025年度)賠償標準說明
- 小學利潤問題應用題100道附答案(完整版)
- 醫(yī)院智能化系統(tǒng)內(nèi)網(wǎng)、外網(wǎng)及設(shè)備網(wǎng)系統(tǒng)拓撲圖-可編輯課件
- 車庫租賃合同
- 小學生心理健康主題家長會
- 社交禮儀-儀態(tài)禮儀
- 安徽省2024年中考語文真題試卷【附答案】
- QB/T 4031-2024 阻燃性汽車空氣濾紙(正式版)
- 2024年南京科技職業(yè)學院單招職業(yè)適應性測試題庫帶答案
- DB52-T 1780-2024 醬香型白酒安全生產(chǎn)規(guī)范
- 2024年皖西衛(wèi)生職業(yè)學院單招職業(yè)適應性測試題庫及參考答案
- 線蟲病疫木及異??菟浪蓸涮幹猛稑朔桨福夹g(shù)方案技術(shù)標)
評論
0/150
提交評論