Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
linux:apache:sendmail_python [2017/02/16 16:04]
vondra [Code]
linux:apache:sendmail_python [2017/02/21 14:27] (current)
tomsa [Code]
Line 2: Line 2:
 Sendmail wrapper limiting amount of emails sent by php Sendmail wrapper limiting amount of emails sent by php
 ===== Installation ===== ===== Installation =====
 +  * <code bash>pip install psutils</​code>​
   *  Copy the script below into /​usr/​sbin/​safe_sendmail   *  Copy the script below into /​usr/​sbin/​safe_sendmail
-  *  Put the path to script into sendmail_path variable in php.ini +  *  Put the path to script into sendmail_path variable in php.ini ​or into /​etc/​php5/​fpm/​pool.d/​www.conf if using php-fpm 
-  *  Database and log files will be created in /tmp/safe_sendmail.db and /tmp/​safe_sendmail.log respectively+  * <​code>​php_admin_value[sendmail_path] = /​usr/​sbin/​safe_sendmail</​code>​ 
 +  *  Database and log files will be created in workdir defined in script ("/usr/local/​safe_sendmail/") this dir should be writable for everyone (limited access could lead to unexpected bahaviour)
   *  Timewindow (default 1 hour) and treshold (default 200 emails) parameters are declared in script   *  Timewindow (default 1 hour) and treshold (default 200 emails) parameters are declared in script
 +  * For deeper inspection of mail traffic uncomment logging lines at the end (logging the mail body)
  
 ===== Testing ===== ===== Testing =====
-  * Put following content in /var/www/​testmail.txt:​ (few blank lines may be needed at the end of the file)<​code file>+  * Put following content in /tmp/​testmail.txt:​ (few blank lines may be needed at the end of the file)<​code file>
 To: firma@starlab.cz To: firma@starlab.cz
 Subject: This is a test message subject Subject: This is a test message subject
Line 19: Line 21:
  
 </​code>​ </​code>​
-  * Run:<​code bash>for i in `seq 1 300`; do cat /var/www/​testmail.txt | safe_sendmail firma@starlab.cz ;  done</​code>​ +  * Run:<​code bash>for i in `seq 1 300`; do cat /tmp/​testmail.txt | safe_sendmail firma@starlab.cz ;  done</​code>​ 
-  * Observe log file:<​code bash>​tail -f /tmp/​safe_sendmail</​code>​+  * Observe log file:<​code bash>​tail -f /usr/local/​safe_sendmail/​safe_sendmail.log</​code>​
   * After the treshold number of emails script refuses to send more emails.   * After the treshold number of emails script refuses to send more emails.
  
Line 57: Line 59:
 time_scope = 60 time_scope = 60
    
 +notification_mail = """​To:​ firma@starlab.cz
 +Subject: Alert! Too many outgoing emails from server {server_name}
 +
 +Safe sendmail script started filtering messages on server {server_name}. Threshold reached.
 +"""​.format(server_name='​webhosting.starlab.cz'​)
 +
    
 def check_db(): def check_db():
Line 64: Line 72:
         is_table = len(c.fetchall())         is_table = len(c.fetchall())
         if is_table == 0:         if is_table == 0:
-            c.execute("​CREATE TABLE mails (date text, address_to text)"​)+            c.execute("​CREATE TABLE mails (date text, address_to text, spamcount integer)")
             conn.commit()             conn.commit()
     return True     return True
Line 95: Line 103:
     logger.debug("​Datetime:​ %s" % timestamp)     logger.debug("​Datetime:​ %s" % timestamp)
     past = timestamp - dt.timedelta(minutes=time_scope)     past = timestamp - dt.timedelta(minutes=time_scope)
-    ​with sqlite3.connect(db_file) as conn:+        ​with sqlite3.connect(db_file) as conn:
         c = conn.cursor()         c = conn.cursor()
-        c.execute('​INSERT INTO mails VALUES(?,?)', (timestamp, address)+        c.execute('​SELECT spamcount FROM mails ORDER BY date DESC LIMIT 1') 
-        ​conn.commit()+        ​last_spam_count = c.fetchone()[0] 
 +        if last_spam_count is None: 
 +            last_spam_count = 0 
         c.execute('​SELECT COUNT(*) FROM mails where date > ?', (past,))         c.execute('​SELECT COUNT(*) FROM mails where date > ?', (past,))
-        count_since_past = c.fetchone()[0]+        count_since_past = c.fetchone()[0] ​+ 1
         logger.debug("​Count since %s %d" % (timestamp, count_since_past))         logger.debug("​Count since %s %d" % (timestamp, count_since_past))
 +        c.execute('​INSERT INTO mails VALUES(?,?,?​)',​ (timestamp, address, count_since_past))
 +        conn.commit()
         if count_since_past < threshold:         if count_since_past < threshold:
             if send_mail(mail):​             if send_mail(mail):​
Line 108: Line 121:
                 sys.exit(2)                 sys.exit(2)
         else:         else:
 +            if last_spam_count < threshold:
 +                send_mail(notification_mail)
             # logger.info("​Parent:​ {}"​.format(parent_process.cmdline())) ​               # uncomment to get parent'​s cmdline             # logger.info("​Parent:​ {}"​.format(parent_process.cmdline())) ​               # uncomment to get parent'​s cmdline
             # logger.info("​Grandparent:​ {}"​.format(grandparent_process.cmdline())) ​     # uncomment to get grandparent'​s cmdline             # logger.info("​Grandparent:​ {}"​.format(grandparent_process.cmdline())) ​     # uncomment to get grandparent'​s cmdline
-            # logger.info(mail) ​                                                                                ​# uncomment to get raw input (mail content and headers)+            # logger.info(mail) ​                                                        ​# uncomment to get raw input (mail content and headers)
             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))             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)             sys.exit(1)
- 
  
 </​code>​ </​code>​
  
 
linux/apache/sendmail_python.1487257487.txt.gz · Last modified: 2017/02/16 16:04 by vondra