CentOS 8.x Control Web panel External Email Caution Banner Configuration

From Notes_Wiki

Home > CentOS > CentOS 8.x > Email servers > Control Web panel > CentOS 8.x Control Web panel External Email Caution Banner Configuration

External Email Caution Banner Configuration in Postfix

1) Create the Filter Script

Create the script file:

vim /usr/local/bin/banner-filter.py

Paste the following content into the file:

#!/usr/bin/env python3
import sys
import email
from email import policy
from email.generator import BytesGenerator
import tempfile
import subprocess
import re

# List of internal domains
INTERNAL_DOMAINS = ["yourdomain.com", "your-anotherdomain.com"]

banner_plain = (
     "***** CAUTION: This email originated outside your organization. Do not click links or open attachments unless you recognize the sender. *****\n\n"
)

banner_html = (
    '<div style="border:1px solid #e6b800; background:#fff8cc; padding:8px; font-size:12px;">'
    '<strong>CAUTION:</strong> This email originated outside your organization. Do not click links or open attachments unless you recognize the sender.'
    '</div><br>'
)

# Read the message
msg = email.message_from_binary_file(sys.stdin.buffer, policy=policy.default)

# Extract sender domain
sender = msg.get("From", "").strip()
sender_domain = None
m = re.search(r'@([\w.-]+)', sender)
if m:
    sender_domain = m.group(1).lower()

# Recipients passed from Postfix
recipients = sys.argv[1:]
if not recipients:
    print("Error: No recipients passed to script!", file=sys.stderr)
    sys.exit(75)

# Determine if banner should be added
should_add_banner = sender_domain not in INTERNAL_DOMAINS

# Debug output
print(f"Sender: {sender} (domain: {sender_domain})", file=sys.stderr)
print(f"Should add banner: {should_add_banner}", file=sys.stderr)

if should_add_banner:
    if msg.is_multipart():
        for part in msg.walk():
            content_type = part.get_content_type()
            if content_type == "text/plain":
                orig = part.get_content()
                part.set_content(banner_plain + orig)
            elif content_type == "text/html":
                orig = part.get_content()
                part.set_content(banner_html + orig, subtype='html')
    else:
        content_type = msg.get_content_type()
        if content_type == "text/plain":
            orig = msg.get_content()
            msg.set_content(banner_plain + orig)
        elif content_type == "text/html":
            orig = msg.get_content()
            msg.set_content(banner_html + orig, subtype='html')

# Write modified message to temp file
with tempfile.NamedTemporaryFile("wb", delete=False) as tmp:
    BytesGenerator(tmp).flatten(msg)
    path = tmp.name

# Reinject message to Postfix
with open(path, "rb") as f:
    result = subprocess.run(["/usr/sbin/sendmail", "-i"] + recipients, stdin=f)

sys.exit(result.returncode)

2) Set Script Permissions

chown root:root /usr/local/bin/banner-filter.py
chmod 755 /usr/local/bin/banner-filter.py

3) Create a System User for the Filter

useradd --system --no-create-home --shell /usr/sbin/nologin filteruser

4) Configure Postfix master.cf

Edit the master.cf file:

vim /etc/postfix/master.cf

Add this block at the end:

bannerfilter unix - n n - - pipe
  flags=Rq user=filteruser argv=/usr/local/bin/banner-filter.py -- ${recipient}

Locate and modify the 127.0.0.1:10025 block as follows:

Find this block:

127.0.0.1:10025 inet n - y - - smtpd
  -o content_filter=
  -o smtpd_helo_restrictions=
  ...

Replace with:

127.0.0.1:10025 inet n - y - - smtpd
  -o content_filter=bannerfilter:dummy
  -o smtpd_helo_restrictions=
  ...

5) Restart Required Services

systemctl restart postfix amavisd

6) Testing

Send test emails from external domains (e.g., gmail.com, yahoo.com) to verify that the banner is added.

Send test emails between your internal domains (e.g., yourdomain.com to your-anotherdomain.com) to verify that the banner is not added.


Home > CentOS > CentOS 8.x > Email servers > Control Web panel > CentOS 8.x Control Web panel External Email Caution Banner Configuration