【转】用C#访问Hotmail

【转自】用C#访问Hotmail

 

 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)。 )

 

 --------------------------------------------------------------------------------------------------------------------------

 

【转自】 C#访问hotmail邮件 (csdn)

 

 如何使用程序来访问HOTMAIL的邮件

  1 using  System;
  2 using  System.Diagnostics;
  3 using  System.IO;
  4 using  System.Net;
  5 using  System.Text;
  6 using  System.Xml;
  7 using  System.Web;
  8
  9 namespace  Hotmail
 10 ExpandedBlockStart.gifContractedBlock.gif {
 11ExpandedSubBlockStart.gifContractedSubBlock.gif /**//// <summary>
 12 /// HotmailProxy is able to speak HttpMail to various
 13 /// Hotmail servers across the world.
 14 /// </summary>

 15 public class HotmailProxy
 16ExpandedSubBlockStart.gifContractedSubBlock.gif {
 17ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//// <summary>
 18  /// Storage area for cookies.
 19  /// </summary>

 20  private CookieContainer ccContainer;
 21
 22ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//// <summary>
 23  /// Creates a new instance of HotmailHttp.
 24  /// </summary>

 25  public HotmailProxy()
 26ExpandedSubBlockStart.gifContractedSubBlock.gif  {
 27   Trace.WriteLine("Creating new instance.");
 28   ccContainer = new CookieContainer();
 29  }

 30
 31ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//// <summary>
 32  /// Sends the given request to the given destination
 33  /// and returns the answer from the server.
 34  /// </summary>
 35  /// <param name="request">The request to send.</param>
 36  /// <param name="destination">The destination to send the request to.</param>
 37  /// <returns>The answer from the remote host.</returns>

 38  public string SendRequest(string request, Uri destination)
 39ExpandedSubBlockStart.gifContractedSubBlock.gif  {
 40   // pass along
 41   return SendRequest(request,destination,null);
 42  }

 43
 44ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//// <summary>
 45  /// Sends the given request to the given destination
 46  /// and returns the answer from the server.
 47  /// </summary>
 48  /// <param name="request">The request to send.</param>
 49  /// <param name="destination">The destination to send the request to.</param>
 50  /// <param name="credential">The network credentials to use with the request.</param>
 51  /// <returns>The answer from the remote host.</returns>

 52  public string SendRequest(string request, Uri destination, NetworkCredential credential)
 53ExpandedSubBlockStart.gifContractedSubBlock.gif  {
 54   // Verify input
 55   if(request == null || request.Trim().Length == 0)
 56    throw new ArgumentNullException("request");
 57   else if (destination == null)
 58    throw new ArgumentNullException("destination");
 59   else
 60ExpandedSubBlockStart.gifContractedSubBlock.gif   {
 61    // Get byte[] and send the request using private method.
 62    byte[] xmlBytes = Encoding.ASCII.GetBytes(request);
 63    return SendRequestTo(xmlBytes,destination, credential);
 64   }

 65  }

 66
 67ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//// <summary>
 68  /// Sends the given byte[] to the given remote host using
 69  /// authentication with the supplied credentials.
 70  /// </summary>
 71  /// <param name="requestBytes"></param>
 72  /// <param name="destination"></param>
 73  /// <param name="credential"></param>
 74  /// <returns></returns>

 75  private string SendRequestTo(byte[] requestBytes, Uri destination, NetworkCredential credential)
 76ExpandedSubBlockStart.gifContractedSubBlock.gif  {
 77   Trace.WriteLine("Sending request to url:" + destination.AbsoluteUri);
 78
 79   // Build the request.
 80   HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(destination);
 81   webRequest.Method = "PROPFIND";
 82   webRequest.Accept = "*/*";
 83   webRequest.AllowAutoRedirect = false;
 84   webRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR v1.1.4322)";
 85   webRequest.CookieContainer = new CookieContainer();
 86   webRequest.ContentLength = requestBytes.Length;
 87   webRequest.ContentType = "text/xml";
 88   // Set the credentials
 89   webRequest.Credentials = credential;
 90   // Add cookies for this request
 91   webRequest.CookieContainer.Add(ccContainer.GetCookies(destination));
 92
 93   try
 94ExpandedSubBlockStart.gifContractedSubBlock.gif   {
 95    // Write the request
 96    Stream reqStream = webRequest.GetRequestStream();
 97    reqStream.Write(requestBytes,0,requestBytes.Length);
 98    reqStream.Close();
 99    // Get a response
100    HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
101    if (webRequest.HaveResponse)
102ExpandedSubBlockStart.gifContractedSubBlock.gif    {
103     // Handle returned cookies
104     foreach(Cookie retCookie in webResponse.Cookies)
105ExpandedSubBlockStart.gifContractedSubBlock.gif     {
106      bool cookieFound = false;
107      
108      foreach(Cookie oldCookie in ccContainer.GetCookies(destination))
109ExpandedSubBlockStart.gifContractedSubBlock.gif      {
110       if (retCookie.Name.Equals(oldCookie.Name))
111ExpandedSubBlockStart.gifContractedSubBlock.gif       {
112        oldCookie.Value = retCookie.Value;
113        cookieFound = true;
114       }

115      }

116      if (!cookieFound)
117       ccContainer.Add(retCookie);
118      
119     }
     
120     // Handle redirection headers
121     if ((webResponse.StatusCode == HttpStatusCode.Found) || 
122      (webResponse.StatusCode == HttpStatusCode.Redirect) ||
123      (webResponse.StatusCode == HttpStatusCode.Moved) ||
124      (webResponse.StatusCode == HttpStatusCode.MovedPermanently))
125ExpandedSubBlockStart.gifContractedSubBlock.gif     {    
126      WebHeaderCollection headers = webResponse.Headers;
127      return SendRequestTo(requestBytes,new Uri(headers["location"]),credential); 
128     }

129     // Read response
130     StreamReader stream = new StreamReader(webResponse.GetResponseStream());
131     string responseString = stream.ReadToEnd();
132     stream.Close();
133   
134     return responseString;
135    }

136    // No response
137    throw new ApplicationException("No response received from host.");
138   }

139   catch(WebException e)
140ExpandedSubBlockStart.gifContractedSubBlock.gif   {
141    // Error occured
142    Trace.WriteLine("Exception occured " + e.Message);
143    throw new ApplicationException("Exception occured while sending request."+e.Message,e);
144   }

145   
146  }

147 }

