【问题标题】:How to send a Message Delivery Status with fail status using MailKit如何使用 MailKit 发送带有失败状态的消息传递状态
【发布时间】:2021-05-09 17:10:00
【问题描述】:

我们有一个 dovecot/postfix 邮件服务器,我们通过 IMAP 和 SMTP 协议将其用于自动化目的。

在某些情况下,系统会处理邮件,但邮件有问题,系统会将邮件从管道中排除。

由于电子邮件消息来自不同的来源,系统需要将失败通知发件人,并且再次出于自动化目的,另一方希望收到状态为失败的消息传递状态消息。

我们使用 MailKit 来处理消息,我一直试图弄清楚如何在 C# 中使用 MailKit 发送这样的消息,但我没有成功。

我拥有的代码的简化版本如下:

// Prepares smtpClient

MultipartReport multipartReport = new MultipartReport("delivery-status")
{
    new TextPart {Content = new MimeContent(new MemoryStream(Encoding.ASCII.GetBytes("The message contains malformed data")))},
    
    new MessageDeliveryStatus {StatusGroups = {new HeaderList {new Header("Action", "failed")}}}
};

MimeMessage  message = new MimeMessage
{
    Body = multipartReport,
    
    From = { new MailboxAddress("Webmaster", "webmaster@our.domain")},
    
    To = { new MailboxAddress("User", "user@origin.domain")},
    
    Subject = "Delivery Status Notification (Failure)",
    
    InReplyTo = "message id of the received message"
};

smtpClient.Send(mimeMessage);

更新: 根据@jstedfast 的建议修改,现在代码会生成以下消息:

From: Webmaster <webmaster@ourdomain.com>
Date: Sat, 06 Feb 2021 23:50:56 +0100
Subject: Delivery Status Notification (Failure)
Message-Id: <GII2AYZOWCU4.AXDWNKVKJ4XD3@ourdomain.com>
To: First Last <someone@gmail.com>
Return-Path: <>
MIME-Version: 1.0
Content-Type: multipart/report; boundary="=-HnKieASbitf0LQ3XjF16Mw==";
    report-type=delivery-status

--=-HnKieASbitf0LQ3XjF16Mw==
Content-Type: text/plain

Attachment not allowed
--=-HnKieASbitf0LQ3XjF16Mw==
Content-Type: message/delivery-status

Reporting-MTA: dns;mail.ourdomain.com

Final-Recipient: rfc822;user@ourdomain.com
Action: failed
Status: 550 5.7.1


--=-HnKieASbitf0LQ3XjF16Mw==--

发送邮件后发生的情况是,它被接收并显示为原始发件人邮箱中的常规电子邮件。

更新 2:

如果有帮助,我使用Postfix 作为 SMTP 服务器,在我看来,可能是 Postfix 修改了 mime 消息并将其转换为常规文本 mime 消息。

【问题讨论】:

    标签: smtp mailkit


    【解决方案1】:

    不知道什么是行不通的,很难知道该建议什么。

    也就是说,快速查看spec 会发现“Action”标头是per-recipient-fields 的一部分,per-recipient-fields 是可选的第二组状态标头。

    第一组标题字段是per-message-fields,其中应包括以下字段:

    per-message-fields =
        [ original-envelope-id-field CRLF ]
        reporting-mta-field CRLF
        [ dsn-gateway-field CRLF ]
        [ received-from-mta-field CRLF ]
        [ arrival-date-field CRLF ]
        *( extension-field CRLF )
    

    per-recipient-fields 定义为:

    per-recipient-fields =
        [ original-recipient-field CRLF ]
        final-recipient-field CRLF
        action-field CRLF
        status-field CRLF
        [ remote-mta-field CRLF ]
        [ diagnostic-code-field CRLF ]
        [ last-attempt-date-field CRLF ]
        [ final-log-id-field CRLF ]
        [ will-retry-until-field CRLF ]
        *( extension-field CRLF )
    

    这意味着,您至少需要将构造 MessageDeliveryStatus 部分的方式更改为类似于以下内容:

    new MessageDeliveryStatus {
        StatusGroups = {
            new HeaderList {
                new Header("Reporting-MTA", "dns;<dns name of the MTA>")
            },
            new HeaderList {
                new Header("Final-Recipient", "rfc822;<address of recipient>",
                new Header("Action", "failed"),
                new Header("Status", "5.something")
            }
        }
    }
    

    您需要从https://www.rfc-editor.org/rfc/rfc3463中选择一个状态码

    【讨论】:

    • 感谢@jstedfast,您一如既往地最有帮助。我会试一试,很快就会回复你。 :)
    • jstedfast,我无法从 MimeMessage 数据中提取 Reporting-MTA(MTA 的 DNS 名称)和 Final-Recipient(收件人地址)值。你能帮我一些代码示例吗?我非常感谢。
    • 我的意思是对于最后的收件人部分,是 TO、CC 和 BCC 电子邮件地址还是我需要使用任何其他值?
    • Reporting-MTA 字段应该只是您的邮件服务器的硬编码值。最终收件人地址应该是您的软件响应的地址。它应该只有 1。或者如果它作为多用户系统的一部分运行,那么您需要发送多条交付状态消息(您的服务器托管的每个收件人一条)。
    • jstedfast 我已经用一些结果更新了我的问题。请再看一遍好吗?
    猜你喜欢
    • 1970-01-01
    • 2017-10-28
    • 2023-03-06
    • 1970-01-01
    • 2017-12-22
    • 1970-01-01
    • 1970-01-01
    • 2014-01-18
    • 1970-01-01
    相关资源
    最近更新 更多