在SharePoint的项目中,经常会把SharePoint 和Exchange整合到一起,所以我们经常会遇到读取OWA中未读邮件的问题,当然解决的方法 也是多种多样的。有以下几种:
  
  1. WebDAV的方式
  示例代码:
  
  
  
  private int GetUnReadMailCount()
   {
  
  
   string url = "http://10.10.10.254/exchange/"; //指定Exchange服务器地址
   System.NET.HttpWebRequest Request;
   System.NET.WebResponse Response;
   System.NET.CredentialCache MyCredentialCache;
   string strUserName = UserName; //指定登录的用户名
   string strRootURI = url + strUserName; //得到要访问邮箱的WebDAV地址
   string strPassword = PassWord; //指定该用户的密码
   string strDomain = "unique.com"; //指定域名
   string strQuery = "";
   byte[] bytes = null;
   System.IO.Stream RequestStream = null;
   System.IO.Stream ResponseStream = null;
   XMLDocument ResponseXmlDoc = null;
   XMLNodeList HrefNodes = null;
   XMLNodeList SizeNodes = null;
   int count = 0;
  
  
   try
   {
   // 用SQL查询WebDAV返回结果中的unreadcount节点.
   strQuery = "<?xml version=\"1.0\"?><D:searchrequest xmlns:D = \"DAV:\" >"
   + "<D:sql>SELECT \"DAV:displayname\",\"urn:schemas:httpmail:unreadcount\" FROM \"" + strRootURI + "\""
   + "</D:sql></D:searchrequest>";
  
   // 创建新的CredentialCache对象,构建身份凭据
   MyCredentialCache = new System.NET.CredentialCache();
   MyCredentialCache.Add(new System.Uri(strRootURI), "NTLM",
   new System.NET.NetworkCredential(strUserName, strPassword, strDomain));
  
  
   // Create the HttpWebRequest object.
   Request = (System.NET.HttpWebRequest)HttpWebRequest.Create(strRootURI);
  
   // 指定HttpWebRequest的身份凭据,此处为关键所在。如果使用之前
   // 创建的MyCredentialCache,则这个身份凭据是可以从Web服务器传递
   // 到Exchange服务器的,但是这样带来的问题也很明显,就是不能够自
   // 动获取当前登录到域的用户的身份。即便已经成功登录到域,那也只
   // 能通过form再次输入用户名密码。因此,我在这里用的是
   // Request.Credentials = CredentialCache.DefaultCredentials,
   // 这样便可以获得当前用户的凭据,但是这样带来的问题便是上面提到的
   // 身份凭据无法传递的问题,解决方法请关注下篇文章。
   Request.Credentials = MyCredentialCache;
   // 指定WebDAV的SEARCH方法
   Request.Method = "SEARCH";
  
   // Encode the body using UTF-8.
   bytes = Encoding.UTF8.GetBytes((string)strQuery);
  
   // 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 SQL query 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 SEARCH method request and get the
   // response from the server.
   Response = (HttpWebResponse)Request.GetResponse();
  
   // Get the XML response stream.
   ResponseStream = Response.GetResponseStream();
  
   // 创建XMLDocument对象,并获取收件箱的unreadcount节点的值
   ResponseXMLDoc = new XmlDocument();
   ResponseXMLDoc.Load(ResponseStream);
   HrefNodes = ResponseXMLDoc.GetElementsByTagName("a:displayname");
   SizeNodes = ResponseXMLDoc.GetElementsByTagName("d:unreadcount");
   for (int i = 0; i < HrefNodes.Count; i++)
   {
   if (HrefNodes[i].InnerText == "收件箱")
   count = int.Parse(SizeNodes[i].InnerText);
   }
   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.
   return -1;
  
  
   }
   return count;
  
   }
  
  
   缺点主要在用户的凭证上面。
  
  a. 通过用户的用户名和密码进行身份的认证。可以通过SharePoint的SSO存储用户的凭证信息
  b. 加域的机器通过默认的身份凭证信息进行身份认证。这里面会有一个认证的设置。因为SharePoint中默认的认证方式是NTLM,认证的时候,需要使用用户名和密码,而Kerberos认证是通过票据进行认证的。所以我们要把相应的认证方式进行设置。详细的操作请参考http://security.ctocio.com.cn/tips/121/8274121.sHTML。我按这种方式没有成功,如果有人弄成功了,可以告诉我一下,怎么弄的。
  
  2. 通过Exchange Web Services方式
  通过Exchange Web Services 访问的方式也有2中得到未读邮件的方式:
  a. 通过用户的用户名和密码进行认证,查询自己的未读邮件
  示例代码:
  
  
  Code
  
  
  
  
  b. 通过身份模拟的方式进行,这个好像只有Exchange 2007 中才有
  示例代码:
  
  
  
  protected int GetUnreadMailCount()
   {
   try
   {
   string domianUserName = System.Configuration.ConfigurationSettings.AppSettings["DomianAdmin"];
   string domianPassword = System.Configuration.ConfigurationSettings.AppSettings["DomainPwd"];
   string domainName = System.Configuration.ConfigurationSettings.AppSettings["DomainName"];
  
   System.NET.NetworkCredential nc = new System.Net.NetworkCredential(domianUserName, domianPassword, domainName);
  
   System.NET.ServicePointManager.ServerCertificateValidationCallback =
   delegate(Object obj, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.NET.Security.SslPolicyErrors errors)
   {
   return true;
   };
  
   string exchUrl = System.Configuration.ConfigurationSettings.AppSettings["SMTPServer"];
  
   string emEmailAddress = string.Empty;
  
   string userName = SPContext.Current.Web.CurrentUser.LoginName;
   emEmailAddress = userName.Substring(userName.IndexOf("\\") + 1) + "@" + domainName;
  
   // Response.Write("LoginName :" + userName.Substring(userName.IndexOf("\\") + 1));
  
   ExchangeServiceBinding esb = new ExchangeServiceBinding();
   esb.Url = string.Format("https://{0}/EWS/Exchange.asmx", exchUrl);
   esb.Credentials = nc;
   ExchangeImpersonationType exExchangeImpersonation = new ExchangeImpersonationType();
   ConnectingSIDType csConnectingSid = new ConnectingSIDType();
   csConnectingSid.PrimarySmtpAddress = emEmailAddress;
   exExchangeImpersonation.ConnectingSID = csConnectingSid;
   esb.ExchangeImpersonation = exExchangeImpersonation;
  
   FindItemType findItemRequest = new FindItemType();
   findItemRequest.Traversal = ItemQueryTraversalType.Shallow;
   ItemResponseShapeType itemProperties = new ItemResponseShapeType();
   itemProperties.BaseShape = DefaultShapeNamesType.IdOnly;
   findItemRequest.ItemShape = itemProperties;
   DistinguishedFolderIdType[] folderIDArray = new DistinguishedFolderIdType[1];
   folderIDArray[0] = new DistinguishedFolderIdType();
   folderIDArray[0].Id = DistinguishedFolderIdNameType.inbox;
   findItemRequest.ParentFolderIds = folderIDArray;
   RestrictionType restriction = new RestrictionType();
   IsEqualToType isEqualTo = new IsEqualToType();
   PathToUnindexedFieldType pathToFieldType = new PathToUnindexedFieldType();
   pathToFieldType.FieldURI = UnindexedFieldURIType.messageIsRead;
   FieldURIOrConstantType constantType = new FieldURIOrConstantType();
   ConstantValueType constantValueType = new ConstantValueType();
   constantValueType.Value = "0";
   constantType.Item = constantValueType;
   isEqualTo.Item = pathToFieldType;
   isEqualTo.FieldURIOrConstant = constantType;
   restriction.Item = isEqualTo;
   findItemRequest.Restriction = restriction;
  
   FindItemResponseType findItemResponse = esb.FindItem(findItemRequest);
  
   FindItemResponseMessageType folder = (FindItemResponseMessageType)findItemResponse.ResponseMessages.Items[0];
   ArrayOfRealItemsType folderContents = new ArrayOfRealItemsType();
   folderContents = (ArrayOfRealItemsType)folder.RootFolder.Item;
   ItemType[] items = folderContents.Items;
  
   return items == null ? 0 : items.Length;
   }
   catch (Exception ex)
   {
   //Response.Write(ex);
   return 0;
   }
  
   return 0;
   }
  
  
  
  
   优点:
  
  可以不用域环境就能访问用户的未读邮件
  缺点:
  直接使用代码是没有用的,会提示相应的错误信息:
  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-08-16 14:20  yxbsmx  阅读(251)  评论(0编辑  收藏  举报