| 订阅 | 在线投稿
分享
 
 
 

用C#访问Hotmail

来源:互联网网民  宽屏版  评论
2006-12-16 17:27:37

POP邮件协议的优点在于它是一个开放的标准,有着完善的文档,这就使得编写POP邮件客户程序不那么困难,只要掌握了POP、SMTP的基础知识,就可以写出代理程序来执行各种任务,例如过滤广告和垃圾邮件,或提供e-mail自动应答服务。

Hotmail是世界上影响最广的Web邮件系统,遗憾的是,当我们要为Hotmail编写独立的客户程序(不通过浏览器访问的客户程序)时,马上就会遇到Hotmail不提供POP网关这一障碍。

虽然Hotmail不提供POP支持,但浏览器并非访问Hotmail的唯一途径。例如,利用Outlook Express可以直接连接到标准的Hotmail或MSN信箱,提取、删除、移动或发送邮件。利用HTTP包监视器,我们可以监视到Outlook Express和Hotmail的通信过程,分析出客户程序如何连接到Hotmail信箱。

Outlook Express利用了一种通常称为HTTPMail的未公开的协议,借助一组HTTP/1.1扩展访问Hotmail。本文将介绍HTTPMail的一些特点以及利用C#客户程序访问Hotmail的过程。本文的示例程序利用COM互操作将XMLHTTP用作一种传输服务。XMLHTTP组件提供了一个完善的HTTP实现,除了包括认证功能,还能够在发送HTTP请求给服务器之前设置定制的HTTP头。

一、连接HTTPMail网关

Hotmail信箱默认的HTTPMail网关在http://services.msn.com/svcs/hotmail/httpmail.asp。HTTPMail协议实际上是一个标准的WebDAV服务,只不过尚未公开而已。在编写C#程序时,我们可以方便地调用.NET框架在System.Net名称空间中提供的各个TCP和HTTP类。另外,由于我们要操作WebDAV,在C#环境下利用XMLHTTP连接Hotmail最为简便,只需引用一下MSXML2组件就可以直接访问。注意在本文的代码片断中,带有下滑线后缀的变量是示例代码中声明的成员域:

// 获得名称空间

using MSXML2;

...

// 创建对象

xmlHttp_ = new XMLHTTP();

为了连接到安全服务器,WebDAV协议要求执行HTTP/1.1验证。HTTPMail客户程序发出的第一个请求利用WebDAV PROPFIND方法查找一组属性,其中包括Hotmail广告条的URL以及信箱文件夹的位置:

<?xml version="1.0"?>

<D:propfind xmlns:D="DAV:" xmlns:h="http://schemas.microsoft.com/hotmail/"

xmlns:hm="urn:schemas:httpmail:">

<D:prop>

<h:adbar/>

<hm:contacts/>

<hm:inbox/>

<hm:outbox/>

<hm:sendmsg/>

<hm:sentitems/>

<hm:deleteditems/>

<hm:drafts/>

<hm:msgfolderroot/>

<h:maxpoll/>

<h:sig/>

</D:prop>

</D:propfind>

通过XMLHTTP发送第一个请求时,首先指定WebDAV服务器URL,然后生成XML请求的内容:

// 指定服务器的URL

string serverUrl = "http://services.msn.com/svcs/hotmail/httpmail.asp";

// 构造查询

string folderQuery = null;

folderQuery += "<?xml version='1.0'?><D:propfind xmlns:D='DAV:' ";

folderQuery += "xmlns:h='http://schemas.microsoft.com/hotmail/' ";

folderQuery += "xmlns:hm='urn:schemas:httpmail:'><D:prop><h:adbar/>";

folderQuery += "<hm:contacts/><hm:inbox/><hm:outbox/><hm:sendmsg/>";

folderQuery += "<hm:sentitems/><hm:deleteditems/><hm:drafts/>";

folderQuery += "<hm:msgfolderroot/><h:maxpoll/><h:sig/></D:prop></D:propfind>";

XMLHTTP组件提供了一个open()方法来建立与HTTP服务器的连接:

void open(string method, string url, bool async, string user, string password);

open()方法的第一个参数指定了用来打开连接的HTTP方法,例如GET、POST、PUT或PROPFIND,通过这些HTTP方法我们可以提取文件夹信息、收集邮件或发送新邮件。为连接到Hotmail网关,我们指定用PROPFIND方法来查询信箱。注意open()方法允许执行异步调用(默认启用),对于带图形用户界面的邮件客户程序来说,异步调用是最理想的调用方式。由于本文的示例程序是一个控制台应用,我们把这个参数设置成false。

