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

1.       WebDAV的方式

示例代码: 

 

 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.       通过用户的用户名和密码进行认证,查询自己的未读邮件

示例代码:

 

 GetUnreadMailCount1()
    {
        int count = 0;

        
try
        {
            
string url = System.Configuration.ConfigurationSettings.AppSettings["SMTPServer"];

            
if (!url.EndsWith("/"))
            {
                url 
+= "/";
            }
            url 
+= "EWS/Exchange.asmx";
            url 
= "https://" + url;

            
// 绑定exchange服务器
            ExchangeServiceBinding exchangeServer = new ExchangeServiceBinding();

            
// 建立信任连接
            exchangeServer.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            exchangeServer.Url 
= url;

            
// 定义邮件的收件箱
            DistinguishedFolderIdType[] folderIDArray = new DistinguishedFolderIdType[1];
            folderIDArray[
0= new DistinguishedFolderIdType();
            folderIDArray[
0].Id = DistinguishedFolderIdNameType.inbox;

            PathToUnindexedFieldType ptuftDisplayName 
= new PathToUnindexedFieldType();
            ptuftDisplayName.FieldURI 
= UnindexedFieldURIType.folderDisplayName;

            PathToExtendedFieldType pteftComment 
= new PathToExtendedFieldType();
            pteftComment.PropertyTag 
= "0x3004"// PR_COMMENT
            pteftComment.PropertyType = MapiPropertyTypeType.String;

            
// 定义GetFolderType对象,设置相应属性
            GetFolderType myfoldertype = new GetFolderType();
            myfoldertype.FolderIds 
= folderIDArray;
            myfoldertype.FolderShape 
= new FolderResponseShapeType();
            myfoldertype.FolderShape.BaseShape 
= DefaultShapeNamesType.IdOnly;
            myfoldertype.FolderShape.AdditionalProperties 
= new BasePathToElementType[2];
            myfoldertype.FolderShape.AdditionalProperties[
0= ptuftDisplayName;
            myfoldertype.FolderShape.AdditionalProperties[
1= pteftComment;

            
// 获取服务器中的文件夹的集合
            GetFolderResponseType myFolder = exchangeServer.GetFolder(myfoldertype);

            
// 获取收件箱
            FolderInfoResponseMessageType firmtInbox =
                (FolderInfoResponseMessageType)myFolder.ResponseMessages.Items[
0];



            PathToUnindexedFieldType ptuftSubject 
= new PathToUnindexedFieldType();
            ptuftSubject.FieldURI 
= UnindexedFieldURIType.itemSubject;

            PathToUnindexedFieldType ptuftBody 
= new PathToUnindexedFieldType();
            ptuftBody.FieldURI 
= UnindexedFieldURIType.itemAttachments;

            PathToExtendedFieldType pteftFlagStatus 
= new PathToExtendedFieldType();
            pteftFlagStatus.PropertyTag 
= "0x1090"// PR_FLAG_STATUS
            pteftFlagStatus.PropertyType = MapiPropertyTypeType.Integer;

            
// 定义FindItemType对象,准备获取收件箱中的集合
            FindItemType findItemRequest = new FindItemType();
            findItemRequest.Traversal 
= ItemQueryTraversalType.Shallow;
            findItemRequest.ItemShape 
= new ItemResponseShapeType();
            findItemRequest.ItemShape.BaseShape 
= DefaultShapeNamesType.AllProperties;


            findItemRequest.ParentFolderIds 
= new FolderIdType[1];
            findItemRequest.ParentFolderIds[
0= firmtInbox.Folders[0].FolderId;

            
// 获取邮件
            FindItemResponseType firt = exchangeServer.FindItem(findItemRequest);

            
// 循环迭代每一封邮件
            foreach (FindItemResponseMessageType firmtMessage in firt.ResponseMessages.Items)
            {
                
// 如果包含邮件,显示出来
                if (firmtMessage.RootFolder.TotalItemsInView > 0)
                {
                    
// 循环迭代每一封邮件详细信息
                    foreach (ItemType it in ((ArrayOfRealItemsType)firmtMessage.RootFolder.Item).Items)
                    {
                        
if (!((MessageType)(it)).IsRead)
                        {
                            count
++;
                        }
                    }
                }

            }
        }
        
catch (Exception ex)
        {
            
//TODO
        }

        
return count;

    }

 

  

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

示例代码:

 

 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
     }

}

 

相关文章:

  • 2022-02-18
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-10-13
  • 2022-12-23
  • 2021-11-17
  • 2021-11-17
猜你喜欢
  • 2022-12-23
  • 2021-07-14
  • 2021-12-09
  • 2021-08-20
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案