How to Limit Email Sending Rate for a Specific User in Postfix to Prevent Server Overload


2 views

On our CentOS server running Postfix with Virtualmin/Webmin management, we've encountered a common but frustrating scenario: a single user sending bulk emails (thousands at once) causes the entire mail server to become unresponsive. This creates a domino effect where other users' emails get delayed or fail entirely while the queue processes the massive batch.

Postfix offers several mechanisms to control email sending rates. The most relevant for our case is the smtpd_client_message_rate_limit and anvil_rate_time_unit parameters. However, these typically apply globally. We need user-specific controls.

# Global rate limiting example (not user-specific)
smtpd_client_message_rate_limit = 100
anvil_rate_time_unit = 60s

For user-specific limits, we'll combine Postfix's check_sender_access with custom lookup tables. Here's how to implement it:

# In main.cf
smtpd_sender_restrictions = 
    check_sender_access hash:/etc/postfix/sender_limits,
    permit_mynetworks,
    reject_unauth_destination

# Create the sender_limits file
echo "problemuser@domain.com   REJECT You are sending too many emails" > /etc/postfix/sender_limits
postmap /etc/postfix/sender_limits

For advanced rate limiting, consider installing policyd-rate (now called opendkim-rate-limit):

# Installation on CentOS
yum install perl-LDAP perl-IO-Socket-SSL
wget https://github.com/porche/policyd-rate/archive/master.zip
unzip master.zip
cd policyd-rate-master
cp policyd-rate.conf /etc/
cp policyd-rate /usr/local/bin/

Then configure Postfix to use it:

# In main.cf
smtpd_recipient_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_destination,
    check_policy_service inet:127.0.0.1:10031

To prevent one user from affecting others, implement these additional measures:

# Limit concurrent connections per sender
default_process_limit = 100
smtpd_client_connection_count_limit = 10
smtpd_client_connection_rate_limit = 30

# Queue management
qmgr_message_active_limit = 1000
qmgr_message_recipient_limit = 1000

Since you're using Virtualmin, you can also set these limits through the web interface:

  1. Go to Server Configuration → Postfix Mail Server
  2. Under "SMTP Restrictions", add custom rules
  3. Use "Per-User Message Rate Limit" option

Set up monitoring to catch abuse early:

# Simple monitoring script
#!/bin/bash
QUEUE=$(mailq | grep problemuser@domain.com | wc -l)
if [ "$QUEUE" -gt 500 ]; then
    echo "Warning: problemuser has $QUEUE emails in queue" | mail -s "Postfix Alert" admin@domain.com
fi

On our CentOS server running Postfix with Virtualmin/Webmin management, we encountered a critical issue where a single user sending bulk emails (thousands at once) caused the entire mail server to become unresponsive. This created a domino effect where other users' emails were delayed or failed during queue processing.

Postfix provides several mechanisms to control email sending rates. The most relevant for our case is the smtpd_client_message_rate_limit and anvil_rate_time_unit parameters. Here's how to implement user-specific throttling:

# In /etc/postfix/main.cf
smtpd_client_message_rate_limit = 100
anvil_rate_time_unit = 60s
default_process_limit = 100

For more granular control, we can use Postfix's sender-dependent rate limiting. Create a file called /etc/postfix/sender_ratelimit:

problemuser@domain.com   10/minute
*@domain.com             50/hour

Then add these lines to main.cf:

smtpd_sender_restrictions = 
    check_sender_access hash:/etc/postfix/sender_ratelimit
    permit_mynetworks
    permit_sasl_authenticated
    reject_unauth_destination

smtpd_client_connection_rate_limit = 10

To prevent server overload regardless of user behavior, implement these additional settings:

# Maximum concurrent deliveries
default_destination_concurrency_limit = 20

# Maximum recipients per message
smtpd_recipient_limit = 1000

# Queue processing control
minimal_backoff_time = 300s
maximal_backoff_time = 4000s

For proactive management, create a monitoring script that checks queue size and user activity:

#!/bin/bash
# monitor_postfix_queue.sh

QUEUE_SIZE=$(mailq | grep -c "^[A-F0-9]")
MAX_QUEUE=1000

if [ "$QUEUE_SIZE" -gt "$MAX_QUEUE" ]; then
    # Identify top senders
    echo "Top email senders:"
    mailq | awk '/^[A-F0-9]/ {print $7}' | sort | uniq -c | sort -nr | head -10
    
    # Optional: Temporarily throttle the server
    postconf -e default_destination_concurrency_limit=5
    systemctl reload postfix
fi

Since you're using Virtualmin, you can also set limits through its interface:

  1. Go to Webmin → Servers → Postfix Mail Server
  2. Select "SMTP Authentication and Encryption"
  3. Set "SMTP client connection rate limit" and "SMTP client message rate limit"
  4. Apply changes and restart Postfix

After making changes, always verify your configuration:

postfix check
postconf -n
systemctl restart postfix

These measures should effectively prevent any single user from overwhelming your mail server while maintaining service for others.