在SharePoint的项目中,经常会把SharePoint Exchange整合到一起,所以我们经常会遇到读取OWA中未读邮件的问题,当然解决的方法 也是多种多样的。有以下几种:

1.  WebDAV的方式

示例代码: 

 

  1. private int GetUnReadMailCount()   
  2.         {   
  3.             string url = "http://10.10.10.254/exchange/"; //指定Exchange服务器地址    
  4.             System.Net.HttpWebRequest Request;   
  5.             System.Net.WebResponse Response;   
  6.             System.Net.CredentialCache MyCredentialCache;   
  7.             string strUserName = UserName; //指定登录的用户名   
  8.             string strRootURI = url + strUserName; //得到要访问邮箱的WebDAV地址   
  9.             string strPassword = PassWord; //指定该用户的密码   
  10.             string strDomain = "unique.com"//指定域名   
  11.             string strQuery = "";   
  12.             byte[] bytes = null;   
  13.             System.IO.Stream RequestStream = null;   
  14.             System.IO.Stream ResponseStream = null;   
  15.             XmlDocument ResponseXmlDoc = null;   
  16.             XmlNodeList HrefNodes = null;   
  17.             XmlNodeList SizeNodes = null;   
  18.             int count = 0;   
  19.             try  
  20.             {   
  21.                 // 用SQL查询WebDAV返回结果中的unreadcount节点.   
  22.                 strQuery = "<?xml version=\"1.0\"?><D:searchrequest xmlns:D = \"DAV:\" >"  
  23.                      + "<D:sql>SELECT \"DAV:displayname\",\"urn:schemas:httpmail:unreadcount\" FROM \"" + strRootURI + "\""  
  24.                    + "</D:sql></D:searchrequest>";   
  25.                 // 创建新的CredentialCache对象,构建身份凭据   
  26.                 MyCredentialCache = new System.Net.CredentialCache();   
  27.                 MyCredentialCache.Add(new System.Uri(strRootURI), "NTLM",   
  28.                 new System.Net.NetworkCredential(strUserName, strPassword, strDomain));   
  29.                 // Create the HttpWebRequest object.   
  30.                 Request = (System.Net.HttpWebRequest)HttpWebRequest.Create(strRootURI);   
  31.                 // 指定HttpWebRequest的身份凭据,此处为关键所在。如果使用之前   
  32.                 // 创建的MyCredentialCache,则这个身份凭据是可以从Web服务器传递   
  33.                 // 到Exchange服务器的,但是这样带来的问题也很明显,就是不能够自   
  34.                 // 动获取当前登录到域的用户的身份。即便已经成功登录到域,那也只   
  35.                 // 能通过form再次输入用户名密码。因此,我在这里用的是   
  36.                 // Request.Credentials = CredentialCache.DefaultCredentials,   
  37.                 // 这样便可以获得当前用户的凭据,但是这样带来的问题便是上面提到的   
  38.                 // 身份凭据无法传递的问题,解决方法请关注下篇文章。   
  39.                 Request.Credentials = MyCredentialCache;   
  40.                 // 指定WebDAV的SEARCH方法   
  41.                 Request.Method = "SEARCH";   
  42.                 // Encode the body using UTF-8.   
  43.                 bytes = Encoding.UTF8.GetBytes((string)strQuery);   
  44.                 // Set the content header length. This must be   
  45.                 // done before writing data to the request stream.   
  46.                 Request.ContentLength = bytes.Length;   
  47.                 // Get a reference to the request stream.   
  48.                 RequestStream = Request.GetRequestStream();   
  49.                 // Write the SQL query to the request stream.   
  50.                 RequestStream.Write(bytes, 0, bytes.Length);   
  51.                 // Close the Stream object to release the connection   
  52.                 // for further use.   
  53.                 RequestStream.Close();   
  54.                 // Set the content type header.   
  55.                 Request.ContentType = "text/xml";   
  56.                 // Send the SEARCH method request and get the   
  57.                 // response from the server.   
  58.                 Response = (HttpWebResponse)Request.GetResponse();   
  59.                 // Get the XML response stream.   
  60.                 ResponseStream = Response.GetResponseStream();   
  61.                 // 创建XmlDocument对象,并获取收件箱的unreadcount节点的值   
  62.                 ResponseXmlDoc = new XmlDocument();   
  63.                 ResponseXmlDoc.Load(ResponseStream);   
  64.                 HrefNodes = ResponseXmlDoc.GetElementsByTagName("a:displayname");   
  65.                 SizeNodes = ResponseXmlDoc.GetElementsByTagName("d:unreadcount");   
  66.                 for (int i = 0; i < HrefNodes.Count; i++)   
  67.                 {   
  68.                     if (HrefNodes[i].InnerText == "收件箱")   
  69.                         count = int.Parse(SizeNodes[i].InnerText);   
  70.                 }   
  71.                 ResponseStream.Close();   
  72.                 Response.Close();   
  73.             }   
  74.             catch (Exception ex)   
  75.             {   
  76.                 // Catch any exceptions. Any error codes from the SEARCH   
  77.                 // method request on the server will be caught here, also.   
  78.                 return -1;   
  79.             }   
  80.             return count;   
  81.         }  
 

 

 缺点主要在用户的凭证上面。

