- [Show pagesource]
- [Old revisions]
- [[unknown link type]]
- []
This is an old revision of the document!
Table of Contents
Python sendmail wrapper
Sendmail wrapper limiting amount of emails sent by php
Installation
- Copy the script below into /usr/sbin/safe_sendmail
- Put the path to script into sendmail_path variable in php.ini
- Database and log files will be created in /tmp/safe_sendmail.db and /tmp/safe_sendmail.log respectively
- Timewindow (default 1 hour) and treshold (default 200 emails) parameters are declared in script
Testing
- Put following content in /var/www/testmail.txt: (few blank lines may be needed at the end of the file)
To: firma@starlab.cz Subject: This is a test message subject X-PHP-Originating-Script: 0:index.php This is a test message body
- Run:
for i in `seq 1 300`; do cat /var/www/testmail.txt | safe_sendmail firma@starlab.cz ; done
- Observe log file:
tail -f /tmp/safe_sendmail
- After the treshold number of emails script refuses to send more emails.
Code
#!/usr/bin/env python import os import sqlite3 import sys import logging import re import datetime as dt import subprocess import shlex logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) # create a file handler logfile = '/tmp/safe_sendmail.log' handler = logging.FileHandler(logfile) handler.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) sendmail_bin = '/usr/sbin/sendmail -t -i' db_file = '/tmp/safe_sendmail.db' # Number of mails in given amount of minutes to stop the sending threshold = 200 time_scope = 60 def check_db(): with sqlite3.connect(db_file) as conn: c = conn.cursor() c.execute("SELECT name FROM sqlite_master WHERE name='mails'") is_table = len(c.fetchall()) if is_table == 0: c.execute("CREATE TABLE mails (date text, address_to text)") conn.commit() return True def send_mail(mail): logger.debug('Sending mail!\n%s' % mail) command = shlex.split(sendmail_bin) try: process = subprocess.Popen(command, stdin=subprocess.PIPE) process.communicate(mail) if process.returncode == 0: return True else: return False except: logger.exception("Unable to send mail") return False if __name__ == "__main__": check_db() mail = sys.stdin.read() address_regex = re.compile(u"To: (?P<mail_address>\S+)", re.UNICODE) address = address_regex.match(mail.replace('\n', ' ')).group('mail_address') timestamp = dt.datetime.now() logger.debug("Address: %s" % address) logger.debug("Datetime: %s" % timestamp) past = timestamp - dt.timedelta(minutes=time_scope) with sqlite3.connect(db_file) as conn: c = conn.cursor() c.execute('INSERT INTO mails VALUES(?,?)', (timestamp, address)) conn.commit() c.execute('SELECT COUNT(*) FROM mails where date > ?', (past,)) count_since_past = c.fetchone()[0] logger.debug("Count since %s %d" % (timestamp, count_since_past)) if count_since_past < threshold: if send_mail(mail): sys.exit(0) else: sys.exit(2) else: logger.warning("Unable to send mail to address %s - quota exceeded! (%d mails sent in last %d minutes - limit %s)" % (address, count_since_past, time_scope, threshold)) sys.exit(1)
linux/apache/sendmail_python.1485181773.txt.gz · Last modified: 2017/01/23 15:29 by vondra