包 | 最新发布 | 最新构建 |
---|---|---|
MimeKit | ||
MailKit |
平台 | 构建状态 | 代码覆盖率 | 静态分析 |
---|---|---|---|
Linux/Mac | |||
Windows |
MailKit是一个基于MimeKit构建的跨平台邮件客户端库。
MailKit是我个人的开源项目,我已经投入了数千小时来完善它,目标是使其成为.NET平台上最好的电子邮件框架。我需要您的帮助来实现这个目标。
捐赠有助于支付诸如网络托管、域名注册以及开发工具许可证等费用,如性能分析器、内存分析器、静态代码分析工具等。它还能激励我继续致力于这个项目。
<a href="https://github.com/sponsors/jstedfast" _target="blank"><img alt="点击这里通过捐赠来支持MailKit!" src="https://yellow-cdn.veclightyear.com/2b54e442/468d48ec-af85-4c20-8d9e-90d0f4d2da05.gif"></a>
本项目的主要目标是为.NET世界提供强大、功能齐全且符合RFC标准的SMTP、POP3和IMAP客户端实现。
我能找到的所有其他.NET IMAP客户端实现都存在重大架构问题,例如忽略意外的未标记响应,假设字面字符串标记只用于消息正文(实际上它们可以用于响应中的几乎任何字符串标记),假设在FETCH响应中找到消息正文结尾的方法是扫描") UID"
,以及不正确处理带有国际字符的邮箱名称,仅举几个例子。
IMAP需要花费大量时间仔细阅读和反复阅读IMAP规范(以及MIME规范)以理解协议的所有细微之处,而大多数(所有?)其他开源.NET IMAP库至少都是由只关心满足自己简单需求的开发人员编写的。这样做没有什么本质上的错误,但网上充斥着半成品、不符合RFC标准的IMAP实现,因此是时候编写一个精心设计和实现的IMAP客户端库了。
对于POP3,像OpenPOP.NET这样的库实际上相当不错,尽管MIME解析器过于严格 - 每当遇到它不认识的Content-Type或Content-Disposition参数时就抛出异常,如果你查看邮件列表,就会发现这是OpenPOP.NET用户经常遇到的问题。当然,MailKit的Pop3Client没有这个问题。它还直接从套接字解析消息,而不是将消息下载到大型字符串缓冲区中再进行解析,因此你可能会发现MailKit不仅更快(MailKit的MIME解析器MimeKit从磁盘解析消息的速度比OpenPOP.NET的解析器快25倍),而且内存使用量也大大减少。
对于SMTP,大多数开发人员使用System.Net.Mail.SmtpClient,它或多或少满足了他们的需求,因此可能不是他们需求列表中的高优先级项目。然而,如果需要跨平台支持或开发人员希望能够在通过SMTP发送之前保存和重新加载MIME消息,那么MailKit中包含的SmtpClient实现是一个更好的选择。MailKit的SmtpClient还支持PIPELINING,这应该会提高发送消息的性能(尽管可能不太明显)。
MIT许可证 版权所有 (C) 2013-2024 .NET基金会和贡献者 特此免费授予任何获得本软件副本和相关文档文件("软件")的人不受限制地处理本软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件副本的权利,以及允许向其提供本软件的人这样做,但须符合以下条件: 上述版权声明和本许可声明应包含在本软件的所有副本或大部分内容中。 本软件按"原样"提供,不提供任何形式的明示或暗示担保,包括但不限于对适销性、特定用途的适用性和非侵权性的担保。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权行为还是其他方面,均源于、出于或与本软件有关,或与本软件的使用或其他交易有关。
安装MailKit最简单的方法是通过NuGet。
在Visual Studio的包管理器控制台中, 输入以下命令:
Install-Package MailKit
首先,你需要从我的GitHub仓库克隆MailKit。要使用命令行版本的Git执行此操作, 你需要在终端中输入以下命令:
git clone --recursive https://github.com/jstedfast/MailKit.git
如果你在Windows上使用TortoiseGit,你需要在要克隆MailKit的目录中右击, 并在菜单中选择Git Clone...。完成后,你会看到以下对话框:
填写红色轮廓标出的区域,然后点击OK。这将递归地将MailKit克隆到你的本地机器上。
如果我在你下载源代码后对MailKit进行了更改,你可能偶尔想要更新本地源代码副本。要使用命令行版本的Git执行此操作,你需要在MailKit目录中的终端中输入以下命令:
git pull
git submodule update
如果你在Windows上使用TortoiseGit,你需要右击MailKit目录, 并在菜单中选择Git Sync...。完成后,你需要在以下对话框中点击Pull和Submodule Update按钮:
在MailKit顶级目录中,有几个解决方案文件;它们是:
一旦你在Visual Studio中打开了适当的MailKit解决方案文件, 你可以选择Debug或Release构建配置,然后进行构建。
Visual Studio 2017和Visual Studio 2019都应该能够毫无问题地构建MailKit,但像Visual Studio 2015这样的旧版本将需要对项目进行修改才能正确构建。据报道,向MimeKit和MailKit项目添加NuGet包引用Microsoft.Net.Compilers >= 3.6.0和System.ValueTuple >= 4.5.0将允许它们成功构建。
注意:Release构建将生成xml API文档,但Debug构建不会。
MailKit的一个更常见的操作是发送电子邮件消息。
using System; using MailKit.Net.Smtp; using MailKit; using MimeKit; namespace TestClient { class Program { public static void Main (string[] args) { var message = new MimeMessage (); message.From.Add (new MailboxAddress ("Joey Tribbiani", "joey@friends.com")); message.To.Add (new MailboxAddress ("Mrs. Chanandler Bong", "chandler@friends.com")); message.Subject = "How you doin'?"; message.Body = new TextPart ("plain") { Text = @"Hey Chandler, I just wanted to let you know that Monica and I were going to go play some paintball, you in? -- Joey" }; using (var client = new SmtpClient ()) { client.Connect ("smtp.friends.com", 587, false); // 注意:只有在SMTP服务器需要身份验证时才需要 client.Authenticate ("joey", "password"); client.Send (message); client.Disconnect (true); } } } }
MailKit的另一个主要用途是从pop3服务器检索消息。
using System; using MailKit.Net.Pop3; using MailKit; using MimeKit; namespace TestClient { class Program { public static void Main (string[] args) { using (var client = new Pop3Client ()) { client.Connect ("pop.friends.com", 110, false); client.Authenticate ("joey", "password"); for (int i = 0; i < client.Count; i++) { var message = client.GetMessage (i); Console.WriteLine ("Subject: {0}", message.Subject); } client.Disconnect (true); } } } }
比POP3支持更重要的是IMAP支持。这里是从IMAP服务器检索消息的一个简单用例:
using System; using MimeKit; using MailKit; using MailKit.Search; using MailKit.Net.Imap; namespace TestClient { class Program { public static void Main (string[] args) { using (var client = new ImapClient ()) { client.Connect ("imap.friends.com", 993, true); client.Authenticate ("joey", "password"); // 收件箱文件夹在所有IMAP服务器上总是可用的... var inbox = client.Inbox; inbox.Open (FolderAccess.ReadOnly); Console.WriteLine ("Total messages: {0}", inbox.Count); Console.WriteLine ("Recent messages: {0}", inbox.Recent); for (int i = 0; i < inbox.Count; i++) { var message = inbox.GetMessage (i); Console.WriteLine ("Subject: {0}", message.Subject); } client.Disconnect (true); } } } }
IMAP相对于POP3的一个优势是IMAP协议允许客户端检索文件夹中消息的信息,而无需首先下载所有消息。
使用Fetch和FetchAsync方法重载(或方便的扩展方法),可以获取给定文件夹中任何范围消息的任何子集摘要信息。
foreach (var summary in inbox.Fetch (0, -1, MessageSummaryItems.Envelope)) { Console.WriteLine ("[summary] {0:D2}: {1}", summary.Index, summary.Envelope.Subject);
也可以使用接受 IFetchRequest 参数的 Fetch/FetchAsync API 来更精细地控制获取内容:
// 让我们获取非 Received 头: var request = new FetchRequest { Headers = new HeaderSet (new HeaderId[] { HeaderId.Received }) { Exclude = true } }; foreach (var summary in inbox.Fetch (0, -1, request)) { Console.WriteLine ("[summary] {0:D2}: {1}", summary.Index, summary.Headers[HeaderId.Subject]);
Fetch 方法的结果也可以用来下载单个 MIME 部分,而不是下载整个消息。例如:
foreach (var summary in inbox.Fetch (0, -1, MessageSummaryItems.UniqueId | MessageSummaryItems.BodyStructure)) { if (summary.TextBody != null) { // 这将只下载 text/plain 部分 var text = inbox.GetBodyPart (summary.UniqueId, summary.TextBody); } if (summary.HtmlBody != null) { // 这将只下载 text/html 部分 var html = inbox.GetBodyPart (summary.UniqueId, summary.HtmlBody); } // 如果你想获取图片附件...可能会像这样: if (summary.Body is BodyPartMultipart) { var multipart = (BodyPartMultipart) summary.Body; var attachment = multipart.BodyParts.OfType<BodyPartBasic> ().FirstOrDefault (x => x.FileName == "logo.jpg"); if (attachment != null) { // 这将只下载附件 var part = inbox.GetBodyPart (summary.UniqueId, attachment); } } }
为了设置或更新特定消息的标志,实际需要的是消息的 UID 或索引以及它所属的文件夹。
想要 更新消息标志的一个明显原因是在用户打开并阅读消息后将其标记为"已读"(即"已看")。
folder.Store (uid, new StoreFlagsRequest (StoreAction.Add, MessageFlags.Seen) { Silent = true });
在 IMAP 中删除消息涉及在消息上设置 \Deleted
标志,并可选择从文件夹中清除它。
将消息标记为 \Deleted
的方式与将消息标记为 \Seen
的方式相同。
folder.Store (uid, new StoreFlagsRequest (StoreAction.Add, MessageFlags.Deleted) { Silent = true }); folder.Expunge ();
你可能也对排序和搜索感兴趣...
// 让我们搜索 2013 年 1 月 12 日之后收到的所有主题中包含 "MailKit" 的消息... var query = SearchQuery.DeliveredAfter (DateTime.Parse ("2013-01-12")) .And (SearchQuery.SubjectContains ("MailKit")).And (SearchQuery.Seen); foreach (var uid in inbox.Search (query)) { var message = inbox.GetMessage (uid); Console.WriteLine ("[match] {0}: {1}", uid, message.Subject); } // 让我们进行相同的搜索,但这次按到达时间倒序排序 var orderBy = new [] { OrderBy.ReverseArrival }; foreach (var uid in inbox.Sort (query, orderBy)) { var message = inbox.GetMessage (uid); Console.WriteLine ("[match] {0}: {1}", uid, message.Subject); } // 你会注意到 orderBy 参数是一个数组...这是因为你 // 实际上可以根据多个列对搜索结果进行排序: orderBy = new [] { OrderBy.ReverseArrival, OrderBy.Subject }; foreach (var uid in inbox.Sort (query, orderBy)) { var message = inbox.GetMessage (uid); Console.WriteLine ("[match] {0}: {1}", uid, message.Subject); }
当然,除了下载消息,你还可以获取匹配消息的摘要信息,或者用返回的 UID 做其他任何事情。
如何导航文件夹?MailKit 也可以做到:
// 获取第一个个人命名空间并列出其下的顶级文件夹。 var personal = client.GetFolder (client.PersonalNamespaces[0]); foreach (var folder in personal.GetSubfolders (false)) Console.WriteLine ("[folder] {0}", folder.Name);
如果 IMAP 服务器支持 SPECIAL-USE 或 XLIST (GMail) 扩展,你可以像这样获取预定义的 All、Drafts、Flagged (又名 Important)、Junk、Sent、Trash 等文件夹:
if ((client.Capabilities & (ImapCapabilities.SpecialUse | ImapCapabilities.XList)) != 0) { var drafts = client.GetFolder (SpecialFolder.Drafts); } else { // 也许检查用户对草稿文件夹的偏好? }
在 IMAP 服 务器不支持 SPECIAL-USE 或 XLIST 扩展的情况下,你必须想出自己的启发式方法来获取 Sent、Drafts、Trash 等文件夹。例如,你可能使用类似这样的逻辑:
static string[] CommonSentFolderNames = { "Sent Items", "Sent Mail", "Sent Messages", /* 可能添加一些翻译后的名称 */ }; static IFolder GetSentFolder (ImapClient client, CancellationToken cancellationToken) { var personal = client.GetFolder (client.PersonalNamespaces[0]); foreach (var folder in personal.GetSubfolders (false, cancellationToken)) { foreach (var name in CommonSentFolderNames) { if (folder.Name == name) return folder; } } return null; }
使用 LINQ,你可以将其简化为类似这样的内容:
static string[] CommonSentFolderNames = { "Sent Items", "Sent Mail", "Sent Messages", /* 可能添加一些翻译后的名称 */ }; static IFolder GetSentFolder (ImapClient client, CancellationToken cancellationToken) { var personal = client.GetFolder (client.PersonalNamespaces[0]); return personal.GetSubfolders (false, cancellationToken).FirstOrDefault (x => CommonSentFolderNames.Contains (x.Name)); }
另一个选择可能是允许应用程序的用户配置他们想要用作 Sent 文件夹、Drafts 文件夹、Trash 文件夹等的文件夹。
如何处理这个问题由你决定。
你需要做的第一件事是将 MailKit 分叉到你自己的 GitHub 仓库。有关如何做到这一点的说明,请参阅标题为获取源代码的部分。
如果你使用 Visual Studio for Mac 或 MonoDevelop, 所有解决方案文件都配置了 MailKit 使用的编码风格。如果你在 Windows 上使用 Visual Studio 或其他编辑器,请尽最大努力保持现有的编码风格。
一旦你有了一些想要提交到官方 MailKit 仓库的更改, 向我发送一个Pull Request,我会尽快审查你的更改。
如果你想做出贡献但没有特别想要处理的功能,请查看问题跟踪器,看看是否有什么能引起你兴趣的!
有 bug 或功能请求吗?请打开一个新的 bug 报告 或 功能请求。
在打开新问题之前,请搜索任何现有问题 以避免提交重复内容。也可能值得查看 FAQ以了解其他开发人员常见的问题。
如果 MailKit 无法与你的邮件服务器配合使用,请在 bug 报告中包含协议日志,否则 我无法修复问题。
如果你在 MailKit 中的某个地方遇到异常,不要只提供 Exception.Message
字符串。请同时包含 Exception.StackTrace
。仅凭 Message
通常是无用的。
API 文档可以在 https://www.mimekit.net/docs 找到。
一些示例代码片段可以在 Documentation/Examples
目录中找到。
示例应用程序可以在 samples
目录中找到。
NuGet 包中还包含了 XML 格式的 API 参考文档的副本。
MailKit 是一个 .NET Foundation 项目。
该项目采用了 Contributor Covenant 定义的行为准则,以明确我们社区中的预期行为。有关更多信息,请参阅 .NET Foundation 行为准则。
一般的 .NET OSS 讨论: .NET Foundation 论坛
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的 效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
字节跳动发布 的AI编程神器IDE
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。
选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。
专业的AI公文写作平台,公文写作神器
AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。
OpenAI Agents SDK,助力开发者便捷使用 OpenAI 相关功能。
openai-agents-python 是 OpenAI 推出的一款强大 Python SDK,它为开发者提供了与 OpenAI 模型交互的高效工具,支持工具调用、结果处理、追踪等功能,涵盖多种应用场景,如研究助手、财务研究等,能显著提升开发效率,让开发者更轻松地利用 OpenAI 的技术优势。
高分辨率纹理 3D 资产生成
Hunyuan3D-2 是腾讯开发的用于 3D 资产生成的强大工具,支持从文本描述、单张图片或多视角图片生成 3D 模型,具备快速形状生成能力,可生成带纹理的高质量 3D 模型,适用于多个领域,为 3D 创作提供了高效解决方案。
一个具备存储、管理和客户端操作等多种功能的分布式文件系统相关项目。
3FS 是一个功能强大的分布式文件系统项目,涵盖了存储引擎、元数据管理、客户端工具等多个模块。它支持多种文件操作,如创建文件和目录、设置布局等,同时具备高效的事件循环、节点选择和协程池管理等特性。适用于需要大规模数据存储和管理的场景,能够提高系统的性能和可靠性,是分布式存储领域的优质解决方案。