使用 MailKit (C#) 转发电子邮件

Posted

技术标签:

【中文标题】使用 MailKit (C#) 转发电子邮件【英文标题】:Forward email using MailKit (C#) 【发布时间】:2015-06-07 12:41:22 【问题描述】:

我正在尝试使用 MailKit(由 jstedfast 创建)访问 IMAP 帐户

我设法下载了消息(作为 MimeMessage),但有时我需要将其“转发”到另一个帐户。

最好的方法是如何做到这一点,以保留原始电子邮件的所有信息(地址、标题、正文内容等)。

谢谢!

【问题讨论】:

【参考方案1】:

不同的人说“前进”时的意思不同,所以我想我会针对我能想到的不同含义提供答案。

1.转发(重新发送)消息而不做任何更改。

“没有变化”,我的字面意思是原始消息数据完全没有变化。这样做的方法是:

var message = FetchMessageFromImapServer ();

using (var client = new SmtpClient ()) 
    client.Connect ("smtp.example.com", 465, true);
    client.Authenticate ("username", "password");

    var sender = new MailboxAddress ("My Name", "username@example.com");
    var recipients = new []  new MailboxAddress ("John Smith", "john@smith.com") ;

    // This version of the Send() method uses the supplied sender and
    // recipients rather than getting them from the message's headers.
    client.Send (message, sender, recipients);

    client.Disconnect (true);

注意:GMail、Hotmail/Office365 等一些网络邮件提供商可能不允许您使用这种方法,因为他们可能认为这是电子邮件欺骗。这些邮件主机可能会将From 标头替换为您帐户的名称/电子邮件地址,因此请注意此潜在问题。

不过,通常人们并不是指这种类型的“转发”。如果他们想重新发送,通常他们会使用下一种重新发送的方法。

2。以自动过滤器可能发送的方式转发(重新发送)消息。

var message = FetchMessageFromImapServer ();

// clear the Resent-* headers in case this message has already been Resent...
message.ResentSender = null;
message.ResentFrom.Clear ();
message.ResentReplyTo.Clear ();
message.ResentTo.Clear ();
message.ResentCc.Clear ();
message.ResentBcc.Clear ();

// now add our own Resent-* headers...
message.ResentFrom.Add (new MailboxAddress ("MyName", "username@example.com"));
message.ResentReplyTo.Add (new MailboxAddress ("MyName", "username@example.com"));
message.ResentTo.Add (new MailboxAddress ("John Smith", "john@smith.com"));
message.ResentMessageId = MimeUtils.GenerateMessageId ();
message.ResentDate = DateTimeOffset.Now;

using (var client = new SmtpClient ()) 
    client.Connect ("smtp.example.com", 465, true);
    client.Authenticate ("username", "password");

    // The Send() method will use the Resent-From/To/Cc/Bcc headers if
    // they are present.
    client.Send (message);

    client.Disconnect (true);

3.通过将邮件(整体)附加到新邮件来转发邮件,某些电子邮件客户端可能会这样做。

var messageToForward = FetchMessageFromImapServer ();

// construct a new message
var message = new MimeMessage ();
message.From.Add (new MailboxAddress ("MyName", "username@example.com"));
message.ReplyTo.Add (new MailboxAddress ("MyName", "username@example.com"));
message.To.Add (new MailboxAddress ("John Smith", "john@smith.com"));
message.Subject = "FWD: " + messageToForward.Subject;

// now to create our body...
var builder = new BodyBuilder ();
builder.TextBody = "Hey John,\r\n\r\nHere's that message I was telling you about...\r\n";
builder.Attachments.Add (new MessagePart  Message = messageToForward );

message.Body = builder.ToMessageBody ();

using (var client = new SmtpClient ()) 
    client.Connect ("smtp.example.com", 465, true);
    client.Authenticate ("username", "password");

    client.Send (message);

    client.Disconnect (true);

4.以许多其他电子邮件客户端的方式“内联”转发消息。

var messageToForward = FetchMessageFromImapServer ();

// construct a new message
var message = new MimeMessage ();
message.From.Add (new MailboxAddress ("MyName", "username@example.com"));
message.ReplyTo.Add (new MailboxAddress ("MyName", "username@example.com"));
message.To.Add (new MailboxAddress ("John Smith", "john@smith.com"));
message.Subject = "FWD: " + messageToForward.Subject;

// now to create our body...
var builder = new BodyBuilder ();

using (var writer = new StringWriter ()) 
    var sender = messageToForward.From.Mailboxes.FirstOrDefault () ?? messageToForward.Sender;
    var senderName = sender != null ? (!string.IsNullOrEmpty (sender.Name) ? sender.Name : sender.Address) : "someone";
    var text = messageToForward.TextBody ?? string.Empty;

    writer.WriteLine ("On 0, 1 wrote:", messageToForward.Date, senderName);

    using (var reader = new StringReader (text)) 
        string line;

        while ((line = reader.ReadLine ()) != null) 
            writer.Write ("> ");
            writer.WriteLine (line);
        
    

    builder.TextBody = writer.ToString ();


message.Body = builder.ToMessageBody ();

using (var client = new SmtpClient ()) 
    client.Connect ("smtp.example.com", 465, true);
    client.Authenticate ("username", "password");

    client.Send (message);

    client.Disconnect (true);

【讨论】:

亚马逊回复。非常感谢! @jstedfast 方法 3 大多数客户如何在新回复中“引用原始消息”?这应该添加到花哨的新http://www.mimekit.net(看起来不错!但奇怪的熟悉) 是的,大多数客户可能会使用 #3 - 我可能会使用 #3 除非我正在编写邮件过滤器以自动将邮件转发到另一个帐户,在这种情况下我可能会使用 #1 或#2(可能是 #1)。 mimekit.net 网站基本上只是从 Json.NET 网站获得一点灵感的引导轮播模板 :-) 还有第 4 种方式 - IMAP 可以写入文件夹,因此如果您有使用 MailKit 检索到的邮件,您可以将其存储在另一个 IMAP 文件夹中(即使在不同的帐户中,在不同的主机),使用 ImapClient.Inbox.Append 方法。这完全避免了 SMTP,并且消息完全保持原样(可能带有“无效”标头),但在某些工作流程中可能很有用。所以从技术上讲,它不是一个前锋,但很可能是这个帖子的一些观众真正想要实现的目标。 使用#2(重新发送) - 邮件也作为重复发送给原始收件人。这会在处理邮箱时创建无限循环。避免这种清除 To 标头 (message.To.clear();)。

以上是关于使用 MailKit (C#) 转发电子邮件的主要内容,如果未能解决你的问题,请参考以下文章

我可以使用 MailKit 通过电子邮件发送文件吗?

使用 Mailkit 或 mimekit 向多个收件人发送一封电子邮件

使用 Mailkit 发送电子邮件无法在 ubuntu 服务器上运行,出现 TimeoutException

如何使用 mailkit/mimekit IMAP 下载/保存所有收件箱/发送的电子邮件?

使用 mailkit 发送的多部分电子邮件的文本/纯文本版本未正确接收

在 MailKit 中搜索电子邮件不是使用 SearchQuery 方法,而是使用简单的文本字符串条件