a.   通过用户的用户名和密码进行身份的认证。可以通过SharePoint的SSO存储用户的凭证信息

b.   加域的机器通过默认的身份凭证信息进行身份认证。这里面会有一个认证的设置。因为SharePoint中默认的认证方式是NTLM,认证的时候,需要使用用户名和密码,而Kerberos认证是通过票据进行认证的。所以我们要把相应的认证方式进行设置。

2.   通过Exchange Web Services方式

      通过Exchange Web Services 访问的方式也有2中得到未读邮件的方式:

a.   通过用户的用户名和密码进行认证,查询自己的未读邮件

示例代码:

 

  1. protected int GetUnreadMailCount1()   
  2.     {   
  3.         int count = 0;   
  4.         try  
  5.         {   
  6.             string url = System.Configuration.ConfigurationSettings.AppSettings["SMTPServer"];   
  7.             if (!url.EndsWith("/"))   
  8.             {   
  9.                 url += "/";   
  10.             }   
  11.             url += "EWS/Exchange.asmx";   
  12.             url = "https://" + url;   
  13.             // 绑定exchange服务器   
  14.             ExchangeServiceBinding exchangeServer = new ExchangeServiceBinding();   
  15.             // 建立信任连接   
  16.             exchangeServer.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;   
  17.             exchangeServer.Url = url;   
  18.             // 定义邮件的收件箱   
  19.             DistinguishedFolderIdType[] folderIDArray = new DistinguishedFolderIdType[1];   
  20.             folderIDArray[0] = new DistinguishedFolderIdType();   
  21.             folderIDArray[0].Id = DistinguishedFolderIdNameType.inbox;   
  22.             PathToUnindexedFieldType ptuftDisplayName = new PathToUnindexedFieldType();   
  23.             ptuftDisplayName.FieldURI = UnindexedFieldURIType.folderDisplayName;   
  24.             PathToExtendedFieldType pteftComment = new PathToExtendedFieldType();   
  25.             pteftComment.PropertyTag = "0x3004"// PR_COMMENT   
  26.             pteftComment.PropertyType = MapiPropertyTypeType.String;   
  27.             // 定义GetFolderType对象,设置相应属性   
  28.             GetFolderType myfoldertype = new GetFolderType();   
  29.             myfoldertype.FolderIds = folderIDArray;   
  30.             myfoldertype.FolderShape = new FolderResponseShapeType();   
  31.             myfoldertype.FolderShape.BaseShape = DefaultShapeNamesType.IdOnly;   
  32.             myfoldertype.FolderShape.AdditionalProperties = new BasePathToElementType[2];   
  33.             myfoldertype.FolderShape.AdditionalProperties[0] = ptuftDisplayName;   
  34.             myfoldertype.FolderShape.AdditionalProperties[1] = pteftComment;   
  35.             // 获取服务器中的文件夹的集合   
  36.             GetFolderResponseType myFolder = exchangeServer.GetFolder(myfoldertype);   
  37.             // 获取收件箱   
  38.             FolderInfoResponseMessageType firmtInbox =   
  39.                 (FolderInfoResponseMessageType)myFolder.ResponseMessages.Items[0];   
  40.             PathToUnindexedFieldType ptuftSubject = new PathToUnindexedFieldType();   
  41.             ptuftSubject.FieldURI = UnindexedFieldURIType.itemSubject;   
  42.             PathToUnindexedFieldType ptuftBody = new PathToUnindexedFieldType();   
  43.             ptuftBody.FieldURI = UnindexedFieldURIType.itemAttachments;   
  44.             PathToExtendedFieldType pteftFlagStatus = new PathToExtendedFieldType();   
  45.             pteftFlagStatus.PropertyTag = "0x1090"// PR_FLAG_STATUS   
  46.             pteftFlagStatus.PropertyType = MapiPropertyTypeType.Integer;   
  47.             // 定义FindItemType对象,准备获取收件箱中的集合   
  48.             FindItemType findItemRequest = new FindItemType();   
  49.             findItemRequest.Traversal = ItemQueryTraversalType.Shallow;   
  50.             findItemRequest.ItemShape = new ItemResponseShapeType();   
  51.             findItemRequest.ItemShape.BaseShape = DefaultShapeNamesType.AllProperties;   
  52.             findItemRequest.ParentFolderIds = new FolderIdType[1];   
  53.             findItemRequest.ParentFolderIds[0] = firmtInbox.Folders[0].FolderId;   
  54.             // 获取邮件   
  55.             FindItemResponseType firt = exchangeServer.FindItem(findItemRequest);   
  56.             // 循环迭代每一封邮件   
  57.             foreach (FindItemResponseMessageType firmtMessage in firt.ResponseMessages.Items)   
  58.             {   
  59.                 // 如果包含邮件,显示出来   
  60.                 if (firmtMessage.RootFolder.TotalItemsInView > 0)   
  61.                 {   
  62.                     // 循环迭代每一封邮件详细信息   
  63.                     foreach (ItemType it in ((ArrayOfRealItemsType)firmtMessage.RootFolder.Item).Items)   
  64.                     {   
  65.                         if (!((MessageType)(it)).IsRead)   
  66.                         {   
  67.                             count++;   
  68.                         }   
  69.                     }   
  70.                 }   
  71.             }   
  72.         }   
  73.         catch (Exception ex)   
  74.         {   
  75.             //TODO   
  76.         }   
  77.         return count;   
  78.     }   
  79.    
  

 

