Accessing Hotmail using C#

HotmailClient contd.

ParseConnectResponse(string response)

To parse the response there are a two things that need to be done; place the returned response in an XmlDocument and parse the document using XPath to obtain the Url of the msgfolderroot.

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)
            throw new Exception("Node '" + xpath +
                "' not found.");
        // Get node text and verify,
        string folderRootUrl = folderRoot.InnerText;
        if ((folderRootUrl == null) ||
            (folderRootUrl.Trim().Length == 0))
            throw new MailException("No url found in node '" +
                xpath + "'.");
        try
        {
            // Return the uri, this may result in a
            // UriFormatException
            return new Uri(folderRootUrl);
        }
        catch
        {
            throw new MailException("Url found in node '" +
                xpath + "' is invalid:" + folderRootUrl);
        }
    }
    catch(Exception e)
    {
        // Something went wrong.
        throw new MailException("Error occured while parsing " +
            "connect response.",e);
    }
}

The way this method works is pretty basic now. The correct query to make can be determined using the webpage stated in the introduction, it's also possible to use a network analyzer for this purpose. Probably you will need to use both. To parse the response, the XmlNamespaceManager is build, and XPath is used.

RetrieveMailboxes(Uri folderRootUrl)

The last method in this example will retrieve information about all mailboxes on the server. Basically it does the same thing as the first two methods combined, so you should already be able to build it yourself. The method is shown here for completion sake. It will build a query and send it to the Url of the msgfolderroot now determined.

private void 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 No Credentials are used!
        string response = hHttp.SendRequest(query,folderRootUrl);
        // Verify response
        if (response == null || response.Trim().Length == 0)
            throw new 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);
                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.
        throw new ApplicationException("Error occured " +
            "while retrieving available mailboxes.",e);
    }
}

Conclusion

As you can see accessing Hotmail from C# can be as easy as any other type of mail server. The code works without any strange loops or use of classes that function only partly. With this code it should be easy to build your own email client that is able to access Hotmail with the same type of interface as you would build for IMAP or POP. Happy coding!

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Memory is like an orgasm. It's a lot better if you don't have to fake it.” - Seymour Cray