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认证是通过票据进行认证的。所以我们要把相应的认证方式进行设置。
2. 通过Exchange Web Services方式
通过Exchange Web Services 访问的方式也有2中得到未读邮件的方式:
a. 通过用户的用户名和密码进行认证,查询自己的未读邮件
示例代码:
- protected int 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 中才有
示例代码:
- 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
}
}