为了执行身份验证,我们在open()方法中指定了用户名字和密码。在使用XMLHTTP组件时,如果open()方法没有提供用户名字和密码参数,但网站要求执行身份验证,XMLHTTP将显示出一个登录窗口。为了打开通向Hotmail网关的连接,我们把PROPFIND请求的头设置成XML查询的内容,消息的正文保持空白,然后发送消息:

// 打开一个通向Hotmail服务器的连接

xmlHttp_.open("PROPFIND", serverUrl, false, username, password);

// 发送请求

xmlHttp_.setRequestHeader("PROPFIND", folderQuery);

xmlHttp_.send(null);

二、分析信箱的文件夹列表

发送给services.msn.com的请求通常要经历几次重定向,经过服务器端的负载平衡处理,最后请求会被传递到一个空闲的Hotmail服务器,并执行身份验证。在客户端,这个重定向、执行身份验证的交互过程由XMLHTTP组件负责处理。成功建立连接后,服务器还会要求设置一些Cookie、验证当前会话的合法性,这部分工作同样也由XMLHTTP组件自动处理。初始的连接请求发出之后,服务器将返回一个XML格式的应答:

// 获得应答的内容

string folderList = xmlHttp_.responseText;

服务器返回的应答包含许多有用的信息,其中包括信箱中文件夹的URL位置,下面是一个例子:

<?xml version="1.0" encoding="Windows-1252"?>

<D:response>

...

<D:propstat>

<D:prop>

<h:adbar>AdPane=Off*...</h:adbar>

<hm:contacts>http://law15.oe.hotmail.com/...</hm:contacts>

<hm:inbox>http://law15.oe.hotmail.com/...</hm:inbox>

<hm:sendmsg>http://law15.oe.hotmail.com/...</hm:sendmsg>

<hm:sentitems>http://law15.oe.hotmail.com/...</hm:sentitems>

<hm:deleteditems>http://law15.oe.hotmail.com/...</hm:deleteditems>

<hm:msgfolderroot>http://law15.oe.hotmail.com/...</hm:msgfolderroot>

...

</D:prop>

</D:response>

</D:multistatus>

在本文的控制台示例程序中,我们感兴趣的两个文件夹是收件箱和发件箱的文件夹,它们分别用于接收和发送邮件。

在C#环境中解析XML的方法很多,由于我们肯定代码涉及的所有XML文档总是合法的,所以可以利用System.XML.XmlTextReader速度快的优势。XmlTextReader是一个“只向前”的读取器,下面把XML字符数据转换成字符流,初始化XML读取器:

// 初始化

inboxUrl_ = null;

sendUrl_ = null;

// 装入XML

StringReader reader = new StringReader(folderList);

XmlTextReader xml = new XmlTextReader(reader);

遍历各个节点,选取出hm:inbox和hm:sendmsg节点,这两个节点分别代表收件箱和发件箱:

// 读取XML数据

while(xml.Read())

{

// 是一个XML元素?

if(xml.NodeType == XmlNodeType.Element)

{

// 获取该节点

string name = xml.Name;

// 该节点代表收件箱?

if(name == "hm:inbox")

{

// 保存收件箱URL

xml.Read();

inboxUrl_ = xml.Value;

}

// 该节点代表发件箱?

if(name == "hm:sendmsg")

{

// 保存发件箱URL

xml.Read();

sendUrl_ = xml.Value;

}

}

}

只有先获取当前这次会话的合法的收件箱和发件箱URL,才可以发送和接收邮件。

三、列举文件夹内容

得到了信箱文件夹(如收件箱)的URL之后,就可以向该文件夹的URL发送WebDAV请求列举其内容。示例程序定义了一个托管类型MailItem,用来保存文件夹里一项内容(即一个邮件)的信息。文件夹内容列举从初始化一个MailItems数组开始:

// 初始化

ArrayList mailItems = new ArrayList();

||||||

为获得邮件主题、收件人地址、发件人地址之类的邮件基本信息,我们要用到下面XML格式的WebDAV查询:

<?xml version="1.0"?>

<D:propfind xmlns:D="DAV:" xmlns:hm="urn:schemas:httpmail:" xmlns:m="

urn:schemas:mailheader:">

