




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、7.6 接收電子郵件的程序?qū)嵗?.6.1 實例程序的目的和實現(xiàn)的技術(shù)要點通過這個實例,讀者可以進(jìn)一步了解POP3的有關(guān)原理和內(nèi)容。程序的用戶界面如圖7.6所示:圖7.6 pop3電子郵件接收程序的用戶界面這個實例不太復(fù)雜,用戶可以利用某個網(wǎng)站的pop3電子郵件接收服務(wù)器來接收你在該網(wǎng)站的電子郵箱里的信件。首先填入pop3服務(wù)器地址、郵箱用戶名和口令,并決定是否要刪除郵箱里的郵件;然后點擊“連接”按鈕,程序會與服務(wù)器建立TCP連接,然后發(fā)送用戶名和口令,經(jīng)過驗證,進(jìn)入POP3會話。通過命令交互,將郵箱中的所有郵件取回。在此過程中,左下方的多文本列表框(RichTextBox)會顯示全部的會話信息
2、。信件全部下載完畢后,左上方的組合列表框中就有了所有信件的標(biāo)題字段。用戶可以從中選擇一封信件,查看或者存儲。然后可以斷開連接。實例只介紹了接收郵件,提取信頭標(biāo)題字段的有關(guān)內(nèi)容,能正確顯示符合Rfc822規(guī)范的郵件。由于目前郵件結(jié)構(gòu)非常復(fù)雜,限于篇幅,程序沒有對收到的信件作進(jìn)一步的分析,也沒有對編碼的信息進(jìn)行譯碼,讀者看到的是收信的原始信息,有興趣的讀者可以進(jìn)一步擴(kuò)展程序的功能,例如,對信件進(jìn)行MIME格式分析,將附件提取出來。程序?qū)崿F(xiàn)的技術(shù)要點是:1運用Windows的消息驅(qū)動機制除了由MFC創(chuàng)建的應(yīng)用程序類和對話框類以外,程序從CAsyncSocket類派生了自己的套接字類,并為它添加了On
3、Connect()、OnClose()和OnReceive()三個事件處理函數(shù)。程序的會話過程幾乎完全是由FD_READ消息驅(qū)動的。建立連接后,服務(wù)器會返回信息,接到命令后,服務(wù)器也會返回信息。當(dāng)信息到達(dá)客戶端套接字的接收緩沖區(qū)時,會觸發(fā)FD_READ消息,并自動執(zhí)行OnReceive()函數(shù)。該函數(shù)接收服務(wù)器發(fā)來的信息,進(jìn)行分析處理,然后再發(fā)送相應(yīng)的命令。這命令又會引來服務(wù)器的響應(yīng),又會觸發(fā)客戶端的FD_READ消息。如此周而復(fù)始,完成POP會話的全過程。2通過狀態(tài)轉(zhuǎn)換來控制會話命令的發(fā)布順序程序定義了一個枚舉類型STATE,并為套接字類定義了一個STATE類型的變量state,用來表示PO
4、P會話的實際狀態(tài)。容易看出,枚舉的成員符號是客戶端向POP3服務(wù)器發(fā)送的命令。typedef enum FIRST=0,USER,PASS,STAT,LIST,RETR,ENDRETR,DELE,GOON STATE;STATE state;當(dāng)用戶點擊“連接”按鈕與服務(wù)器建立TCP連接時,將state置為初值FIRST;然后,每當(dāng)收到服務(wù)器的信息,一方面根據(jù)會話的當(dāng)前狀態(tài)作響應(yīng)的分析處理,決定應(yīng)當(dāng)繼續(xù)發(fā)送哪條命令,另一方面發(fā)出下一個命令以后,改變state的值,將它置為該命令的狀態(tài)對應(yīng)的值,這就實現(xiàn)了會話過程中的狀態(tài)轉(zhuǎn)換,并保證會話按照既定的順序進(jìn)行。讀者可仔細(xì)分析mySock:Analyze
5、Msg()函數(shù)。3用結(jié)構(gòu)向量來緩存信件信息首先程序定義了一個結(jié)構(gòu)類型,用來緩存一封信件信息。typedef struct CString text; /存儲信件的文本int msgSize; /信件的大小int retrSize; /信件實際下載的大小,在下載過程中動態(tài)變化 MESSAGEPROP;然后為套接字類定義了一個向量型的成員變量,相當(dāng)于一個數(shù)組,其成員是上述的結(jié)構(gòu)。vector msgs; 在pop會話中,一次性地將信箱中所有信件的信息轉(zhuǎn)入這個向量,然后可以查閱,存儲到文件中,或者進(jìn)行其他處理。7.6.2 創(chuàng)建應(yīng)用程序的過程1使用MFC AppWizard創(chuàng)建應(yīng)用程序框架工程名是po
6、p3,應(yīng)用程序的類型是基于對話框的,對話框的標(biāo)題是“接收電子郵件客戶端程序”,需要Windows Sockets的支持,其它部分接受系統(tǒng)的默認(rèn)設(shè)置就可以。向?qū)ё詣訛閼?yīng)用程序創(chuàng)建了兩個類:應(yīng)用程序類:CPop3App,基類是CWinApp,對應(yīng)的文件是pop3.h和pop3.cpp。對話框類:CPop3Dlg,基類是CDialog,對應(yīng)的文件是pop3Dlg.h和pop3Dlg.cpp。2為對話框添加控件在程序的主對話框界面中按照圖7.6添加相應(yīng)的可視控件對象,并按照表7.6修改控件的屬性。表7.6 對話框中的控件屬性控件類型控件IDCaption靜態(tài)文本 static textIDC_STAT
7、ICpop3服務(wù)器地址靜態(tài)文本 static textIDC_STATIC用戶名靜態(tài)文本 static textIDC_STATIC口令編輯框 edit boxIDC_EDIT_SERVER編輯框 edit boxIDC_EDIT_USER編輯框 edit boxIDC_EDIT_PASS復(fù)選框 Check BoxIDC_CHECK_DEL刪除郵箱中的郵件多文本框 RichEdit BoxIDC_RICH_INFO組合選擇框ComboBoxIDC_COMB_LIST(Drop List型)命令按鈕 buttonIDC_BTN_CONN連接命令按鈕 buttonIDC_BTN_DISC斷開命令按
8、鈕 buttonIDCANCAL取消命令按鈕 buttonIDC_BTN_VIEW查看郵件命令按鈕 buttonIDC_BTN_SAVE存 儲3定義控件的成員變量按照表7.7,用類向?qū)?Class Wizard)為對話框中的控件對象定義相應(yīng)的成員變量。表7.7 控件對象的成員變量控件IDControl IDs變量名稱Member Variable Name變量類別Category變量類型Variable TypeIDC_EDIT_SERVERm_strServerValueCStringIDC_EDIT_USERm_strUserValueCStringIDC_EDIT_PASSm_strPa
9、ssValueCStringIDC_CHECK_DELm_bolDelValueBOOLIDC_COMB_LISTm_ctrListControlCComboBoxIDC_RICH_INFOm_InfoValueCStringm_ctrlnfoControlCRichEditCtrl4為對話框中的控件對象添加事件響應(yīng)函數(shù)按照表7.8,用類向?qū)?Class Wizard )為對話框中的控件對象添加事件響應(yīng)函數(shù)。表7.8 對話框控件的事件響應(yīng)函數(shù)控件類型對象標(biāo)識 ObjectID消息 Message函數(shù)Member functions命令按鈕IDC_BTN_CONNBN_CLICKEDOnBtnC
10、onn命令按鈕IDC_BTN_DISCBN_CLICKEDOnBtnDisc命令按鈕IDC_BTN_VIEWBN_CLICKEDOnBtnView命令按鈕IDC_BTN_SAVEBN_CLICKEDOnBtnSave5為Cpop3Dlg類添加其它的成員void Disp(LONG flag); /在不同的會話階段顯示不同的信息mySock pop3Socket; /套接字類對象實例6創(chuàng)建從CAsyncSocket類繼承的派生類為了能夠捕獲并響應(yīng)socket事件,應(yīng)創(chuàng)建用戶自己的套接字類,可利用類向?qū)砑印lass Type選擇MFC Class,類名為mySock,基類是CAsyncSock
11、et類,創(chuàng)建后對應(yīng)的文件是mysock.h和mysock.cpp。在利用類向?qū)閙ysock類添加OnConnect,OnClose和OnReceive三個事件處理函數(shù),并為它添加一般的成員函數(shù)和變量??蓞⒖聪乱恍」?jié)的程序代碼。7手工添加包含語句以及事件函數(shù)和成員函數(shù)的代碼8分階段編譯執(zhí)行,進(jìn)行測試7.6.3 程序清單1CPop3App應(yīng)用程序類對應(yīng)的文件pop3.h不動,在pop3.cpp的InitInstance()函數(shù)中添加一句初始化多文本框控件的函數(shù)。BOOL CPop3App:InitInstance()if (!AfxSocketInit()AfxMessageBox(IDP_SO
12、CKETS_INIT_FAILED);return FALSE;AfxEnableControlContainer(); /MFC自動創(chuàng)建的代碼AfxInitRichEdit(); /用戶添加的.2CPop3Dlg對話框類對應(yīng)的文件(1)pop3Dlg.h包含文件.#include mySock.h /添加套接字類的包含文件.class CPop3Dlg : public CDialog/ Constructionpublic:void Disp(LONG flag); /在不同的會話階段顯示不同的信息mySock pop3Socket; /套接字類對象實例CPop3Dlg(CWnd* pPa
13、rent = NULL); / standard constructor.(2)pop3Dlg.cpp實現(xiàn)文件#include stdafx.h#include pop3.h#include pop3Dlg.h#include mySock.h /手工添加的包含語句.BOOL CPop3Dlg:OnInitDialog()./ TODO: Add extra initialization here/用戶在這里添加控件成員變量的初始化代碼m_strServer = _T(); /POP3服務(wù)器地址m_strUser = _T(example); /郵箱的用戶名m_strPass = _T(123
14、456); /口令m_bolDel = FALSE; /下載郵件后不刪除m_Info = _T(); /多文本框清空return TRUE; / return TRUE unless you set the focus to a control./以下是事件處理函數(shù)和其他成員函數(shù)的代碼/當(dāng)用戶點擊連接按鈕時,執(zhí)行此函數(shù)void CPop3Dlg:OnBtnConn() /設(shè)定pop3類的對話框指針變量,使之指向本對話框,以便傳遞信息pop3Socket.SetParent(this); UpdateData(TRUE); /取來用戶在對話框中輸入的數(shù)據(jù)pop3Socket.Create();
15、/創(chuàng)建套接字對象的底層套接字pop3Socket.Connect(LPCSTR)m_strServer,110); /連接pop3服務(wù)器m_Info = ; /多文本列表框清空UpdateData(FALSE); /更新用戶界面/當(dāng)用戶點擊斷開按鈕時,執(zhí)行此函數(shù)void CPop3Dlg:OnBtnDisc() pop3Socket.Close();/當(dāng)用戶點擊查看郵件按鈕時,執(zhí)行此函數(shù)void CPop3Dlg:OnBtnView() int i;i = m_ctrList.GetCurSel(); /獲得用戶在組合框中的選擇/獲得并顯示指定信件的基本屬性及信件內(nèi)容m_Info += pop
16、3Socket.GetMsgStuff(i);m_Info += pop3Socket.GetMsgBody(i);/在不同的情況下,向用戶顯示不同的信息void CPop3Dlg:Disp(LONG flag)CString s;switch(flag)case S_CONNECT: /已連接到服務(wù)器,顯示信息s = 已連接到+m_strServer+.rn;m_Info+=s;/禁用連接按鈕GetDlgItem(IDC_BTN_CONN)-EnableWindow(FALSE);/啟用斷開按鈕GetDlgItem(IDC_BTN_DISC)-EnableWindow(TRUE);/禁用查看
17、郵件按鈕GetDlgItem(IDC_BTN_VIEW)-EnableWindow(FALSE);break;case S_RECEIVE:/收到服務(wù)器發(fā)來的響應(yīng),顯示它的內(nèi)容m_Info+=pop3Socket.lastMsg;break; case S_CLOSE: /顯示關(guān)閉連接的信息m_Info+=pop3Socket.error;s = 連接已經(jīng)關(guān)閉rn;m_Info+=s; /啟用連接按鈕GetDlgItem(IDC_BTN_CONN)-EnableWindow(TRUE);/禁用斷開按鈕GetDlgItem(IDC_BTN_DISC)-EnableWindow(FALSE); b
18、reak;case S_GETNUM: /已經(jīng)知道了郵箱中信件的總數(shù)s.Format(郵箱中共有 %d 封信rn,pop3Socket.numMsg);m_Info+=s;break;case S_GETSIZE: /顯示信件的大小s.Format(信箱中信件大小為:%d字節(jié)rn,pop3Socket.sizeMsg);m_Info+=s; break;case S_ENDRETR: /所有信件已下載完畢,顯示信息s.Format(共下載了 %d 封信件rn,pop3Socket.msgs.size();m_Info+=s;/如果有信件下載,啟用查看郵件按鈕if(pop3Socket.msgs
19、.size()0)GetDlgItem(IDC_BTN_VIEW)-EnableWindow(TRUE);break;UpdateData(FALSE); /更新用戶界面/當(dāng)點擊“存儲”按鈕時,執(zhí)行此函數(shù)。void CPop3Dlg:OnBtnSave() int i;CString s;i = m_ctrList.GetCurSel();/獲得指定信件的基本屬性及信件內(nèi)容s = pop3Socket.GetMsgStuff(i);s += pop3Socket.GetMsgBody(i);CFileDialog dlg(FALSE);if(dlg.DoModal()=IDOK)CFile f
20、ile(dlg.GetPathName(),CFile:modeCreate | CFile:modeWrite | CFile:typeBinary);file.Write(LPCSTR)s,s.GetLength();file.Close();3mySock套接字類對應(yīng)的文件(1)mysock.h包含文件.#include #include #include using namespace std;class CPop3Dlg;/顯示不同信息的標(biāo)志#define S_CLOSE 1 /當(dāng)關(guān)閉連接時,顯示關(guān)閉信息#define S_CONNECT 2 /當(dāng)連接成功時,顯示連接信息#defin
21、e S_RECEIVE 3 /當(dāng)收到服務(wù)器發(fā)來的信息時,顯示該信息#define S_GETNUM 4 /當(dāng)所有信件下載完畢后,顯示信箱中的信件總數(shù)#define S_GETSIZE 5 /當(dāng)所有信件下載完畢后,顯示信箱中的信件總大小#define S_ENDRETR 6 /當(dāng)所有信件下載完畢后,顯示相關(guān)信息/描述pop3會話狀態(tài)的枚舉類型typedef enum FIRST=0,USER,PASS,STAT,LIST,RETR,ENDRETR,DELE,GOON STATE;/用來緩存一封信件信息的結(jié)構(gòu)typedef struct CString text; /存儲信件的文本int msgS
22、ize; /信件的大小int retrSize; /信件實際下載的大小,在下載過程中動態(tài)變化 MESSAGEPROP;/自己的套接字類class mySock : public CAsyncSocket/ Attributespublic:CString lastMsg;CString error;int numMsg, sizeMsg, retrMsg;vector msgs; /盛放信件信息的向量/ Operationspublic:/獲得基本的郵件信頭字段: From, To, Date, Subject, BodyCString GetMsgStuff(int i); CString
23、GetMsgBody(int i); /獲得信件體CString GetMsgSubject(int i); /獲得信件標(biāo)題CString GetMsg(int i); /獲得整封信的內(nèi)容void Close(); /退出服務(wù)器void SetParent(CPop3Dlg * pDlg);mySock();virtual mySock();/ Overridespublic:/ ClassWizard generated virtual function overrides/AFX_VIRTUAL(mySock)public:virtual void OnConnect(int nError
24、Code);virtual void OnClose(int nErrorCode);virtual void OnReceive(int nErrorCode);/AFX_VIRTUAL/ Generated message map functions/AFX_MSG(mySock)/ NOTE - the ClassWizard will add and remove member functions here./AFX_MSG/ Implementationprotected:private:void ReadLn(int index,CString src, CString &dst)
25、;void AnalyzeMsg();CPop3Dlg* m_pDlg;STATE state;int delMsg;.(2)mysock.cpp實現(xiàn)文件#include stdafx.h#include pop3.h#include mySock.h#include pop3Dlg.h /自己添加的包含語句.#define MAX_BUFF 20000/構(gòu)造函數(shù),對某些成員變量初始化mySock:mySock()m_pDlg = NULL;state=FIRST;error=Not connected to serverrn;mySock:mySock()m_pDlg = NULL;./如果
26、連接成功,執(zhí)行此函數(shù)。/接到此消息僅僅顯示了一句話,開關(guān)了一些按鈕連接成功后,服務(wù)器發(fā)來響應(yīng),因此/又立即收到了OnReceive消息,后來的會話過程中,一來一往,程序總是收到/OnReceive消息,所以真正的事情在那里作。void mySock:OnConnect(int nErrorCode) if(nErrorCode=0) m_pDlg-Disp(S_CONNECT);/服務(wù)器端關(guān)閉連接,才會收到此消息。void mySock:OnClose(int nErrorCode) if(nErrorCode=0) m_pDlg-Disp(S_CLOSE);/套接字收到服務(wù)器發(fā)來的數(shù)據(jù)時,執(zhí)
27、行此函數(shù)void mySock:OnReceive(int nErrorCode) if(nErrorCode=0)char buffMAX_BUFF; /接收緩沖區(qū)int rec=Receive(buff,MAX_BUFF); /接收服務(wù)器發(fā)來的數(shù)據(jù)buffrec=NULL; /結(jié)尾置為NULL。lastMsg=buff;AnalyzeMsg(); /分析收到的數(shù)據(jù),作不同的處理 else error=在接收數(shù)據(jù)時發(fā)送了錯誤!rn;m_pDlg-Disp(S_CLOSE); /顯示信息/設(shè)置套接字類的對話框指針變量void mySock:SetParent(CPop3Dlg *pDlg)m_
28、pDlg = pDlg;/獲得第 i 封信件的標(biāo)題信息CString mySock:GetMsgStuff(int i)CString ret;int where=msgsi.text.Find(From:);ReadLn(where,msgsi.text,ret);ret+=rn;where=msgsi.text.Find(To:);if (where!=-1)ReadLn(where,msgsi.text,ret);ret+=rn;where=msgsi.text.Find(Date:);if (where!=-1)ReadLn(where,msgsi.text,ret);ret+=rn;
29、ret+=GetMsgSubject(i);ret+=rn;return ret;/獲得第 i 封信件的信件體CString mySock:GetMsgBody(int i)CString ret;int where=msgsi.text.Find(rnrn);if(where!=-1) where+=4;else where=0;ret=msgsi.text.Right(msgsi.text.GetLength()-where);ret=ret.Left(ret.GetLength()-3);return ret;/獲得第 i 封信件的標(biāo)題CString mySock:GetMsgSubje
30、ct(int i)int where=msgsi.text.Find(Subject:);CString ret;if (where!=-1) ReadLn(where,msgsi.text,ret);return ret;/獲得第 i 封信整封信的內(nèi)容CString mySock:GetMsg(int i)return msgsi.text;/從src串中,從index所指的位置開始,取子字串,直到行末符r為止。/dst是一個串的地址,取出的行追加在該串的原內(nèi)容之后void mySock:ReadLn(int index,CString src, CString &dst)CString c
31、omp;comp=srcindex;while(comp!=r)dst+=comp;comp=src+index;/退出服務(wù)器void mySock:Close()CString str;str.Format(quit%c%c,13,10);Send(LPCSTR)str,str.GetLength();m_pDlg-Disp(S_CLOSE);state=FIRST;CAsyncSocket:Close();error=Not connected to serverrn;void mySock:AnalyzeMsg()CString s;strstream str;string check;
32、strcheck; /提取所收到信息的第一段代碼if(check=-ERR) /如果有錯誤error=Received -ERR from server :+lastMsg;Close(); /斷開連接,然后關(guān)閉return;/如果沒有錯誤,則根據(jù)不同的會話階段響應(yīng)來處理switch(state) case FIRST: /如果已經(jīng)連接成功,類初始化的時候state為FIRSTmsgs.clear();/顯示連接成功后服務(wù)器返回的消息m_pDlg-Disp(S_RECEIVE); /發(fā)送 user 用戶名 命令s.Format(user %s%c%c,m_pDlg-m_strUser,13,1
33、0);Send(LPCSTR)s,s.GetLength(); /發(fā)送用戶帳號state=USER;break;case USER:/顯示服務(wù)器對于user命令的響應(yīng)m_pDlg-Disp(S_RECEIVE);/發(fā)送 pass 口令命令,發(fā)送密碼s.Format(pass %s%c%c,m_pDlg-m_strPass,13,10); Send(LPCSTR)s,s.GetLength(); state=PASS;break;case PASS:/顯示服務(wù)器對 pass 命令的響應(yīng)m_pDlg-Disp(S_RECEIVE);/發(fā)送 stat 命令,請求服務(wù)器返回信箱中/郵件的數(shù)量和所占空間
34、的大小s.Format(stat%c%c,13,10);Send(LPCSTR)s,s.GetLength();state=STAT; break;case STAT:string s1;str.seekg(0); /將字符流的當(dāng)前指針置為0strs1numMsgsizeMsg; /獲得數(shù)量和大小flush(str);m_pDlg-Disp(S_GETNUM);m_pDlg-Disp(S_GETSIZE);if(numMsg0) /如果有郵件,則發(fā)送RETR獲得郵件信息retrMsg=1; /要取第一封信MESSAGEPROP prop; /準(zhǔn)備存放信件的地方prop.msgSize=0; /
35、成員置初值prop.retrSize=0;prop.text=;msgs.push_back(prop); /壓入向量表s.Format(retr 1%c%c,13,10);Send(LPCSTR)s,s.GetLength(); state=RETR;else /如果沒有郵件,則斷開error=No new messagesrn;Close();break;case RETR:/顯示取回來的信件文本m_pDlg-Disp(S_RECEIVE);/一封信的內(nèi)容可能多次才能接受回來,但是對于一封信,第一次/接收到數(shù)據(jù)的時候,對應(yīng)向量結(jié)構(gòu)的msgSize成員變量為0if(msgsretrMsg-1
36、.msgSize=0) string temp;str.seekg(0);/將該信件的大小存放到成員變量中strtempmsgsretrMsg-1.msgSize; /將數(shù)據(jù)追加保存到text成員變量中msgsretrMsg-1.text+=lastMsg; /將數(shù)據(jù)大小累加到retrSize成員變量中,代表已經(jīng)取回來的數(shù)量msgsretrMsg-1.retrSize+=lastMsg.GetLength();/判斷是否獲得所有數(shù)據(jù)if(msgsretrMsg-1.retrSize=msgsretrMsg-1.msgSize) /檢查是否有其他郵件if(retrMsgm_bolDel & nu
37、mMsg0) state=DELE;delMsg=1;s.Format(dele %d%c%c,delMsg,13,10);Send(LPCSTR)s,s.GetLength(); else /否則退出state=ENDRETR;m_pDlg-Disp(S_ENDRETR);error=Session endedrn;s.Format(quit%c%c,13,10);Send(LPCSTR)s,s.GetLength();Close();for(int i=0;im_ctrList.AddString(LPCSTR)GetMsgSubject(i);m_pDlg-m_ctrList.SetCu
38、rSel(0);break;case DELE:/刪除剩余郵件if(delMsgDisp(S_ENDRETR);state=GOON;error=Deleted all messagesrn;s.Format(quit%c%c,13,10);Send(LPCSTR)s,s.GetLength();Close();break;case GOON:default:m_pDlg-Disp(S_RECEIVE);break;7.7 發(fā)送電子郵件的程序?qū)嵗?.7.1 實例程序的目的和實現(xiàn)的技術(shù)要點通過這個實例,讀者可以進(jìn)一步了解SMTP的有關(guān)原理和內(nèi)容。程序的用戶界面如圖7.7所示:圖7.7 smtp電
39、子郵件發(fā)送程序的用戶界面這個實例實現(xiàn)了smtp電子郵件發(fā)送程序的一些功能,用戶可以利用某個網(wǎng)站的smtp電子郵件發(fā)送服務(wù)器來發(fā)送電子郵件。你必須是該網(wǎng)站的注冊用戶,并在該網(wǎng)站申請了免費郵箱。首先填入smtp服務(wù)器地址、郵箱用戶名和口令,端口號是25,并填入發(fā)信人,發(fā)信地址填入你在該網(wǎng)站的免費郵箱地址。在對話框的右面填入發(fā)送電子郵件的相關(guān)信息,選擇一個附件,然后點擊“發(fā)送”按鈕,程序會與服務(wù)器建立TCP連接,然后按照ESMTP協(xié)議發(fā)送ELHO命令,然后發(fā)送用戶名和口令,經(jīng)過驗證,進(jìn)入SMTP會話。通過命令交互,將郵件和附件發(fā)送出去,然后斷開連接。在此過程中,右下方的多文本列表框(RichText
40、Box)會顯示全部的會話信息?,F(xiàn)在的SMTP服務(wù)器與以前不一樣,一般都要經(jīng)過驗證身份后,才為你提供傳輸郵件的服務(wù),驗證的方法有很多種,這里只實現(xiàn)了一種,僅僅為了說明問題。程序?qū)崿F(xiàn)的技術(shù)要點是:1運用Windows的消息驅(qū)動機制與7.6節(jié)的實例基本相同。2通過狀態(tài)轉(zhuǎn)換來控制會話命令的發(fā)布順序與7.6節(jié)的實例基本相同。3實現(xiàn)了base64編碼和譯碼。7.7.2 創(chuàng)建應(yīng)用程序的過程1使用MFC AppWizard創(chuàng)建應(yīng)用程序框架工程名是smtp,應(yīng)用程序的類型是基于對話框的,對話框的標(biāo)題是“電子郵件發(fā)送客戶端程序”,需要Windows Sockets的支持,其它部分接受系統(tǒng)的默認(rèn)設(shè)置就可以。向?qū)ё詣?/p>
41、為應(yīng)用程序創(chuàng)建了兩個類:應(yīng)用程序類:CSmtpApp,基類是CWinApp,對應(yīng)的文件是smtp.h和smtp.cpp。對話框類:CSmtpDlg,基類是CDialog,對應(yīng)的文件是smtpDlg.h和smtpDlg.cpp。2為對話框添加控件在程序的主對話框界面中按照圖7.7添加相應(yīng)的可視控件對象,并按照表7.9修改控件的屬性。表7.9 對話框中的控件屬性控件類型控件IDCaption靜態(tài)文本 static textIDC_STATIC發(fā)信人靜態(tài)文本 static textIDC_STATIC發(fā)信地址靜態(tài)文本 static textIDC_STATICSMTP服務(wù)器靜態(tài)文本 static t
42、extIDC_STATIC端口靜態(tài)文本 static textIDC_STATIC用戶名靜態(tài)文本 static textIDC_STATIC口令編輯框 edit boxIDC_EDIT_NAME編輯框 edit boxIDC_EDIT_ADDR編輯框 edit boxIDC_EDIT_SERVER編輯框 edit boxIDC_EDIT_PORT編輯框 edit boxIDC_EDIT_USER編輯框 edit boxIDC_EDIT_PASS靜態(tài)文本 static textIDC_STATIC收信靜態(tài)文本 static textIDC_STATIC主題靜態(tài)文本 static textIDC_
43、STATIC抄送靜態(tài)文本 static textIDC_STATIC暗送靜態(tài)文本 static textIDC_STATIC附件靜態(tài)文本 static textIDC_STATIC信件內(nèi)容編輯框 edit boxIDC_EDIT_RECEIVER編輯框 edit boxIDC_EDIT_TITLE編輯框 edit boxIDC_EDIT_CC編輯框 edit boxIDC_EDIT_BCC編輯框 edit boxIDC_EDIT_ATTACH編輯框 edit boxIDC_EDIT_LETTER命令按鈕 buttonIDC_BTN_VIEW瀏覽靜態(tài)文本 static textIDC_STATI
44、Csmtp 會話的狀態(tài)信息多文本框 RichEdit BoxIDC_RICH_LIST命令按鈕 buttonIDOK發(fā)送命令按鈕 buttonIDCANCEL取消3定義控件的成員變量按照表7.10,用類向?qū)?Class Wizard)為對話框中的控件對象定義相應(yīng)的成員變量。表7.10 控件對象的成員變量控件IDControl IDs變量名稱Member Variable Name變量類別Category變量類型Variable TypeIDC_EDIT_NAMEm_NameValueCStringIDC_EDIT_ADDRm_AddrValueCStringIDC_EDIT_SERVERm_S
45、erverValueCStringIDC_EDIT_PORTm_PortValueUINTIDC_EDIT_USERm_UserValueCStringIDC_EDIT_PASSm_PassValueCStringIDC_EDIT_RECEIVERm_ReceiverValueCStringIDC_EDIT_TITLEm_TitleValueCStringIDC_EDIT_CCm_CCValueCStringIDC_EDIT_BCCm_BCCValueCStringIDC_EDIT_ATTACHm_AttachValueCStringIDC_EDIT_LETTERm_LetterValueCS
46、tringIDC_RICH_INFOm_InfoValueCString4為對話框中的控件對象添加事件響應(yīng)函數(shù)按照表7.11,用類向?qū)?Class Wizard )為對話框中的控件對象添加事件響應(yīng)函數(shù)。表7.11 對話框控件的事件響應(yīng)函數(shù)控件類型對象標(biāo)識 ObjectID消息 Message函數(shù)Member functions命令按鈕IDC_BTN_VIEWBN_CLICKEDOnBtnView命令按鈕IDOKBN_CLICKEDOnIDOK5創(chuàng)建一個普通的類CBase64,用來實現(xiàn)base64編碼和解碼。6創(chuàng)建從CAsyncSocket類繼承的派生類為了能夠捕獲并響應(yīng)socket事件,應(yīng)創(chuàng)建
47、用戶自己的套接字類,可利用類向?qū)砑印lass Type選擇MFC Class,類名為mySock,基類是CAsyncSocket類,創(chuàng)建后對應(yīng)的文件是mysock.h和mysock.cpp。在利用類向?qū)閙ysock類添加OnConnect,OnClose和OnReceive三個事件處理函數(shù),并為它添加一般的成員函數(shù)和變量??蓞⒖聪乱恍」?jié)的程序代碼。7手工添加包含語句以及事件函數(shù)和成員函數(shù)的代碼8分階段編譯執(zhí)行,進(jìn)行測試7.7.3 程序清單1CSmtpApp應(yīng)用程序類對應(yīng)的文件smtp.h不動,在smtp.cpp的InitInstance()函數(shù)中添加一句初始化多文本框控件的函數(shù)。BOOL
48、 CSmtpApp:InitInstance()if (!AfxSocketInit()AfxMessageBox(IDP_SOCKETS_INIT_FAILED);return FALSE;AfxEnableControlContainer(); /MFC自動創(chuàng)建的代碼AfxInitRichEdit(); /用戶自己添加的.2CSmtpDlg對話框類對應(yīng)的文件(1)smtpDlg.h包含文件.#include mySock.h /自己添加的包含語句#include Base64.h /自己添加的包含語句.class CSmtpDlg : public CDialog/ Constructionpublic:void Disp(LONG flag); /顯示信息void GetHeader(); /創(chuàng)建電子郵件的
溫馨提示
- 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五工傷私了賠償協(xié)議范本深度修訂
- 2025年度物業(yè)賠償業(yè)主公共區(qū)域設(shè)施損壞協(xié)議書
- 二零二五年度自媒體平臺內(nèi)容創(chuàng)作者扶持計劃合作協(xié)議
- 2025年度汽車抵押貸款利息調(diào)整合同
- 二零二五年度診所合伙人投資合作與權(quán)益保障協(xié)議
- 二零二五年度餐飲店面租賃合同含節(jié)假日特色活動策劃
- 鼎捷E10-6.0培訓(xùn)教材-質(zhì)量管理
- 《物流系統(tǒng)分析》課件 項目二任務(wù)三 了解物流需求預(yù)測
- 2025年蚌埠道路客貨運輸從業(yè)資格證模擬考試下載
- 2025年濟(jì)南貨運從業(yè)資格證考試題答案
- 藍(lán)色卡通風(fēng)好書推薦教育PPT模板
- 《納米復(fù)合材料》第2章 納米復(fù)合材料概論
- 建設(shè)工程圍擋標(biāo)準(zhǔn)化管理圖集(2022年版)
- 宮頸癌HPV疫苗知識培訓(xùn)(課堂PPT)
- 2019版外研社高中英語必選擇性必修一單詞表
- 建設(shè)工程綠色施工圍蔽指導(dǎo)圖集
- 班主任培訓(xùn)-家校溝通課件
- 河南省縣普通高中學(xué)生學(xué)籍卡片
- 中級Java軟件開發(fā)工程師筆試題(附答案)
- 高一物理必修一加速度(課堂PPT)
- 難免壓瘡申報表
評論
0/150
提交評論