【问题标题】:Converting MailMessage to Stream removes Bcc将 MailMessage 转换为 Stream 会删除 Bcc
【发布时间】:2014-01-01 13:46:55
【问题描述】:

使用此 SO 帖子 (Convert MailMessage to Raw text),我们能够将 MailMessage 作为流获取。但是,密件抄送已被删除。 To 和 CC 仍然有效,但 Bcc 无效。

为什么会被删除,如何保留?

【问题讨论】:

标签: c# mailmessage


【解决方案1】:

很确定 BCC 字段永远不会与邮件一起发送。

密件抄送字段用于向收件人发送“密件抄送”。来自WikiPedia

在通信的上下文中,密件抄送(缩写为 Bcc:)允许消息的发件人向其他收件人隐藏在 Bcc: 字段中输入的人。

如果密件抄送字段中的收件人实际上包含在电子邮件的原始 SMTP 文本中,则无法强制执行此保证。

SmtpClient 很可能使用您在问题中链接的方法来准备要传输的消息。因此,它必须忽略 BCC 字段才能保持预期的行为。

要真正保留它,您必须手动将其插入到输出文本中:

var email = new MailMessage();
using (var reader = new StreamReader(email.RawMessage())) 
using (var writer = new StringWriter()) {
    while(true) {
        var line = reader.ReadLine();
        if (line == null) break; // EOF

        if (line != "") { 
            // Header line
            writer.WriteLine(line);
            continue;
        }

        // End of headers, insert bcc, read body, then bail
        writer.WriteLine("Bcc: " + email.Bcc.ToString()); // or however you want to format it
        writer.WriteLine("");
        writer.Write(reader.ReadToEnd());
        break;
    }

    var messageText = writer.ToString();
    // Do something with message text which now has Bcc: header
}

【讨论】:

  • 既然你提到了它,那确实有点道理。 SmtpClient.Send() 方法将删除密件抄送。我们通过 SendRawEmail() 方法将此发送到 Amazon SES。相反,我想我将手动创建 MIME 消息字符串,创建流,然后完成。澄清一下,如果您将密件抄送发送给 SES,它确实会正确处理。
  • 可能是因为它在RCPT TO: <the.bcc.address@foo.com> 交换期间在实际的 SMTP 信封(不是邮件标头/正文的一部分)中使用了密件抄送。
【解决方案2】:

这是我对 RawMessage() 的 VB.NET 重新散列,其中在标头中包含 BCC。基于其他人对原始 SO 链接的重新散列:http://colinmackay.co.uk/2011/11/10/sending-more-than-a-basic-email-with-amazon-ses

Public Class BuildRawMailHelper
    Private Const nonPublicInstance As BindingFlags = BindingFlags.Instance Or BindingFlags.NonPublic

    Private Shared ReadOnly _mailWriterContructor As ConstructorInfo
    Private Shared ReadOnly _sendMethod As MethodInfo
    Private Shared ReadOnly _closeMethod As MethodInfo
    Private Shared ReadOnly _writeHeadersMethod As MethodInfo

    Shared Sub New()
        Dim systemAssembly As Assembly = GetType(SmtpClient).Assembly
        Dim mailWriterType As Type = systemAssembly.[GetType]("System.Net.Mail.MailWriter")

        _mailWriterContructor = mailWriterType.GetConstructor(nonPublicInstance, Nothing, {GetType(Stream)}, Nothing)

        _sendMethod = GetType(MailMessage).GetMethod("Send", nonPublicInstance)

        _closeMethod = mailWriterType.GetMethod("Close", nonPublicInstance)

        _writeHeadersMethod = mailWriterType.GetMethod("WriteHeaders", nonPublicInstance)
    End Sub

    Public Shared Function ConvertMailMessageToMemoryStream(message As MailMessage) As MemoryStream
        Using memoryStream As New MemoryStream()
            Dim mailWriter As Object = _mailWriterContructor.Invoke(New Object() {memoryStream})

            ' BCC is not output in headers by Send method, so we add it in manually
            If message.Bcc.Any Then
                Dim bccHeaders As New NameValueCollection()
                bccHeaders.Add("BCC", String.Join(", ", message.Bcc.Select(Function(x) x.ToString())))
                _writeHeadersMethod.Invoke(mailWriter, nonPublicInstance, Nothing, {bccHeaders, False}, Nothing)
            End If

            ' See http://stackoverflow.com/questions/9595440/getting-system-net-mail-mailmessage-as-a-memorystream-in-net-4-5-beta
            _sendMethod.Invoke(message, nonPublicInstance, Nothing, {mailWriter, True, True}, Nothing)

            _closeMethod.Invoke(mailWriter, nonPublicInstance, Nothing, {}, Nothing)

            Return memoryStream
        End Using
    End Function
End Class

【讨论】:

  • 注意:由于 API 更改,这不再适用于 NET50。
猜你喜欢
  • 2010-11-03
  • 2019-11-08
  • 2022-11-28
  • 1970-01-01
  • 2011-11-22
  • 1970-01-01
  • 2021-02-11
  • 2023-03-11
相关资源
最近更新 更多