rfcd12 发表于 2015-9-10 12:51:40

90%使用WebDAV开发的Exchange邮件管理(三)——获取邮件

                        90%使用WebDAV开发的Exchange邮件管理(三)
                                                                                          ——获取邮件

      这段时间在做项目的用户培训,闲下来的工夫抱着三本书乱啃一通:《C# Primer Plus》,用来反复巩固OO的概念和基础,《JAVA与模式》,既是对模式的学习,也是对OO的深入。还有就是《.net 框架程序设计》。感觉收获不小,但时间越往后,对这个项目里的一些技术细节和内容遗忘得越快。前几天去蓝凌面试,填完表后就做题,连win1=window.open('herf','name','')这样的JS都写错了,回来才想起来,但当时大脑就是一片混沌。所以决定尽快将这部分的个人知识管理工作做完。这段时间,在.net开发群里也有人问到这些相关的,不过我还没写出来,没能帮到别人,真是惭愧。

一、用Search方法获取邮件列表。
      如上一篇所讲,首先定义要查询的URL:
string strRootURI = "http://191.0.0.111/exchange/"+userID.Trim()+"/收件箱/";         然后,生成发送查询请求的XML:

// Build the SQL query.
                strQuery = "<?xml version=\"1.0\"?><D:searchrequest xmlns:D = \"DAV:\" >"
                  + "<D:sql>SELECT \"urn:schemas:httpmail:importance\",\"urn:schemas:httpmail:from\",\"urn:schemas:httpmail:read\",\"urn:schemas:httpmail:datereceived\",\"urn:schemas:httpmail:subject\",\"urn:schemas:httpmail:hasattachment\","
                  +"\"DAV:contentclass\",\"DAV:getcontentlength\",\"DAV:displayname\""
                  + "FROM \""    + strRootURI + "\""
                  + "WHERE \"DAV:ishidden\" = false AND \"DAV:isfolder\" = false"
                  + "</D:sql></D:searchrequest>"; 最后,解析查询返回的XML文档,得到各项内容:

// Get the XML response stream.
                ResponseStream = Response.GetResponseStream();
               
                // Create the XmlDocument object from the XML response stream.
                ResponseXmlDoc = new XmlDocument();
                ResponseXmlDoc.Load(ResponseStream);
            
                // Build a list of the DAV:href XML nodes, corresponding to the folders
                // in the mailbox.The DAV: namespace is typically assgigned the a:
                // prefix in the XML response body.
                XmlNodeList idNodes=ResponseXmlDoc.GetElementsByTagName("a:displayname");
                XmlNodeList SenderNodes = ResponseXmlDoc.GetElementsByTagName("d:from");
                XmlNodeList importanceNodes=ResponseXmlDoc.GetElementsByTagName("d:importance");
                XmlNodeList contextclassNodes=ResponseXmlDoc.GetElementsByTagName("a:contentclass");
                XmlNodeList    readNodes=ResponseXmlDoc.GetElementsByTagName("d:read");
                XmlNodeList    datareceiveNodes=ResponseXmlDoc.GetElementsByTagName("d:datereceived");
                XmlNodeList subjectNodes=ResponseXmlDoc.GetElementsByTagName("d:subject");
                XmlNodeList getcontentlengthNodes=ResponseXmlDoc.GetElementsByTagName("a:getcontentlength");
                XmlNodeList    hasattachmentNodes=ResponseXmlDoc.GetElementsByTagName("d:hasattachment");             然后通过将得到的属性添加到DataTable,绑定到DataGrid上。

      这里要注意的是:虽然邮件是以邮件主题来命名,但相同的邮件主题,其displayname是不一致的,而这个我个人认为也应该是其在WWS中唯一的标志符。如图中的前两封邮件,subject都是ffffffff,但displayname分别为fffffffff.EML和fffffffff-1.EML。
      另外就是DataGrid上重要性和是否已读等的图片绑定,这个可能对初学者比较有用。当时因时间仓促,我是这样来做的:

<asp:Label id=Label1 runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.importance").ToString()=="1"?"":"<img src=\"images/prio"+DataBinder.Eval(Container, "DataItem.importance")+".gif\">" %>'>将图片的名字分别与重要性的标识位相对应。默认不显示,如果重要性为2,则显示的图片就是prio2.gif。

