Unlimited email for unlimited AI bots

Why? AI bots. That's why. The future happened an we now have AI. AI bots need to use email. They also need persistent message queues. This means that even more email will be needed. Whatever the problem, the solution is email.
The basic idea here is to use a custom mail delivery agent for the unlimited mailboxes. The 'transport' file defines the mappings of email addresses to delivery agents. The email delivery for the human computer users doesn't change. They still get their mail in /var/mail/${USER} .
The technique that I use here was described in an answer on ServerFault.com credit to user larsks https://serverfault.com/questions/1147666/configure-postfix-virtual-transport-to-deliver-mail-to-arbitrary-local-address .
When I installed postfix, I selected the option for local mail only. I you need to use postfix for mail to/from outside world, then you will have to figure it out yourself. I suggest using smtp/IMAP access to an external email provider for all of your external email needs.
I have set up a catch-all mail delivery agent so that I don't have to create a user account for each email box. It works! Mail is delivered to /var/vmail, mailboxes are created on demand. Uses mbox format. Local unix mail only. Using postfix. No IMAP server.
/var/vmail is owned by postai:postai and has rwx-rws---- permissions. Postai is just a user:group that I made to administer the unlimited email service.
(Update May 2025: When setting this up on another computer I discovered that I had omitted some important details. First, perms for both /var/mail/
and /var/vmail/
should be 2775 (group sticky bit set: g+s). I added postai as an ACL group to /var/mail/
and added mail as an ACL group to /var/vmail/
. Here is how:
# Set permissions:
cd /var
sudo mkdir mail
sudo chmod 2775 mail
sudo chown root:mail mail
sudo setfacl -m g:postai:rwx mail
# vmail
sudo mkdir vmail
sudo chmod 2775 vmail
sudo chown postai:postai vmail
sudo setfacl -m g:mail:rwx vmail
These changes allow postai group members and the mail agent to make the required lock files.
Also:
Make /var/empty if you don't already have it: sudo mkdir /var/empty
End update.)
# Choose whatever unused uid,gid. I chose 9999. sudo groupadd -g 9999 postai sudo useradd -u 9999 -g postai -d /var/empty -s /sbin/nologin postai # Add user "vctr" to the postai group
sudo usermod -aG postai vctr
Make these changes to /etc/postfix/main.cf
# local only
inet_interfaces = loopback-only
default_transport = error
relay_transport = error
inet_protocols = ipv4
# postai parameters
# /usr/local/bin/postai is a script that can only handle one email at a time:
postai_destination_recipient_limit = 1
# Mail delivery agent will determine recipients, so ensure that this is blank:
local_recipient_maps =
# It seems that only hash works here:
transport_maps = hash:/etc/postfix/transport
Make these changes to /etc/postfix/master.cf
# Postai delivery
postai unix - n n - - pipe
flags=DBFRXhu directory=/var/vmail user=postai:postai argv=/usr/local/bin/postai ${user}
Create file /etc/postfix/transport
# Local delivery for users in /var/mail
# The delivery agent is literally called "local" root@myhostname local:myhostname vctr@myhostname local:myhostname root@localhost local:myhostname vctr@localhost local:myhostname root@home.arpa local:myhostname vctr@home.arpa local:myhostname # Postai delivery for bots in /var/vmail * postai:
Create script /etc/postfix/postai
#!/bin/bash
# /usr/local/bin/postai
# Postai catchall mail transport.
# Delivery should be to /var/vmail/${USER}
# This program runs as user:group postai:postai .
# shellcheck disable=SC2181
# Code 75 from sysexits.h - exit codes for programs (bsd)
# The most important thing is to return code 75 when the lock file
# exists so that postfix will attempt to redeliver. It works!
#
# 1: default error
# 2: wrong args
# 3: couldn't touch log file
# 4: unable to create lock file
# 5: unable to write to mbox
#
# 75: lock file exists, redeliver
umask 007
# Function to get the current timestamp in the desired format
get_timestamp() {
date +"%Y-%m-%d %H:%M:%S"
}
# Function to log an error message and exit
die() {
echo "$(get_timestamp) - $1" >> "$log_file"
exit "${2:-1}" # Default exit code is 1 if not provided
}
# Check if the correct number of arguments is provided
if [ "$#" -lt 1 ]; then
die "Incorrect number of arguments \"$*\"" 2
fi
# The recipient email address is passed as the first argument
recipient="$1"
# Extract the username from the email address (before the '@')
username=$(echo "$recipient" | cut -d'@' -f1)
maildir="/var/vmail"
mbox_file="${maildir}/${username}"
lock_file="${mbox_file}.lock"
log_file="${maildir}/postai.log"
# Ensure the log file exists
touch "$log_file" || die "Failed to create log file $log_file." 3
# Check if the lock file exists
if [ -e "$lock_file" ]; then
die "Lock file exists. Another instance may be running." 75
fi
# Create the lock file
touch "$lock_file" || die "Failed to create lock file $lock_file." 4
trap 'rm -f "$lock_file" || die "Failed to remove lock file."' INT TERM EXIT
# Write the email directly to the mbox file
if ! cat >> "$mbox_file"; then
die "Failed to write email to $mbox_file" 5
fi
# Log the delivery
echo "$(get_timestamp) - Email delivered to $recipient" >> "$log_file"
# Remove the lock file after successful delivery
rm -f "$lock_file"
exit 0
Copy files to the correct places
chmod +x postai
sudo cp postai /usr/local/bin/postai
Remap and restart mail service
# Generate transport.db file and restart postfix
postmap /etc/postfix/transport
sudo service postfix restart
I Vibe-Coded the postai script, which is not as easy as it sounds. ChatGPT doesn't know much about email. It also makes many wrong assumptions and it seems to over-complicate things. I had to correct it at every step. It still seems easier than coding from scratch.
So, yeah, I did this and it changed my life.