<D:prop>

<D:isfolder/>

<hm:read/>

<m:hasattachment/>

<m:to/>

<m:from/>

<m:subject/>

<m:date/>

<D:getcontentlength/>

</D:prop>

</D:propfind>

生成上述XML查询字符串的C#代码:

// 构造查询

string getMailQuery = null;

getMailQuery += "<?xml version='1.0'?><D:propfind xmlns:D='DAV:' ";

getMailQuery += "xmlns:hm='urn:schemas:httpmail:' ";

getMailQuery += "xmlns:m='urn:schemas:mailheader:'><D:prop><D:isfolder/>";

getMailQuery += "<hm:read/><m:hasattachment/><m:to/><m:from/><m:subject/>";

getMailQuery += "<m:date/><D:getcontentlength/></D:prop></D:propfind>";

就象前面获取信箱文件夹清单的方式一样,上述请求也通过XMLHTTP用PROPFIND方法发送,这次我们把请求的正文设置成查询字符串。由于当前会话的用户身份已经通过验证,所以XMLHTTP open()调用中不必再提供用户名字和密码:

// 获取邮件信息

xmlHttp_.open("PROPFIND", folderUrl, false, null, null);

xmlHttp_.send(getMailQuery);

string folderInfo = xmlHttp_.responseText;

如果请求成功,服务器返回的应答XML流包含了该文件夹中各个邮件的信息:

<D:multistatus>

<D:response>

<D:href>

http://sea1.oe.hotmail.com/cgi-bin/hmdata/...

</D:href>

<D:propstat>

<D:prop>

<hm:read>1</hm:read>

<m:to/>

<m:from>Mark Anderson</m:from>

<m:subject>RE: New Information</m:subject>

<m:date>2002-08-06T16:38:39</m:date>

<D:getcontentlength>1238</D:getcontentlength>

</D:prop>

<D:status>HTTP/1.1 200 OK</D:status>

</D:propstat>

</D:response>

...

观察服务器返回的应答,我们发现每一个节点包含一组标识邮件的域,例如通过标记可提取出邮件。下面我们再次使用System.XML.XmlTextReader解析这个XML数据流,首先初始化流读取器:

MailItem mailItem = null;

// 装入XML

StringReader reader = new StringReader(folderInfo);

XmlTextReader xml = new XmlTextReader(reader);

四、分析邮件基本信息

为了遍历一次就解析好整个XML文档,我们在每次打开元素时就创建一个新的MailItem实例,一遇到标记的末尾就保存该实例,在此期间,我们提取并设置MailItem的域:

// 读取XML数据

while(xml.Read())

{

string name = xml.Name;

XmlNodeType nodeType = xml.NodeType;

// 是一个email?

if(name == "D:response")

{

// 开始?

if(nodeType == XmlNodeType.Element)

{

// 创建一个新的MailItem

mailItem = new MailItem();

}

// 结束?

if(nodeType == XmlNodeType.EndElement)

{

// 保存email

mailItems.Add(mailItem);

// 清除变量

mailItem = null;

}

}

// 是一个元素?

if(nodeType == XmlNodeType.Element)

{

// 邮件的URL属性

if(name == "D:href")

{

// 继续读取

xml.Read();

mailItem.Url = xml.Value;

}

// 邮件的“已阅读”属性

if(name == "hm:read")

{

// 继续读取

xml.Read();

mailItem.IsRead = (xml.Value == "1");

}

// 其他MailItem的属性...

}

}

上面的代码枚举指定文件夹内的每一个MailItem,分别提取各个MailItem的下列属性:

XML节点 说明

D:href 用来提取邮件的URL

hm:read 如果邮件已阅读,则该标记被设置

m:to 收件人

m:from 发件人

m:subject 邮件主题

m:date 时间标记

D:getcontentlength 邮件的大小(字节数)

五、接收邮件

枚举出文件夹里面的MailItem之后,我们就可以利用MailItem的URL获得邮件本身,只需要向Hotmail服务器发送一个HTTP/1.1 GET请求就可以了。示例代码中的LoadMail()函数输入一个MailItem实例作为参数,返回邮件的内容:

/// <summary>

/// 下载MailItem指定的邮件

/// </summary>

public string LoadMail(MailItem mailItem)