二、用PROPFIND方法得到某邮件的具体属性
      在上述的内容中,我们得到了邮件列表的DataGrid,接着就要通过邮件的displayname,来获取邮件的具体属性。基本方式还是如上。这里用来显示邮件内容的地方用到了一点JS的东东,至于实现上,应该是和EXCHANGE一样的。效果如图:
首先在页面中放了一个IFrame,IFrame中引用的blank.htm为完全空白文件,下面放了一个隐藏的TextArea,将其设为服务器端组件,html代码如下:

<IFRAME class="ipFlat" id="idHtmlBody" name="idHtmlBody" src="blank.htm" frameBorder="0"
                                                    width="100%" height="100%" security="restricted"></IFRAME><TEXTAREA id="idBody" style="DISPLAY: none" runat="server"></TEXTAREA>在程序中获取邮件的正文信息:

XmlNodeList htmldescription=ResponseXmlDoc.GetElementsByTagName("e:htmldescription");
this.idBody.InnerHtml=htmldescription.InnerText;最后是页面中的JAVASCRIPT:
      <script language="JavaScript">
function window.onload()
{
var oFrm = document.frames["idHtmlBody"];
g_winDocAll = window.document.all;
oFrm.document.write(g_winDocAll.idBody.value);
oFrm.document.close();
}
      </script>
三、用X-MS-ENUMATTS方法获取附件名称及属性
      X-MS-ENUMATTS据说是微软以前未公布的方法,这次在Exchange2003里面才公布出来的。但我用的时候,还是发现一些小问题。这里的问题是当我用PR_ATTACH_FILENAME_W得到附件的名称时,发现文件名只能显示8个字符,简直晕死,恍惚回到了DOS时代(偶没学过dos,但考计算机三级的时候学到开始是不支持长文件名的)。不过还好可以得到附件的路径。还是在附件路径上作分拆字符串吧。
    Response = (HttpWebResponse)Request.GetResponse();

                // Get the XML response stream.
                ResponseStream = Response.GetResponseStream();

                // Create the XmlDocument object from the XML response stream.
                ResponseXmlDoc = new System.Xml.XmlDocument();

                // Load the XML response stream.
                ResponseXmlDoc.Load(ResponseStream);

                // Get the root node.
                root = ResponseXmlDoc.DocumentElement;

                // Create a new XmlNamespaceManager.
                nsmgr = new System.Xml.XmlNamespaceManager(ResponseXmlDoc.NameTable);

                // Add the DAV: namespace, which is typically assigned the a: prefix
                // in the XML response body.The namespaceses and their associated
                // prefixes are listed in the attributes of the DAV:multistatus node
                // of the XML response.
                nsmgr.AddNamespace("a", "DAV:");

                // Add the http://schemas.microsoft.com/mapi/proptag/ namespace, which
                // is typically assigned the d: prefix in the XML response body.
                nsmgr.AddNamespace("d", "http://schemas.microsoft.com/mapi/proptag/");

                // Use an XPath query to build a list of the DAV:propstat XML nodes,
                // corresponding to the returned status and properties of
                // the file attachment(s).
                PropstatNodes = root.SelectNodes("//a:propstat", nsmgr);

                // Use an XPath query to build a list of the DAV:href nodes,
                // corresponding to the URIs of the attachement(s) on the message.
                // For each DAV:href node in the XML response, there is an
                // associated DAV:propstat node.
                HrefNodes = root.SelectNodes("//a:href", nsmgr);  然而,此时通过HrefNodes.InnerText得到的却是形如http://191.0.0.111/exchange/zhouhongying/%E6%94%B6%E4%BB%B6%E7%AE%B1/No%20Subject-7.EML/%E6%A0%B7%E5%93%81.jpg的字符串,也就说中文字符被转换成了UTF8的编码,详细参考见《IIS如何接收ServerXMLHTTP传过来的编码字符》(原作者不详)。那么将分拆的字符串进行码制转换即可。

