using System; using System.Diagnostics; using System.IO; using System.Net; using System.Text; using System.Xml; using System.Web; namespace Hotmail { /**////<summary> /// HotmailProxy is able to speak HttpMail to various /// Hotmail servers across the world. ///</summary> publicclass HotmailProxy { /**////<summary> /// Storage area for cookies. ///</summary> private CookieContainer ccContainer; /**////<summary> /// Creates a new instance of HotmailHttp. ///</summary> public HotmailProxy() { Trace.WriteLine("Creating new instance."); ccContainer =new CookieContainer(); } /**////<summary> /// Sends the given request to the given destination /// and returns the answer from the server. ///</summary> ///<param name="request">The request to send.</param> ///<param name="destination">The destination to send the request to.</param> ///<returns>The answer from the remote host.</returns> publicstring SendRequest(string request, Uri destination) { // pass along return SendRequest(request,destination,null); } /**////<summary> /// Sends the given request to the given destination /// and returns the answer from the server. ///</summary> ///<param name="request">The request to send.</param> ///<param name="destination">The destination to send the request to.</param> ///<param name="credential">The network credentials to use with the request.</param> ///<returns>The answer from the remote host.</returns> publicstring SendRequest(string request, Uri destination, NetworkCredential credential) { // Verify input if(request ==null|| request.Trim().Length ==0) thrownew ArgumentNullException("request"); elseif (destination ==null) thrownew ArgumentNullException("destination"); else { // Get byte[] and send the request using private method. byte[] xmlBytes = Encoding.ASCII.GetBytes(request); return SendRequestTo(xmlBytes,destination, credential); } } /**////<summary> /// Sends the given byte[] to the given remote host using /// authentication with the supplied credentials. ///</summary> ///<param name="requestBytes"></param> ///<param name="destination"></param> ///<param name="credential"></param> ///<returns></returns> privatestring SendRequestTo(byte[] requestBytes, Uri destination, NetworkCredential credential) { Trace.WriteLine("Sending request to url:"+ destination.AbsoluteUri); // Build the request. HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(destination); webRequest.Method ="PROPFIND"; webRequest.Accept ="*/*"; webRequest.AllowAutoRedirect =false; webRequest.UserAgent ="Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR v1.1.4322)"; webRequest.CookieContainer =new CookieContainer(); webRequest.ContentLength = requestBytes.Length; webRequest.ContentType ="text/xml"; // Set the credentials webRequest.Credentials = credential; // Add cookies for this request webRequest.CookieContainer.Add(ccContainer.GetCookies(destination)); try { // Write the request Stream reqStream = webRequest.GetRequestStream(); reqStream.Write(requestBytes,0,requestBytes.Length); reqStream.Close(); // Get a response HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse(); if (webRequest.HaveResponse) { // Handle returned cookies foreach(Cookie retCookie in webResponse.Cookies) { bool cookieFound =false; foreach(Cookie oldCookie in ccContainer.GetCookies(destination)) { if (retCookie.Name.Equals(oldCookie.Name)) { oldCookie.Value = retCookie.Value; cookieFound =true; } } if (!cookieFound) ccContainer.Add(retCookie); } // Handle redirection headers if ((webResponse.StatusCode == HttpStatusCode.Found) || (webResponse.StatusCode == HttpStatusCode.Redirect) || (webResponse.StatusCode == HttpStatusCode.Moved) || (webResponse.StatusCode == HttpStatusCode.MovedPermanently)) { WebHeaderCollection headers = webResponse.Headers; return SendRequestTo(requestBytes,new Uri(headers["location"]),credential); } // Read response StreamReader stream =new StreamReader(webResponse.GetResponseStream()); string responseString = stream.ReadToEnd(); stream.Close(); return responseString; } // No response thrownew ApplicationException("No response received from host."); } catch(WebException e) { // Error occured Trace.WriteLine("Exception occured "+ e.Message); thrownew ApplicationException("Exception occured while sending request."+e.Message,e); } } } } using System; using System.Diagnostics; using System.Net; using System.Xml; namespace Hotmail { publicclass HotmailClient { Class Instances and Properties#region Class Instances and Properties /**////<summary> /// The Http proxy used for Hotmail ///</summary> private HotmailProxy hHttp =null; /**////<summary> /// Indicator if connected to remote host. ///</summary> privatebool connected =false; #endregion Public Interface( Constructor, Connect, Disconnect, RetrieveFilledMailBox)#region Public Interface( Constructor, Connect, Disconnect, RetrieveFilledMailBox) /**////<summary> /// Create a new instance of HotmailClient. ///</summary> public HotmailClient() { } /**////<summary> /// Connect this client to the remote hotmail host and /// retrieve a list of mailboxes. ///</summary> ///<param name="username">The username to connect with.</param> ///<param name="password">The password to connect with.</param> publicvoid Connect(string username, string password) { // Verify input if (username ==null|| username.Trim().Length ==0) thrownew ArgumentNullException("username"); if (password ==null|| password.Trim().Length ==0) thrownew ArgumentNullException("password"); if (username.IndexOf("@") ==-1) thrownew ArgumentException("Illegal username, must contain an @ sign: (user@hotmail.com)."); // Create the specialized Http client and the neccesary credentials hHttp =new HotmailProxy(); NetworkCredential credentials =new NetworkCredential(username,password,null); // Build the query for the msgfolderroot string query ="<?xml version='1.0'?>"+ "<D:propfind xmlns:D='DAV:' "+ "xmlns:h='http://schemas.microsoft.com/hotmail/' "+ "xmlns:hm='urn:schemas:httpmail:'>"+ "<D:prop>"+ "<hm:msgfolderroot/>"+ "</D:prop>"+ "</D:propfind>"; // Connect try { // Get a response from the query, connect to the hotmail entry page. string hotmailEntryPoint ="http://services.msn.com/svcs/hotmail/httpmail.asp"; string response = hHttp.SendRequest(query, new Uri(hotmailEntryPoint),credentials); // Verify response if (response ==null|| response.Trim().Length ==0) thrownew ApplicationException("No response received from host."); // Parse the response, further verifying it. Uri folderRootUri = ParseConnectResponse(response); // Obtain available folders using folderRootUrl RetrieveMailboxes(folderRootUri); // Now we're connected connected =true; } catch(Exception e) { // Something went wrong. thrownew ApplicationException("Exception occured while connecting to remote host.",e); } } #endregion Private Interface( ParseConnectResponse, ParseFillResponse, RetrieveMailboxes, CreateNamespaceManager)#region Private Interface( ParseConnectResponse, ParseFillResponse, RetrieveMailboxes, CreateNamespaceManager) /**////<summary> /// This method parses the response from the server from /// the Connect() call, and returns the Uri contained in /// the msgfolderroot. This is the root for all mailboxes. ///</summary> ///<param name="response">The response from the remote host.</param> ///<returns>The Uri contained in msgfolderroot.</returns> private Uri ParseConnectResponse(string response) { try { // Load response into XmlDocument XmlDocument dom =new XmlDocument(); dom.LoadXml(response); // Query XmlDocument for msgfolderroot node. string xpath ="//hm:msgfolderroot"; XmlNamespaceManager context = CreateNamespaceManager(dom.NameTable); XmlNode folderRoot = dom.SelectSingleNode(xpath,context); // Verify node if (folderRoot ==null) thrownew ApplicationException("Node '"+ xpath +"' not found."); // Get node text and verify, string folderRootUrl = folderRoot.InnerText; if ((folderRootUrl ==null) || (folderRootUrl.Trim().Length ==0)) thrownew ApplicationException("No url found in node '"+ xpath +"'."); try { // Return the uri, this may result in a UriFormatException returnnew Uri(folderRootUrl); } catch { thrownew ApplicationException("Url found in node '"+ xpath +"' is invalid:"+ folderRootUrl); } } catch(Exception e) { // Something went wrong. thrownew ApplicationException("Error occured while parsing connect response.",e); } } /**////<summary> /// Requests available mailboxes from the remote host using the /// given msgfolderroot url, and parses the response into /// the mailBoxes container. ///</summary> ///<param name="folderRootUrl">The Uri of the msgfolderroot.</param> privatevoid RetrieveMailboxes(Uri folderRootUrl) { try { // Build the needed query string query ="<?xml version='1.0'?>"+ "<D:propfind xmlns:D='DAV:' xmlns:hm='urn:schemas:httpmail:'>"+ "<D:prop>"+ "<D:displayname/>"+ "<hm:special/>"+ "<hm:unreadcount/>"+ "<D:visiblecount/>"+ "</D:prop>"+ "</D:propfind>"; // Get a response from server string response = hHttp.SendRequest(query,folderRootUrl); // Verify response if (response ==null|| response.Trim().Length ==0) thrownew ApplicationException("No response received from host."); // Load response into XmlDocument XmlDocument dom =new XmlDocument(); dom.LoadXml(response); // Query XmlDocument for all mailboxes using XPath string xpath ="//D:response"; XmlNamespaceManager context = CreateNamespaceManager(dom.NameTable); XmlNodeList mailBoxNodes = dom.SelectNodes(xpath,context); // Parse each node found foreach(XmlNode mailBoxNode in mailBoxNodes) { try { // Direct mapping using XPath, should not result in any errors // as long as Hotmail keeps it protocol the same. string type = mailBoxNode.SelectSingleNode("descendant::hm:special",context).InnerText; string nameUrl = mailBoxNode.SelectSingleNode("descendant::D:href",context).InnerText; int visibleCount = Int32.Parse(mailBoxNode.SelectSingleNode("descendant::D:visiblecount",context).InnerText); int unreadCount = Int32.Parse(mailBoxNode.SelectSingleNode("descendant::hm:unreadcount",context).InnerText); // Add the mailbox Console.WriteLine("MailBox found: "+ type +"\r\n"+ "\turl: "+ nameUrl +"\r\n"+ "\tVisible: "+ visibleCount +"\r\n"+ "\tUnread: "+ unreadCount +"\r\n"); } catch(Exception e) { Console.WriteLine("Exception occured while obtaining mailbox info: "+ e.Message); } } } catch(Exception e) { // Something went wrong. thrownew ApplicationException("Error occured while retrieving available mailboxes.",e); } } /**////<summary> /// Helper method to create the XmlNamespaceManager needed for /// correctly querying the response using XPath. ///</summary> ///<param name="table"></param> ///<returns></returns> private XmlNamespaceManager CreateNamespaceManager(XmlNameTable table) { XmlNamespaceManager m =new XmlNamespaceManager(table); m.AddNamespace("hm","urn:schemas:httpmail:"); m.AddNamespace("D","DAV:"); m.AddNamespace("m","urn:schemas:mailheader:"); m.AddNamespace("c","urn:schemas:contacts:"); m.AddNamespace("h","http://schemas.microsoft.com/hotmail/"); return m; } #endregion } } 程序进入点 privatevoid button1_Click(object sender, System.EventArgs e) { HotmailClient client=new HotmailClient(); client.Connect("xxxx@hotmail.com","urPassword"); }