{

// 邮件的URL

string mailUrl = mailItem.Url;

// 打开Hotmail服务器连接

xmlHttp_.open("GET", mailUrl, false, null, null);

// 发送请求

xmlHttp_.send(null);

// 获取应答

string mailData = xmlHttp_.responseText;

// 返回邮件数据

return mailData;

}

六、发送邮件

LoadMail()方法通过发送HTTP/1.1 GET请求获取邮件,类似地,用Hotmail发件箱发送邮件时我们提交一个POST请求,如下面的SendMail()方法所示。

/// <summary>

/// 发送一个邮件

/// </summary>

public void SendMail(string from, string fromName,

string to, string subject, string body)

{

...

}

首先准备好后面要用到的引号字符以及邮件的时间标记:

// 引号字符

string quote = "\u0022";

// 时间标记

DateTime now = DateTime.Now;

string timeStamp = now.ToString("ddd, dd MMM yyyy hh:mm:ss");

HTTPMail协议采用与SMTP相似的通信模式。Outlook Express用MIME格式发送邮件,但为简单计,本例我们只发送纯文本的邮件:

// 构造POST请求的内容

string postBody = null;

// 邮件头.

postBody += "MAIL FROM:<" + from + ">\r\n";

postBody += "RCPT TO:<" + to + ">\r\n";

postBody += "\r\n";

postBody += "From: " + quote + fromName + quote + " <" + from + ">\r\n";

postBody += "To: <" + to + ">\r\n";

postBody += "Subject: " + subject +"\r\n";

postBody += "Date: " + timeStamp + " -0000\n";

postBody += "\r\n";

// 邮件正文

postBody += body;

发送邮件时,我们要把Content-Type请求头设置成message/rfc821,表示这个请求包含一个遵从RFC821的消息。最后要做的就是把邮件发送到服务器:

// 打开连接

xmlHttp_.open("POST", sendUrl_, false, null, null);

// 发送请求

xmlHttp_.setRequestHeader("Content-Type", "message/rfc821");

xmlHttp_.send(postBody);

只要目标地址正确无误,Hotmail就会把邮件发送到目的地。

结束语:

Hotmail是世界上最大的免费Web邮件提供商。但是,Hotmail使用的HTTPMail协议是非公开的,从而为编写直接访问Hotmail的客户程序带来了困难。本文示范了如何在C#环境中利用XMLHTTP组件直接连接到Hotmail,以及如何发送和接收邮件,证明了通过HTTPMail连接Hotmail可以做到象使用POP3、IMAP4、SMTP等协议一样简单。

下载本文的完整代码: HotmailCSharp_code.zip(8K)。

 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