148}

149 using  System;
150 using  System.Diagnostics;
151 using  System.Net;
152 using  System.Xml;
153
154 namespace  Hotmail
155 ExpandedBlockStart.gifContractedBlock.gif {
156 public class HotmailClient
157ExpandedSubBlockStart.gifContractedSubBlock.gif {
158ContractedSubBlock.gifExpandedSubBlockStart.gif  Class Instances and Properties#region Class Instances and Properties
159ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//// <summary>
160  /// The Http proxy used for Hotmail
161  /// </summary>

162  private HotmailProxy hHttp   = null;
163ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//// <summary>
164  /// Indicator if connected to remote host.
165  /// </summary>

166  private bool connected    = false;
167  #endregion

168
169ContractedSubBlock.gifExpandedSubBlockStart.gif  Public Interface( Constructor, Connect, Disconnect, RetrieveFilledMailBox)#region Public Interface( Constructor, Connect, Disconnect, RetrieveFilledMailBox)
170ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//// <summary>
171  /// Create a new instance of HotmailClient.
172  /// </summary>

173  public HotmailClient()
174ExpandedSubBlockStart.gifContractedSubBlock.gif  {
175  }

176
177ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//// <summary>
178  /// Connect this client to the remote hotmail host and 
179  /// retrieve a list of mailboxes.
180  /// </summary>
181  /// <param name="username">The username to connect with.</param>
182  /// <param name="password">The password to connect with.</param>

183  public void Connect(string username, string password)
184ExpandedSubBlockStart.gifContractedSubBlock.gif  {
185   // Verify input
186   if (username == null || username.Trim().Length == 0)
187    throw new ArgumentNullException("username");
188   if (password == null || password.Trim().Length == 0)
189    throw new ArgumentNullException("password");
190   if (username.IndexOf("@"== -1)
191    throw new ArgumentException("Illegal username, must contain an @ sign: (user@hotmail.com).");
192   // Create the specialized Http client and the neccesary credentials
193   hHttp = new HotmailProxy();
194   NetworkCredential credentials = new NetworkCredential(username,password,null);
195   // Build the query for the msgfolderroot
196   string query = "<?xml version='1.0'?>" +
197    "<D:propfind xmlns:D='DAV:' " + 
198    "xmlns:h='http://schemas.microsoft.com/hotmail/' " + 
199    "xmlns:hm='urn:schemas:httpmail:'>" + 
200    "<D:prop>"     + 
201    "<hm:msgfolderroot/>" +
202    "</D:prop>"     + 
203    "</D:propfind>";
204   // Connect
205   try
206ExpandedSubBlockStart.gifContractedSubBlock.gif   {
207    // Get a response from the query, connect to the hotmail entry page.
208    string hotmailEntryPoint = "http://services.msn.com/svcs/hotmail/httpmail.asp";
209    string response = hHttp.SendRequest(query, new Uri(hotmailEntryPoint),credentials);
210    // Verify response
211    if (response == null || response.Trim().Length == 0)
212     throw new ApplicationException("No response received from host.");
213    // Parse the response, further verifying it.
214    Uri folderRootUri = ParseConnectResponse(response);
215    // Obtain available folders using folderRootUrl
216    RetrieveMailboxes(folderRootUri);
217    // Now we're connected
218    connected = true;
219   }

220   catch(Exception e)
221ExpandedSubBlockStart.gifContractedSubBlock.gif   {
222    // Something went wrong.
223    throw new ApplicationException("Exception occured while connecting to remote host.",e);
224   }

225  }

226  #endregion

227
228ContractedSubBlock.gifExpandedSubBlockStart.gif  Private Interface( ParseConnectResponse, ParseFillResponse, RetrieveMailboxes, CreateNamespaceManager)#region Private Interface( ParseConnectResponse, ParseFillResponse, RetrieveMailboxes, CreateNamespaceManager)
229
230ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//// <summary>
231  /// This method parses the response from the server from
232  /// the Connect() call, and returns the Uri contained in
233  /// the msgfolderroot. This is the root for all mailboxes.
234  /// </summary>
235  /// <param name="response">The response from the remote host.</param>
236  /// <returns>The Uri contained in msgfolderroot.</returns>

237  private Uri ParseConnectResponse(string response)
238ExpandedSubBlockStart.gifContractedSubBlock.gif  {
239   try
240ExpandedSubBlockStart.gifContractedSubBlock.gif   {
241    // Load response into XmlDocument
242    XmlDocument dom = new XmlDocument();
243    dom.LoadXml(response);
244    // Query XmlDocument for msgfolderroot node.
245    string xpath = "//hm:msgfolderroot";
246    XmlNamespaceManager context = CreateNamespaceManager(dom.NameTable);
247    XmlNode folderRoot = dom.SelectSingleNode(xpath,context);
248    // Verify node
249    if (folderRoot == null)
250     throw new ApplicationException("Node '" + xpath + "' not found.");
251    // Get node text and verify,
252    string folderRootUrl = folderRoot.InnerText;
253    if ((folderRootUrl == null|| (folderRootUrl.Trim().Length == 0))
254     throw new ApplicationException("No url found in node '" + xpath + "'.");
255    try
256ExpandedSubBlockStart.gifContractedSubBlock.gif    {
257     // Return the uri, this may result in a UriFormatException
258     return new Uri(folderRootUrl);
259    }

260    catch
261ExpandedSubBlockStart.gifContractedSubBlock.gif    {
262     throw new ApplicationException("Url found in node '" + xpath + "' is invalid:" + folderRootUrl);
263    }

264   }

265   catch(Exception e)
266ExpandedSubBlockStart.gifContractedSubBlock.gif   {
267    // Something went wrong.
268    throw new ApplicationException("Error occured while parsing connect response.",e);
269   }

270  }

271  
272ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//// <summary>
273  /// Requests available mailboxes from the remote host using the
274  /// given msgfolderroot url, and parses the response into 
275  /// the mailBoxes container.
276  /// </summary>
277  /// <param name="folderRootUrl">The Uri of the msgfolderroot.</param>

278  private void RetrieveMailboxes(Uri folderRootUrl)
279ExpandedSubBlockStart.gifContractedSubBlock.gif  {
280   try
281ExpandedSubBlockStart.gifContractedSubBlock.gif   {
282    // Build the needed query
283    string query = "<?xml version='1.0'?>" + 
284     "<D:propfind xmlns:D='DAV:' xmlns:hm='urn:schemas:httpmail:'>" + 
285     "<D:prop>"    + 
286     "<D:displayname/>" +
287     "<hm:special/>"  +
288     "<hm:unreadcount/>" +
289     "<D:visiblecount/>" +
290     "</D:prop>"    + 
291     "</D:propfind>";
292    // Get a response from server
293    string response = hHttp.SendRequest(query,folderRootUrl);
294    // Verify response
295    if (response == null || response.Trim().Length == 0)
296     throw new ApplicationException("No response received from host."); 
297    // Load response into XmlDocument
298    XmlDocument dom = new XmlDocument();
299    dom.LoadXml(response);
300    // Query XmlDocument for all mailboxes using XPath
301    string xpath = "//D:response";
302    XmlNamespaceManager context = CreateNamespaceManager(dom.NameTable);
303    XmlNodeList mailBoxNodes = dom.SelectNodes(xpath,context);
304    // Parse each node found
305    foreach(XmlNode mailBoxNode in mailBoxNodes)
306ExpandedSubBlockStart.gifContractedSubBlock.gif    {  
307     try
308ExpandedSubBlockStart.gifContractedSubBlock.gif     {
309      // Direct mapping using XPath, should not result in any errors
310      // as long as Hotmail keeps it protocol the same.
311      string type = mailBoxNode.SelectSingleNode("descendant::hm:special",context).InnerText;     
312      string nameUrl = mailBoxNode.SelectSingleNode("descendant::D:href",context).InnerText;
313      int visibleCount = Int32.Parse(mailBoxNode.SelectSingleNode("descendant::D:visiblecount",context).InnerText);
314      int unreadCount = Int32.Parse(mailBoxNode.SelectSingleNode("descendant::hm:unreadcount",context).InnerText);
315      // Add the mailbox
316      Console.WriteLine("MailBox found: " + type + "\r\n" +
317       "\turl: " + nameUrl + "\r\n" +
318       "\tVisible: " + visibleCount + "\r\n" +
319       "\tUnread: " + unreadCount + "\r\n");
320
321     }

322     catch(Exception e)
323ExpandedSubBlockStart.gifContractedSubBlock.gif     {
324      Console.WriteLine("Exception occured while obtaining mailbox info: " + e.Message);
325     }

326    }

327   }

328   catch(Exception e)
329ExpandedSubBlockStart.gifContractedSubBlock.gif   {
330    // Something went wrong.
331    throw new ApplicationException("Error occured while retrieving available mailboxes.",e);
332   }

333  }

334  
335ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//// <summary>
336  /// Helper method to create the XmlNamespaceManager needed for
337  /// correctly querying the response using XPath.
338  /// </summary>
339  /// <param name="table"></param>
340  /// <returns></returns>

341  private XmlNamespaceManager CreateNamespaceManager(XmlNameTable table)
342ExpandedSubBlockStart.gifContractedSubBlock.gif  {
343   XmlNamespaceManager m = new XmlNamespaceManager(table);
344   m.AddNamespace("hm","urn:schemas:httpmail:");
345   m.AddNamespace("D","DAV:");
346   m.AddNamespace("m","urn:schemas:mailheader:");
347   m.AddNamespace("c","urn:schemas:contacts:");
348   m.AddNamespace("h","http://schemas.microsoft.com/hotmail/");
349   return m;
350  }

351  #endregion

352
353 }

354}

355
356
357 程序进入点
358
359 private   void  button1_Click( object  sender, System.EventArgs e)
360 ExpandedBlockStart.gifContractedBlock.gif   {
361   HotmailClient client=new HotmailClient();
362   client.Connect("xxxx@hotmail.com","urPassword");
363  }

转载于:https://www.cnblogs.com/yencain/articles/1388048.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值