开发者

Sending/Fowarding Emails with duplicate subject line using WebDav in C#

I have some code that uses the WEBDAV 'SEARCH' method to retrieve emails from an an Exchange Mailboxs 'Inbox' folder - my code takes the the innerXML of the HTTPWebRquests WEBresponse.

Using 'selectingSingleNode' on these namsspaces:

'urn:schemas:httpmail' & urn:schemas:mailheader

Alows me to extract the elements:

f:textdescription d:fromd:subject f:datareceived...and so on

I then create a collection of these details in a list and using the 'Subject' along with the URI use the 'PUT' method to recreate these messages in the 'draft's folder before using the 'MOVE' to send the mails (puts them in the sent items using '/##DavMailSubmissionURI##/"' statement.

The problem i have is the nature of the emails i am dealing with tend to come in with the same subject line so it gets confused with which emails have been sent/or not.

Does anyone know of a way around this, I dont know why the 'PUT' relies on the Subject line for the URI to the mail resource rather than say the HREF tag which is unique. Any ideas:

Code is below:

public class EmailReaderWebDav
{

    public enum enmHTTPType 
    {
        HTTP,
        HTTPS,
    }

    private String strServer { get; set; }      //"mail1"              ------ Exchange server name
    public String strPassword { get; set; }     //"password"           ------ Account Domain Password
    public String strDomain { get; set; }       //"mydocmian"          ------ Domain
    public String strMailBox { get; set; }      //"mymailbox"          ------ UserName
    public String mailFolder { get; set; }      //"inbox"              ------ Mail Folder 
    private String httpProtocol { get; set; }   //http:// ? or https://
    private String mailboxURI { get; set; }     //httpprotocol// + strserver + "/exhange/" + strmailbox

    public List<MailStruct > ListOfEmailDetails { get; private set; }

    private String strQuerySearch { get; set; }

    public EmailReaderWebDav(String serverName, String domain, String mailBox, String password, String mailmailFolder,enmHTTPType HTTPType)
    {
        strServer = serverName;
        strDomain = domain;
        strMailBox = mailBox;
        strPassword = password;
        mailFolder = mailmailFolder;

        httpProtocol = (HTTPType == enmHTTPType.HTTPS) ? "https://" : "http://";
        mailboxURI = httpProtocol + strServer + "/exchange/"  + strMailBox + "/inbox/";

    }


    public void forwardEmails(List<MailStruct> emailsToSend)
    {

        emailsToSend.ForEach(x => SendEmail(x,enmHTTPType.HTTP ));

    }

    public void MakeListofEmailsToForward()
    {

        String tmpQuery =                   

            "<?xml version=\"1.0\"?>"
                + "<D:searchrequest xmlns:D = \"DAV:\" >"
                + "<D:sql>"

                    + " SELECT "
                    + "\"urn:schemas:mailheader:to\","
                    + "\"urn:schemas:mailheader:from\","
                    + "\"urn:schemas:mailheader:subject\","
                    + "\"urn:schemas:httpmail:datereceived\","
                    + "\"urn:schemas:httpmail:textdescription\""
                    + " FROM \"" + mailboxURI + "\""
                    + " WHERE \"DAV:ishidden\" = false AND \"DAV:isfolder\" = false"
                    + "</D:sql>"
            + "</D:searchrequest>";


            // Search Request to get emails from target folder.
        HttpWebRequest SearchRequest = MakeWebRequest("SEARCH", "text/xml", mailboxURI);

        Byte[] bytes = Encoding.UTF8.GetBytes((String)tmpQuery);
            SearchRequest.ContentLength = bytes.Length;

        Stream SearchRequestStream = SearchRequest.GetRequestStream();

            SearchRequestStream.Write(bytes, 0, bytes.Length);
            SearchRequestStream.Close();

                // get the webresponse from the searchrequest.
        WebResponse SearchResponse = MakeWebResponse(SearchRequest);

        String EmailsInXML = extractXMLFromWebResponse(SearchResponse);

            ListOfEmailDetails = extractMailPropertiesFromXMLString(EmailsInXML);

    }

    public void SendEmail(MailStruct mailToForward, enmHTTPType HTTPType)
    {

        String submissionUri = httpProtocol + strServer + "/" + "exchange"  + "/" + strMailBox + "/##DavMailSubmissionURI##/";
        String draftsUri = httpProtocol + strServer + "/" +"exchange" + "/" + strMailBox + "/Drafts/" + mailToForward.Subject + ".eml";

        String message = "To: " + mailToForward.To + "\n"
            + "Subject: " + mailToForward.Subject + "\n"
            + "Date: " + mailToForward.Received 
            + "X-Mailer: mailer" + "\n"
            + "MIME-Version: 1.0" + "\n"
            + "Content-Type: text/plain;" + "\n"
            + "Charset = \"iso-8859-1\"" + "\n"
            + "Content-Transfer-Encoding: 7bit" + "\n"
            + "\n" + mailToForward.MailBody;

        // Request to put an email the drafts folder.
        HttpWebRequest putRequest = MakeWebRequest("PUT", "message/rfc822",draftsUri );

        Byte[] bytes = Encoding.UTF8.GetBytes((String)message);
        putRequest.Headers.Add("Translate", "f");
        putRequest.Timeout = 300000开发者_如何学C;
        putRequest.ContentLength = bytes.Length;

        Stream putRequestStream = putRequest.GetRequestStream();

        putRequestStream.Write(bytes, 0, bytes.Length);
        putRequestStream.Close();



        // Put the message in the Drafts folder of the sender's mailbox.
        HttpWebResponse putResponse = MakeWebResponse(putRequest);

        putResponse.Close();

        // Request to move the email from the drafts to the mail submission Uri.
        HttpWebRequest moveRequest = MakeWebRequest("MOVE", "text/xml", draftsUri);

        moveRequest.Headers.Add("Destination", submissionUri);


        // Put the message in the mail submission folder.
        HttpWebResponse moveResponse = MakeWebResponse(moveRequest);
            moveResponse.Close();

    }


    private CredentialCache getCredentials(String URI)
    {
        CredentialCache tmpCreds = new CredentialCache();

            tmpCreds.Add(new Uri(URI), "NTLM", new NetworkCredential(strMailBox, strPassword,strDomain ));

            ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate pCertificate, System.Security.Cryptography.X509Certificates.X509Chain pChain, System.Net.Security.SslPolicyErrors pSSLPolicyErrors)
            {
                return true;
            };

        return tmpCreds;
    }

    private HttpWebRequest MakeWebRequest(String method,String contentType,String URI)
    {

        HttpWebRequest tmpWebRequest;
        tmpWebRequest  = (HttpWebRequest)HttpWebRequest.Create(URI);
        tmpWebRequest.Credentials = getCredentials (URI);
        tmpWebRequest.Method = method;
        tmpWebRequest.ContentType = contentType ;

            return tmpWebRequest ;
    }

    private HttpWebResponse MakeWebResponse(HttpWebRequest webRequest)
    {
        HttpWebResponse tmpWebresponse = (HttpWebResponse)webRequest.GetResponse();

            return tmpWebresponse;
    }


    WebResponse getMailsFromWebRequest(String strRootURI, String strQuerySearch)
    {

        HttpWebRequest SEARCHRequest;
        WebResponse SEARCHResponse;
        CredentialCache MyCredentialCache;
        Byte[] bytes = null;
        Stream SEARCHRequestStream = null;

        try
        {

            MyCredentialCache = new CredentialCache();
            MyCredentialCache.Add(new Uri(strRootURI ), "NTLM", new NetworkCredential(strMailBox.ToLower(), strPassword, strDomain));

            SEARCHRequest = (HttpWebRequest)HttpWebRequest.Create(strRootURI );

            ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate pCertificate, System.Security.Cryptography.X509Certificates.X509Chain pChain, System.Net.Security.SslPolicyErrors pSSLPolicyErrors)
            {
                return true;
            };

            SEARCHRequest.Credentials = MyCredentialCache;
            SEARCHRequest.Method = "SEARCH";
            SEARCHRequest.ContentType = "text/xml";

            bytes = Encoding.UTF8.GetBytes((string)strQuerySearch);

           SEARCHRequest.ContentLength = bytes.Length;
           SEARCHRequestStream = SEARCHRequest.GetRequestStream();


           SEARCHRequestStream.Write(bytes, 0, bytes.Length);
           SEARCHResponse =(HttpWebResponse ) SEARCHRequest.GetResponse();
           SEARCHRequestStream.Close();
           SEARCHRequest.Timeout = 300000;

            System.Text.Encoding enc = System.Text.Encoding.Default;

                if (SEARCHResponse == null)
                {
                    Console.WriteLine("Response returned NULL!");
                }
                else
                {
                    Console.WriteLine(SEARCHResponse.ContentLength);

                }

                    return SEARCHResponse;

        }

        catch (Exception ex)
        {
            Console.WriteLine("Problem: {0}", ex.Message);
                return null;

        }
    }


    private String extractXMLFromWebResponse(WebResponse SearchResponse)
    {
        String tmpStream;

        using(StreamReader strmReader = new StreamReader(SearchResponse.GetResponseStream(), System.Text.Encoding.ASCII))
        {
            tmpStream  = strmReader.ReadToEnd();

            strmReader.Close();
        }

            return tmpStream;

    }

    private List<MailStruct > extractMailPropertiesFromXMLString(String strXmlStream)
    {

        List<MailStruct> tmpListOfMailProperties = new List<MailStruct>();
        XmlDocument doc = new XmlDocument();
        doc.InnerXml = strXmlStream ;

        XmlNamespaceManager xmlNameSpaces = new XmlNamespaceManager(doc.NameTable);

        xmlNameSpaces.AddNamespace("a", "DAV:");
        xmlNameSpaces.AddNamespace("f", "urn:schemas:httpmail:");
        xmlNameSpaces.AddNamespace("d", "urn:schemas:mailheader:");

        XmlNodeList mailNodes = doc.SelectNodes("//a:propstat[a:status='HTTP/1.1 200 OK']/a:prop", xmlNameSpaces);

        foreach (XmlElement node in mailNodes)
        {

            tmpListOfMailProperties.Add(new MailStruct()
                            {
                                MailBody = node.SelectSingleNode("//f:textdescription",xmlNameSpaces ).InnerText ,
                                from = node.SelectSingleNode ("//d:from",xmlNameSpaces ).InnerText ,
                                To = "dfoster@liquidcapital.com",
                                Subject = node.SelectSingleNode("//d:subject",xmlNameSpaces ).InnerText.ToString () ,
                                Received = node.SelectSingleNode ("//f:datereceived",xmlNameSpaces ).InnerText.ToString ()
                            }
                         );
        }

        return tmpListOfMailProperties;

    }


    public struct MailStruct
    {
        public String To { get; set; }
        public String from { get; set; }
        public String Subject { get; set; }
        public String Received { get; set; }
        public String MailBody { get; set; }
    }
}

}


Using just the subject to identify email is, indeed, not a good way. If I remember it's correct, there are no automatic / obvious email id for exchange / webdav?

If you parse the subject to pick message, I would also pick more information of the email envelope - Like it size, length to create my own id. The best step should be that you create some sort of hash (check Cryptography) out of the whole message body OR i.e. first character of first xx word in the email body (heavier processing though). That will end up in same hash value everytime you call it on same email envelope. Of until the email content is leaved unchanged.


Looks like you're working with Exchange 2003. Be aware that WebDAV is no longer supported in Exchange Version 2010... and with 2007 and newer you can use a WSDL to do everything you need. All you need is an Exchange 2007 CAS to do this.

What I mentioned is a better longer term approach and has less headaches than parsing unsupported WEBDAV XML

To answer your question, there is a property that is unique per message. Use MFCMapi (on codeplex) to look for it. The property will be named "MessageURL" or something like that. Use that property in the URL for your webdav calls.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