我需要能够监视和读取MS Exchange Server(我公司内部)上特定邮箱的电子邮件。我还需要能够阅读发件人的电子邮件地址,主题,邮件正文并下载附件(如果有)。
使用C#(或VB.NET)执行此操作的最佳方法是什么?
我需要能够监视和读取MS Exchange Server(我公司内部)上特定邮箱的电子邮件。我还需要能够阅读发件人的电子邮件地址,主题,邮件正文并下载附件(如果有)。
使用C#(或VB.NET)执行此操作的最佳方法是什么?
Answers:
一团糟。Microsoft官方不支持通过 .NET互操作DLL的MAPI或CDO-看起来可以正常工作,但是由于内存模型不同,存在内存泄漏问题。您可以使用CDOEX,但它只能在Exchange服务器本身上使用,而不能在远程上使用;无用。您可以与Outlook互操作,但是现在您已经对Outlook有了依赖性。过度杀伤力。最后,您可以使用Exchange 2003的WebDAV支持,但是WebDAV很复杂,.NET对它的内置支持很差,并且(更糟的是)Exchange 2007 几乎完全放弃了 WebDAV的支持。
一个人做什么?我最终使用AfterLogic的IMAP组件通过IMAP与我的Exchange 2003服务器进行通信,并且最终运行良好。(我通常会寻找免费的或开放源代码的库,但是我发现所有.NET库都想要-特别是在涉及2003 IMAP实现的一些怪癖时-这个库足够便宜,并且可以在第一个库中使用试试。我知道那里还有其他人。
但是,如果您的组织使用的是Exchange 2007,那么您会很幸运。Exchange 2007附带了一个基于SOAP的Web服务接口,该接口最终提供了与Exchange服务器交互的统一的,独立于语言的方式。如果您可以使2007+成为必需,那么这绝对是可行的方法。(对我来说,可悲的是,我的公司制定了“但2003年没有失败”的政策。)
如果您需要桥接Exchange 2003和2007,则绝对可以使用IMAP或POP3。
嗯
我在这里可能为时已晚,但这不是EWS的重点吗?
https://msdn.microsoft.com/zh-CN/library/dd633710(EXCHG.80).aspx
从邮箱获取邮件大约需要6行代码:
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
//service.Credentials = new NetworkCredential( "{Active Directory ID}", "{Password}", "{Domain Name}" );
service.AutodiscoverUrl( "First.Last@MyCompany.com" );
FindItemsResults<Item> findResults = service.FindItems(
WellKnownFolderName.Inbox,
new ItemView( 10 )
);
foreach ( Item item in findResults.Items )
{
Console.WriteLine( item.Subject );
}
service.autodiscoverurl
,我需要输入service.credentials
,对吗?
当前首选的(Exchange 2013和2016)API是EWS。它完全基于HTTP,可以从任何语言进行访问,但是有.Net和Java特定的库。
您可以使用EWSEditor来使用API。
扩展的MAPI。这是Outlook使用的本机API。最终使用MSEMS
Exchange MAPI提供程序,该提供程序可以使用RPC(Exchange 2013不再支持它)或RPC-over-HTTP(Exchange 2007或更高版本)或MAPI-over-HTTP(Exchange 2013和更高版本)与Exchange通信。
该API本身只能从非托管C ++或Delphi访问。您还可以使用Redemption(任何语言)-它的RDO对象系列是Extended MAPI包装器。若要使用扩展MAPI,您需要安装Outlook或MAPI的独立(Exchange)版本(在扩展支持上,它不支持Unicode PST和MSG文件,并且无法访问Exchange 2016)。扩展MAPI可以在服务中使用。
您可以使用OutlookSpy或MFCMAPI来使用API 。
Outlook对象模型 -不是特定于Exchange的,但它允许在运行代码的计算机上访问Outlook中的所有可用数据。不能在服务中使用。
交换活动同步。Microsoft不再在此协议上投入大量资源。
Outlook曾经用于安装CDO 1.21库(它包装了Extended MAPI),但是Microsoft已弃用它,并且不再接收任何更新。
曾经有一个名为.NET MAPI33的第三方.Net MAPI包装器,但是不再开发或支持它。
WebDAV-已弃用。
Exchange协作数据对象(CDOEX)-已过时。
Exchange OLE DB提供程序(EXOLEDB)-已过时。
这是我编写WebDAV时使用的一些旧代码。我认为它是针对Exchange 2003写的,但我已经不记得了。如果有帮助,请随时借用...
class MailUtil
{
private CredentialCache creds = new CredentialCache();
public MailUtil()
{
// set up webdav connection to exchange
this.creds = new CredentialCache();
this.creds.Add(new Uri("http://mail.domain.com/Exchange/me@domain.com/Inbox/"), "Basic", new NetworkCredential("myUserName", "myPassword", "WINDOWSDOMAIN"));
}
/// <summary>
/// Gets all unread emails in a user's Inbox
/// </summary>
/// <returns>A list of unread mail messages</returns>
public List<model.Mail> GetUnreadMail()
{
List<model.Mail> unreadMail = new List<model.Mail>();
string reqStr =
@"<?xml version=""1.0""?>
<g:searchrequest xmlns:g=""DAV:"">
<g:sql>
SELECT
""urn:schemas:mailheader:from"", ""urn:schemas:httpmail:textdescription""
FROM
""http://mail.domain.com/Exchange/me@domain.com/Inbox/""
WHERE
""urn:schemas:httpmail:read"" = FALSE
AND ""urn:schemas:httpmail:subject"" = 'tbintg'
AND ""DAV:contentclass"" = 'urn:content-classes:message'
</g:sql>
</g:searchrequest>";
byte[] reqBytes = Encoding.UTF8.GetBytes(reqStr);
// set up web request
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://mail.domain.com/Exchange/me@domain.com/Inbox/");
request.Credentials = this.creds;
request.Method = "SEARCH";
request.ContentLength = reqBytes.Length;
request.ContentType = "text/xml";
request.Timeout = 300000;
using (Stream requestStream = request.GetRequestStream())
{
try
{
requestStream.Write(reqBytes, 0, reqBytes.Length);
}
catch
{
}
finally
{
requestStream.Close();
}
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
try
{
XmlDocument document = new XmlDocument();
document.Load(responseStream);
// set up namespaces
XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable);
nsmgr.AddNamespace("a", "DAV:");
nsmgr.AddNamespace("b", "urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/");
nsmgr.AddNamespace("c", "xml:");
nsmgr.AddNamespace("d", "urn:schemas:mailheader:");
nsmgr.AddNamespace("e", "urn:schemas:httpmail:");
// Load each response (each mail item) into an object
XmlNodeList responseNodes = document.GetElementsByTagName("a:response");
foreach (XmlNode responseNode in responseNodes)
{
// get the <propstat> node that contains valid HTTP responses
XmlNode uriNode = responseNode.SelectSingleNode("child::a:href", nsmgr);
XmlNode propstatNode = responseNode.SelectSingleNode("descendant::a:propstat[a:status='HTTP/1.1 200 OK']", nsmgr);
if (propstatNode != null)
{
// read properties of this response, and load into a data object
XmlNode fromNode = propstatNode.SelectSingleNode("descendant::d:from", nsmgr);
XmlNode descNode = propstatNode.SelectSingleNode("descendant::e:textdescription", nsmgr);
// make new data object
model.Mail mail = new model.Mail();
if (uriNode != null)
mail.Uri = uriNode.InnerText;
if (fromNode != null)
mail.From = fromNode.InnerText;
if (descNode != null)
mail.Body = descNode.InnerText;
unreadMail.Add(mail);
}
}
}
catch (Exception e)
{
string msg = e.Message;
}
finally
{
responseStream.Close();
}
}
return unreadMail;
}
}
和model.Mail:
class Mail
{
private string uri;
private string from;
private string body;
public string Uri
{
get { return this.uri; }
set { this.uri = value; }
}
public string From
{
get { return this.from; }
set { this.from = value; }
}
public string Body
{
get { return this.body; }
set { this.body = value; }
}
}
我使用了在CodeProject.com上发布的代码。如果要使用POP3,它是我发现的更好的解决方案之一。
您应该能够使用MAPI访问邮箱并获取所需的信息。不幸的是,我所知道的唯一.NET MAPI库(MAPI33)似乎无法维护。这曾经是通过.NET访问MAPI的好方法,但是我现在不能说它的有效性。有关在哪里可以找到它的更多信息:MAPI33.dll的下载位置?
我终于有了使用救赎的解决方案,看看这些问题...
一种选择是使用Outlook。我们有一个邮件管理器应用程序,该应用程序访问交换服务器并使用Outlook作为界面。它很脏但是可以用。
示例代码:
public Outlook.MAPIFolder getInbox()
{
mailSession = new Outlook.Application();
mailNamespace = mailSession.GetNamespace("MAPI");
mailNamespace.Logon(mail_username, mail_password, false, true);
return MailNamespace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
}