我需要有能力监控并读取公司内部MS Exchange服务器上特定邮箱的电子邮件。我还需要能够阅读发件人的电子邮件地址、主题、消息正文以及下载附件(如果有的话)。
使用C#(或VB.NET),最好的方法是什么?
我需要有能力监控并读取公司内部MS Exchange服务器上特定邮箱的电子邮件。我还需要能够阅读发件人的电子邮件地址、主题、消息正文以及下载附件(如果有的话)。
使用C#(或VB.NET),最好的方法是什么?
现在的情况很混乱。使用MAPI或CDO通过.NET互操作DLL是Microsoft官方不支持的,虽然它看起来可以正常工作,但由于它们的内存模型不同而存在内存泄漏问题。您可以使用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
,对吗? - gymcodeGraph - 目前,访问存储在Exchange Server上的电子邮件、联系人、约会、任务等数据以及Microsoft(Teams、Sharepoint等)托管的其他数据的首选统一API(纯HTTP)。
使用Graph Explorer或OutlookSpy(我是它的作者)来操作API。
Microsoft提供了Graph SDK以供多种语言使用。
EWS。完全支持。它是纯HTTP的,可以从任何语言访问,但有.Net和Java特定的库。
微软表示不会添加新功能,而Graph更可取,即使Graph中并非所有EWS功能都可用(例如通过ExportItems/ImportItems公开的高保真度快速传输流导出/导入)。
您可以使用EWSEditor或OutlookSpy(我是它的作者)来操作API。
Extended 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包装器。要使用Extended MAPI,您需要安装Outlook或独立(Exchange)版本的MAPI(在扩展支持上,并且不支持Unicode PST和MSG文件,也无法访问Exchange 2016)。 Extended MAPI可用于服务。
您可以使用OutlookSpy(我是它的作者)或MFCMAPI来操作API。
Outlook Object Model - 不是Exchange特定的,但它允许访问代码运行所在计算机上Outlook中的所有数据。不能用于服务。
Exchange Active Sync。微软不再投入任何重要资源到这个协议中。
Outlook曾经安装CDO 1.21库(它包装了Extended MAPI),但已被Microsoft弃用,不再接收任何更新。
曾经有一个名为MAPI33的第三方.Net MAPI包装器,但它不再得到开发或支持。
WebDAV - 已弃用。
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; }
}
}
如果您的Exchange服务器配置支持POP或IMAP,则这是一种简单的方法。
另一个选择是WebDAV访问。有一个库可用于此。这可能是您最好的选择。
我认为使用COM对象访问Exchange也有选项,但我不确定它有多容易。
我想这完全取决于您的管理员愿意给您访问权限的具体内容。
你应该能够使用MAPI来访问邮箱并获取所需信息。不幸的是,我所知道的唯一的.NET MAPI库(MAPI33)似乎已经不再维护了。这曾经是通过.NET访问MAPI的好方法,但我无法确定它现在的有效性。可以在这里获取有关其下载位置的更多信息:MAPI33.dll的下载位置?