Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
647 views
in Technique[技术] by (71.8m points)

smtp - How to send a Message Delivery Status with fail status using MailKit

We have a dovecot/postfix mail server which we use for automation purposes through IMAP and SMTP protocols.

There are situations that the system processes the email message but there is something wrong with the message and the system will exclude the message from the pipeline.

As the email messages are coming in from different sources, the system needs to inform the sender about the failure, and again for automation purposes, the other party expects a Message Delivery Status message with status fail.

We use MailKit for handling the messages and I had been trying to figure out how I can send such a message using MailKit in C#, but I have not been successful.

A simplified version of the code I have is as following:

// 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", "[email protected]")},
    
    To = { new MailboxAddress("User", "[email protected]")},
    
    Subject = "Delivery Status Notification (Failure)",
    
    InReplyTo = "message id of the received message"
};

smtpClient.Send(mimeMessage);

Update: With the suggested modification by @jstedfast now the code generates the following message:

From: Webmaster <[email protected]>
Date: Sat, 06 Feb 2021 23:50:56 +0100
Subject: Delivery Status Notification (Failure)
Message-Id: <[email protected]>
To: First Last <[email protected]>
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;[email protected]
Action: failed
Status: 550 5.7.1


--=-HnKieASbitf0LQ3XjF16Mw==--

What happens after sending the message is that, it is received and displayed as a regular email message in the original sender's mailbox.

Update 2:

If it helps, I use Postfix as the SMTP server and it seems to me that, it might be Postfix that modifies the mime message and converts it to a regular text mime message.

question from:https://stackoverflow.com/questions/66061920/how-to-send-a-message-delivery-status-with-fail-status-using-mailkit

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Without knowing what isn't working, it's hard to know what to suggest.

That said, a quick look at the spec reveals that the "Action" header is part of the per-recipient-fields which is an optional second group of status headers.

The first grouping of header fields is the per-message-fields which should include fields like:

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 )

The per-recipient-fields are defined as:

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 )

This means, at a minimum, you'd need to change the way you construct the MessageDeliveryStatus part to something more like the following:

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")
        }
    }
}

You'll need to choose a status code from https://tools.ietf.org/html/rfc3463


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...