域名频道-专业提供域名注册,网站空间,电子邮箱,VPS主机等服务
首页 域名注册 虚拟主机 香港主机 美国主机 VPS主机 网站建设 ShopEX网店 软件开发 客户中心 购物车
域名服务,域名注册 常见问题
文章搜索


本类TOP10
·松江网页设计_松江网页制...
·上海轨道交通图-上海地图
·松江公交线路图-松江地图
·marquee连续滚动
·今天几度?-天气预报-全...
·松江新城地图-松江地图
·松江城区地图-松江地图
·HAO123邮箱登陆代码
·shopex免费模板,下...
·松江DNS服务器地址,松...
当前位置:域名频道首页 > 常见问题 > 网页制作
用C#访问Hotmail

POP邮件协议的优点在于它是一个开放的标准, 有着完善的文档,这就使得编写POP邮件客户程序不那么困难,只 要掌握了POP、SMTP的基础知识,就可以写出代理程序来执行 各种任务,例如过滤广告和垃圾邮件,或提供e-mail自动应答 服务。
  Hotmail是世界上影响最广的Web邮 件系统,遗憾的是,当我们要为Hotmail编写独立的客户程序 (不通过浏览器访问的客户程序)时,马上就会遇到Hotmail 不提供POP网关这一障碍。
  虽然Hotmail不 提供POP支持,但浏览器并非访问Hotmail的唯一途径。例 如,利用Outlook Express可以直接连接到标准的H otmail或MSN信箱,提取、删除、移动或发送邮件。利用H TTP包监视器,我们可以监视到Outlook Express 和Hotmail的通信过程,分析出客户程序如何连接到Hotm ail信箱。
  Outlook Express利用 了一种通常称为HTTPMail的未公开的协议,借助一组HTT P/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类。另外,由于我们要操作WebD AV,在C#环境下利用XMLHTTP连接Hotmail最为简 便,只需引用一下MSXML2组件就可以直接访问。注意在本文的 代码片断中,带有下滑线后缀的变量是示例代码中声明的成员域:

 

// 获得名称空间< br> using MSXML2;

...
// 创建对象
xmlHttp_ = new XMLHTTP();

 


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

< br>
<
?xml version=&q uot;
1.0"
?>

<
D: propfind xmlns:D="
DAV:&qu ot;
xmlns:h="
http://schem as.microsoft.com/hotmail/" ;

xmlns:hm="
urn:schem as:httpmail:"
>

<
D:prop>

<
h: adbar/>

<
hm:con tacts/>

<
hm:inb ox/>

<
hm:outbox />

<
hm:sendmsg/ >

<
hm:sentitems />

<
hm:deletedi tems/>

<
hm:draf ts/>

<
hm:msgfol derroot/>

<
h:ma xpoll/>

<
h:sig/ >

<
/D:prop>

<
/D:propfind>

 

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

 

// 指定服务器的 URL
string serverUrl = &q uot;
http://services.msn.com/sv cs/hotmail/httpmail.asp"
;

// 构造查询
string fold erQuery = null;

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

folderQu ery += "
xmlns:h='http://s chemas.microsoft.com/hotmail/' "
;

folderQuery += & quot;
xmlns:hm='urn:schemas:htt pmail:'>
<
D:prop>
<
h :adbar/>
"
;

folder Query += "
<
hm:contacts />
<
hm:inbox/>
<
hm:o utbox/>
<
hm:sendmsg/>
& quot;
;

folderQuery += &qu ot;
<
hm:sentitems/>
<
hm :deleteditems/>
<
hm:draft s/>
"
;

folderQuery += "
<
hm:msgfolderroot />
<
h:maxpoll/>
<
h:s ig/>
<
/D:prop>
<
/D:p ropfind>
"
;

 

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


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

 


  open()方法的第一个参数指 定了用来打开连接的HTTP方法,例如GET、POST、PUT 或PROPFIND,通过这些HTTP方法我们可以提取文件夹信 息、收集邮件或发送新邮件。为连接到Hotmail网关,我们指 定用PROPFIND方法来查询信箱。注意open()方法允许 执行异步调用(默认启用),对于带图形用户界面的邮件客户程序来 说,异步调用是最理想的调用方式。由于本文的示例程序是一个控制 台应用,我们把这个参数设置成false。
  为了执 行身份验证,我们在open()方法中指定了用户名字和密码。在 使用XMLHTTP组件时,如果open()方法没有提供用户名 字和密码参数,但网站要求执行身份验证,XMLHTTP将显示出 一个登录窗口。为了打开通向Hotmail网关的连接,我们把P ROPFIND请求的头设置成XML查询的内容,消息的正文保持 空白,然后发送消息:

 

