使用C#中的WebDav发送/转发具有重复主题行的电子邮件

时间:2011-03-08 09:33:23

标签: c# webdav

我有一些代码使用WEBDAV'SEARCH'方法从Exchange邮箱的“收件箱”文件夹中检索电子邮件 - 我的代码采用HTTPWebRquests WEB响应的innerXML。

在这些namsspace上使用'chooseSingleNode':

'urn:schemas:httpmail'&瓮:模式:mailheader

让我抽出元素:

F:textdescription d:fromd:主题 f:datareceived ...等等

然后我在列表中创建这些详细信息的集合,并使用'主题'和URI使用'PUT'方法在'草稿文件夹中重新创建这些消息,然后使用'MOVE'发送邮件(使用'/ ## DavMailSubmissionURI ## /''声明将它们放入已发送的项目中。

我遇到的问题是我正在处理的电子邮件的性质往往与同一主题行有关,因此它与已发送/不发送的电子邮件相混淆。

有没有人知道解决这个问题的方法,我不知道为什么'PUT'依赖于主题行来获取邮件资源的URI,而不是说HREF标签是唯一的。任何想法:

代码如下:

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;
        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; }
    }
}

}

2 个答案:

答案 0 :(得分:0)

使用主题识别电子邮件确实不是一个好方法。如果我记得它是正确的,交换/ webdav没有自动/明显的电子邮件ID?

如果您解析主题以选择消息,我还会选择更多关于电子邮件信封的信息 - 比如它的大小,长度来创建我自己的ID。最好的步骤应该是你在整个邮件正文中创建某种哈希(检查加密),或者在邮件正文中创建第一个xx单词的第一个字符(尽管处理较重)。每次在同一个电子邮件信封上调用时,这将以相同的哈希值结束。直到电子邮件内容保持不变。

答案 1 :(得分:0)

看起来您正在使用Exchange 2003.请注意,Exchange版本2010不再支持WebDAV ...而使用2007及更高版本,您可以使用WSDL来执行所需的一切。您只需要Exchange 2007 CAS就可以完成此任务。

我提到的是一种更好的长期方法,并且比解析不支持的WEBDAV XML更少麻烦

要回答您的问题,每个邮件都有一个唯一的属性。使用MFCMapi(在codeplex上)查找它。该属性将被命名为“MessageURL”或类似的东西。在webdav调用的URL中使用该属性。