b.  通过身份模拟的方式进行,这个好像只有Exchange 2007 中才有

示例代码:

  1. protected int GetUnreadMailCount()   
  2.     {   
  3.         try  
  4.         {   
  5.             string domianUserName = System.Configuration.ConfigurationSettings.AppSettings["DomianAdmin"];   
  6.             string domianPassWord = System.Configuration.ConfigurationSettings.AppSettings["DomainPwd"];   
  7.             string domainName = System.Configuration.ConfigurationSettings.AppSettings["DomainName"];   
  8.             System.Net.NetworkCredential nc = new System.Net.NetworkCredential(domianUserName, domianPassWord, domainName);   
  9.             System.Net.ServicePointManager.ServerCertificateValidationCallback =   
  10.                     delegate(Object obj, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors errors)   
  11.                     {   
  12.                         return true;   
  13.                     };   
  14.             string exchUrl = System.Configuration.ConfigurationSettings.AppSettings["SMTPServer"];   
  15.                
  16.             string emEmailAddress = string.Empty;   
  17.             string userName = SPContext.Current.Web.CurrentUser.LoginName;   
  18.             emEmailAddress = userName.Substring(userName.IndexOf("\\") + 1) + "@" + domainName;   
  19.             //  Response.Write("LoginName :" + userName.Substring(userName.IndexOf("\\") + 1));   
  20.             ExchangeServiceBinding esb = new ExchangeServiceBinding();   
  21.             esb.Url = string.Format("https://{0}/EWS/Exchange.asmx", exchUrl);   
  22.             esb.Credentials = nc;   
  23.             ExchangeImpersonationType exExchangeImpersonation = new ExchangeImpersonationType();   
  24.             ConnectingSIDType csConnectingSid = new ConnectingSIDType();   
  25.             csConnectingSid.PrimarySmtpAddress = emEmailAddress;   
  26.             exExchangeImpersonation.ConnectingSID = csConnectingSid;   
  27.             esb.ExchangeImpersonation = exExchangeImpersonation;   
  28.             FindItemType findItemRequest = new FindItemType();   
  29.             findItemRequest.Traversal = ItemQueryTraversalType.Shallow;   
  30.             ItemResponseShapeType itemProperties = new ItemResponseShapeType();   
  31.             itemProperties.BaseShape = DefaultShapeNamesType.IdOnly;   
  32.             findItemRequest.ItemShape = itemProperties;   
  33.             DistinguishedFolderIdType[] folderIDArray = new DistinguishedFolderIdType[1];   
  34.             folderIDArray[0] = new DistinguishedFolderIdType();   
  35.             folderIDArray[0].Id = DistinguishedFolderIdNameType.inbox;   
  36.             findItemRequest.ParentFolderIds = folderIDArray;   
  37.             RestrictionType restriction = new RestrictionType();   
  38.             IsEqualToType isEqualTo = new IsEqualToType();   
  39.             PathToUnindexedFieldType pathToFieldType = new PathToUnindexedFieldType();   
  40.             pathToFieldType.FieldURI = UnindexedFieldURIType.messageIsRead;   
  41.             FieldURIOrConstantType constantType = new FieldURIOrConstantType();   
  42.             ConstantValueType constantValueType = new ConstantValueType();   
  43.             constantValueType.Value = "0";   
  44.             constantType.Item = constantValueType;   
  45.             isEqualTo.Item = pathToFieldType;   
  46.             isEqualTo.FieldURIOrConstant = constantType;   
  47.             restriction.Item = isEqualTo;   
  48.             findItemRequest.Restriction = restriction;   
  49.             FindItemResponseType findItemResponse = esb.FindItem(findItemRequest);   
  50.             FindItemResponseMessageType folder = (FindItemResponseMessageType)findItemResponse.ResponseMessages.Items[0];   
  51.             ArrayOfRealItemsType folderContents = new ArrayOfRealItemsType();   
  52.             folderContents = (ArrayOfRealItemsType)folder.RootFolder.Item;   
  53.             ItemType[] items = folderContents.Items;   
  54.             return items == null ? 0 : items.Length;   
  55.         }   
  56.         catch (Exception ex)   
  57.         {   
  58.             //Response.Write(ex);   
  59.             return 0;   
  60.         }   
  61.         return 0;   
  62.     }      
 优点:

可以不用域环境就能访问用户的未读邮件

缺点:

直接使用代码是没有用的,会提示相应的错误信息:

The server to which the application is connected cannot impersonate the requested user due to insufficient permission.

必须在Exchange上的控制台上面使用以下的命令,才能正常的使用:

foreach ($exchangeServer in Get-ExchangeServer)
{
     if ($exchangeServer.ServerRole -match 'ClientAccess')
     {
          Add-ADPermission -Identity $exchangeServer.DistinguishedName -User 'domain"user' -ExtendedRights ms-Exch-EPI-Impersonation
     }

}

posted on 2009-10-27 15:21  yxbsmx  阅读(623)  评论(0编辑  收藏  举报