// 打开一个通向Hotmail服务器的连接
x mlHttp_.open("
PROPFIND&qu ot;
, serverUrl, false, usernam e, password);

// 发送请求
xmlHttp_.setRequestHeader(&q uot;
PROPFIND"
, folderQuer y);

xmlHttp_.send(null);
< br>


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

 

// 获得 应答的内容
string folderList = xmlHttp_.responseText;

< br>

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

 

<
?xml vers ion="
1.0"
encoding=& quot;
Windows-1252"
?>
<
D:response>

...
<
D:propsta t>

<
D:prop> ;

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

<
hm:contacts& gt;
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:senti tems>
http://law15.oe.hotmai l.com/...<
/hm:sentitems>

<
hm:deletedit ems>
http://law15.oe.hotmail .com/...<
/hm:deleteditems&g t;

<
hm:msgfold erroot>
http://law15.oe.hotm ail.com/...<
/hm:msgfolderro ot>

...
<
/D:prop>

&l t;
/D:response>

<
/D: multistatus>

 

< br>  在本文的控制台示例程序中,我们感兴趣的两个文件夹是 收件箱和发件箱的文件夹,它们分别用于接收和发送邮件。
  在C#环境中解析XML的方法很多,由于我们肯定代码涉及 的所有XML文档总是合法的,所以可以利用System.XML .XmlTextReader速度快的优势。XmlTextRe ader是一个“只向前”的读取器,下面把XML字符数据转换成 字符流,初始化XML读取器:

 

// 初始化
inboxUrl_ = n ull;

sendUrl_ = null;

// 装入XML
StringReader r eader = new StringReader(folde rList);

XmlTextReader xml = new XmlTextReader(reader);
< br>


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

 

/ / 读取XML数据
while(xml.Read( ))
{
// 是一个XML元素?< br> if(xml.NodeType == XmlN odeType.Element)
{
// 获取该节点
string name = xml.Name;

// 该 节点代表收件箱?
if(name == & quot;
hm:inbox"
)
{
// 保存收件箱URL
xml.Read();

i nboxUrl_ = xml.Value;

}
// 该节点代表发件箱?
if(name == "
hm:sendms g"
)
{
// 保存发件箱URL
xml.Re ad();

sendUrl_ = xm l.Value;

}
} }

 

  只有先获取 当前这次会话的合法的收件箱和发件箱URL,才可以发送和接收邮 件。
  三、列举文件夹内容
  得到了信箱 文件夹(如收件箱)的URL之后,就可以向该文件夹的URL发送 WebDAV请求列举其内容。示例程序定义了一个托管类型Mai lItem,用来保存文件夹里一项内容(即一个邮件)的信息。文 件夹内容列举从初始化一个MailItems数组开始:

 

// 初始化
A rrayList mailItems = new Array List();

 


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

 

<
?xml version=&quo t;
1.0"
?>

<
D:pr opfind xmlns:D="
DAV:" ;
xmlns:hm="
urn:schemas:h ttpmail:"
xmlns:m="
< br>   urn:schemas:mailheader:& quot;
>

<
D:prop> ;

<
D:isfolder/>

<
hm:read/>

<
m:hasattachment/>

<
m:to/>

<
m:from/>

&l t;
m:subject/>

<
m:date/>

<
D:get contentlength/>

<
/D:prop>

<
/D:propfi nd>

 


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

 

// 构造查询
string getMa ilQuery = null;

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

getMail Query += "
xmlns:hm='urn:s chemas:httpmail:' "
;

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

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

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

 


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

 

// 获取邮件信息
xmlHtt p_.open("
PROPFIND"
, folderUrl, false, null, null);

xmlHttp_.send(getMailQue ry);

string folderInfo = xmlHttp_.responseText;

 

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

 

<
D:multistatus>
< br> <
D:response>

<
D:href>

http://sea1.oe.hotmail.com/cg i-bin/hmdata/...
<
/D:href>

<
D:pr opstat>

<
D:pr op>

<
hm:rea d>
1<
/hm:read>

<
m:to/>

<
m:from>
Mark Anders on<
/m:from>

<
m:subject>
RE: New Inf ormation<
/m:subject>

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

<
D:getcontent length>
1238<
/D:getconten tlength>

