版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第8章 郵件接收和發(fā)送客戶端 郵件接收和發(fā)送客戶端的作用是在本地計算機和遠程計算機之間傳送電子信件以及接收電子信件。用戶平時所用的Foxmail就是一種郵件接收和發(fā)送客戶端。通常情況下,F(xiàn)oxmail由發(fā)送者將電子信件發(fā)送到郵件服務(wù)器(SMTP)中,再由SMTP服務(wù)器將該郵件發(fā)送到POP3(接收郵件)服務(wù)器中,郵件接收者通過賬戶和口令再從POP3服務(wù)器中獲取信件。在本章中,將向用戶介紹郵件接收和發(fā)送客戶端的原理以及開發(fā)過程。8.1 調(diào)用Windows自帶的郵件發(fā)送程序 一般情況下,用戶所使用的Windows操作系統(tǒng)中都帶有默認的郵件發(fā)送程序。通過該郵件發(fā)送程序,用戶可以將郵件發(fā)送到任何目的地址
2、。這種方法比較簡單適用,所以很受大部分用戶歡迎。用戶可以在操作系統(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)用相應(yīng)的Windows進程實現(xiàn)的。調(diào)用該Windows進程所使用的命令是“mailto:+string”,其中,string表示郵件發(fā)送的目的地址。例如,用戶需要將郵件發(fā)送到郵件地址為的郵箱中,使
3、用的命令是“mailto:”。 首先,在Windows系統(tǒng)界面下選擇“開始”|“運行”命令,彈出“運行”對話框,如圖8.1所示。圖8.1 “運行”對話框 然后,在運行對話框中輸入命令“mailto:”,可以打開Windows自帶的郵件發(fā)送程序進行郵件發(fā)送,如圖8.2所示。圖8.2 Windows郵件收發(fā)器 以上過程是用戶通過Windows命令調(diào)用郵件收發(fā)器必須做的。實際上,除了這種方法,用戶還可以在程序中通過函數(shù)調(diào)用Windows郵件收發(fā)器。此種方法將在8.1.2節(jié)中進行講解。8.1.2 CreateProcess()函數(shù) 在VC中編程,MFC類庫已經(jīng)提供了幾個庫函數(shù)用于調(diào)用Windows的外
4、部程序,包括郵件收發(fā)程序。在本節(jié)中,將向用戶介紹其中的兩個函數(shù)CreateProcess()和ShellExecute()。1使用CreateProcess()函數(shù)CreateProcess()函數(shù)可以創(chuàng)建Windows進程,同時也可以調(diào)用已經(jīng)存在的進程。該函數(shù)的原型如下:BOOL CreateProcess( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInh
5、eritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ); 該函數(shù)創(chuàng)建進程成功則返回true,否則返回false。其參數(shù)意義如下: 參數(shù)lpApplicationName表示可執(zhí)行文件的名字。用戶指定該參數(shù)后,該函數(shù)會在當(dāng)前路徑下搜索可執(zhí)行文件,但不會按照系統(tǒng)的搜索路徑進行搜索。 注意:使用該參數(shù)時,需要加上擴展名,因為系統(tǒng)不會自動為其
6、添加“.exe”后綴名。 參數(shù)lpCommandLine表示將要傳遞到新進程的命令行字符串。使用該參數(shù)時,該函數(shù)會自動為其添加后綴名“.exe”。如果參數(shù)字符串沒有指定所在路徑,那么該函數(shù)則會按照系統(tǒng)的搜索路徑進行搜索文件。 參數(shù)bInheritHandles表示該進程創(chuàng)建的子進程是否能繼承父進程的對象句柄。 參數(shù)lpStartupInfo指向結(jié)構(gòu)體STARTUPINFO的指針變量。該結(jié)構(gòu)體的聲明如下:typedef struct _STARTUPINFO DWORD cb;/表示該結(jié)構(gòu)體的大小 LPTSTR lpReserved;/保留,必須將該參數(shù)初始化為NULL LPTSTR lpDes
7、ktop; LPTSTR lpTitle; /設(shè)置控制臺程序的名稱 DWORD dwX; /設(shè)置應(yīng)用程序窗口的X坐標 DWORD dwY; /設(shè)置應(yīng)用程序窗口的Y坐標 DWORD dwXSize; /設(shè)置應(yīng)用程序窗口的橫向大小 DWORD dwYSize; /設(shè)置應(yīng)用程序窗口的縱向大小 DWORD dwXCountChars; /以字符為單位設(shè)置應(yīng)用程序窗口的X坐標 DWORD dwYCountChars; /以字符為單位設(shè)置應(yīng)用程序窗口的Y坐標 DWORD dwFillAttribute; /設(shè)置應(yīng)用程序窗口所使用的背景色等 DWORD dwFlags; /表示創(chuàng)建窗口的標志 WORD wS
8、howWindow; /是否顯示應(yīng)用程序窗口 WORD cbReserved2; /保留,將該參數(shù)必須設(shè)置為0 LPBYTE lpReserved2;/保留,將該參數(shù)必須設(shè)置為0 HANDLE hStdInput; /設(shè)置控制臺程序的輸入輸出緩存句柄 HANDLE hStdOutput; HANDLE hStdError; /錯誤輸出句柄 STARTUPINFO, *LPSTARTUPINFO; 該結(jié)構(gòu)體主要用于保存新創(chuàng)建進程的窗口信息,如窗口的大小或窗口的顯示方式等。其中,參數(shù)dwFlags標識了窗口創(chuàng)建成功以后,在顯示之前以何種方式進行顯示。其取值如表8.1所示。表8.1 程序窗口顯示標志
9、取值注意:在表8.1中所示的程序窗口顯示標志的作用僅僅是為了控制相應(yīng)的成員變量是否有效而已。例如,用戶在程序中,需要使用到該結(jié)構(gòu)體中的dwFillAttribute成員。那么,用戶必須將參數(shù)dwFlags取值為STARTF_USEFILLATTRIBUTE。否則,該成員變量將無效。參數(shù)lpProcessInformation是指向結(jié)構(gòu)體PROCESS_INFORMATION的指針變量。該結(jié)構(gòu)體聲明如下:typedef struct _PROCESS_INFORMATION HANDLE hProcess; /進程句柄 HANDLE hThread; /線程句柄 DWORD dwProcessI
10、d; /進程ID DWORD dwThreadId; /線程ID PROCESS_INFORMATION;取取 值值含含 義義STARTF_USESIZE使用使用dwXSize和和dwYSize成員成員STARTF_USESHOWWINDOW使用使用wShowWindow成員成員STARTF_USEPOSITION使用使用dwX和和dwY成員成員STARTF_USECOUNTCHARS使用使用dwXCountChars和和dwYCountChars成員成員STARTF_USEFILLATTRIBUTE使用使用dwFillAttribute成員成員STARTF_USESTDHANDLES使用使用
11、hStdInput、hStdOutput、hStdError成員成員STARTF_RUN_FULLSCREEN以全屏方式啟動程序以全屏方式啟動程序該結(jié)構(gòu)體主要用于保存進程的相關(guān)信息。其他參數(shù)均可以默認設(shè)置為NULL。例如,調(diào)用操作系統(tǒng)的記事本程序。代碼如下:01. /省略部分代碼02STARTUPINFO si=sizeof(si);/定義結(jié)構(gòu)體變量03PROCESS_INFORMATION pi;/定義結(jié)構(gòu)體對象04CString *str=notepad”;/記事本名稱05CreateProcess(NULL,str,NULL,NULL,false,NULL,NULL,NULL,&si,&
12、pi);06/調(diào)用函數(shù)打開記事本程序07. /省略部分代碼同樣的道理,用戶在本例中,也可以使用函數(shù)CreateProcess()調(diào)用郵件收發(fā)程序。代碼如下:01. /省略部分代碼02STARTUPINFO si=sizeof(si);/定義結(jié)構(gòu)體變量03PROCESS_INFORMATION pi;04CString *str=mailto:;/打開郵件程序的系統(tǒng)命令05CreateProcess(NULL,str,NULL,NULL,false,NULL,NULL,NULL,&si,&pi);06/調(diào)用函數(shù)打開記事本程序07. /省略部分代碼2使用ShellExecute()函數(shù)在MFC編程
13、中,除了函數(shù)CreateProcess()以外,還可以調(diào)用函數(shù)ShellExecute()實現(xiàn)相同的功能。該函數(shù)原型如下:HINSTANCE ShellExecute( HWND hwnd, /父窗口句柄 LPCTSTR lpOperation,/將要進行的操作形式 LPCTSTR lpFile, /目錄文件名稱或文件路徑 LPCTSTR lpParameters, /傳遞的參數(shù) LPCTSTR lpDirectory,/一般為NULL INT nShowCmd/顯示方式);該函數(shù)執(zhí)行成功會返回調(diào)用程序的應(yīng)用程序指針,否則返回錯誤代碼。部分錯誤代碼如表8.2所示。表8.2 部分錯誤代碼錯錯 誤
14、誤 代代 碼碼意意 義義ERROR_FILE_NOT_FOUND找不到相應(yīng)文件找不到相應(yīng)文件ERROR_PATH_NOT_FOUND找不到所需路徑找不到所需路徑ERROR_BAD_FORMAT無效的無效的.exe文件文件SE_ERR_ASSOCINCOMPLETE無效的文件名無效的文件名0 操作系統(tǒng)的內(nèi)存溢出操作系統(tǒng)的內(nèi)存溢出 該函數(shù)各個參數(shù)的說明已在函數(shù)原型中標出。使用該函數(shù)調(diào)用操作系統(tǒng)自帶的郵件發(fā)送程序,代碼如下: 以上代碼是使用C語言編寫,并且使用命令行窗口界面,目的是為了讓用戶了解整個調(diào)用過程。在隨書光盤的第8章中附有代碼,請用戶自行參考。此段代碼在VC中編譯后的結(jié)果,如圖8.3所示。
15、用戶在運行界面1中輸入字符Y或y,然后按下Enter鍵。程序提示郵件程序正在打開,當(dāng)郵件程序打開以后,實例程序會提示已經(jīng)打開郵件程序,如圖8.4所示。圖8.3 運行界面1圖8.4 運行界面2 注意:在程序中為了模擬計算機的工作,所以筆者使用了while循環(huán)產(chǎn)生時間差,僅僅是為了讓用戶重復(fù)了解該調(diào)用過程。在實際編程中,不提倡使用該方法產(chǎn)生時間差,因為這種方法很危險,容易造成系統(tǒng)的崩潰。通常,使用多線程編程的方法比較安全,也是筆者極力推薦的一種方法。該類方法將在后面的相關(guān)章節(jié)中講述。8.2 SMTP會話過程 SMTP是發(fā)送郵件協(xié)議,與前面所講的FTP、HTTP等協(xié)議一樣被用作某種行為的規(guī)范標準。本
16、節(jié)的主要內(nèi)容就是向用戶講解郵件客戶端怎么連接SMTP服務(wù)器以及向SMTP服務(wù)器發(fā)送信件等操作。8.2.1 怎么連接服務(wù)器 在網(wǎng)絡(luò)中傳輸郵件信息都是基于TCP/IP協(xié)議的,所以用戶在Windows操作系統(tǒng)中編寫郵件發(fā)送程序時可以使用Windows套接字來完成。一般情況下,客戶端連接服務(wù)器的幾個步驟如下。 (1)客戶端指定IP地址和端口連接服務(wù)器。 (2)服務(wù)器收到連接請求,并同意客戶端連接請求。 (3)客戶端和服務(wù)器互相發(fā)送數(shù)據(jù)。 (4)關(guān)閉服務(wù)器和客戶端的套接字。 基于以上幾個步驟,用戶可以VC中編寫程序?qū)崿F(xiàn)郵件客戶端。1創(chuàng)建套接字對象 該實例與一般網(wǎng)絡(luò)程序一樣,需要Windows套接字的支持
17、,所以用戶應(yīng)該首先初始化套接字庫。代碼如下: 01 BOOL CMyEMAIL:OnInitDialog() 02 03WSADATA data; 04WORDss=MAKEWORD(2,0);/指定套接字庫版本 05:WSAStartup(ss,&data);/初始化套接字庫 06 用戶初始化套接字庫以后,還必須記得在程序退出之前釋放該套接字庫。代碼如下: 01 void CMyEMAIL:OnClose() 02 03:WSACleanup();/釋放已經(jīng)加載的套接字庫 04 然后,用戶可以調(diào)用API函數(shù)socket()創(chuàng)建連接服務(wù)器的套接字了。代碼如下: 在代碼中,函數(shù)socket()創(chuàng)
18、建了基于TCP通信的流式套接字句柄。2連接服務(wù)器用戶創(chuàng)建好套接字以后,可以調(diào)用API函數(shù)connect()連接服務(wù)器。其原型如下:int connect (SOCKETs, const struct sockaddr FAR*name, intnamelen);該函數(shù)用于連接遠程計算機,如果連接失敗則返回1,否則成功。參數(shù)及其意義如下:參數(shù)s表示將要連接服務(wù)器的套接字句柄,該套接字是用戶之前已經(jīng)創(chuàng)建好的套接字句柄。參數(shù)name是指向套接字地址結(jié)構(gòu)體的指針變量。該套接字結(jié)構(gòu)體聲明如下: struct sockaddr_in short sin_family; u_short sin_port;
19、struct in_addr sin_addr; char sin_zero8; ; 該結(jié)構(gòu)體是sockaddr結(jié)構(gòu)的擴充結(jié)構(gòu),一般被用在Windows Socket 2中。 參數(shù)namelen表示套接字結(jié)構(gòu)對象的大小。 使用該函數(shù)在套接字s上連接SMTP服務(wù)器。例如,SMTP服務(wù)器地址為“”,端口為25。代碼如下: 通過上面的代碼,用戶已經(jīng)向SMTP服務(wù)器發(fā)送了連接請求。當(dāng)服務(wù)器接受客戶端的連接請求以后,服務(wù)器會返回相關(guān)響應(yīng)碼給客戶端。該響應(yīng)碼的前3位數(shù)字表示服務(wù)器端響應(yīng)的結(jié)果。部分SMTP響應(yīng)碼如表8.3所示。表8.3 部分SMTP響應(yīng)碼響響 應(yīng)應(yīng) 碼碼意意 義義220服務(wù)器就緒服務(wù)器就緒
20、221服務(wù)器關(guān)閉傳輸通道服務(wù)器關(guān)閉傳輸通道250客戶端所請求的郵件操作完成客戶端所請求的郵件操作完成450郵件地址不可用郵件地址不可用421服務(wù)器服務(wù)不可用,關(guān)閉傳輸通道服務(wù)器服務(wù)不可用,關(guān)閉傳輸通道451由于處理過程中出錯,請求的操作被終止由于處理過程中出錯,請求的操作被終止452服務(wù)器存儲空間不足服務(wù)器存儲空間不足500SMTP命令語法錯誤命令語法錯誤501命令參數(shù)的語法錯誤命令參數(shù)的語法錯誤502命令暫時不可實現(xiàn)命令暫時不可實現(xiàn)503錯誤的命令序列錯誤的命令序列550客戶端請求的操作不能被執(zhí)行或者郵件地址不可用客戶端請求的操作不能被執(zhí)行或者郵件地址不可用552服務(wù)器的存儲不足服務(wù)器的存儲
21、不足553郵箱名稱不合法郵箱名稱不合法554服務(wù)失敗服務(wù)失敗334發(fā)送驗證用戶名發(fā)送驗證用戶名235驗證賬號密碼失敗驗證賬號密碼失敗 在該實例中,客戶端如果連接服務(wù)器成功則會返回響應(yīng)碼220,表示服務(wù)器服務(wù)就緒,否則返回554??蛻舳私邮枕憫?yīng)碼應(yīng)該調(diào)用API函數(shù)recv()。代碼如下: 本節(jié)中,向用戶講述了連接SMTP服務(wù)器、SMTP響應(yīng)碼的具體意義以及客戶端接收響應(yīng)碼,并且配有相關(guān)的代碼實例。8.2.2 SMTP命令 在客戶端與SMTP服務(wù)器之間進行數(shù)據(jù)傳輸時,雙方都是使用SMTP命令進行交流。因此,SMTP命令在E-mail通信中起著很重要的作用。但是,在向用戶講解SMTP命令之前,用戶必
22、須首先了解一下電子郵件的基本格式。1E-mail構(gòu)造格式 在SMTP協(xié)議中,規(guī)定了E-mail信件的基本格式。該格式與第5章中向用戶所講述的HTTP基本格式一樣,都包含有數(shù)據(jù)頭和數(shù)據(jù)體,并且在兩者之間均使用一個空白行隔開。例如,一封簡單的郵件構(gòu)造格式如下: /郵件頭 From: Subject: This is a E-mail /空白行 Hello lymlrl!/郵件體 This is a E-mail! 在例子中,E-mail的基本格式包括郵件頭和郵件體。郵件頭中的內(nèi)容是關(guān)于該郵件的一些基本信息。例如,發(fā)送者和主題信息。而郵件體中是純文本的郵件內(nèi)容,并且在SMTP協(xié)議中,還規(guī)定在郵件頭和
23、郵件體之間需要使用一個空白行隔開。 在郵件頭中,主要是由SMTP標準字段組成,這些字段包含郵件的基本信息。例如: /郵件頭 From: Subject: This is a E-mail 以上字段所包含的信息:郵件發(fā)送者的郵件地址是,郵件主題是This is a E-mail。在SMTP協(xié)議中,包含了很多郵件頭標準字段,部分SMTP郵件頭字段如表8.4所示。緊跟著郵件頭的是一個空白行,用于區(qū)分郵件頭和郵件體。在郵件體中,主要是郵件需要發(fā)送的信息內(nèi)容。在郵件體中,不包含任何字段信息,只有文本格式的郵件內(nèi)容而已。表8.4 SMTP郵件頭字段字字 段段意意 義義From郵件創(chuàng)建者的郵件地址郵件創(chuàng)建者
24、的郵件地址To郵件目的地郵件目的地Sender郵件發(fā)送者郵件發(fā)送者Reply-to郵件回復(fù)地址郵件回復(fù)地址Cc郵件抄送人郵件抄送人In- Reply-To郵件正被回復(fù)郵件正被回復(fù)Data郵件創(chuàng)建的時間郵件創(chuàng)建的時間Subject郵件主題郵件主題Comments郵件的其他說明郵件的其他說明Keywords郵件的關(guān)鍵字郵件的關(guān)鍵字Bcc郵件的密件抄送人郵件地址郵件的密件抄送人郵件地址Message-ID郵件的標識符郵件的標識符在表8.4中列出了部分SMTP標準字段。其中,F(xiàn)rom表示郵件的創(chuàng)建者地址,該地址在一般情況下僅有一個。Sender表示郵件的發(fā)送者,該發(fā)送者可能是轉(zhuǎn)發(fā)郵件,該字段可以有多個
25、郵件地址,地址之間使用逗號隔開。同時可以有多個地址的字段是To。例如:01Data:Tue,04 Feb 2009 21:18:03+080002From:03Sender: , , 04/發(fā)送者為多個地址05To:, /接收者也為多個06Subject: This is a E-mail/郵件主題07/空行08Hello lymlrl! /郵件數(shù)據(jù)體09This is a E-mail!如果郵件沒有發(fā)送成功,則客戶端應(yīng)該將該郵件重新進行發(fā)送。郵件的重發(fā)必須在保證郵件內(nèi)容不發(fā)生改變的情況下進行。實際上,郵件進行重發(fā)只用在原有郵件頭的標題字段前加上字符串“Resent-”。例如,將上述實例中的郵
26、件進行重發(fā),內(nèi)容如下:01Resent-Data:Tue,04 Feb 2009 21:18:03+080002Resent-From:03Resent-Sender: , ,04/發(fā)送者為多個地址05Resent-To:, This is a E-mail/郵件主題0708Hello lymlrl!/郵件數(shù)據(jù)體09This is a E-mail!注意:在連接SMTP服務(wù)器成功以后,客戶端在接收到服務(wù)器返回的DATA命令后,就可以將以上構(gòu)造的郵件內(nèi)容發(fā)送到SMTP服務(wù)器了。2SMTP命令 前面已經(jīng)向用戶介紹過客戶端與SMTP服務(wù)器之間的交流是通過SMTP命令來完成的。常見的SMTP命令如表8
27、.5所示。表8.5 常用SMTP命令命命 令令含含 義義HELO客戶機向服務(wù)器問候客戶機向服務(wù)器問候MAIL指定郵件的發(fā)送者指定郵件的發(fā)送者RCPT指定郵件的接收者指定郵件的接收者DATA指示客戶端或服務(wù)器端可以發(fā)送郵件內(nèi)容指示客戶端或服務(wù)器端可以發(fā)送郵件內(nèi)容RSET重新初始化會話狀態(tài)重新初始化會話狀態(tài)VRFY驗證郵件地址的有效性驗證郵件地址的有效性NOOP空操作空操作QUIT終止會話終止會話TURN交換服務(wù)器與客戶端交換服務(wù)器與客戶端下面將參照表8.5中所列舉的部分SMTP命令進行講解。命令HELO是在郵件客戶端連接服務(wù)器成功以后,第一個發(fā)送到服務(wù)器的命令。其作用是向SMTP服務(wù)器問候。例如
28、,客戶端向服務(wù)器問候并表明自己的身份。內(nèi)容如下:HELO lymlrl其中,字符表示結(jié)束符號。以上內(nèi)容表示客戶端向服務(wù)器問候并且表明自己的身份。例如,在VC中向服務(wù)器發(fā)送該命令,代碼如下:./省略部分代碼char sendmail=HELO lymlrlrn;/構(gòu)造命令字符串send(s, sendmail,sizeof(sendmail),0);/發(fā)送命令到服務(wù)器./省略部分代碼命令MAIL FROM/ RCPT TO分別表示指定郵件的發(fā)送和接收者。例如:MAIL FROM:RCPT TO:上述代碼分別指定了郵件的發(fā)送者和接收者的郵件地址。命令DATA是客戶端發(fā)送到服務(wù)器表明客戶端將要發(fā)送郵
29、件到服務(wù)器。服務(wù)器收到該命令后會返回SMTP響應(yīng)碼到客戶端,表示服務(wù)器已經(jīng)準備好接收客戶端的郵件數(shù)據(jù)。命令VRFY是被用來驗證某個郵件地址的有效性。例如,用戶用該命令來驗證自己的郵箱地址是否有效,則可以發(fā)送命令字符串“VRFY:”到SMTP服務(wù)器。如果該郵箱地址是有效的地址,則服務(wù)器會返回響應(yīng)碼250,表示客戶端所請求的操作成功,否則返回450,表示郵件地址無效。命令QUIT表示終止服務(wù)器和客戶端的會話。例如客戶端向服務(wù)器發(fā)送該命令,代碼如下:. /省略部分代碼char sendmail=QUITrn;/構(gòu)造命令字符串send(s, sendmail,sizeof(sendmail),0);/
30、發(fā)送命令到服務(wù)器. /省略部分代碼當(dāng)服務(wù)器接收到該命令以后,會返回響應(yīng)碼220到客戶端,表示服務(wù)器已經(jīng)關(guān)閉相關(guān)的數(shù)據(jù)通道。注意:表8.5中的命令在程序中被發(fā)送時必須加上換行符號“rn”,或者用戶在構(gòu)造完成整個郵件內(nèi)容后,需要在郵件內(nèi)容后面加上“0”,表示數(shù)據(jù)內(nèi)容發(fā)送或者接收完畢。8.2.3 發(fā)送命令與接收響應(yīng) 在客戶端編程中,通常情況下客戶端都是通過向SMTP服務(wù)器發(fā)送命令表示需要進行的操作。在表8.5中,已經(jīng)列出了部分SMTP常用命令,這些命令都是在客戶端連接服務(wù)器成功以后發(fā)送的??蛻舳税l(fā)送命令以后,服務(wù)器通過向客戶端發(fā)送SMTP響應(yīng)碼告知其所發(fā)送的命令是否成功或被執(zhí)行。1與服務(wù)器一問一答客
31、戶端與SMTP服務(wù)器的通信過程是通過問答形式完成的,這個過程是典型的C/S通信模式。下面介紹一下郵件客戶端發(fā)送的命令與服務(wù)器端返回的信息。內(nèi)容如下:01./省略發(fā)送連接請求02220 163 .com Anti-spam GT for Coremail System (163com071018)03HELO 04250 OK05auth login06334 dXNlcm5hbWU607USER base64/加密后的用戶名08334 UGFzc3dvcmQ609PASS base64/加密后的密碼10235 Authentication successful11MAIL FROM:XXX16
32、3.COM12250 Mail OK13RCPT TO:XXX163.COM14250 Mail OK15DATA/準備發(fā)送信件16354 End data with ./信件以rn.rn結(jié)束17./省略構(gòu)造信件內(nèi)容并發(fā)送18QUIT/退出命令19221 bye 以上內(nèi)容單數(shù)為客戶端發(fā)送的命令,雙數(shù)為從服務(wù)器端返回的信息。通過上面的內(nèi)容,用戶可以看到這是發(fā)送郵件所要經(jīng)歷的一個典型的C/S(客戶端/服務(wù)器)通信過程,通過問答的形式將一封郵件發(fā)送到服務(wù)器。 注意:在客戶端發(fā)送DATA命令以后,服務(wù)器會返回是否準備好接收客戶端將要發(fā)送郵件的響應(yīng)碼,該響應(yīng)碼是354,表示服務(wù)器已經(jīng)準備好接收郵件。接下
33、來,客戶端可以直接將郵件發(fā)送到服務(wù)器。2發(fā)送SMTP命令 在實例中,客戶端發(fā)送命令是通過API函數(shù)send()進行的。該函數(shù)的作用是向套接字的另一方發(fā)送指定緩沖區(qū)中的內(nèi)容。函數(shù)原型如下: int send(SOCKET s,const char* buff,int len,int flags); 該函數(shù)調(diào)用成功返回非0值,否則失敗。部分參數(shù)意義如下: 參數(shù)s表示客戶端所創(chuàng)建的套接字句柄。 參數(shù)buff指向緩沖區(qū)的字符指針。 參數(shù)len表示緩沖區(qū)的大小,可以使用函數(shù)sizeof()獲得。 例如,用戶使用函數(shù)send()將命令DATA發(fā)送到服務(wù)器,代碼如下: CString str=DATArn;
34、/定義命令字符串 send(socket_client,str.GetBuffer(1),str.GetLength(),0);3接收郵件服務(wù)器響應(yīng)客戶端接收的消息來自于服務(wù)器端返回的響應(yīng)碼。實現(xiàn)該功能的函數(shù)是recv(),該函數(shù)原型如下:int recv(SOCKET s,const char* buff,int len,int flags);該函數(shù)調(diào)用成功,則返回實際接收到的字符數(shù),否則失敗。主要參數(shù)意義如下:參數(shù)s套接字句柄。參數(shù)buff表示接收數(shù)據(jù)的緩沖區(qū)指針,與函數(shù)send()一樣。參數(shù)len表示將接收的數(shù)據(jù)大小。在這里將該參數(shù)設(shè)置為3。char recv_message512 =
35、;recv(socket_client,recv_message,512,0);在這里,關(guān)于客戶端接收服務(wù)器響應(yīng)消息的功能不再進行重復(fù)講述,請用戶復(fù)習(xí)本章前面所講述的相關(guān)內(nèi)容。8.3 SMTP客戶端發(fā)送郵件 用戶通過學(xué)習(xí)前面關(guān)于郵件收發(fā)的基本原理和編程方法,對郵件收發(fā)器的制作已經(jīng)熟悉。在本節(jié)中,將通過編程制作程序?qū)嵗?,向用戶講述在VC環(huán)境下編程的具體方法。通過本節(jié)實例的學(xué)習(xí),用戶可以仿照該實例的設(shè)計方法,自行編程實現(xiàn)郵件收發(fā)器。8.3.1 準備工作 在程序中,窗口界面是最重要的,因為程序界面直接面向用戶。當(dāng)用戶第一次使用軟件時,其窗口界面決定了用戶對該軟件的第一印象,所以我們先從設(shè)計對話框的界
36、面開始,然后做些編程前的準備工作。1創(chuàng)建工程 創(chuàng)建基于對話框的工程,工程名為sendemil,注意在向?qū)У牡?步選中Windows Sockets復(fù)選框,如圖8.5所示。圖8.5 Windows Sockets復(fù)選框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中添加成員變量,即與服務(wù)器端交流的套接字。8.3.2 SMTP登錄身份驗證方式 SMTP既可允許匿名登錄也可以要求身份驗證,實際應(yīng)該中當(dāng)然是要求身份
37、認證的。身份認證的方式有多種。1.LOGIN方式如下為與SMTP服務(wù)器的對話01auth login02334 VXNlcm5hbWU6 -BASE64編碼“Username:”03Y29zdGFAYW1heGl0Lm5ldA= -發(fā)送BASE64編碼的用戶名04334 UGFzc3dvcmQ6 -BASE64編碼Password:05MTk4MjIxNA= -客戶端發(fā)送BASE64編碼的密碼06235 auth successfully -登錄成功用戶向服務(wù)器發(fā)送auth login命令,表示采用此種方式驗證。單號是由客戶端發(fā)送,雙號是由服務(wù)器端返回,對話中提到了BASE64編碼,它是網(wǎng)絡(luò)上
38、最常見的用于傳輸8Bit字節(jié)代碼的編碼方式,可用于在HTTP環(huán)境下傳遞較長的標識信息,此種編碼方式不僅比較簡短,同時也具有不可讀性,即所編碼的數(shù)據(jù)不會被人用肉眼所直接看到。相當(dāng)于對所發(fā)送數(shù)據(jù)進行簡單的加密,有興趣的讀者可以查閱相關(guān)書籍來對它有更多的了解。 本章所講的工程實例就是采用此種登錄驗證方式。實例中專門引入了兩個文件Base64.h和Base64.cpp,它們封裝了一個CBase64類,可以用它的成員函數(shù)Encode()對需要進行BASE64編碼的數(shù)據(jù)進行處理。2.PLAIN方式 基于明文的SMTP驗證,其向服務(wù)器發(fā)送的用戶名和密碼的格式應(yīng)該為“usernamepassword”。use
39、rname是用戶名,后邊的password是口令,NULL是ASCII的0。3.CRAM-MD5方式 CRAM-MD5即是一種Keyed-MD5驗證方式,CRAM是“Challenge-Response Authentication Mechanism”的縮寫。所謂Keyed-MD5,是將Client與Server共享的一個Key作為一部分MD5的輸入,正好郵件系統(tǒng)的用戶名和口令可以作為這個Key。 SMTP服務(wù)器對以上3種驗證方式并不一定全部支持。8.3.3 連接登錄服務(wù)器 為“登錄服務(wù)器”按鈕添加消息響應(yīng)函數(shù)OnConnect()。1.加載套接字庫 WSAStartup()必須是應(yīng)用程序調(diào)
40、用的第一個Windows Sockets函數(shù)。 使用函數(shù)WSAStartup()來加載指定版本的套接字庫。2.創(chuàng)建套接字并獲取SMTP服務(wù)器的IP地址 獲取的IP地址會被用在之后的連接服務(wù)器的操作中。 m_address是由用戶輸入的SMTP服務(wù)器的網(wǎng)址,通過調(diào)用函數(shù)gethostbyname()來返回一個指向hostent結(jié)構(gòu)的指針,hostent結(jié)構(gòu)的成員h_addr_list包含了SMTP服務(wù)器網(wǎng)絡(luò)字節(jié)序的IP地址,通過字節(jié)拷貝函數(shù)memmove()將host-h_addr_list0所指向內(nèi)存的4個字節(jié)拷貝到in_addr類型的變量中。3.連接SMTP服務(wù)器 需要用默認的端口號25和之
41、前獲得的IP地址填充sockaddr_in結(jié)構(gòu)。 代碼通過調(diào)用connect()函數(shù)來連接SMTP服務(wù)器,調(diào)用函數(shù)recv()來接收來自服務(wù)器的響應(yīng)信息,返回220表示連接成功。4.發(fā)送命令HELO 習(xí)慣上要問候服務(wù)器一下,就像與熟人第一次見面時的問候一樣。 代碼發(fā)送HELO smtp向服務(wù)器問候,服務(wù)器通常會返回250 OK響應(yīng)。當(dāng)然也可以不想它問候,如果你不滿意它的“回答”的話。5.登錄驗證 選擇一種服務(wù)器支持的驗證方式,通過驗證后才可以進入自己的郵箱。 代碼選擇了LOGIN的登錄驗證方式,并先后向服務(wù)器發(fā)送了經(jīng)過Base64處理的用戶名和密碼。代碼中是通過調(diào)用類CBase64的成員函數(shù)E
42、ncode()來實現(xiàn)Base64處理的,函數(shù)接收的參數(shù)分別為要處理的數(shù)據(jù)和數(shù)據(jù)的長度。 一切正常的話服務(wù)器的響應(yīng)如下: auth login 334 dXNlcm5hbWU6 USER base64/加密后的用戶名 334 UGFzc3dvcmQ6 PASS base64/加密后的密碼 235 Authentication successful/成功登錄 綜上所述,“登錄服務(wù)器”按鈕的消息響應(yīng)函數(shù)OnConnect()編寫如下: 登錄服務(wù)器的代碼實現(xiàn)效果如圖8.8所示。圖8.8 程序連接SMTP服務(wù)器過程8.3.4 構(gòu)造并發(fā)送郵件 服務(wù)器端服務(wù)成功啟動以后,客戶端可以將郵件發(fā)送到SMTP服務(wù)器
43、,但是在郵件發(fā)送之前必須對郵件的數(shù)據(jù)進行順序調(diào)整,以符合SMTP協(xié)議的規(guī)范。例如,一封正確的郵件數(shù)據(jù)格式應(yīng)該如下。 From: Subject: This is a E-Mail/郵件主題 /空白行 Hello lymlrl!/郵件內(nèi)容 This is a E-mail! 接下來將分別向SMTP服務(wù)器發(fā)送如下命令,正常情況下服務(wù)器的響應(yīng)如下: MAIL FROM:XXX163.COM 250 Mail OK RCPT TO:XXX163.COM 250 Mail OK DATA/準備發(fā)送信件 354 End data with ./信件以rn.rn結(jié)束 ./省略構(gòu)造信件內(nèi)容并發(fā)送 QUIT/退
44、出命令 221 bye1.發(fā)送MAIL FROM命令 發(fā)送郵件前必須要首先提供的關(guān)鍵信息之發(fā)件人。 m_name是用戶填寫的用戶名信息,代碼首先構(gòu)造了MAIL FROM:字符串,然后通過send()函數(shù)發(fā)送到SMTP服務(wù)器,最后用recv()函數(shù)來接收SMTP服務(wù)器的消息響應(yīng)。2.發(fā)送RCPT TO命令 發(fā)送郵件前必須要提供的關(guān)鍵信息之收件人。 m_rely是用戶填寫的收件人信息,代碼首先構(gòu)造了RCPT TO:字符串,然后通過send()函數(shù)發(fā)送到SMTP服務(wù)器,最后用recv()函數(shù)來接收SMTP服務(wù)器的消息響應(yīng)。3.發(fā)送DATA命令 發(fā)送DATA提示服務(wù)器:客戶端即將發(fā)送郵件。同時希望得到
45、服務(wù)器“已經(jīng)準備好了”的響應(yīng)信息。 代碼首先構(gòu)造了DATA字符串,然后通過send()函數(shù)發(fā)送到SMTP服務(wù)器,最后用recv()函數(shù)來接收SMTP服務(wù)器的消息響應(yīng)。4.發(fā)送郵件 選擇感興趣的關(guān)鍵字并填充,如主題。按照約定郵件的結(jié)束以“rn.rn”為標志。 m_subject是用戶填寫的主題信息,m_context是用戶填寫的郵件內(nèi)容,代碼將用戶填寫的信息進行了格式化,然后整合在了一起。最后通過send()函數(shù)發(fā)送到SMTP服務(wù)器,最后用recv()函數(shù)來接收SMTP服務(wù)器的消息響應(yīng)。5.發(fā)送QUIT命令 QUIT命令用來通知服務(wù)器結(jié)束會話、斷開連接。 代碼首先構(gòu)造了QUIT字符串,然后通過s
46、end()函數(shù)發(fā)送到SMTP服務(wù)器,最后用recv()函數(shù)來接收SMTP服務(wù)器的消息響應(yīng)。 綜上所述,添加“郵件發(fā)送”按鈕的消息響應(yīng)函數(shù)如下: 郵件發(fā)送的代碼實現(xiàn)效果如圖8.9所示。圖8.9 程序發(fā)送郵件的過程 打開收件人的郵箱查看收到的郵件如圖8.10所示:圖8.10 查看郵箱中收到的郵件8.3.5 退出程序 雙擊“退出程序”按鈕,添加消息響應(yīng)函數(shù)OnCancel()。 代碼主要調(diào)用函數(shù)closesocket()和WSACleanup()完成關(guān)閉套接字和卸載socket庫的功能。8.4 POP3簡介 一般,用戶接收郵件是通過向POP3服務(wù)器發(fā)送命令獲取的。具體發(fā)送命令的步驟與SMTP協(xié)議一樣
47、,所以在這里不再贅述,如有不清楚的地方請用戶復(fù)習(xí)服務(wù)器前面的知識。在本節(jié)中,將向用戶介紹部分POP3命令以及編程實現(xiàn)接收郵件功能。1POP3命令 POP3通信方式與SMTP一樣,使用標準命令與服務(wù)器進行數(shù)據(jù)交換。POP3協(xié)議中還規(guī)定了標準端口為110號端口。POP3標準命令如表8.6所示。表8.6 部分POP3標準命令命命 令令意意 義義QUIT終止與服務(wù)器會話終止與服務(wù)器會話STAT提供信箱大小提供信箱大小LIST獲取郵件大小獲取郵件大小USER客戶端發(fā)送賬號信息到服務(wù)器驗證客戶端發(fā)送賬號信息到服務(wù)器驗證PASS客戶端發(fā)送密碼信息到服務(wù)器驗證客戶端發(fā)送密碼信息到服務(wù)器驗證TOP取出第取出第M
48、封郵件信頭和郵件內(nèi)容的前封郵件信頭和郵件內(nèi)容的前N行行DELE刪除第刪除第N封郵件封郵件RSET復(fù)位復(fù)位POP3會話會話RETR取出第取出第N封郵件封郵件在上表中列出了POP3的相關(guān)命令,下面將對其中的命令進行詳解。命令QUIT的作用是終止與服務(wù)器的會話連接。格式如下:QUIT該命令如果發(fā)送到服務(wù)器執(zhí)行成功,服務(wù)器則會返回OK,表示服務(wù)器同意客戶端退出對話。命令STAT的作用是請求服務(wù)器信箱的大小信息。命令LIST可以獲取指定郵件的大小信息。如果不帶任何命令參數(shù),則服務(wù)器會返回所有郵件的大小。格式如下:LIST/客戶端發(fā)送命令LIST1 1024/表示第一封郵件的大小2 2048/表示第二封郵
49、件的大小.注意:格式中的序號表示郵件的序列號,緊跟后面的數(shù)字表示該郵件的大小信息。使用該命令獲得的郵件列表序號是從1開始的。命令USER將標識客戶端發(fā)送的賬號信息。格式如下:USER lymlrl命令PASS將標識客戶端發(fā)送的密碼信息。格式如下:PASS lwlwlw命令TOP表示將取出指定郵件的信頭和其郵件內(nèi)容的前N行。例如,用戶需要取出第一封郵件的前兩行內(nèi)容,則發(fā)送TOP命令到服務(wù)器即可。代碼如下:CString str(TOP 1 2rn);/構(gòu)造命令字符串send(s,str.GetBuffer(1),sizeof(str),0); /發(fā)送命令到服務(wù)器 命令DELE表示對郵件進行刪除操
50、作。如果該命令配合其命令參數(shù)可以刪除第N封郵件。例如,用戶將刪除第N封郵件,格式如下: DELE N 命令RSET的作用是對POP3會話過程進行復(fù)位。 命令RETR的作用是取出第N封郵件。例如,用戶需要取出第N封郵件。格式 如下: RETR N 當(dāng)客戶端發(fā)送該命令以后,服務(wù)器會返回被請求郵件的全部內(nèi)容(包括郵件頭和郵件內(nèi)容)。 如果服務(wù)器成功接收到POP3命令之后,都會返回相應(yīng)的請求數(shù)據(jù)到客戶端。返回的數(shù)據(jù)格式如下: +OK 服務(wù)器將返回相應(yīng)的數(shù)據(jù)2POP3會話POP3會話過程與SMTP一樣,必須首先連接服務(wù)器成功以后才能進行相關(guān)操作。下面簡單介紹一下POP3會話的過程,會話如下:01/建立連
51、接02+OK Welcome to coremail Mail Pop3 Server 03user everyone_ core mail05pass XXXXXX/嘿嘿,這個得保密,實際是明文的06+OK 6 message(s) 6689 byte(s)07list/命令服務(wù)器給出各郵件長度08+OK 6 6689091 2125102 2033113 537124 576135 581146 83715./標識16stat/查詢客戶郵箱中郵件的總數(shù)和郵件總長度 17+OK 6 6689 該會話過程是一個交互式的問答過程。 注意:因為POP3的工作方式與SMTP相似,所以在本章中不再向讀
52、者繼續(xù)講解關(guān)于POP3的其他知識。如果用戶需要具體了解,請參考其他書籍。8.5 POP3客戶端接收郵件 用戶接收郵件是通過POP3(接收郵件服務(wù)器)協(xié)議完成的。一般情況下,客戶端通過向服務(wù)器發(fā)送相應(yīng)的POP3命令獲取郵件。服務(wù)器接收到命令以后,會將數(shù)據(jù)按照E-Mail的數(shù)據(jù)格式整理郵件,然后將郵件發(fā)送到客戶端進行解析、顯示。在本節(jié)中,將向用戶講解POP3命令等相關(guān)知識。8.5.1 準備工作 在程序中,窗口界面是最重要的,因為程序界面直接面向用戶。當(dāng)用戶第一次使用軟件時,其窗口界面決定了用戶對該軟件的第一印象,所以我們先從設(shè)計對話框的界面開始,然后做些編程前的準備工作。1創(chuàng)建工程 創(chuàng)建基于對話框的工程,工程名為recvemil,注意在向?qū)У牡?步選中Windows Sockets復(fù)選框,如圖8.11所示。圖8.11 Windows Sockets復(fù)選框2. 添加控件 為對話框添加控件并設(shè)計界面如圖8.12所示:圖8.12 程序設(shè)計界面及其關(guān)鍵控件ID號 控件的ID以及為控件關(guān)聯(lián)的變量名和類型如圖8.13所示:圖8.13 控件關(guān)聯(lián)的變量名及類型
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度綠色餐飲采購標準合同3篇
- 二零二五年度冷鏈物流倉儲管理服務(wù)合同2篇
- 2025年度苗木種植基地土地租賃合同樣本(含品牌授權(quán))
- 2025年度飛行員勞動合同(含飛行業(yè)績獎勵)4篇
- 中醫(yī)師專屬2024聘用協(xié)議模板版B版
- 個性化全新承諾協(xié)議文檔(2024版)版B版
- 二零二五年度出租車公司股權(quán)置換及運營權(quán)轉(zhuǎn)讓協(xié)議3篇
- 2025年度個人商鋪租賃稅費代繳及財務(wù)結(jié)算合同4篇
- 二零二五年度農(nóng)民合作社加盟社員入社合同范本
- 個人寵物寄養(yǎng)服務(wù)2024年度合同
- 皮膚內(nèi)科過敏反應(yīng)病例分析
- 電影《獅子王》的視聽語言解析
- 妊娠合并低鉀血癥護理查房
- 煤礦反三違培訓(xùn)課件
- 向流程設(shè)計要效率
- 2024年中國航空發(fā)動機集團招聘筆試參考題庫含答案解析
- 當(dāng)代中外公司治理典型案例剖析(中科院研究生課件)
- 動力管道設(shè)計手冊-第2版
- 2022年重慶市中考物理試卷A卷(附答案)
- Python繪圖庫Turtle詳解(含豐富示例)
- 煤礦機電設(shè)備檢修技術(shù)規(guī)范完整版
評論
0/150
提交評論