POP邮件协议的优点在于它是一个开放的标准,有着完善的文档,这就使得编写POP邮件客户程序不那么困难,只要掌握了POP、SMTP的基础知识,就可以写出代理程序来执行各种任务,例如过滤广告和垃圾邮件,或提供e-mail自动应答服务。   Hotmail是世界上影响最广的Web邮件系统,遗憾的是,当我们要为Hotmail编写独立的客户程序(不通过浏览器访问的客户程序)时,马上就会遇到Hotmail不提供POP网关这一障碍。   虽然Hotmail不提供POP支持,但浏览器并非访问Hotmail的唯一途径。例如,利用Outlook Express可以直接连接到标准的Hotmail或MSN信箱,提取、删除、移动或发送邮件。利用HTTP包监视器,我们可以监视到Outlook Express和Hotmail的通信过程,分析出客户程序如何连接到Hotmail信箱。   Outlook Express利用了一种通常称为HTTPMail的未公开的协议,借助一组HTTP/1.1扩展访问Hotmail。本文将介绍HTTPMail的一些特点以及利用C#客户程序访问Hotmail的过程。本文的示例程序利用COM互操作将XMLHTTP用作一种传输服务。XMLHTTP组件提供了一个完善的HTTP实现,除了包括认证功能,还能够在发送HTTP请求给服务器之前设置定制的HTTP头。   一、连接HTTPMail网关   Hotmail信箱默认的HTTPMail网关在http://services.msn.com/svcs/hotmail/httpmail.asp。HTTPMail协议实际上是一个标准的WebDAV服务,只不过尚未公开而已。在编写C#程序时,我们可以方便地调用.NET框架在System.Net名称空间中提供的各个TCP和HTTP类。另外,由于我们要操作WebDAV,在C#环境下利用XMLHTTP连接Hotmail最为简便,只需引用一下MSXML2组件就可以直接访问。注意在本文的代码片断中,带有下滑线后缀的变量是示例代码中声明的成员域: // 获得名称空间 using MSXML2; ... // 创建对象 xmlHttp_ = new XMLHTTP();   为了连接到安全服务器,WebDAV协议要求执行HTTP/1.1验证。HTTPMail客户程序发出的第一个请求利用WebDAV PROPFIND方法查找一组属性,其中包括Hotmail广告条的URL以及信箱文件夹的位置: <?xml version="1.0"?> <D:propfind xmlns:D="DAV:" xmlns:h="http://schemas.microsoft.com/hotmail/" xmlns:hm="urn:schemas:httpmail:"> <D:prop> <h:adbar/> <hm:contacts/> <hm:inbox/> <hm:outbox/> <hm:sendmsg/> <hm:sentitems/> <hm:deleteditems/> <hm:drafts/> <hm:msgfolderroot/> <h:maxpoll/> <h:sig/> </D:prop> </D:propfind>   通过XMLHTTP发送第一个请求时,首先指定WebDAV服务器URL,然后生成XML请求的内容: // 指定服务器的URL string serverUrl = "http://services.msn.com/svcs/hotmail/httpmail.asp"; // 构造查询 string folderQuery = null; folderQuery += "<?xml version='1.0'?><D:propfind xmlns:D='DAV:' "; folderQuery += "xmlns:h='http://schemas.microsoft.com/hotmail/' "; folderQuery += "xmlns:hm='urn:schemas:httpmail:'><D:prop><h:adbar/>"; folderQuery += "<hm:contacts/><hm:inbox/><hm:outbox/><hm:sendmsg/>"; folderQuery += "<hm:sentitems/><hm:deleteditems/><hm:drafts/>"; folderQuery += "<hm:msgfolderroot/><h:maxpoll/><h:sig/></D:prop></D:propfind>";   XMLHTTP组件提供了一个open()方法来建立与HTTP服务器的连接: void open(string method, string url, bool async, string user, string password);   open()方法的第一个参数指定了用来打开连接的HTTP方法,例如GET、POST、PUT或PROPFIND,通过这些HTTP方法我们可以提取文件夹信息、收集邮件或发送新邮件。为连接到Hotmail网关,我们指定用PROPFIND方法来查询信箱。注意open()方法允许执行异步调用(默认启用),对于带图形用户界面的邮件客户程序来说,异步调用是最理想的调用方式。由于本文的示例程序是一个控制台应用,我们把这个参数设置成false。   为了执行身份验证,我们在open()方法中指定了用户名字和密码。在使用XMLHTTP组件时,如果open()方法没有提供用户名字和密码参数,但网站要求执行身份验证,XMLHTTP将显示出一个登录窗口。为了打开通向Hotmail网关的连接,我们把PROPFIND请求的头设置成XML查询的内容,消息的正文保持空白,然后发送消息: // 打开一个通向Hotmail服务器的连接 xmlHttp_.open("PROPFIND", serverUrl, false, username, password); // 发送请求 xmlHttp_.setRequestHeader("PROPFIND", folderQuery); xmlHttp_.send(null);   二、分析信箱的文件夹列表   发送给services.msn.com的请求通常要经历几次重定向,经过服务器端的负载平衡处理,最后请求会被传递到一个空闲的Hotmail服务器,并执行身份验证。在客户端,这个重定向、执行身份验证的交互过程由XMLHTTP组件负责处理。成功建立连接后,服务器还会要求设置一些Cookie、验证当前会话的合法性,这部分工作同样也由XMLHTTP组件自动处理。初始的连接请求发出之后,服务器将返回一个XML格式的应答: // 获得应答的内容 string folderList = xmlHttp_.responseText;   服务器返回的应答包含许多有用的信息,其中包括信箱中文件夹的URL位置,下面是一个例子: <?xml version="1.0" encoding="Windows-1252"?> <D:response> ... <D:propstat> <D:prop> <h:adbar>AdPane=Off*...</h:adbar> <hm:contacts>http://law15.oe.hotmail.com/...</hm:contacts> <hm:inbox>http://law15.oe.hotmail.com/...</hm:inbox> <hm:sendmsg>http://law15.oe.hotmail.com/...</hm:sendmsg> <hm:sentitems>http://law15.oe.hotmail.com/...</hm:sentitems> <hm:deleteditems>http://law15.oe.hotmail.com/...</hm:deleteditems> <hm:msgfolderroot>http://law15.oe.hotmail.com/...</hm:msgfolderroot> ... </D:prop> </D:response> </D:multistatus>   在本文的控制台示例程序中,我们感兴趣的两个文件夹是收件箱和发件箱的文件夹,它们分别用于接收和发送邮件。   在C#环境中解析XML的方法很多,由于我们肯定代码涉及的所有XML文档总是合法的,所以可以利用System.XML.XmlTextReader速度快的优势。XmlTextReader是一个“只向前”的读取器,下面把XML字符数据转换成字符流,初始化XML读取器: // 初始化 inboxUrl_ = null; sendUrl_ = null; // 装入XML StringReader reader = new StringReader(folderList); XmlTextReader xml = new XmlTextReader(reader);   遍历各个节点,选取出hm:inbox和hm:sendmsg节点,这两个节点分别代表收件箱和发件箱: // 读取XML数据 while(xml.Read()) { // 是一个XML元素? if(xml.NodeType == XmlNodeType.Element) { // 获取该节点 string name = xml.Name; // 该节点代表收件箱? if(name == "hm:inbox") { // 保存收件箱URL xml.Read(); inboxUrl_ = xml.Value; } // 该节点代表发件箱? if(name == "hm:sendmsg") { // 保存发件箱URL xml.Read(); sendUrl_ = xml.Value; } } }   只有先获取当前这次会话的合法的收件箱和发件箱URL,才可以发送和接收邮件。   三、列举文件夹内容   得到了信箱文件夹(如收件箱)的URL之后,就可以向该文件夹的URL发送WebDAV请求列举其内容。示例程序定义了一个托管类型MailItem,用来保存文件夹里一项内容(即一个邮件)的信息。文件夹内容列举从初始化一个MailItems数组开始: // 初始化 ArrayList mailItems = new ArrayList(); ||||||   为获得邮件主题、收件人地址、发件人地址之类的邮件基本信息,我们要用到下面XML格式的WebDAV查询: <?xml version="1.0"?> <D:propfind xmlns:D="DAV:" xmlns:hm="urn:schemas:httpmail:" xmlns:m="    urn:schemas:mailheader:"> <D:prop> <D:isfolder/> <hm:read/> <m:hasattachment/> <m:to/> <m:from/> <m:subject/> <m:date/> <D:getcontentlength/> </D:prop> </D:propfind>   生成上述XML查询字符串的C#代码: // 构造查询 string getMailQuery = null; getMailQuery += "<?xml version='1.0'?><D:propfind xmlns:D='DAV:' "; getMailQuery += "xmlns:hm='urn:schemas:httpmail:' "; getMailQuery += "xmlns:m='urn:schemas:mailheader:'><D:prop><D:isfolder/>"; getMailQuery += "<hm:read/><m:hasattachment/><m:to/><m:from/><m:subject/>"; getMailQuery += "<m:date/><D:getcontentlength/></D:prop></D:propfind>";   就象前面获取信箱文件夹清单的方式一样,上述请求也通过XMLHTTP用PROPFIND方法发送,这次我们把请求的正文设置成查询字符串。由于当前会话的用户身份已经通过验证,所以XMLHTTP open()调用中不必再提供用户名字和密码: // 获取邮件信息 xmlHttp_.open("PROPFIND", folderUrl, false, null, null); xmlHttp_.send(getMailQuery); string folderInfo = xmlHttp_.responseText;   如果请求成功,服务器返回的应答XML流包含了该文件夹中各个邮件的信息: <D:multistatus> <D:response> <D:href> http://sea1.oe.hotmail.com/cgi-bin/hmdata/... </D:href> <D:propstat> <D:prop> <hm:read>1</hm:read> <m:to/> <m:from>Mark Anderson</m:from> <m:subject>RE: New Information</m:subject> <m:date>2002-08-06T16:38:39</m:date> <D:getcontentlength>1238</D:getcontentlength> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response> ...   观察服务器返回的应答,我们发现每一个节点包含一组标识邮件的域,例如通过标记可提取出邮件。下面我们再次使用System.XML.XmlTextReader解析这个XML数据流,首先初始化流读取器: MailItem mailItem = null; // 装入XML StringReader reader = new StringReader(folderInfo); XmlTextReader xml = new XmlTextReader(reader);   四、分析邮件基本信息   为了遍历一次就解析好整个XML文档,我们在每次打开元素时就创建一个新的MailItem实例,一遇到标记的末尾就保存该实例,在此期间,我们提取并设置MailItem的域: // 读取XML数据 while(xml.Read()) { string name = xml.Name; XmlNodeType nodeType = xml.NodeType; // 是一个email? if(name == "D:response") { // 开始? if(nodeType == XmlNodeType.Element) { // 创建一个新的MailItem mailItem = new MailItem(); } // 结束? if(nodeType == XmlNodeType.EndElement) { // 保存email mailItems.Add(mailItem); // 清除变量 mailItem = null; } } // 是一个元素? if(nodeType == XmlNodeType.Element) { // 邮件的URL属性 if(name == "D:href") { // 继续读取 xml.Read(); mailItem.Url = xml.Value; } // 邮件的“已阅读”属性 if(name == "hm:read") { // 继续读取 xml.Read(); mailItem.IsRead = (xml.Value == "1"); } // 其他MailItem的属性... } }   上面的代码枚举指定文件夹内的每一个MailItem,分别提取各个MailItem的下列属性: XML节点 说明 D:href 用来提取邮件的URL hm:read 如果邮件已阅读,则该标记被设置 m:to 收件人 m:from 发件人 m:subject 邮件主题 m:date 时间标记 D:getcontentlength 邮件的大小(字节数)   五、接收邮件   枚举出文件夹里面的MailItem之后,我们就可以利用MailItem的URL获得邮件本身,只需要向Hotmail服务器发送一个HTTP/1.1 GET请求就可以了。示例代码中的LoadMail()函数输入一个MailItem实例作为参数,返回邮件的内容: /// <summary> /// 下载MailItem指定的邮件 /// </summary> public string LoadMail(MailItem mailItem) { // 邮件的URL string mailUrl = mailItem.Url; // 打开Hotmail服务器连接 xmlHttp_.open("GET", mailUrl, false, null, null); // 发送请求 xmlHttp_.send(null); // 获取应答 string mailData = xmlHttp_.responseText; // 返回邮件数据 return mailData; }   六、发送邮件   LoadMail()方法通过发送HTTP/1.1 GET请求获取邮件,类似地,用Hotmail发件箱发送邮件时我们提交一个POST请求,如下面的SendMail()方法所示。 /// <summary> /// 发送一个邮件 /// </summary> public void SendMail(string from, string fromName, string to, string subject, string body) { ... }   首先准备好后面要用到的引号字符以及邮件的时间标记: // 引号字符 string quote = "\u0022"; // 时间标记 DateTime now = DateTime.Now; string timeStamp = now.ToString("ddd, dd MMM yyyy hh:mm:ss");   HTTPMail协议采用与SMTP相似的通信模式。Outlook Express用MIME格式发送邮件,但为简单计,本例我们只发送纯文本的邮件: // 构造POST请求的内容 string postBody = null; // 邮件头. postBody += "MAIL FROM:<" + from + ">\r\n"; postBody += "RCPT TO:<" + to + ">\r\n"; postBody += "\r\n"; postBody += "From: " + quote + fromName + quote + " <" + from + ">\r\n"; postBody += "To: <" + to + ">\r\n"; postBody += "Subject: " + subject +"\r\n"; postBody += "Date: " + timeStamp + " -0000\n"; postBody += "\r\n"; // 邮件正文 postBody += body;   发送邮件时,我们要把Content-Type请求头设置成message/rfc821,表示这个请求包含一个遵从RFC821的消息。最后要做的就是把邮件发送到服务器: // 打开连接 xmlHttp_.open("POST", sendUrl_, false, null, null); // 发送请求 xmlHttp_.setRequestHeader("Content-Type", "message/rfc821"); xmlHttp_.send(postBody);   只要目标地址正确无误,Hotmail就会把邮件发送到目的地。   结束语:   Hotmail是世界上最大的免费Web邮件提供商。但是,Hotmail使用的HTTPMail协议是非公开的,从而为编写直接访问Hotmail的客户程序带来了困难。本文示范了如何在C#环境中利用XMLHTTP组件直接连接到Hotmail,以及如何发送和接收邮件,证明了通过HTTPMail连接Hotmail可以做到象使用POP3、IMAP4、SMTP等协议一样简单。   下载本文的完整代码: HotmailCSharp_code.zip(8K)。
󰈣󰈤
 
 
 
>>返回首页<<
 
 热帖排行
 
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
©2005- 王朝网络 版权所有