<
/D :prop>

<
D:sta tus>
HTTP/1.1 200 OK<
/D:s tatus>

<
/D:pro pstat>

<
/D:respon se>

...

 

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

 

MailItem mailItem = null;


// 装入XML
String Reader reader = new StringRead er(folderInfo);

XmlTextRe ader xml = new XmlTextReader(r eader);

 


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

 

/ / 读取XML数据
while(xml.Read( ))
{
string name = xml.Name;

XmlNodeType nodeType = xml.NodeType;

// 是一个email?
if(name == "
D:response"
)
{
// 开始?
if(nodeType == XmlNodeTyp e.Element)
{
// 创建一个新的MailItem
mailItem = new MailIte m();

}
/ / 结束?
if(nodeType = = XmlNodeType.EndElement)
{
// 保存ema il
mailItems.Add( mailItem);

// 清除变 量
mailItem = null ;

}
}
< br> // 是一个元素?
if (nodeType == XmlNodeType.Eleme nt)
{
// 邮 件的URL属性
if(name == "
D:href"
)
{
// 继续读取
xml.Read();

mailItem.Url = xml.Value;

}

// 邮 件的“已阅读”属性
if(name = = "
hm:read"
)
{
// 继续读取
xml.Read();

mailItem.IsRead = (xml.V alue == "
1"
);

}

// 其他Mai lItem的属性...
}
}

 

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

 

XM L节点 说明
D:href 用来提取邮件的UR L
hm:read 如果邮件已阅读,则该标记被设 置
m:to 收件人
m:from 发件人
m:subject 邮件主题
m:date 时间标记
D:getcontent length 邮件的大小(字节数)


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

 

/// <
su mmary>

/// 下载MailItem指 定的邮件
/// <
/summary>

public string LoadMail(M ailItem mailItem)
{
// 邮件的URL
string mail Url = mailItem.Url;

// 打开Hotmail服务器连接
xmlHttp_ .open("
GET"
, mailUrl , false, null, null);

/ / 发送请求
xmlHttp_.send(nu ll);

// 获取应答
str ing mailData = xmlHttp_.respon seText;

// 返回邮件数据
return mailData;

}

 

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

 

/// <
summar y>

/// 发送一个邮件
/// <
/summary>

public void SendMail(string from, str ing fromName,
string to , string subject, string body)
{
...
}

 

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

 

// 引号字符
string quote = & quot;
\u0022"
;


// 时间标记
DateTime now = Date Time.Now;

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

 


  HTTPMail协议采用与S MTP相似的通信模式。Outlook Express用MIM E格式发送邮件,但为简单计,本例我们只发送纯文本的邮件: < br>


// 构造POST请求 的内容
string postBody = nul l;

// 邮件头.
postBody += "
MAIL FROM:<
"
+ from + "
>
\r\n"
;

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

postBody += & quot;
\r\n"
;

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

postBody += &q uot;
To: <
"
+ to + &quo t;
>
\r\n"
;

postBod y += "
Subject: "
+ s ubject +"
\r\n"
;

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

postBody += " ;
\r\n"
;

// 邮件正文
postBody += body;

 

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

 

// 打开连接 xmlHttp_.open("
POST&q uot;
, sendUrl_, false, null, n ull);

// 发送请求
xmlHtt p_.setRequestHeader("
Cont ent-Type"
, "
message/ rfc821"
);

xmlHttp_.s end(postBody);

 

  只要目标地址正确无误,Hotmail就会把邮件发送到 目的地。
  结束语:
  Hotmail是世 界上最大的免费Web邮件提供商。但是,Hotmail使用的H TTPMail协议是非公开的,从而为编写直接访问Hotmai l的客户程序带来了困难。本文示范了如何在C#环境中利用XML HTTP组件直接连接到Hotmail,以及如何发送和接收邮件 ,证明了通过HTTPMail连接Hotmail可以做到象使用 POP3、IMAP4、SMTP等协议一样简单。
   下载本文的完整代码: HotmailCSharp_code. zip(8K)。

来自:域名频道 时间:2006-9-19 返回 常见问题 首页
关于我们 联系方式 付款事宜 招聘启事 网站地图 域名注册 虚拟主机 法律顾问

Copyright 2000-2013 域名频道(www.DNS110.com)
地址:上海市松江区新松江路1188弄37号 邮编:201620
电话:021-67820741 67820742 67820743 传真:转分机805 值班电话:021-67820743
QQ:219854 Email:support@dns110.com