Skip to content

Instantly share code, notes, and snippets.

@marios88
Last active February 3, 2017 15:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marios88/4079d50b6eb241ad703bb3c9ed1b1081 to your computer and use it in GitHub Desktop.
Save marios88/4079d50b6eb241ad703bb3c9ed1b1081 to your computer and use it in GitHub Desktop.
Postfix cron based rate limiting / throttling with mail alert and automatic postfix shutdown on abnormal queue size

NOTHING WORKED, postfix does not want to throttle outgoing emails.NO MORE

This will delay sending emails and put extra load on the cpu

Why, you ask?

My server normaly sends 1000-2000 emails per day, one day a client got hacked and sent out 2million of them Outgoing email workload is fairly predictable in my case

Instructions

add in /etc/postfix/main.cf and copy header_checks to the same location
"header_checks = regexp:/etc/postfix/header_checks"

make your own txt files or use sendmail directry the current postqueue.sh -will release 4 mails every 1 minute -alert when mailq is over 10 -alert and stop postfix when queue is over 100

postqueue.sh borrowed and adapted from https://lists.nongnu.org/archive/html/monit-general/2015-01/msg00037.html

Now all outgoing email goes to HOLD queue except those that contain the secret mailfrom then gets moved on incoming by the following cron

setup root cron
* * * * * sh /root/postqueue.sh > /dev/null 2>&1

# Do not indent the patterns between "if" and "endif".
#/etc/postfix/header_checks
if /^From:/
!/^From: thoushallnotbeheld@example.com/ HOLD 9988:DEFAULTHOLD
endif
#!/bin/bash
postfix_queue=`mailq | grep Requests | awk {'print $5'}`
if [ -z "$postfix_queue" ]
then
postfix_queue="0";
fi
if [ "$postfix_queue" -le "10" ]
then
#all is quite
#http://serverfault.com/questions/408482/postfix-hold-queue-release-x-oldest-messages-or-all-messages-queued-before-x-da
mailq |egrep "^[[:alnum:]]{10}\!" |sort -k 4,4M -k 5,5n -k 6,6|head -4|awk '{print "mv /var/spool/postfix/hold/" substr($1, 1, length($1)-1) " /var/spool/postfix/incoming/" substr($1, 1, length($1)-1)}'|sh
/usr/sbin/postfix flush
echo 'OK'
exit 0
elif [ "$postfix_queue" -ge "10" ] && [ "$postfix_queue" -le "20" ]
then
#picking up some load better mail me with special header
echo 'SEMI'
mailq |egrep "^[[:alnum:]]{10}\!" |sort -k 4,4M -k 5,5n -k 6,6|head -4|awk '{print "mv /var/spool/postfix/hold/" substr($1, 1, length($1)-1) " /var/spool/postfix/incoming/" substr($1, 1, length($1)-1)}'|sh
/usr/sbin/postfix flush
/usr/sbin/sendmail -vt < /root/semi-mail.txt
exit 1
else
#Hell breaks loose
#mail me with special header
#wait 3 sec for mail delivery
/usr/sbin/sendmail -vt < /root/high-mail.txt
/usr/sbin/postfix flush
sleep 10s
/usr/sbin/service postfix stop
#stop postfix
echo 'FAIL'
exit 2
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment