I would like to pass incoming mail using virtual_transport
to a transport spamassassin
(main.cf: virtual_transport=spamassassin
) and then reinject the scanned mail into postfix using sendmail.
The transport looks like this:
spamassassin unix - n n - - pipe
flags=hu user=vmail:mail argv=/usr/bin/spamc -u ${recipient} -e /usr/sbin/sendmail -f ${sender} ${recipient}
This should be possible acording to the postfix documentation:
High volume sites should avoid using "simple" content filters that re-inject scanned mail via Postfix sendmail(1) and postdrop(1).
With my current sendmail call /usr/sbin/sendmail -f ${sender} ${recipient}
, the mail loops by getting passed back into the queue and then back to spamassassin and so on.
From my understanding of the postfix documentation, mail delivered using postfix sendmail
is dropped in the maildrop
directory and then picked up using pickup
. I tried to append a -o virtual_transport=dovecot
to the pickup transport to avoid the queue, but this didn't help. (Those options can only get appended to smtp transports I suppose).
How can I reinject mail scanned with spamassassin back into the queue for final delivery without causing a loop?
NO You can't
Explanation
I understand the reason you use
virtual_transport
to pipe email into Spam Assassin. You only want to scan the email intended to yourvirtual_mailbox_domain
. Unfortunately it doesn't follow the recommended setup for simple content filter that usingcontent_filter
parameter insteadvirtual_transport
.Why I can't pass
virtual_transport
to pickup or smtpd?Generally, here the email journey across postfix code
In
cleanup
daemon, postfix will 'route' your email, whether they are belong to virtual, local, smtp or other transports. One exception is when non-blankcontent_filter
parameter was passed into input service (smtpd
,pickup
,qmqpd
). When this happened, postfix will override the message route and send the email intocontent_filter
instead.Another note, by default all postfix service was get parameter value from
main.cf
unless you override it by using -o parameter=value onmaster.cf
. But not every parameter inman 5 postconf
used by a service. For example, content_filter only used bypickup
,smtpd
andqmqpd
so you can put -o content_filter=amavis:[127.0.0.1:10025 on them. Another example, it is not sensible to put -o smtp_bind_address insmtpd
as this parameter only used insmtp
service.The same argument can be applied to your question, "why I can pass -o virtual_transport in
pickup
?"So here are the several alternatives for your setup
Use
content_filter
as explained in postfix documentation. The downside is you also scan the email that relayed outside your domain.Use
content_filter
via ACCESS table and FILTER action. With this way, you can selectively scan the incoming email.Unfortunately you must enlist your. You can avoid it by carefully placing ACCESS table aftervirtual domain
again in that table.permit_mynetworks
,permit_sasl_authenticated
. With this way, outgoing email will be already permitted and you only scan incoming email. (Credit to OP comment :) )Using Postfix Multiple Instance. With this way, you can keep the
virtual_transport
parameter and spamc will inject the email to your second instance. And then you can define differentvirtual_transport
in different instance. But it's a bit overkill if you want to keep your setup simple.