WebDAV mark as read?



  • Basically I need to write a service that periodically checks a mailbox.  It needs to download any file attachments and mark messages as read.  Server side is Exchange 2003.  I tried a few APIs, but settled on WebDAV.  I can check new messages and download all the attachments perfectly, but I just cannot mark messages as read.  I'm doing a PROPPATCH and setting "urn:schemas:httpmail:read" to "1", and it is returning a success status message, but it is not being marked as read.  Marking as unread (i.e. "0") returns success but does not actually mark as unread.  Basically it appears as if PROPPATCH "urn:schemas:httpmail:read" does nothing.  I don't know what to do next.



  • Hi, did you manage to do that?



  • Blast from the past.  Yes, I managed to get it working.  I don't know why it wasn't working at first, but a short while later all of a sudden it just started working as expected.  I didn't change anything on my end, so maybe something was being cached.  Anyway, WebDAV is not the way to go unless that's your only option.  IMAP or POP3 is better if you only need relatively limited functionality.  I went with MAPI because I already had Outlook installed, it has the lowest overhead, and it gives you access to 100% of the functionality at the cost of more complexity.



  • Hi Luke,

    I just saw your original post stating that you were able to download attachments from exchange server using webdav. Can you please post a sample code for the same. It is very urgent as our project is in a critical position and I need to implement this. I have reached the stage were I can get the list of attachment names and attachment file paths as url. Please help me with this.

    Thanks

    Aneetha.



  • Well if you can get the list of attachment urls all you need to do is request each url and save it to a file.  It's been a while and I don't have the code in front of me so I can't really help you right now.  A word of warning, though: Exchange blocks certain file types from being downloaded through webdav.  Shockingly it would refuse to let me download xml attachments but would let zip files through with no problem.  There is a registry key on the Exchange server to change this, but in my case it wasn't worth it.  It would have affected a hundred mailboxes just for my one little dinky application that monitors a single mailbox.  That and a handful of other problems which I can't recall led me to dump webdav in favor of mapi.  If you still want help I can look at the code tomorrow.



  • I could get all the attachments but when I do a request on each url I couldn't get a response which I could write into a file. It is giving an error. I am supposed to use only webdav. The file I am trying to download is an excel and I want to maintain the format also. If you could give a sample code for doing this it will be very helpful. Thanks for the immediate response.

    Thanks

    Aneetha.



  • Here's the main part of my code (minus exception handling, etc).  Basically it downloads all attachments from all messages in your inbox.  I don't have access to an Exchange server at home so I can't verify it, but it worked the last time I tried it.  It's in C# but it shouldn't be too hard to translate it to other languages.  Hope it helps.

    namespace ExchangeTest
    {
        public class WebDAV
        {
            public static class Authentications
            {
                public const string ANONYMOUS = "ANONYMOUS";
                public const string BASIC = "BASIC";
                public const string DIGEST = "DIGEST";
                public const string NTLM = "NTLM";
                public const string NEGOTIATE = "NEGOTIATE";
                public const string PASSPORT = "PASSPORT";
            }
            public static class Methods
            {
                public const string BCOPY = "BCOPY";
                public const string BDELETE = "BDELETE";
                public const string BMOVE = "BMOVE";
                public const string BPROPFIND = "BPROPFIND";
                public const string BPROPPATCH = "BPROPPATCH";
                public const string COPY = "COPY";
                public const string DELETE = "DELETE";
                public const string LOCK = "LOCK";
                public const string MKCOL = "MKCOL";
                public const string MOVE = "MOVE";
                public const string NOTIFY = "NOTIFY";
                public const string POLL = "POLL";
                public const string PROPFIND = "PROPFIND";
                public const string PROPPATCH = "PROPPATCH";
                public const string SEARCH = "SEARCH";
                public const string SUBSCRIBE = "SUBSCRIBE";
                public const string UNLOCK = "UNLOCK";
                public const string UNSUBSCRIBE = "UNSUBSCRIBE";
                public const string X_MS_ENUMATTS = "X-MS-ENUMATTS";
            }
            public const string CONTENT_TYPE_TEXT_XML = "text/xml";
            public const string NS_DAV = "DAV:";
            public const string PR_DAV_SEARCHREQUEST = "searchrequest";
            public const string PR_DAV_SQL = "sql";
            public const string PR_DAV_PROPFIND = "propfind";
            public const string PR_DAV_PROP = "prop";
            public const string PR_DAV_PROPERTYUPDATE = "propertyupdate";
            public const string PR_DAV_SET = "set";
            public const string PR_DAV_HREF = "href";
            public const string PR_DAV_PROPSTAT = "propstat";
            public const string PR_DAV_STATUS = "status";
            public const string PR_DAV_RESPONSE = "response";
            public const string NS_HTTPMAIL = "urn:schemas:httpmail:";
            public const string PR_HTTPMAIL_DATE = "date";
            public const string PR_HTTPMAIL_SUBJECT = "subject";
            public const string PR_HTTPMAIL_FROM = "from";
            public const string PR_HTTPMAIL_TO = "to";
            public const string PR_HTTPMAIL_READ = "read";
            public const string PR_HTTPMAIL_HASATTACHMENT = "hasattachment";
            public const string PR_HTTPMAIL_ATTACHMENTFILENAME = "attachmentfilename";
            public const string PR_HTTPMAIL_TEXTDESCRIPTION = "textdescription";
            public System.Net.ICredentials Credentials;
            public System.Xml.XmlDocument Search(System.Uri uri, string query)
            {
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(ms, null);
                writer.WriteStartDocument();
                writer.WriteStartElement(PR_DAV_SEARCHREQUEST, NS_DAV);
                writer.WriteStartElement(PR_DAV_SQL, NS_DAV);
                writer.WriteValue(query);
                writer.WriteEndElement();
                writer.WriteEndElement();
                writer.WriteEndDocument();
                writer.Close();
                writer = null;
                byte[] data = ms.ToArray();
                ms.Close();
                ms = null;
                return GetXmlResponse(uri, Methods.SEARCH, data);
            }
            public System.Xml.XmlDocument PropFind(System.Uri uri, string localname, string ns)
            {
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(ms, null);
                writer.WriteStartDocument();
                writer.WriteStartElement(PR_DAV_PROPFIND, NS_DAV);
                writer.WriteStartElement(PR_DAV_PROP, NS_DAV);
                writer.WriteStartElement(localname, ns);
                writer.WriteEndElement();
                writer.WriteEndElement();
                writer.WriteEndElement();
                writer.WriteEndDocument();
                writer.Close();
                writer = null;
                byte[] data = ms.ToArray();
                ms.Close();
                ms = null;
                return GetXmlResponse(uri, Methods.SEARCH, data);
            }
            public void Delete(System.Uri uri)
            {
                GetEmptyResponse(uri, Methods.DELETE, null);
            }
            public System.Xml.XmlDocument PropPatch(System.Uri uri, string localname, string ns, object value)
            {
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(ms, null);
                writer.WriteStartDocument();
                writer.WriteStartElement(PR_DAV_PROPERTYUPDATE, NS_DAV);
                writer.WriteStartElement(PR_DAV_SET, NS_DAV);
                writer.WriteStartElement(PR_DAV_PROP, NS_DAV);
                writer.WriteStartElement(localname, ns);
                writer.WriteValue(value);
                writer.WriteEndElement();
                writer.WriteEndElement();
                writer.WriteEndDocument();
                writer.Close();
                writer = null;
                byte[] data = ms.ToArray();
                ms.Close();
                ms = null;
                return GetXmlResponse(uri, Methods.PROPPATCH, data);
            }
            public System.Xml.XmlDocument EnumAtts(System.Uri uri)
            {
                return GetXmlResponse(uri, Methods.X_MS_ENUMATTS, null);
            }
            private string GetHtmlResponse(System.Uri uri, string method, byte[] data)
            {
                System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
                request.Credentials = Credentials;
                request.Method = method;
                if (data != null)
                {
                    string xml = System.Text.Encoding.UTF8.GetString(data);
                    request.ContentType = CONTENT_TYPE_TEXT_XML;
                    request.ContentLength = data.Length;
                    System.IO.Stream requestStream = request.GetRequestStream();
                    requestStream.Write(data, 0, data.Length);
                    requestStream.Close();
                }
                System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
                System.IO.Stream responseStream = response.GetResponseStream();
                System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();
                int length = 8192;
                byte[] buffer = new byte[length];
                int count = responseStream.Read(buffer, 0, length);
                while (count > 0)
                {
                    memoryStream.Write(buffer, 0, count);
                    count = responseStream.Read(buffer, 0, length);
                }
                buffer = memoryStream.ToArray();
                memoryStream.Close();
                responseStream.Close();
                response.Close();
                return System.Text.Encoding.UTF8.GetString(buffer);
            }
            private void GetEmptyResponse(System.Uri uri, string method, byte[] data)
            {
                System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
                request.Credentials = Credentials;
                request.Method = method;
                if (data != null)
                {
                    string xml = System.Text.Encoding.UTF8.GetString(data);
                    request.ContentType = CONTENT_TYPE_TEXT_XML;
                    request.ContentLength = data.Length;
                    System.IO.Stream requestStream = request.GetRequestStream();
                    requestStream.Write(data, 0, data.Length);
                    requestStream.Close();
                }
                System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
                response.Close();
            }
            private System.Xml.XmlDocument GetXmlResponse(System.Uri uri, string method, byte[] data)
            {
                System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
                request.Credentials = Credentials;
                request.Method = method;
                if (data != null)
                {
                    string xml = System.Text.Encoding.UTF8.GetString(data);
                    request.ContentType = CONTENT_TYPE_TEXT_XML;
                    request.ContentLength = data.Length;
                    System.IO.Stream requestStream = request.GetRequestStream();
                    requestStream.Write(data, 0, data.Length);
                    requestStream.Close();
                }
                System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
                System.IO.Stream responseStream = response.GetResponseStream();
                System.Xml.XmlDocument document = new System.Xml.XmlDocument();
                document.Load(responseStream);
                responseStream.Close();
                response.Close();
                return document;
            }
        }
        public class ExchangeDownloader
        {
            public string Username;
            public string Domain;
            public string Password;
            public string MailboxUrl;
            public string DownloadPath;
            public void Download()
            {
                System.Uri mailboxUri = new System.Uri(MailboxUrl);
                System.Net.NetworkCredential credential = new System.Net.NetworkCredential(Username, Password, Domain);
                WebDAV webdav = new WebDAV();
                System.Net.CredentialCache credentials = new System.Net.CredentialCache();
                credentials.Add(mailboxUri, WebDAV.Authentications.NTLM, credential);
                webdav.Credentials = credentials;
                System.Uri[] messageUris = getMessagesWithAttachments(webdav, mailboxUri);
                foreach (System.Uri messageUri in messageUris)
                {
                    System.Uri[] attachmentUris = getAttachments(webdav, messageUri);
                    foreach (System.Uri attachmentUri in attachmentUris)
                    {
                        downloadAttachment(webdav, attachmentUri);
                    }
                    webdav.PropPatch(messageUri, WebDAV.PR_HTTPMAIL_READ, WebDAV.NS_HTTPMAIL, "1");
                }
            }
            private void downloadAttachment(WebDAV webdav, System.Uri uri)
            {
                System.Net.WebClient webClient = new System.Net.WebClient();
                webClient.Credentials = webdav.Credentials;
                string file = System.IO.Path.GetFileName(uri.AbsolutePath);
                string filename = System.IO.Path.Combine(DownloadPath, file);
                webClient.DownloadFile(uri, filename);
            }
            private System.Uri[] getAttachments(WebDAV webdav, System.Uri uri)
            {
                System.Collections.ArrayList attachmentList = new System.Collections.ArrayList();
                System.Xml.XmlDocument document = webdav.EnumAtts(uri);
                System.Xml.XmlNodeList responseElements = document.GetElementsByTagName(WebDAV.PR_DAV_RESPONSE, WebDAV.NS_DAV);
                foreach (System.Xml.XmlElement responseElement in responseElements)
                {
                    System.Xml.XmlElement hrefElement = responseElement[WebDAV.PR_DAV_HREF, WebDAV.NS_DAV];
                    System.Uri href = new System.Uri(hrefElement.InnerText);
                    attachmentList.Add(href);
                }
                return (System.Uri[])attachmentList.ToArray(typeof(System.Uri));
            }
            private System.Uri[] getMessagesWithAttachments(WebDAV webdav, System.Uri uri)
            {
                System.Collections.ArrayList messageList = new System.Collections.ArrayList();
                string query = string.Format(
                    "SELECT \"urn:schemas:httpmail:subject\" " +
                    "FROM \"{0}\" " +
                    "WHERE \"urn:schemas:httpmail:hasattachment\"=true " +
                    "ORDER BY \"urn:schemas:httpmail:date DESC\""
                    , uri);
                System.Xml.XmlDocument document = webdav.Search(uri, query);
                System.Xml.XmlNodeList responseElements = document.GetElementsByTagName(WebDAV.PR_DAV_RESPONSE, WebDAV.NS_DAV);
                foreach (System.Xml.XmlElement responseElement in responseElements)
                {
                    System.Xml.XmlElement hrefElement = responseElement[WebDAV.PR_DAV_HREF, WebDAV.NS_DAV];
                    System.Uri href = new System.Uri(hrefElement.InnerText);
                    messageList.Add(href);
                }
                return (System.Uri[])messageList.ToArray(typeof(System.Uri));
            }
        }
        static class Program
        {
            static void Main()
            {
                ExchangeDownloader exchangeDownloader = new ExchangeDownloader();
                exchangeDownloader.Username = "username";
                exchangeDownloader.Domain = "domain";
                exchangeDownloader.Password = "password";
                exchangeDownloader.MailboxUrl = "http://server/exchange/account/inbox";
                exchangeDownloader.DownloadPath = "C:\\Downloads";
                exchangeDownloader.Download();
            }
        }
    }



  • Hi

    Thanks for the immediate response with the code. It was very useful. But while downloading I am not able to use WebClient as the exchange server uses form based authentication. Even for Webdav i had to attach cookies before requesting. But for web client I don't know a work around :(.

    i am still trying ...



  • How it will work in case of secure mail server i.e. HTTPS://

    It is throwing an exception



  • @rahul said:

    How it will work in case of secure mail server i.e. HTTPS://

    It is throwing an exception

    You're talking about trying to connect to Outlook Web Access?  or some other webmail service?  I would not expect it to work.  It sounds like it has to connect directly to the IMAP, Exchange, or POP server.

    But I don't honestly know.  I made that judgement after reading only four of the posts in the thread.



  • I am trying to connect to exchange server.



  • @Aneetha said:

    Hi Luke,

    I just saw your original post stating that you were able to download attachments from exchange server using webdav. Can you please post a sample code for the same. It is very urgent as our project is in a critical position and I need to implement this. I have reached the stage were I can get the list of attachment names and attachment file paths as url. Please help me with this.

    Thanks

    Aneetha.

    This is not the phrase you are looking for.  All together now:

     

    Pleez send to me teh codez...



  • @LoztInSpace said:

    @Aneetha said:

    Hi Luke,

    I just saw your original post stating that you were able to download attachments from exchange server using webdav. Can you please post a sample code for the same. It is very urgent as our project is in a critical position and I need to implement this. I have reached the stage were I can get the list of attachment names and attachment file paths as url. Please help me with this.

    Thanks

    Aneetha.

    This is not the phrase you are looking for.  All together now:

     

    Pleez send to me teh codez...

    Actually, I was looking for another phrase. Namely, "OMG a dead thread! Mod, halp!". But whatever.



  • @Spectre said:

    Actually, I was looking for another phrase. Namely, "OMG a dead thread! Mod, halp!". But whatever.
    Nah, I view this as a righteous rez.



  • Hi There,

     

    2 years later and I decide to reply to this thread...... I know this thread is dead, but this is also the ONLY Open Source example I have found in the last 4 days!!!

    I am receiving the following error : The remote server returned an error: (440) Login Timeout.

    This pops up on the following code :

    <FONT size=2>

    response </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>As</FONT></FONT><FONT size=2> System.Net.HttpWebResponse = </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>DirectCast</FONT></FONT><FONT size=2>(request.GetResponse(), System.Net.HttpWebResponse)</FONT>

    <FONT size=2></FONT> 

    <FONT size=2>Please could someone assist - I have no idea how to fix this :(</FONT>

    <FONT size=2></FONT> 

    <FONT size=2>Thank you!!

    </FONT>


  • hi luke,

     

    i tried your code and it is working for me yesterday. It's successfully downloads all the attachment. But when I try to run it today I got below error and don't know what happen.

     The remote server returned an error: (400) Bad Request.

     Line : <FONT size=2>System.Net.</FONT><FONT color=#008080 size=2><FONT color=#008080 size=2>HttpWebResponse</FONT></FONT><FONT size=2> response = (System.Net.</FONT><FONT color=#008080 size=2><FONT color=#008080 size=2>HttpWebResponse</FONT></FONT><FONT size=2>)request.GetResponse();</FONT>

    <FONT size=2>Method : <FONT size=2><FONT color=#0000ff size=2><FONT color=#0000ff size=2>private</FONT></FONT><FONT size=2> System.</FONT><FONT color=#008080 size=2><FONT color=#008080 size=2>Uri</FONT></FONT><FONT size=2>[] getAttachments(</FONT><FONT color=#008080 size=2><FONT color=#008080 size=2>WebDAV</FONT></FONT><FONT size=2> webdav, System.</FONT><FONT color=#008080 size=2><FONT color=#008080 size=2>Uri</FONT></FONT><FONT size=2> uri)</FONT></FONT></FONT>

    <FONT size=2><FONT size=2><FONT size=2>Thanks in advance for the help ...</FONT></FONT></FONT>

    <FONT size=2>Liezl</FONT>



  • Since no one answered your question:

    That error is caused by Forms Based Authentication and throws when you call request.GetResponse.  The code to fix it is here: http://support.microsoft.com/kb/891748

     Note that the Request properties (when you set the cookie) are set in a specific order in the example.  Getting the order wrong will get you an error 400 (Bad Request).

    -Jake



  • Thank you Luke727. U saved my day.

    However I have other requirement, an email has attachment of eml file(which is other email). I want to read the content of that eml file. Im able to read the attachments with your method but, Im unable to read the body of that eml file.  Please help me to rectify this too.

    thanks

    Rajesh



  • @chrc999 said:

    Thank you Luke727. U saved my day.

    However I have other requirement, an email has attachment of eml file(which is other email). I want to read the content of that eml file. Im able to read the attachments with your method but, Im unable to read the body of that eml file.  Please help me to rectify this too.

    thanks

    Rajesh

    use the webdav to retrive the body message from the server, but the only disadvantage is that it only show the plain text format from the body content, if you want the full content, u should change .eml to .mht, and put it on the container, it will display on the website.


Log in to reply