all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: Stoiko Ivanov <s.ivanov@proxmox.com>, pmg-devel@lists.proxmox.com
Subject: Re: [pmg-devel] [PATCH pmg-api 1/1] fix #2795: add support for DSN
Date: Wed, 24 Nov 2021 10:33:19 +0100	[thread overview]
Message-ID: <ccfe4516-08ed-9fa1-ffe6-dcdb2016932b@proxmox.com> (raw)
In-Reply-To: <20211122195032.359071-1-s.ivanov@proxmox.com>

works generally as advertised, i have some (minor) remarks
though (comments inline)

On 11/22/21 20:50, Stoiko Ivanov wrote:
> Delivery status notifications (DSN) are defined in RFC 3464 [0].
> They introduce additional key-value parameters for the MAIL and RCPT
> commands.
> 
> The default config we ship offers DSN on the internal port (but not on
> the external port) - which works fine in after-queue filtering mode,
> but not in before-queue filtering mode.
> 
> This patchset adds support for collecting the relevant parameters and
> passing them on to the postfix instance [1], which actually sends out the
> mail.
> 
> additionally postfix does syntax-checking before passing the mail to
> the proxy (before queue filtering).
> 
> Since the handling is done by postfix we don't need to generate the
> DSN for any of the cases.
> 
> tested with various combinations of the -V, -N and -R parameters to
> sendmail (e.g.):
> ```
> /usr/sbin/sendmail -N success,delay,failure \
> -V '<xxxxxxxx@test.proxmox.com>'\
> -R hdrs test@test.domain.example
> ```
> 
> some tests with invalid combinations were also done with netcat.
> 
> [0] https://tools.ietf.org/html/rfc3464
> [1] http://www.postfix.org/DSN_README.html
> Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
> ---
>   src/PMG/RuleDB/Accept.pm |  2 +-
>   src/PMG/RuleDB/BCC.pm    |  6 +++++-
>   src/PMG/SMTP.pm          | 46 +++++++++++++++++++++++++++++++++-------
>   src/PMG/Utils.pm         | 19 ++++++++++++++---
>   src/bin/pmg-smtp-filter  |  1 +
>   5 files changed, 61 insertions(+), 13 deletions(-)
> 
> diff --git a/src/PMG/RuleDB/Accept.pm b/src/PMG/RuleDB/Accept.pm
> index 0bcf250..cd67ea2 100644
> --- a/src/PMG/RuleDB/Accept.pm
> +++ b/src/PMG/RuleDB/Accept.pm
> @@ -122,7 +122,7 @@ sub execute {
>   	} else {
>   	    my ($qid, $code, $mess) = PMG::Utils::reinject_mail(
>   		$entity, $msginfo->{sender}, $tg,
> -		$msginfo->{xforward}, $msginfo->{fqdn});
> +		$msginfo->{xforward}, $msginfo->{fqdn}, $msginfo->{param});
>   	    if ($qid) {
>   		foreach (@$tg) {
>   		    syslog('info', "%s: accept mail to <%s> (%s) (rule: %s)", $queue->{logid}, encode('UTF-8', $_), $qid, $rulename);
> diff --git a/src/PMG/RuleDB/BCC.pm b/src/PMG/RuleDB/BCC.pm
> index a8db3f5..d364690 100644
> --- a/src/PMG/RuleDB/BCC.pm
> +++ b/src/PMG/RuleDB/BCC.pm
> @@ -156,9 +156,13 @@ sub execute {
>   	    $entity->print ($fh);
>   	    print $fh "bcc end\n";
>   	} else {
> +	    my $param = {};
> +	    for my $bcc (@bcc_targets) {
> +		$param->{rcpt}->{$bcc}->{notify} = "never";
> +	    }
>   	    my $qid = PMG::Utils::reinject_mail(
>   		$entity, $msginfo->{sender}, \@bcc_targets,
> -		$msginfo->{xforward}, $msginfo->{fqdn}, 1);
> +		$msginfo->{xforward}, $msginfo->{fqdn}, $param);
>   	    foreach (@bcc_targets) {
>   		if ($qid) {
>   		    syslog('info', "%s: bcc to <%s> (rule: %s, %s)", $queue->{logid}, $_, $rulename, $qid);
> diff --git a/src/PMG/SMTP.pm b/src/PMG/SMTP.pm
> index 68c833e..c7aba01 100644
> --- a/src/PMG/SMTP.pm
> +++ b/src/PMG/SMTP.pm
> @@ -38,6 +38,7 @@ sub reset {
>       delete $self->{smtputf8};
>       delete $self->{xforward};
>       delete $self->{status};
> +    delete $self->{param};
>   }
>   
>   sub abort {
> @@ -100,25 +101,54 @@ sub loop {
>   	    $self->reply ("250 2.5.0 OK");
>   	    next;
>   	} elsif ($cmd eq 'mail') {
> -	    if ($args =~ m/^from:\s*<([^\s\>]*)>([^>]*)$/i) {
> +	    if ($args =~ m/^from:\s*<([^\s\>]*?)>(.*)$/i) {

this change looks like it's unrelated on the first glance
i understand this is because options can contain '>'
(i mean local parts of mails can too, but this'll break other
parts already...)

a small notice in the commit message (or a comment) would be good though

could also be it's own patch (smthg like 'fix smtp option parsing' ?)


>   		delete $self->{to};
> -		my ($from, $opts) = ($1, $2);
> -		if ($opts =~ m/\sSMTPUTF8/) {
> -		    $self->{smtputf8} = 1;
> -		    $from = decode('UTF-8', $from);
> +		my ($from, $opts) = ($1, lc($2));
> +
> +		my $err = 0;
> +		for my $opt (split(' ', $opts)) {
> +		    if ($opt =~ /(ret|envid)=([^ =]+)/ ) {
> +			$self->{param}->{mail}->{$1} = $2;
> +		    } elsif ($opt =~ m/smtputf8/) {
> +			$self->{smtputf8} = 1;
> +			$from = decode('UTF-8', $from);
> +		    } elsif ($opt =~ m/(?:size=(:?\d+)|body=8bitmime)/) {
> +			#skip
> +		    } else {
> +			$err = 1;
> +			last;
> +		    }

as talked off-list, i am unsure if rejecting 'unknown' parameters is
the best way. before, we simply ignore them, so if a mail-server already
sent invalid/unknown paramters it will now be blocked which is not
that good imho. i think we should still ignore/drop them or pass them
along.

>   		}
>   		$self->{from} = $from;
> -		$self->reply ('250 2.5.0 OK');
> +		if ($err) {
> +		    $self->reply ("501 5.5.2 Syntax: MAIL FROM: unknown parameter");
> +		} else {
> +		    $self->reply ('250 2.5.0 OK');
> +		}
>   		next;
>   	    } else {
>   		$self->reply ("501 5.5.2 Syntax: MAIL FROM: <address>");
>   		next;
>   	    }
>   	} elsif ($cmd eq 'rcpt') {
> -	    if ($args =~ m/^to:\s*<([^\s\>]+)>[^>]*$/i) {
> +	    if ($args =~ m/^to:\s*<([^\s\>]+?)>(.*)$/i) {
>   		my $to = $self->{smtputf8} ? decode('UTF-8', $1) : $1;
> +		my $opts = lc($2);
>   		push @{$self->{to}} , $to;
> -		$self->reply ('250 2.5.0 OK');
> +		my $err = 0;
> +		for my $opt (split(' ', $opts)) {
> +		    if ($opt =~ /(notify|orcpt)=([^ =]+)/i ) {
> +			$self->{param}->{rcpt}->{$to}->{$1} = $2;
> +		    } else {
> +			$err = 1;
> +			last;
> +		    }
> +		}
> +		if ($err) {
> +		    $self->reply ("501 5.5.2 Syntax: RCPT TO: unknown parameter");
> +		} else {
> +		    $self->reply ('250 2.5.0 OK');
> +		}
>   		next;
>   	    } else {
>   		$self->reply ("501 5.5.2 Syntax: RCPT TO: <address>");
> diff --git a/src/PMG/Utils.pm b/src/PMG/Utils.pm
> index 92c3a7a..4eebfa5 100644
> --- a/src/PMG/Utils.pm
> +++ b/src/PMG/Utils.pm
> @@ -203,7 +203,7 @@ sub subst_values {
>   }
>   
>   sub reinject_mail {
> -    my ($entity, $sender, $targets, $xforward, $me, $nodsn) = @_;
> +    my ($entity, $sender, $targets, $xforward, $me, $params) = @_;
>   
>       my $smtp;
>       my $resid;
> @@ -244,15 +244,28 @@ sub reinject_mail {
>   	    $mail_opts .= " SMTPUTF8" if $has_utf8_targets;
>   	}
>   
> +	if (defined($params->{mail})) {
> +	    my $mailparams = $params->{mail};
> +	    for my $p (keys %$mailparams) {
> +		$mail_opts .= " $p=$mailparams->{$p}";
> +	    }
> +	}
> + >   	if (!$smtp->_MAIL("FROM:" . $sender_addr . $mail_opts)) {
>   	    syslog('err', "smtp error - got: %s %s", $smtp->code, scalar ($smtp->message));
>   	    die "smtp from: ERROR";
>   	}
>   
> -	my $rcpt_opts = $nodsn ? " NOTIFY=NEVER" : "";
> -
>   	foreach my $target (@$targets) {
>   	    my $rcpt_addr;
> +	    my $rcpt_opts = '';
> +	    if (defined($params->{rcpt}->{$target})) {
> +		my $rcptparams = $params->{rcpt}->{$target};
> +		for my $p (keys %$rcptparams) {
> +		    $rcpt_opts .= " $p=$rcptparams->{$p}";
> +		}
> +	    }
> +
>   	    if (utf8::is_utf8($target)) {
>   		$rcpt_addr = encode('UTF-8', $smtp->_addr($target));
>   	    } else {
> diff --git a/src/bin/pmg-smtp-filter b/src/bin/pmg-smtp-filter
> index b070c8e..45eb125 100755
> --- a/src/bin/pmg-smtp-filter
> +++ b/src/bin/pmg-smtp-filter
> @@ -640,6 +640,7 @@ sub handle_smtp {
>   	$msginfo->{sender} = $smtp->{from};
>   	$msginfo->{xforward} = $smtp->{xforward};
>   	$msginfo->{targets} = $smtp->{to};
> +	$msginfo->{param} = $smtp->{param};
>   
>   	my $dkim_sign = $msginfo->{trusted} && $pmg_cfg->get('admin', 'dkim_sign');
>   	if ($dkim_sign) {
> 





      reply	other threads:[~2021-11-24  9:33 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-22 19:50 Stoiko Ivanov
2021-11-24  9:33 ` Dominik Csapak [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ccfe4516-08ed-9fa1-ffe6-dcdb2016932b@proxmox.com \
    --to=d.csapak@proxmox.com \
    --cc=pmg-devel@lists.proxmox.com \
    --cc=s.ivanov@proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal