有些项目中, 需要获取获取未读邮件数量, 比如在sharepoint项目中, 需要一个webpart来展示未读邮件. 做这个事情呢, 我也是第一次,之前连OWA,WebDAV是玩意也不知道是个什么东西.
当然还是借助强大的网络了, 网上其实很多人做个这个东西,多数都是一样,大多转载别人的(很多有注明地址.) 下面主要先贴出主要代码, 其实主要代码也不是我写的, 都是网上分享的. 只说说我期间遇到的一些问题.
code:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Configuration; using Microsoft.SharePoint; using Microsoft.SharePoint.Administration;
///这里你需要添加web引用;ExchangeServiceBinding
using CompanyName.App.net.mail; namespace CompanyName.App { /// <summary> /// GetUnReadEmailCountHandler 的摘要说明 /// </summary> public class GetUnReadEmailCountHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; string unRead = "-1"; try { unRead = @"<a href=""" + ConfigurationManager.AppSettings["MailServer"] + @""" target=""_blank"">" + GetUnreadMailCount().ToString() + "</a>"; } catch (Exception ex) { ///写入错误日志 SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory("读取邮件出错", TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected, ex.Message, ex.StackTrace); } context.Response.Write(unRead); } public bool IsReusable { get { return false; } } protected int GetUnreadMailCount() { try { string connectionString = System.Configuration.ConfigurationManager.AppSettings["ExchangeContext"]; int unreadCount = 0; ///绑定exchange服务器 这里你需要添加web引用,https://mail.Address.com/EWS/Exchange.asmx ExchangeServiceBinding exchangeServer = new ExchangeServiceBinding(); ///下面这句可以解决:"基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系" 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; }; // 建立信任连接 //exchangeServer.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials; //exchangeServer.Credentials = System.Net.CredentialCache.DefaultCredentials; //exchangeServer.UseDefaultCredentials = true; string url = string.Format("{0}/EWS/Exchange.asmx", connectionString); if (connectionString.IndexOf("|") > -1) { string[] strs = connectionString.Split('|'); url = string.Format("{0}/EWS/Exchange.asmx", strs[0]); System.Net.NetworkCredential nc = new System.Net.NetworkCredential(strs[1], strs[2], strs[3]); string userEmail = SPContext.Current.Web.CurrentUser.Email; if (userName.IndexOf("@") < 0) { throw new Exception(SPContext.Current.Web.CurrentUser.Name+"用户未配置邮件地址."); } exchangeServer.Credentials = nc; ExchangeImpersonationType exExchangeImpersonation = new ExchangeImpersonationType(); ConnectingSIDType csConnectingSid = new ConnectingSIDType(); csConnectingSid.Item = userEmail; exExchangeImpersonation.ConnectingSID = csConnectingSid; exchangeServer.ExchangeImpersonation = exExchangeImpersonation; } else { exchangeServer.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials; } exchangeServer.Url = url; // 定义邮件的收件箱 DistinguishedFolderIdType[] folderIDArray = new DistinguishedFolderIdType[1]; folderIDArray[0] = new DistinguishedFolderIdType(); folderIDArray[0].Id = DistinguishedFolderIdNameType.inbox; FindItemType findItemRequest = new FindItemType(); findItemRequest.Traversal = ItemQueryTraversalType.Shallow; ItemResponseShapeType itemProperties = new ItemResponseShapeType(); // itemProperties.BaseShape = DefaultShapeNamesType.IdOnly; findItemRequest.ItemShape = itemProperties; 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; //SPSecurity.RunWithElevatedPrivileges(delegate() //{ // 获取邮件 FindItemResponseType firt = exchangeServer.FindItem(findItemRequest); FindItemResponseMessageType folder = (FindItemResponseMessageType)firt.ResponseMessages.Items[0]; ArrayOfRealItemsType folderContents = new ArrayOfRealItemsType(); folderContents = (ArrayOfRealItemsType)folder.RootFolder.Item; ItemType[] items = folderContents.Items; unreadCount = items == null ? 0 : items.Length; //}); return unreadCount; } catch (Exception ex) { throw ex;
} } } }
说明: 配置文件: <add key=”ExchangeContext” value=”https://mail.mailServer.com|administrator|p@ssw0rd|domain.com” />
目前我使用:exchangeServer.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials 一直抛出401 错误. 如果你成功了,不妨告诉我一下, 因为配置模拟账户和密码的确不是很好.
如果exchange服务器上面你没有配置过模拟账号,那么你将得到"该帐户无权模拟所请求的用户",这个问题困扰了很多天, 因为exchange上面的设置我不是很懂, 其实网上很多人也遇到该问题, 只是我关键字没有用对, 所以找问题关键字很重要. 如果你也遇到同样问题了,很庆幸, 这里给你答案:
1.Open the Exchange Management Shell
2.输入: New-ManagementRoleAssignment –Name:impersonationAssignmentName –Role:ApplicationImpersonation –User:administrator
administrator就是你要设置的模拟账号,当然你也可以设置其他.
Configuring Exchange Impersonation:http://msdn.microsoft.com/en-us/library/bb204095.aspx
如果你需要读取未读邮件的标题和内容等其他内容,itemProperties.BaseShape = DefaultShapeNamesType.IdOnly; 需要修改为:itemProperties.BaseShape = DefaultShapeNamesType.AllProperties;前者只读取了ID属性,如果你试图获取其他字段将得到一个异常.
code: 获取未读邮件带标题.
int unReadCount = items == null ? 0 : items.Length; System.Text.StringBuilder sb = new System.Text.StringBuilder(); string linkUrl = @"<a href=""" + ConfigurationManager.AppSettings["MailServer"] + @""" title=""{0}"" target=""_blank"">{0}</a>"; sb.Append(string.Format(linkUrl, "未读邮件:[" + unReadCount + "]封"); sb.Append("<ul>"); int titleLength = 0; int.TryParse(HttpContext.Current.Request.QueryString["tl"], out titleLength); if (items != null) { foreach (ItemType curItem in items) { string subject = (curItem.Subject ?? "").Trim(); sb.Append("<li>" + string.Format(linkUrl, subject, (subject.Length > titleLength ? subject.Substring(0, titleLength) + "..." : subject)) + "</li>"); } } sb.Append("</ul>"); return sb.ToString();
另:如果邮件已经从服务器中获取了, 那么获取outlook中未读邮件可用下面方法:
using Outlook = Microsoft.Office.Interop.Outlook;
public int GetUnreadMailCount() { Outlook.Application outlook = new Outlook.ApplicationClass(); Outlook.NameSpace ns = outlook.GetNamespace("MAPI"); object _missing = Type.Missing; ns.Logon(_missing, _missing, false, true); Outlook.MAPIFolder inbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox); int unread = inbox.UnReadItemCount; return unread; }
区别在于:一个在服务器中获取未读邮件(确切的应该叫未收邮件),一个在客户端获取未读邮件.
http://msdn.microsoft.com/en-us/library/bb204095.aspx
http://support.microsoft.com/kb/2015567
由于当时网上参考比较多,不能一一罗列链接.