1

Bcc'ing the archive@domain.tld user, we do not want people to receive that Bcc list, apart from the archive@domain.tld "user".

Goal

  1. We want to archive all mails going through postfix, sent and received. The setup uses:
  • postfix,
  • dovecot authentication with Pam (pulling from Ldap) users,
  • and delivery to the mailboxes via Dovecot's LMTP.
  1. We want to include the Bcc recipients in the message archive.

  2. We do not want people to receive that Bcc list, apart from the archive@domain.tld "user".

Trial

  1. Using always_bcc = archive@domain.tld Works. But the Bcc recipiets (which as per rights are in the envelope as RCPT TO and not in a header) get lost.

  2. Using: (as per What options are there to archive Postfix email and preserve any BCC information in the header)

main.cf
smtpd_recipient_restrictions =
  check_recipient_access pcre:/etc/postfix/prepend.pcre

while the pcre expression is:

prepend.pcre
/(.+)/          PREPEND X-Envelope-To: $1

which works like a charm: my message stored has the headers To:; Cc; X-Envelope-To. If any day we need to dig into it, we can know who received the message even in Bcc. (NB: the X-Envelope-To includes the To and Cc people, pas well as the external domains recipients).

  1. To eliminate the X-Envelope-To: For sending out:
smtp_header_checks = pcre:/etc/postfix/smtp_header_checks.pcre

With the contents:

smtp_header_checks.pcre
/^X-Envelope-To:/               IGNORE

All ok until there.

Problem

To eliminate the X-Envelope-To for emails not leaving the server. I did:

lmtp_header_checks = pcre:/etc/postfix/lmtp_header_checks.pcre

lmtp_header_checks.pcre
/^X-Envelope-To:/               IGNORE

But this is not selective, even archive@domain.tld looses the header that was "saved" the Bcc list.

I cannot find a way to the that header check selective since it only evaluates the line itself and cannot use the recipient to make a condition (even using the "if" of the pcre). (http://www.postfix.org/pcre_table.5.html)

Is there any variable that can be used ? A thought was to: include "archive@domain.tld" in the X-Envelope-To header prepended, in the lmtp_header_checks.pcre, include something like: archive@domain.tld not equal to $LMTP_DELIVERY_RECIPIENT Delivered-To or X-Delivered-To remain a separate header that the pcre cannot evaluate as a variable.

Otherwise is there a way to have lmtp trigger some milter ? And a simple lmtp_milter filter I can use for that ?

Been chasing for days in all docs possible, Thanks in advance

2 Answers2

1

Oh YES ! Thanks you so much.

The sieve langugage will not allow iteration over multiple X-Envelope-To headers. So one needs to pass it to an external program.

Here is what I came up with:

require "fileinto";
require "imap4flags";
require ["editheader", "envelope"];
require "vnd.dovecot.filter";
if header :contains "X-Spam-Flag" "YES"
{
   fileinto "Junk";
   stop;
}
if envelope :is "to" "archive@bogo.ovh" {
   filter "EnvelopeToBcc.sh";
} else {
   deleteheader "X-Envelope-To";
}
#!/bin/bash
# Store mail in a variable
# input stream
mail=`cat /dev/stdin`
# Extract headers
envelope=$(echo "$mail" | formail -x X-Envelope-To | tr -d '\015')
tos=$(echo "$mail" | formail -x To  | tr -d '\015')
copies=$(echo "$mail" | formail -x Cc  | tr -d '\015')

# Loop excluding the To: fields and concatenate in variable
bcc=""
for i in $envelope; do
        if [[ ${tos} != *"${i}"* && ${copies} != *"${i}"* ]];then
                bcc="${bcc} ${i},"
        fi
done
# Eliminate trailing comma
bcc=$(echo $bcc | sed s/,$//)
# Add Bcc header to mail 
echo "${mail}" | formail -a "Bcc: $bcc"

If you open the archive with any MUA you can see the bcc rebuilt. NB: script a bit longer but it avoids duplication of the To people in the Bcc list.

0

Use the Sieve language.

Since your mail is delivered via LMTP to Dovecot, you will have all addressing and header editing capabilities there, with a whole bunch of more complex logic capabilities than those offered by simple Postfix header checks.

If you are not using Pigeonhole sieve yet, you may need to enable it as a Dovecot plugin, enable the extensions you need in your script, and configure a suitable script.

# step1 enable sieve (append to $mail_plugins to *add*)
protocol lmtp {
  mail_plugins = $mail_plugins sieve
}
# step2 enable sieve extensions, as required (prefix with + to *add*)
plugin {
    sieve_extensions = +editheader
}
# step3 configure the path a of a script to be executed

Then in a script executed globally, or specifically for users that shall not see the envelope address, delete the header - unless delivering to the archive mailbox:

require ["editheader", "envelope"];
if not envelope :is "to" "archive@example.com" {
    deleteheader "X-Envelope-To";
}
anx
  • 6,875
  • 4
  • 22
  • 45