版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
/無(wú)須SMTP服務(wù)器中轉(zhuǎn)直接發(fā)送電子郵件前言大家一定熟悉Foxmail中的“特快專遞”,它能直接將電子郵件發(fā)送到對(duì)方的郵件服務(wù)器中,而不需要經(jīng)過(guò)SMTP服務(wù)器中轉(zhuǎn),這樣做有什么好處?第一:發(fā)送速度比較快,不需要等SMTP服務(wù)器對(duì)郵件進(jìn)行查毒、派發(fā)、驗(yàn)證;第二:你可以及時(shí)掌握郵件是否發(fā)送成功的信息.有時(shí)我們用Outlook發(fā)送一封郵件,到第二天對(duì)方都沒(méi)收到,可我這邊確實(shí)已經(jīng)發(fā)送成功了,只好讓對(duì)方多收幾次,到了第三天SMTP服務(wù)器回信說(shuō)“不好意思,你發(fā)往XXX的郵件因?yàn)閄XX原因未能送達(dá)……”,原來(lái)郵件被打回來(lái)了,尤其最近163郵箱非常離譜,我發(fā)出去的10封郵件,至少有3封會(huì)被無(wú)故打回來(lái),說(shuō)什么“網(wǎng)絡(luò)連接失敗"所以被打回,莫名其妙,可能我是免費(fèi)郵箱的緣故吧,沒(méi)辦法只好再申請(qǐng)多幾個(gè)郵箱,我現(xiàn)在已經(jīng)有“chry、chrys.xi、……”好多郵箱了,就是為了防止給別人發(fā)郵件時(shí)被無(wú)故退回……扯遠(yuǎn)了,不好意思。第三:我們有時(shí)需要在程序里將某些敏感信息發(fā)送至公司郵箱,例如:計(jì)算注冊(cè)碼時(shí)我們需要用戶操作我們的軟件將申請(qǐng)注冊(cè)的信息發(fā)送回我們的售后服務(wù)郵箱,由我們的工作人員處理來(lái)這些郵件。大家一定會(huì)想用SMTP(SimpleMailTransferProtocol)借助SMTP服務(wù)器也能通過(guò)程序?qū)崿F(xiàn)郵件發(fā)送,但是有一個(gè)很大問(wèn)題就是安全問(wèn)題,很多著名的郵件服務(wù)器運(yùn)營(yíng)商對(duì)于用軟件方式通過(guò)SMTP協(xié)議頻繁提交郵件轉(zhuǎn)發(fā)的申請(qǐng)是不歡迎的,我的163郵箱就曾經(jīng)深受其害,我那次是在寫SMTP客戶端發(fā)送郵件的程序,順手就用了163的SMTP服務(wù)器,我剛發(fā)到第5封郵件時(shí)就發(fā)送失敗了,我再登錄163網(wǎng)站一查,原來(lái)我的賬號(hào)被封了,原因就是我用軟件發(fā)送郵件太多了(天啦,才5封而已啊),后來(lái)我花了近兩個(gè)月時(shí)間跟新浪公司又賠禮又道歉,還把身份證傳真過(guò)去了我的賬號(hào)才被恢復(fù)。剖析郵件傳送過(guò)程廢話說(shuō)太多請(qǐng)別介意,現(xiàn)在言歸正傳,要直接將郵件送到對(duì)方(POP或IMAP)服務(wù)器上,而不經(jīng)過(guò)SMTP郵件服務(wù)器轉(zhuǎn)交,其實(shí)也不難,你只要改用Unix/Linux操作系統(tǒng),直接SendMail命令就能完成,但在Windows下想要實(shí)現(xiàn)這個(gè)功能恐怕得花一點(diǎn)心思了.我們首先要從協(xié)議RFC821—SimpleMailTransferProtocol入手來(lái)分析.首先我們看一下Email的遞送過(guò)程:郵件原文→編碼→SMTP客戶端→SMTP轉(zhuǎn)交服務(wù)器→遠(yuǎn)程SMTP服務(wù)器(對(duì)方郵局).“特快專遞”的實(shí)現(xiàn)思路郵件編碼后被遞送到一個(gè)SMTP轉(zhuǎn)交服務(wù)器上,該服務(wù)器對(duì)信件分檢(到同一郵局的被放在一起)后,根據(jù)優(yōu)先級(jí)以及信件的先后次序被發(fā)送到遠(yuǎn)程郵局的SMTP服務(wù)器上。換句話說(shuō),只要我們知道了SMTP轉(zhuǎn)交服務(wù)器是如何確定遠(yuǎn)程郵局SMTP服務(wù)器的地址的,就可以直接遞送到遠(yuǎn)程郵局服務(wù)器。SMTP轉(zhuǎn)交服務(wù)器又是知道遠(yuǎn)程郵局的地址呢?這就是域名解析所完成的工作了,就好比我們?cè)冢蒃瀏覽器輸入“”這個(gè)域名,IE瀏覽器又如何知道目標(biāo)服務(wù)器的IP地址呢?也是域名解析服務(wù)器的功勞.電子郵件地址由兩部分組成,例如:chry,這里的chrys是郵箱名(即用戶名,一個(gè)用戶對(duì)應(yīng)一個(gè)郵箱),163。com是郵箱服務(wù)器地址,郵箱名和郵箱服務(wù)器地址之間以“@”作為分隔.我們只要向域名服務(wù)器發(fā)送查詢“163。com"的遠(yuǎn)程郵局服務(wù)器地址便可找到遠(yuǎn)程郵局SMTP服務(wù)器的IP地址,該查詢指令被稱作MX(MailExchange)郵件交換服務(wù)器的地址查詢。遠(yuǎn)程郵局SMTP服務(wù)器的地址可能不止一個(gè),這時(shí),你可根據(jù)信件優(yōu)先級(jí)的不同來(lái)選擇對(duì)應(yīng)的遠(yuǎn)程郵局,我為了安全起見(jiàn)會(huì)對(duì)每一個(gè)遠(yuǎn)程郵局服務(wù)器按照等級(jí)高低逐一嘗試,只要將郵件成功地發(fā)送到其中一個(gè)郵局我們的任務(wù)就完成了.我們要完成幾項(xiàng)編程工作:本機(jī)DNS的獲取、與DNS服務(wù)器通信實(shí)現(xiàn)MX指令查詢、SMTP郵件提交,下面我們一一闡述。獲取本機(jī)DNS代碼中我封裝了一個(gè)類CnetAdapterInfo,該類可以獲取本機(jī)網(wǎng)卡的系列信息,包括本機(jī)IP地址、子網(wǎng)掩碼、DNS、Wins、網(wǎng)卡MAC地址等相關(guān)信息。首先我們需要調(diào)用IPHelpAPI庫(kù)中的GetAdaptersInfo()函數(shù)來(lái)獲取系統(tǒng)中所有網(wǎng)卡信息。DWORDGetAdaptersInfo(__outPIP_ADAPTER_INFOpAdapterInfo,__(dá)inoutPULONGpOutBufLen);該函數(shù)有兩個(gè)參數(shù),pAdapterInfo是一個(gè)指針,指向一個(gè)用戶定義的結(jié)構(gòu)體,一般是用HeapAlloc()申請(qǐng)的內(nèi)存空間,pOutBufLen傳入pAdapterInfo所指空間的大小,傳出實(shí)際需要的緩沖大小,第一次調(diào)用該函數(shù)時(shí)pOutBufLen傳入0,函數(shù)將返回ERROR_BUFFER_OVERFLOW表示需要更多的緩沖,并將實(shí)際需要的緩沖長(zhǎng)度返回,我們根據(jù)實(shí)際長(zhǎng)度用HeapAlloc()函數(shù)申請(qǐng)空間再次調(diào)用該函數(shù),以下代碼是枚舉所有網(wǎng)卡并將信息保存到數(shù)組m_Ary_NetAdapterInfo中:#defineMALLOC(bytes)::HeapAlloc(::GetProcessHeap(),HEAP_ZERO_MEMORY,(bytes))
#defineFREE(ptr)if(ptr)::HeapFree(cuò)(::GetProcessHeap(),0,ptr)?#defineREMALLOC(ptr,bytes)::HeapReAlloc(::GetProcessHeap(),HEAP_ZERO_MEMORY,ptr,bytes)?//?//枚舉網(wǎng)絡(luò)適配器?//return:---——————-—-—-——-—-——---—--—-----—---—————-—-—-----—--?//—1—失敗?//>=0—網(wǎng)絡(luò)適配器數(shù)量?//?intCNetAdapterInfo::EnumNetworkAdapters()?{
DeleteAllNetAdapterInfo();
IP_ADAPTER_INFO*pAdptInfo=NULL;
IP_ADAPTER_INFO*pNextAd=NULL;
ULONGulLen=0;
intnCnt=0;
?DWORDdwError=::GetAdaptersInfo(pAdptInfo,&ulLen);
if(dwError!=ERROR_BUFFER_OVERFLOW)return-1;
pAdptInfo=(IP_ADAPTER_INFO*)MALLOC(ulLen);?dwError=::GetAdaptersInfo(pAdptInfo,&ulLen);
if(dwError!=ERROR_SUCCESS)return—1;
pNextAd=pAdptInfo;
while(pNextAd)?{?COneNetAdapterInfo*pOneNetAdapterInfo=newCOneNetAdapterInfo(pNextAd);?if(pOneNetAdapterInfo)?{?m_Ary_NetAdapterInfo.Add(pOneNetAdapterInfo);?}?nCnt++;
pNextAd=pNextAd-〉Next;
}
?//freeanymemoryweallocatedfromtheheapbefore?//exit.wewouldn'twannaleavememoryleaksnowwouldwe?;p?FREE(pAdptInfo);
returnnCnt;
}針對(duì)每個(gè)網(wǎng)卡信息,我們需要調(diào)用GetPerAdapterInfo()函數(shù)來(lái)獲取指定網(wǎng)卡的DNS信息,使用方法和GetAdaptersInfo()類似。以下代碼獲取網(wǎng)卡基本信息://
//根據(jù)傳入的pAdptInfo信息來(lái)獲取指定網(wǎng)卡的基本信息?//
BOOLCOneNetAdapterInfo::Init()?{?IP_ADDR_STRING*pNext=NULL;?IP_PER_ADAPTER_INFO*pPerAdapt=NULL;?ULONGulLen=0;
DWORDdwErr=ERROR_SUCCESS;?ASSERT(m_AdptInfo.AddressLength〉0);?t_IPINFOiphold;?//將變量清空?m_bInitOk=FALSE;
m_csName.Empty();?m_csDesc.Empty();
m_CurIPInfo。csIP.Empty();?m_CurIPInfo。csSubnet.Empty();
m_Ary_IP.RemoveAll();
m_Ary_DNS.RemoveAll();
m_Ary_Gateway.RemoveAll();?
#ifndef_UNICODE?m_csName=m_AdptInfo.AdapterName;?m_csDesc=m_AdptInfo.Description;
#else
USES_CONVERSION;
m_csName=A2W(m_AdptInfo.AdapterName);
m_csDesc=A2W(m_AdptInfo。Description);
#endif?//獲取當(dāng)前正在使用的IP地址
if(m_AdptInfo.CurrentIpAddress)
{
m_CurIPInfo。csIP=m_AdptInfo.CurrentIpAddress—〉IpAddress.String;
m_CurIPInfo。csSubnet=m_AdptInfo.CurrentIpAddress->IpMask.String;?}?else?{
m_CurIPInfo.csIP=_T(”0.0。0.0”);?m_CurIPInfo。csSubnet=_T(”0。0.0。0");
}
?//獲取本網(wǎng)卡中所有的IP地址
pNext=&(m_AdptInfo。IpAddressList);?while(pNext)
{?iphold.csIP=pNext—〉IpAddress.String;
iphold。csSubnet=pNext->IpMask。String;
m_Ary_IP。Add(iphold);?pNext=pNext->Next;?}
?//獲取本網(wǎng)卡中所有的網(wǎng)關(guān)信息?pNext=&(m_AdptInfo.GatewayList);
while(pNext)?{
m_Ary_Gateway.Add(pNext-〉IpAddress。String);
pNext=pNext->Next;?}
//獲取本網(wǎng)卡中所有的DNS
dwErr=::GetPerAdapterInfo(m_AdptInfo。Index,pPerAdapt,&ulLen);
if(dwErr==ERROR_BUFFER_OVERFLOW)?{?pPerAdapt=(IP_PER_ADAPTER_INFO*)MALLOC(ulLen);
dwErr=::GetPerAdapterInfo(m_AdptInfo。Index,pPerAdapt,&ulLen);
//ifwesucceedthanweneedtodropintoourloop
//andfillthednsarraywillallavailableIP?//addresses.
if(dwErr==ERROR_SUCCESS)?{
pNext=&(pPerAdapt-〉DnsServerList);?while(pNext)
{
m_Ary_DNS.Add(pNext—>IpAddress。String);
pNext=pNext-〉Next;
}?m_bInitOk=TRUE;
}?//thisisdoneoutsidethedwErr==ERROR_SUCCESjustincase.themacro?//usesNULLpointercheckingsoitisokifpPerAdaptwasneverallocat(yī)ed。?FREE(pPerAdapt);?}
returnm_bInitOk;?}至此我們已經(jīng)獲取到系統(tǒng)中所有DNS服務(wù)器地址了.MX指令查詢獲取遠(yuǎn)程郵局地址與DNS服務(wù)器通信其實(shí)就是一個(gè)簡(jiǎn)單的UDP網(wǎng)絡(luò)通信,端口號(hào)為53,通信的數(shù)據(jù)格式如下:所有的DNS消息基本上都是相同的數(shù)據(jù)結(jié)構(gòu),但DNSRR是采用了其他的數(shù)據(jù)結(jié)構(gòu)。QNAME是一個(gè)表示域長(zhǎng)度的變量,表示每一節(jié)有多少字節(jié),例如:將表示為:最后的“Additional”通常包含了查詢服務(wù)器期望被發(fā)送的紀(jì)錄以減少通信量,例如,回應(yīng)MX查詢時(shí)通常在“Additional”中包含‘A'紀(jì)錄。具體的MX查詢過(guò)程請(qǐng)參加源代碼,以下代碼實(shí)現(xiàn)了獲取本機(jī)所有DNS,然后逐一嘗試MX查詢的方法://?//嘗試所有的DNS來(lái)查詢郵局服務(wù)器地址?//
BOOLGetMX(
char*pszQuery,//要查詢的域名?OUTt_Ary_MXHostInfos&Ary_MXHostInfos//輸出MailExchange主機(jī)名
)
{?CNetAdapterInfom_NetAdapterInfo;?m_NetAdapterInfo.Refresh();
intnNetAdapterCount=m_NetAdapterInfo.GetNetCardCount();
for(inti=0;i<nNetAdapterCount;i++)
{
COneNetAdapterInfo*pOneNetAdapterInfo=m_NetAdapterInfo。Get_OneNetAdapterInfo(i);
if(pOneNetAdapterInfo)?{
intnDNSCount=pOneNetAdapterInfo—〉Get_DNSCount();?for(intj=0;j〈nDNSCount;j++)?{
CStringcsDNS=pOneNetAdapterInfo—>Get_DNSAddr(j);?if(GetMX(pszQuery,csDNS.GetBuffer(0),Ary_MXHostInfos))
returnTRUE;?}?}?}
returnFALSE;
}如果查詢“”的郵局服務(wù)器地址,將得到如下的結(jié)果:505051010用SMTP協(xié)議給遠(yuǎn)程郵局直接發(fā)送郵件SMTP是一個(gè)簡(jiǎn)單郵件傳輸協(xié)議,通過(guò)TCP連接服務(wù)器的25端口號(hào)即可進(jìn)行數(shù)據(jù)通信,以下是我用telnet手工發(fā)送郵件的過(guò)程:其中紅色矩形框起來(lái)的是服務(wù)器回應(yīng)的數(shù)據(jù),綠色矩形框起來(lái)的是我手工輸入的數(shù)據(jù),這里發(fā)送的郵件內(nèi)容為“我是手工發(fā)送的電子郵件",郵件被直接發(fā)送到chrys.xi郵箱中,不需要討厭的SMTP服務(wù)器中轉(zhuǎn),當(dāng)然,因?yàn)檫@是手工發(fā)送的郵件,其內(nèi)容未經(jīng)過(guò)任何MIME編碼,這封郵件可以被Foxmail或Outlook收到,但可能被判為垃圾郵件,因?yàn)檫@封郵件連標(biāo)題都沒(méi)有,是無(wú)頭蒼蠅,肯定是垃圾,呵呵……關(guān)于郵件內(nèi)容的編碼請(qǐng)參考其他相關(guān)資料,我有一本書,名叫《VisualC++網(wǎng)絡(luò)通信協(xié)議分析與應(yīng)用實(shí)現(xiàn)》,這本書有詳細(xì)的電子郵件編碼介紹,可以下載電子文檔看看。當(dāng)我們知道了SMTP通信的全過(guò)程,再編寫一個(gè)TCP網(wǎng)絡(luò)通信程序處理與SMTP服務(wù)器請(qǐng)求就不是難事了。本代碼中的CHwSMTP類已經(jīng)封裝了整個(gè)通信過(guò)程
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024版汽車銷售合同范本
- 2024陜西智能制造行業(yè)勞動(dòng)合同范本3篇
- 二零二五年度餐飲品牌加盟店合同范本3篇
- 2024版施工工程勞務(wù)分包合同
- 二零二五年高溫高壓管道材料購(gòu)銷合同2篇
- 專用倉(cāng)儲(chǔ)物流倉(cāng)庫(kù)建設(shè)施工協(xié)議模板版B版
- 二零二五版國(guó)有企業(yè)員工勞動(dòng)合同解除與經(jīng)濟(jì)補(bǔ)償協(xié)議3篇
- 二零二五版?zhèn)€人購(gòu)房貸款擔(dān)保與房屋權(quán)屬登記服務(wù)合同3篇
- 2024版代生產(chǎn)加工服務(wù)合同范本2篇
- 二零二五年度特色餐飲品牌加盟保密合同范本3篇
- 國(guó)網(wǎng)山東電力生產(chǎn)技術(shù)改造原則
- 鐵路運(yùn)輸安全現(xiàn)場(chǎng)管理
- 2023年某保險(xiǎn)公司春節(jié)經(jīng)營(yíng)教材
- 劉都才-南方水稻田雜草發(fā)生動(dòng)態(tài)及防控技術(shù)
- 全自動(dòng)化學(xué)發(fā)光分析儀操作規(guī)程
- 北侖區(qū)建筑工程質(zhì)量監(jiān)督站監(jiān)督告知書
- 深藍(lán)的故事(全3冊(cè))
- GB/T 42461-2023信息安全技術(shù)網(wǎng)絡(luò)安全服務(wù)成本度量指南
- 職校開學(xué)第一課班會(huì)PPT
- 央國(guó)企信創(chuàng)白皮書 -基于信創(chuàng)體系的數(shù)字化轉(zhuǎn)型
- GB/T 36964-2018軟件工程軟件開發(fā)成本度量規(guī)范
評(píng)論
0/150
提交評(píng)論