[pmg-devel] [RFC pmg-api 3/4] add generate_ndr to PMG::SMTP

Stoiko Ivanov s.ivanov at proxmox.com
Tue Nov 12 15:16:13 CET 2019


In order to selectively accept and reject mails when multiple recepients
are present for a mail, without silently dropping mails to certain recepients
the sender needs to be informed about those recepients which did not receive
the mail (via a non-delivery report - NDR).

The format of delivery status notifications (of which an ndr is a subset) is
specified in RFC 6522 [0]. The format for the 'message/delivery-status'
MIME-Type is specified in RFC 6533 [1]

The message text was adapted from Postfix' default bounce-messages, however
we do not attach the original mail to the report. This is acceptable by [0]
and makes sense (not sending mail, which is likely spam or a virus, back to the
(potentially faked) sender).

[0] https://tools.ietf.org/html/rfc6522
[1] https://tools.ietf.org/html/rfc6533

Signed-off-by: Stoiko Ivanov <s.ivanov at proxmox.com>
---
 src/PMG/SMTP.pm | 61 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/src/PMG/SMTP.pm b/src/PMG/SMTP.pm
index a2a6c48..b311265 100644
--- a/src/PMG/SMTP.pm
+++ b/src/PMG/SMTP.pm
@@ -4,10 +4,12 @@ use strict;
 use warnings;
 use IO::Socket;
 use Encode;
+use MIME::Entity;
 
 use PVE::SafeSyslog;
 
 use PMG::MailQueue;
+use PMG::Utils;
 
 sub new {
     my($this, $sock) = @_;
@@ -233,4 +235,63 @@ sub save_data {
     return 1;
 }
 
+sub generate_ndr {
+    my ($sender, $receivers, $hostname, $queueid) = @_;
+
+    my $ndr_text = <<EOF
+This is the mail system at host $hostname.
+
+I'm sorry to have to inform you that your message could not
+be delivered to one or more recipients.
+
+For further assistance, please send mail to postmaster.
+
+If you do so, please include this problem report.
+                   The mail system
+
+554 5.7.1 Recipient address(es) rejected for policy reasons
+EOF
+;
+    my $ndr = MIME::Entity->build(
+	Type => 'multipart/report; report-type=delivery-status;',
+	To => $sender,
+	From => 'postmaster',
+	Subject => 'Undelivered Mail');
+
+    $ndr->attach(
+	Data => $ndr_text,
+	Type => 'text/plain; charset=utf-8',
+	Encoding => '8bit');
+
+    my $delivery_status = <<EOF
+Reporting-MTA: dns; $hostname
+X-Proxmox-Queue-ID: $queueid
+X-Proxmox-Sender: rfc822; $sender
+EOF
+;
+    foreach my $rec (@$receivers) {
+	$delivery_status .= <<EOF
+Final-Recipient: rfc822; $rec
+Original-Recipient: rfc822;$rec
+Action: failed
+Status: 5.7.1
+Diagnostic-Code: smtp; 554 5.7.1 Recipient address rejected for policy reasons
+
+EOF
+;
+    }
+    $ndr->attach(
+	Data => $delivery_status,
+	Type => 'message/delivery-status',
+	Encoding => '7bit',
+	Description => 'Delivery report');
+
+    my $qid = PMG::Utils::reinject_mail($ndr, '', [$sender], undef, $hostname);
+    if ($qid) {
+	syslog('info', "sent NDR for rejecting recepients - $qid");
+    } else {
+	syslog('err', "sending NDR for rejecting recepients failed");
+    }
+}
+
 1;
-- 
2.20.1




More information about the pmg-devel mailing list