【问题标题】:Strip attachments from emails using MailKit / MimeKit使用 MailKit / MimeKit 从电子邮件中删除附件
【发布时间】:2014-08-01 23:29:13
【问题描述】:

我正在使用 MailKit 库来处理电子邮件,效果很好。但是,我正在尝试将电子邮件拆分为其组成文件 a) 主要电子邮件(无附件) b) 单独的附件文件,以存储在文件系统上。

我可以单独保存附件,但似乎无法从电子邮件正文代码中删除它们。 IE。它们与主电子邮件一起保存,因此重复数据。 :/

我试过了:

foreach (MimePart part in inMessage.BodyParts)
{ 
    if (part.IsAttachment)
    {
        // Remove MimePart    < This function isn't available on the collection.
    }
}

也试过了:

var builder = new BodyBuilder();
foreach (MimePart part in inMessage.BodyParts)
{ 
    if (!part.IsAttachment)
    {
        // Add MimeParts to collection    < This function isn't available on the collection.
    }
}
outMessage.Body = builder.ToMessageBody();

如果有人能提供帮助,我将不胜感激。

解决方案实施仅供参考:

private string GetMimeMessageOnly(string outDirPath)
        {
            MimeMessage message = (Master as fsEmail).GetMimeMessage();

            if (message.Attachments.Any())
            {
                var multipart = message.Body as Multipart;
                if (multipart != null)
                {
                    while (message.Attachments.Count() > 0)
                    {
                        multipart.Remove(message.Attachments.ElementAt(0));
                    }
                }
                message.Body = multipart;
            }

            string filePath = outDirPath + Guid.NewGuid().ToString() + ".eml";
            Directory.CreateDirectory(Path.GetDirectoryName(outDirPath));
            using (var cancel = new System.Threading.CancellationTokenSource())
            {    
                using (var stream = File.Create(filePath)) 
                {
                    message.WriteTo(stream, cancel.Token);
                }
            }
            return filePath;
        }

并且只获取附件:

private List<string> GetAttachments(string outDirPath)
        {
            MimeMessage message = (Master as fsEmail).GetMimeMessage();

            List<string> list = new List<string>();
            foreach (MimePart attachment in message.Attachments)
            {
                using (var cancel = new System.Threading.CancellationTokenSource())
                {
                    string filePath = outDirPath + Guid.NewGuid().ToString() + Path.GetExtension(attachment.FileName);
                    using (var stream = File.Create(filePath))
                    {
                        attachment.ContentObject.DecodeTo(stream, cancel.Token);
                        list.Add(filePath);
                    }
                }
            }
            return list;
        }

【问题讨论】:

  • 谢谢,但是这个链接是基于 Mail.dll 的,我想最好还是使用 MailKit。
  • FWIW,除非您计划取消将附件保存到磁盘,否则您无需创建取消令牌。您可以使用 CancellationToken.None 或根本不传递取消令牌。

标签: c# email mime mailkit


【解决方案1】:

您可以检索作为附件https://github.com/jstedfast/MimeKit/blob/master/MimeKit/MimeMessage.cs#L734 的所有MimeParts,然后遍历所有Multiparts 并调用https://github.com/jstedfast/MimeKit/blob/master/MimeKit/Multipart.cs#L468 以删除附件。

下面的示例对邮件做了一些假设,例如只有一个Multipart 一些电子邮件客户端(Outlook)在邮件的制作方式上非常有创意。

static void Main(string[] args)
{
    var mimeMessage = MimeMessage.Load(@"x:\sample.eml");
    var attachments = mimeMessage.Attachments.ToList();
    if (attachments.Any())
    {
        // Only multipart mails can have attachments
        var multipart = mimeMessage.Body as Multipart;
        if (multipart != null)
        {
            foreach(var attachment in attachments)
            {
                multipart.Remove(attachment);
            }
        }
        mimeMessage.Body = multipart;
    }
    mimeMessage.WriteTo(new FileStream(@"x:\stripped.eml", FileMode.CreateNew));
}

【讨论】:

  • 啊,这可能就是为什么 Add 和 Remove 方法没有以我期望的集合方式显示给我的原因。我想我会选择 MimeEntity;也许 Multipart 是我需要的。我明天试试这个。
【解决方案2】:

MimeKit 0.38.0.0 开始,您将能够使用MimeIterator 遍历MIME 树结构以收集您要删除(并删除它们)的附件列表。为此,您的代码应如下所示:

var attachments = new List<MimePart> ();
var multiparts = new List<Multipart> ();
var iter = new MimeIterator (message);

// collect our list of attachments and their parent multiparts
while (iter.MoveNext ()) {
    var multipart = iter.Parent as Multipart;
    var part = iter.Current as MimePart;

    if (multipart != null && part != null && part.IsAttachment) {
        // keep track of each attachment's parent multipart
        multiparts.Add (multipart);
        attachments.Add (part);
    }
}

// now remove each attachment from its parent multipart...
for (int i = 0; i < attachments.Count; i++)
    multiparts[i].Remove (attachments[i]);

【讨论】:

    【解决方案3】:

    我创建了一个应用程序,它也使用 Mailkit 下载电子邮件和附件。 我遇到了一个问题:从 iOS 发送的附有图片的电子邮件没有得到正确处理。 MailKit 没有将图像添加到附件列表中。

    我用这个方法只得到消息的文本:

    private static string GetPlainTextFromMessageBody(MimeMessage message)
        {
            //content type needs to match text/plain otherwise i would store html into DB
            var mimeParts = message.BodyParts.Where(bp => bp.IsAttachment == false && bp.ContentType.Matches("text", "plain"));
            foreach (var mimePart in mimeParts)
            {
                if (mimePart.GetType() == typeof(TextPart))
                {
                    var textPart = (TextPart)mimePart;
                    return textPart.Text;
                }
            }
            return String.Empty;
        }
    

    这是我用来只下载 .jpg 文件的方法:

    foreach (var attachment in message.BodyParts.Where(bp => !string.IsNullOrEmpty(bp.FileName)))
    {
        if (attachment.FileName.ToLowerInvariant().EndsWith(".jpg"))
        {
            //do something with the image here
        }
    }
    

    【讨论】:

    • 这如何处理 HTML 与纯文本?我问是因为 MailKit 对我来说做得很好,当我使用 .eml 扩展名做 MimeMessage.WriteTo(file) 时。这些文件在 Outlook 中作为查看器可以很好地呈现,我想保留它,但只需在保存 .eml 之前从 MimeTree 中删除附件。
    • 好的,一开始我好像没有完全得到你的要求。我没有存储 .eml,但我将文本存储在数据库中 - 我只想获取纯文本。所以安德烈亚斯的答案似乎更符合您的要求。但正如我所提到的:尝试从 iOS 设备发送图片,看看它是否会按照您的意图从 .eml 中删除。也许那么第二个代码 sn-p 也可以帮助您删除这些图像。
    • FWIW,MimeKit 仅列出在 MimeMessage.Attachments 属性中具有“附件”(+任何参数)值的 Content-Disposition 标头的部分。这是因为任何其他语义都是非标准的。 iOS 可能没有 Content-Disposition 标头,或者将值设置为“内联”或其他内容。
    • 很好地解释了为什么附件不在附件列表中。
    猜你喜欢
    • 2019-05-17
    • 2021-12-02
    • 1970-01-01
    • 2021-08-27
    • 2014-09-09
    • 2017-12-15
    • 1970-01-01
    • 2014-09-03
    • 2019-04-26
    相关资源
    最近更新 更多