You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用MailKit/MimeKit转移邮件附件?基于ImapClient与目标邮件UniqueId的实现方法

嘿,这个问题我刚好实操过,用MailKit和MimeKit来转移邮件附件其实没那么复杂,我给你拆解成通用逻辑+结合ImapClient UniqueId的完整流程,连代码示例都给你备好:

一、通用的附件转移核心逻辑

不管你是已经拿到了原邮件的MimeMessage实例,还是从本地文件加载的邮件,核心步骤都是「提取原邮件附件 → 添加到新邮件」:

1. 提取原邮件中的附件

首先要从原MimeMessage里筛选出真正的附件(要区分开邮件里的内嵌图片这类资源):

var originalMessage = ...; // 你的原邮件MimeMessage实例
var attachments = originalMessage.Attachments
    .Where(part => part.ContentDisposition?.DispositionType == DispositionTypeNames.Attachment)
    .ToList();

注意:如果不想区分内嵌资源,直接用originalMessage.Attachments就行,但这样会把邮件里的内嵌图片也当成附件转移过去,按需选择~

2. 创建新邮件并添加附件

接下来创建新的MimeMessage,把提取到的附件加进去:

var newMessage = new MimeMessage();
newMessage.From.Add(new MailboxAddress("发件人", "sender@example.com"));
newMessage.To.Add(new MailboxAddress("收件人", "recipient@example.com"));
newMessage.Subject = "转存附件的新邮件";

// 构建邮件内容(正文+附件)
var bodyBuilder = new BodyBuilder();
bodyBuilder.TextBody = "这是转移过来的附件:";

// 把每个附件添加到新邮件
foreach (var attachment in attachments)
{
    // 直接添加原附件的MimePart,会保留原文件名、格式等属性
    bodyBuilder.Attachments.Add(attachment);
}

newMessage.Body = bodyBuilder.ToMessageBody();
二、结合ImapClient和UniqueId的完整流程

如果你是通过ImapClient拿到了目标邮件的UniqueId,那完整流程还要加上「从IMAP服务器获取指定邮件」这一步,具体步骤如下:

1. 连接IMAP服务器并登录

using var client = new ImapClient();
await client.ConnectAsync("imap.example.com", 993, SecureSocketOptions.SslOnConnect);
await client.AuthenticateAsync("your-email@example.com", "your-password-or-app-password");

2. 选择目标文件夹并获取指定UniqueId的邮件

// 选择收件箱(或者你存放目标邮件的文件夹)
var inbox = client.Inbox;
await inbox.OpenAsync(FolderAccess.ReadOnly);

// 通过UniqueId获取完整邮件(如果邮件很大,也可以先Fetch结构再按需下载附件,下面会提)
var originalMessage = await inbox.GetMessageAsync(uniqueId);

高效优化:如果邮件体积很大,不想下载完整邮件,可以先Fetch邮件的BodyStructure,再单独下载附件:

// 先获取邮件的结构信息
var summary = await inbox.FetchAsync(uniqueId, MessageSummaryItems.BodyStructure);
var bodyStructure = summary[0].BodyStructure;

// 遍历结构找到附件部分,单独下载
foreach (var part in bodyStructure.OfType<MimePart>().Where(p => p.ContentDisposition?.DispositionType == DispositionTypeNames.Attachment))
{
    var attachmentStream = new MemoryStream();
    await inbox.GetPartAsync(uniqueId, part, attachmentStream);
    // 把attachmentStream转成MimePart添加到新邮件
    var attachment = new MimePart(part.ContentType.MediaType, part.ContentType.MediaSubtype)
    {
        Content = new MimeContent(attachmentStream),
        ContentDisposition = part.ContentDisposition,
        ContentTransferEncoding = part.ContentTransferEncoding,
        FileName = part.FileName
    };
    bodyBuilder.Attachments.Add(attachment);
}

3. 转移附件并发送/保存新邮件

拿到原邮件的附件后,就可以按照上面通用逻辑的步骤创建新邮件,然后发送或者保存到邮箱:

// 发送新邮件(用SmtpClient)
using var smtpClient = new SmtpClient();
await smtpClient.ConnectAsync("smtp.example.com", 587, SecureSocketOptions.StartTls);
await smtpClient.AuthenticateAsync("your-email@example.com", "your-password");
await smtpClient.SendAsync(newMessage);
await smtpClient.DisconnectAsync(true);

// 或者保存到IMAP服务器的指定文件夹
var sentFolder = client.GetFolder(SpecialFolder.Sent);
await sentFolder.AppendAsync(newMessage, MessageFlags.Seen);
一些额外提示
  • 如果你需要保留附件的原始文件名、ContentId等属性,直接复用原MimePart实例是最稳妥的,不要自己重新构建,避免丢失信息
  • 处理大附件时,用GetPartAsync单独下载附件比下载完整邮件更节省带宽和内存
  • 如果要批量转移多封邮件的附件,只需要遍历UniqueId列表重复上述步骤即可

内容的提问来源于stack exchange,提问作者SpiritBob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 14:17:28