int index=HrefNodes.InnerText.LastIndexOf('/')+1;
                            string attachmentName=HrefNodes.InnerText.Substring(index);                           
                            int    mLastIndex=attachmentName.LastIndexOf('.');
                            string mMainName=attachmentName.Substring(0,mLastIndex);
                            mMainName=Server.UrlDecode(mMainName);
                            int mExtLength=attachmentName.Length - mLastIndex;
                            string mExtName= attachmentName.Substring(mLastIndex,mExtLength);               
                            this.LAttachment.Text+="<a href=\"MailAttachment/"+displayname+"/"+mMainName+"."+mExtName+"\" target=\"_blank\">"+mMainName+"."+mExtName+"("+size+")</a>&nbsp;&nbsp;&nbsp;&nbsp;";
                            _attachmentName=mMainName+"."+mExtName;
附录代码:

private void GetDateToForm(string displayname)
      {
            System.Net.HttpWebRequest Request;
            System.Net.WebResponse Response;
            System.Net.CredentialCache MyCredentialCache;
//            string strSrcURI = "http://191.0.0.111/exchange/administrator/收件箱/"+displayname;
//            string strUserName = "administrator";

            string userID=User.Identity.Name.Trim();
            string strSrcURI = "http://191.0.0.111/exchange/"+userID+"/收件箱/"+displayname;
            string strUserName = userID;

            //string strPassword = "afineday";
            string strPassword=DAL.Data.UserModel.SelectByUserId(userID).Password.Trim();
            string strDomain = "oa.lgyw";
            string strBody = "";
            byte[] bytes = null;
            System.IO.Stream RequestStream = null;
            System.IO.Stream ResponseStream = null;
            XmlDocument ResponseXmlDoc = null;
            
            try
            {
                // Build the PROPFIND request body.
                //            strBody = "<?xml version=\"1.0\"?>"
                //                + "<d:propfind xmlns:d='DAV:'><d:prop>"
                //                + "<d:displayname/></d:prop></d:propfind>";
                strBody="<?xml version=\"1.0\"?>"
                  + "<d:propfind xmlns:d='DAV:'><d:allprop/>"
                  +"</d:propfind>";
                // Create a new CredentialCache object and fill it with the network
                // credentials required to access the server.
                MyCredentialCache = new System.Net.CredentialCache();
                MyCredentialCache.Add( new System.Uri(strSrcURI),
                  "NTLM",
                  new System.Net.NetworkCredential(strUserName, strPassword, strDomain)
                  );

                // Create the HttpWebRequest object.
                Request = (System.Net.HttpWebRequest)HttpWebRequest.Create(strSrcURI);

                // Add the network credentials to the request.
                Request.Credentials = MyCredentialCache;

                // Specify the method.
                Request.Method = "PROPFIND";

                // Encode the body using UTF-8.
                bytes = Encoding.UTF8.GetBytes((string)strBody);

                // Set the content header length.This must be
                // done before writing data to the request stream.
                Request.ContentLength = bytes.Length;

                // Get a reference to the request stream.
                RequestStream = Request.GetRequestStream();

                // Write the request body to the request stream.
                RequestStream.Write(bytes, 0, bytes.Length);

                // Close the Stream object to release the connection
                // for further use.
                RequestStream.Close();

                // Set the content type header.
                Request.ContentType = "text/xml";

                // Send the PROPFIND method request and get the
                // response from the server.
                Response = (HttpWebResponse)Request.GetResponse();

                // Get the XML response stream.
                ResponseStream = Response.GetResponseStream();
                // Create the XmlDocument object from the XML response stream.
                ResponseXmlDoc = new XmlDocument();
                ResponseXmlDoc.Load(ResponseStream);
            
                // Build a list of the DAV:href XML nodes, corresponding to the folders
                // in the mailbox.The DAV: namespace is typically assgigned the a:
                // prefix in the XML response body.            
                XmlNodeList SenderNodes = ResponseXmlDoc.GetElementsByTagName("e:from");
                XmlNodeList ToNodes=ResponseXmlDoc.GetElementsByTagName("e:to");
                XmlNodeList CCNodes=ResponseXmlDoc.GetElementsByTagName("d:cc");
                XmlNodeList importanceNodes=ResponseXmlDoc.GetElementsByTagName("e:importance");      
                XmlNodeList sensitivityNodes=ResponseXmlDoc.GetElementsByTagName("d:sensitivity");
                XmlNodeList    datareceiveNodes=ResponseXmlDoc.GetElementsByTagName("e:datereceived");
                XmlNodeList subjectNodes=ResponseXmlDoc.GetElementsByTagName("e:subject");
                XmlNodeList htmldescription=ResponseXmlDoc.GetElementsByTagName("e:htmldescription");            
                XmlNodeList    hasattachmentNodes=ResponseXmlDoc.GetElementsByTagName("e:hasattachment");      
                if(subjectNodes.Count > 0)
                {
                  this.Lfrom.Text=SenderNodes.InnerText.Replace("<","&lt").Replace(">","&gt");
                  this.Ldatareceived.Text=DateTime.Parse(datareceiveNodes.InnerText).ToString();
                  this.Lreceive.Text=ToNodes.InnerText.Replace("<","&lt").Replace(">","&gt");
                  this.LSubject.Text=subjectNodes.InnerText;      
                  if(CCNodes.Count>0)
                  {
                        this.LCC.Text=CCNodes.InnerText.Replace("<","&lt").Replace(">","&gt");
                  }               
                  if(importanceNodes.Count>0)
                  {
                        if(importanceNodes.InnerText=="2")
                        {
                            this.LImportance.Text="该邮件重要性为高!";
                        }
                        else if((importanceNodes.InnerText=="0"))
                        {   
                            this.LImportance.Text="该邮件重要性为低!";
                        }
                  }
                  if(sensitivityNodes.Count>0)
                  {
                        if(sensitivityNodes.InnerText=="Private")
                        {
                            this.Lsensitivity.Text="私人邮件";
                        }
                        else if(sensitivityNodes.InnerText=="Personal")
                        {
                            this.Lsensitivity.Text="个人邮件";
                        }
                        else if(sensitivityNodes.InnerText=="Company-Confidential")
                        {
                            this.Lsensitivity.Text="机密邮件";
                        }      
                  }                              
                  this.idBody.InnerHtml=htmldescription.InnerText;
                }
                if(hasattachmentNodes.InnerText=="1")
                {
                  this.GetAttachment(displayname);
                }
                // Clean up.
                ResponseStream.Close();
                Response.Close();
            }
            catch(Exception ex)
            {
                // Catch any exceptions. Any error codes from the SEARCH
                // method request on the server will be caught here, also.      
                Context.Response.Write(ex.Message);
            }
      }

      private void GetAttachment(string displayname)
      {
            // Variables.
            System.Net.HttpWebRequest Request;
            System.Net.WebResponse Response;
            System.Net.CredentialCache MyCredentialCache;
            string userID=User.Identity.Name.Trim();
            string password=DAL.Data.UserModel.SelectByUserId(userID).Password.Trim();
//            string strMessageURI = "http://191.0.0.111/exchange/administrator/收件箱/"+displayname;
//            string strUserName = "administrator";
            string strMessageURI = "http://191.0.0.111/exchange/"+userID+"/收件箱/"+displayname;
            string strUserName = userID;
            string strPassword = password;
            string strDomain = "oa.lgyw";
            System.IO.Stream ResponseStream = null;
            System.Xml.XmlDocument ResponseXmlDoc = null;
            System.Xml.XmlNode root = null;
            System.Xml.XmlNamespaceManager nsmgr = null;
            System.Xml.XmlNodeList PropstatNodes = null;
            System.Xml.XmlNodeList HrefNodes = null;
            System.Xml.XmlNode StatusNode = null;
            System.Xml.XmlNode PropNode = null;

            string[] _attachmentName=null;

            System.Xml.XmlNode NameNode=null;
            try
            {
                // Create a new CredentialCache object and fill it with the network
                // credentials required to access the server.
                MyCredentialCache = new System.Net.CredentialCache();
                MyCredentialCache.Add( new System.Uri(strMessageURI),
                  "NTLM",
                  new System.Net.NetworkCredential(strUserName, strPassword, strDomain)
                  );

                // Create the HttpWebRequest object.
                Request = (System.Net.HttpWebRequest)HttpWebRequest.Create(strMessageURI);

                // Add the network credentials to the request.
                Request.Credentials = MyCredentialCache;

                // Specify the method.
                Request.Method = "X-MS-ENUMATTS";

                // Send the X-MS-ENUMATTS method request and get the
                // response from the server.
                Response = (HttpWebResponse)Request.GetResponse();

                // Get the XML response stream.
                ResponseStream = Response.GetResponseStream();

                // Create the XmlDocument object from the XML response stream.
                ResponseXmlDoc = new System.Xml.XmlDocument();

                // Load the XML response stream.
                ResponseXmlDoc.Load(ResponseStream);

                // Get the root node.
                root = ResponseXmlDoc.DocumentElement;

                // Create a new XmlNamespaceManager.
                nsmgr = new System.Xml.XmlNamespaceManager(ResponseXmlDoc.NameTable);

                // Add the DAV: namespace, which is typically assigned the a: prefix
                // in the XML response body.The namespaceses and their associated
                // prefixes are listed in the attributes of the DAV:multistatus node
                // of the XML response.
                nsmgr.AddNamespace("a", "DAV:");

                // Add the http://schemas.microsoft.com/mapi/proptag/ namespace, which
                // is typically assigned the d: prefix in the XML response body.
                nsmgr.AddNamespace("d", "http://schemas.microsoft.com/mapi/proptag/");

                // Use an XPath query to build a list of the DAV:propstat XML nodes,
                // corresponding to the returned status and properties of
                // the file attachment(s).
                PropstatNodes = root.SelectNodes("//a:propstat", nsmgr);

                // Use an XPath query to build a list of the DAV:href nodes,
                // corresponding to the URIs of the attachement(s) on the message.
                // For each DAV:href node in the XML response, there is an
                // associated DAV:propstat node.
                HrefNodes = root.SelectNodes("//a:href", nsmgr);
               
                // Attachments found?
                if(HrefNodes.Count > 0)
                {
                  _attachmentName=new string;
                  // Display the number of attachments on the message.
                  // Iterate through the attachment properties.
                  for(int i=0;i<HrefNodes.Count;i++)
                  {
                        // Use an XPath query to get the DAV:status node from the DAV:propstat node.
                        StatusNode = PropstatNodes.SelectSingleNode("a:status", nsmgr);

                        // Check the status of the attachment properties.
                        if(StatusNode.InnerText != "HTTP/1.1 200 OK")
                        {
                            return;
                        }
                        else
                        {
                           
                            // Get the CdoPR_ATTACH_FILENAME_W MAPI property tag,
                            // corresponding to the attachment file name.The
                            // http://schemas.microsoft.com/mapi/proptag/ namespace is typically
                            // assigned the d: prefix in the XML response body.
                            NameNode = PropstatNodes.SelectSingleNode("a:prop/d:x3704001f", nsmgr);
                            // Get the CdoPR_ATTACH_SIZE MAPI property tag,
                            // corresponding to the attachment file size.
                            PropNode = PropstatNodes.SelectSingleNode("a:prop/d:x0e200003", nsmgr);
                            string size;
                            if(Convert.ToInt32(PropNode.InnerText)>1024*1224)
                            {
                              size=(Convert.ToInt32(PropNode.InnerText)/(1024*1024)).ToString()+"M";
                            }
                            else if(Convert.ToInt32(PropNode.InnerText)>1024)
                            {
                              size=(Convert.ToInt32(PropNode.InnerText)/1024).ToString()+"KB";
                            }
                            else
                            {
                              size=PropNode.InnerText+"B";
                            }
                            int index=HrefNodes.InnerText.LastIndexOf('/')+1;
                            string attachmentName=HrefNodes.InnerText.Substring(index);                           
                            int    mLastIndex=attachmentName.LastIndexOf('.');
                            string mMainName=attachmentName.Substring(0,mLastIndex);
                            mMainName=Server.UrlDecode(mMainName);
                            int mExtLength=attachmentName.Length - mLastIndex;
                            string mExtName= attachmentName.Substring(mLastIndex,mExtLength);               
                            this.LAttachment.Text+="<a href=\"MailAttachment/"+displayname+"/"+mMainName+"."+mExtName+"\" target=\"_blank\">"+mMainName+"."+mExtName+"("+size+")</a>&nbsp;&nbsp;&nbsp;&nbsp;";
                            _attachmentName=mMainName+"."+mExtName;
                        }
                  }
                  
                }               

                // Clean up.
                ResponseStream.Close();
                Response.Close();
   
            }
            catch(Exception ex)
            {
                // Catch any exceptions. Any error codes from the X-MS-ENUMATTS
                // method request on the server will be caught here, also.
               
            }
            this.GetAttachmentFile(displayname,HrefNodes.Count,_attachmentName);
      }
页: [1]
查看完整版本: 90%使用WebDAV开发的Exchange邮件管理(三)——获取邮件