Docs / Email Servers / Email Autoresponders with Postfix

Email Autoresponders with Postfix

By Admin · Mar 15, 2026 · Updated Apr 23, 2026 · 423 views · 3 min read

Email autoresponders (vacation messages and out-of-office replies) automatically send predefined responses to incoming messages. While modern email clients handle this client-side, server-side autoresponders work 24/7 regardless of whether the user's email client is running. This guide covers implementing autoresponders with Postfix using both simple and advanced approaches.

Method 1: Postfix vacation Command

The vacation utility is the traditional Unix autoresponder. It tracks who has been replied to and avoids sending duplicate responses.

# Install vacation
sudo apt install vacation    # Ubuntu/Debian

# Set up for a user
su - username
vacation -I    # Initialize the .vacation.db file

# Create vacation message
cat > ~/.vacation.msg  ~/.forward

# Disable vacation
rm ~/.forward

Method 2: Sieve-Based Autoresponder

If you use Dovecot with Sieve (recommended for virtual domains):

# User Sieve script (~/.dovecot.sieve)
require ["vacation", "variables"];

vacation
    :days 1
    :subject "Out of Office - Will return Jan 20"
    :from "User Name "
    :addresses ["user@example.com", "u.name@example.com"]
    :mime
"MIME-Version: 1.0
Content-Type: text/html; charset=utf-8



Thank you for your email.

I am currently out of the office and will return on January 20, 2025.

For urgent matters, please contact backup@example.com.

Best regards,
User Name

";

Method 3: Custom Autoresponder Script

#!/usr/bin/env python3
# /usr/local/bin/autoresponder.py
# Advanced autoresponder with rate limiting and template support

import sys
import email
import sqlite3
import time
import subprocess
from email.mime.text import MIMEText

DB_PATH = "/var/lib/autoresponder/responses.db"
RATE_LIMIT = 86400  # Reply once per sender per day

def init_db():
    conn = sqlite3.connect(DB_PATH)
    conn.execute("""CREATE TABLE IF NOT EXISTS sent (
        recipient TEXT, sender TEXT, sent_at REAL,
        PRIMARY KEY (recipient, sender))""")
    return conn

def should_respond(conn, recipient, sender):
    row = conn.execute(
        "SELECT sent_at FROM sent WHERE recipient=? AND sender=?",
        (recipient, sender)).fetchone()
    if row and time.time() - row[0] < RATE_LIMIT:
        return False
    return True

def record_response(conn, recipient, sender):
    conn.execute(
        "INSERT OR REPLACE INTO sent VALUES (?, ?, ?)",
        (recipient, sender, time.time()))
    conn.commit()

def get_template(recipient):
    # Load per-user template
    template_path = f"/var/lib/autoresponder/templates/{recipient}.txt"
    try:
        with open(template_path) as f:
            return f.read()
    except FileNotFoundError:
        return None

# Read incoming message
msg = email.message_from_bytes(sys.stdin.buffer.read())
sender = email.utils.parseaddr(msg["From"])[1]
recipient = email.utils.parseaddr(msg["To"])[1]

# Skip automated messages
if msg.get("Auto-Submitted", "").lower() != "no" and msg.get("Auto-Submitted"):
    sys.exit(0)
if msg.get("X-Auto-Response-Suppress"):
    sys.exit(0)
if msg.get("Precedence", "").lower() in ("bulk", "junk", "list"):
    sys.exit(0)

template = get_template(recipient)
if not template:
    sys.exit(0)

conn = init_db()
if not should_respond(conn, recipient, sender):
    sys.exit(0)

# Send response
reply = MIMEText(template)
reply["From"] = recipient
reply["To"] = sender
reply["Subject"] = f"Re: {msg.get('Subject', 'Your email')}"
reply["Auto-Submitted"] = "auto-replied"
reply["X-Auto-Response-Suppress"] = "All"
reply["In-Reply-To"] = msg.get("Message-ID", "")

subprocess.run(["/usr/sbin/sendmail", "-t", "-oi"], input=reply.as_bytes())
record_response(conn, recipient, sender)
conn.close()

Integrate with Postfix

# /etc/postfix/main.cf — use as a content filter
content_filter = autoresponder:dummy

# /etc/postfix/master.cf
autoresponder unix - n n - 10 pipe
    flags=DRhu user=autoresponder argv=/usr/local/bin/autoresponder.py

# Or use always_bcc to copy messages to the autoresponder
# without modifying the delivery pipeline

Managing Autoresponders

# Enable autoresponder for a user
cat > /var/lib/autoresponder/templates/user@example.com.txt         

Was this article helpful?