用 C# 读取 MS Exchange 电子邮件
-
19-08-2019 - |
题
我需要能够监视和读取 MS Exchange Server(我公司内部)上特定邮箱的电子邮件。我还需要能够读取发件人的电子邮件地址、主题、邮件正文并下载附件(如果有)。
使用 C#(或 Vb.net)执行此操作的最佳方法是什么?
解决方案
一团糟。通过 .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/en -us /库/ 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 );
}
当前首选(Exchange 2013 和 2016)API 是 环境预警系统. 。它纯粹基于 HTTP,可以从任何语言访问,但是有 。网 和 爪哇 特定的库。
您可以使用 EWS编辑器 使用 API。
扩展MAPI. 。这是 Outlook 使用的本机 API。它最终使用
MSEMS
Exchange MAPI 提供程序,可以使用 RPC(Exchange 2013 不再支持它)或 RPC-over-HTTP(Exchange 2007 或更高版本)或 MAPI-over-HTTP(Exchange 2013 和更高版本)与 Exchange 通信。API 本身只能从非托管 C++ 或 德尔福. 。您还可以使用 赎回 (任何语言) - 它 RDO 对象族是扩展 MAPI 包装器。要使用扩展 MAPI,您需要安装 Outlook 或 MAPI 的独立 (Exchange) 版本 (在扩展支持上,它不支持 Unicode PST 和 MSG 文件,并且无法访问 Exchange 2016)。扩展 MAPI 可以在服务中使用。
您可以使用 API 进行操作 Outlook间谍软件 或者 MFCMAPI.
Outlook 对象模型 - 不是特定于 Exchange 的,但它允许访问运行代码的计算机上 Outlook 中可用的所有数据。不能在服务中使用。
Exchange 活动同步. 。Microsoft 不再为此协议投入任何重要资源。
Outlook 曾经安装 CDO 1.21 库(它包装了扩展 MAPI),但它已被 Microsoft 弃用,并且不再接收任何更新。
曾经有一个名为 MAPI33 的第三方 .Net MAPI 包装器,但它不再被开发或支持。
WebDAV - 已弃用。
用于交换的协作数据对象 (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,那就是我已经找到了更好的解决方案之一。
如果您的Exchange服务器配置为支持POP或IMAP,这是一个简单的办法。
另一种选择是WebDAV访问。有一个库使用了点。这可能是你最好的选择。
我觉得有使用COM对象访问Exchange的选择,但我不知道它是多么容易。
这一切都取决于究竟您的管理员愿意我想给你的访问。
您应该能够使用MAPI访问邮箱,并得到你所需要的信息。不幸的是,只有.NET MAPI库(MAPI33)我知道的好像没有被维护。过去,这是通过.NET访问MAPI的好方法,但我不能给它的效力,现在说话。有一个关于在那里你可以在这里获得更多信息:下载位置MAPI33.dll ? p>
我最终使用救赎得到了一个解决方案,看看这些问题......
一种选择是使用Outlook。我们有一个访问Exchange服务器和使用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);
}