無(wú)須SMTP服務(wù)器中轉(zhuǎn)直接發(fā)送電子郵件_第1頁(yè)
無(wú)須SMTP服務(wù)器中轉(zhuǎn)直接發(fā)送電子郵件_第2頁(yè)
無(wú)須SMTP服務(wù)器中轉(zhuǎn)直接發(fā)送電子郵件_第3頁(yè)
無(wú)須SMTP服務(wù)器中轉(zhuǎn)直接發(fā)送電子郵件_第4頁(yè)
無(wú)須SMTP服務(wù)器中轉(zhuǎn)直接發(fā)送電子郵件_第5頁(yè)
已閱讀5頁(yè),還剩11頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論