Auto Responser

最後更新: 2018-12-16

目錄

  • Install
  • Cron jobs
  • Postfix configuration
  • Usage
  • DOC

介紹:

HomePage: https://code.google.com/p/response/

program:

- Python 2.6
- Daemons program
- Backends: MySQL, PostgreSQL, ...

supports:

    * response limits per recipient ("one autoresponse per recipient in 7 days")
    * relies on the delivering MTA to silently copy a given mail and hand it over. (Postfix: recipient_bcc_maps)
    * custom subjects and custom bodies per response-sender
    * No local file access
    
Components (3):

A LMTP-daemon
* handle incoming messages, validate sender, recipient, and headers.

The Notifier.(Cron)
* It can use any custom SMTP relay to send the responses. (keep it as flexible as possible)

Cleanup component
* It takes care of disabling expired autoresponse configurations
* removing obsolete response records.

 


Install

 

Debian6 Dependencies:

aptitude install python python-{mysqldb,sqlalchemy}

Centos6 Dependencies:

yum install MySQL-python python-sqlalchemy

# 建立 DB:

修改 /opt/response/examples/DATABASE.mysql 的以下一行 FIXME

# response-lmtpd, response-notify and response-cleanup
GRANT USAGE ON *.* TO 'response'@'localhost' IDENTIFIED BY 'FIXME';

# roundcube webmail user
GRANT USAGE ON *.* TO 'responserc'@'localhost' IDENTIFIED BY 'FIXME';

mysql -p < DATABASE.mysql

# 建立 User:

useradd  --system  --home-dir  /opt/response  --shell /bin/false  response

# 放 file 及設定它們的 permission:

cd /opt/

ln -s response-0.8 response

mv response/response.cfg /etc/

mkdir -p /var/run/response

# Set permission

chown response:response /etc/response.cfg /var/run/response

chmod 600 /etc/response.cfg

chmod 700 /var/run/response

chmod 770 /opt/response-0.8/

chown root.response /opt/response-0.8/

# 設定 response.cfg

vi /etc/response.cfg

[LMTPD]
# default 的 10024 好多時被 amavisd 用了
SOCKET_PORT = 10027
SOCKET_ADDR = 127.0.0.1

# 什麼人可以連它
SOCKET_ACL = 127.0.0.1


#### Error Handling / Informing the client of problems ( The "client" is the application speaking to LMTP-daemon )

# a non-delivery status-notification issued by the MTA back to the sender!(5xx error-code)
HARDFAIL = False

# Ask the client to re-send a message if we have problems (4xx error-code)
SOFTFAIL = True

# silently drop a message if the backend is unavailable (missing autoresponse)
FAILSAFE = False

[BACKEND]
USERNAME = response
PASSWORD = FIXME
DATABASE = response
ADAPTER = MySQL
DATABASE_HOST = 127.0.0.1
DATABASE_PORT = 3306

# For better performance this should be performed directly by the MTA
query_validate_recipient_enabled = False

[NOTIFY]
SMTP_HOST = localhost
SMTP_PORT = 25
SMTP_TIMEOUT = 20

SMTP_AUTH = False
SMTP_USERNAME =
SMTP_PASSWORD =

SMTP_STARTTLS = False

# The null sender ("<>") is *strongly* recommended to avoid loops and other bad stuff!
SMTP_ENVELOPE_FROM = <>

# Set a realname to use in the "From" header.
MESSAGE_HEADER_FROM_NAME = Autoresponder
MESSAGE_HEADER_FROM_ADDRESS = [email protected]

# 多耐才 sent 多次 auto response, Default 7 天
REQUIRED_TIMEDELTA = 604800

MESSAGE_CHARSET = UTF-8

# Insert special headers to prevent other systems responding to our autoresponses?
MESSAGE_INSERT_SPECIAL_HEADERS = True

MESSAGE_HEADER_SUBJECT_PREFIX = [AutoResponse]

[CLEANUP]
# Delete last hit 耐過幾時的 reponse record, Default 7 天 (response-cleanup --delete-old-response-records 用到)
DELETE_RECORDS_WITH_LAST_HIT_BEFORE = 604800

 

# Start it:

Debian7:

cp -a examples/debian-initscript /etc/init.d/response-lmtpd

chmod 755 /etc/init.d/response-lmtpd

/etc/init.d/response-lmtpd start

Centos6:

/root/scripts/response.sh

#!/bin/bash

DAEMON_ARGS="--syslog --syslog-facility=MAIL"
PID_FILE="/var/run/response/lmtpd.pid"
RESPONSE="/opt/response/response-lmtpd"
USER="response"

if [ -e $PID_FILE ];then
        echo "Kill Old lmtpd"
        kill -9 `cat $PID_FILE` &> /dev/null
        rm -f $PID_FILE
fi

echo "Start New One"
if [ "`whoami`" = "root" ]
then
        echo "switch to user: $USER"
        sudo -u $USER $RESPONSE $DAEMON_ARGS &> /dev/null
else
        $RESPONSE $DAEMON_ARGS &> /dev/null
fi

# check pid
sleep 2
echo "PID: `cat $PID_FILE`"

Set permission

chmod 770 /etc/scripts/response.sh

chmod g=rx /etc/scripts/response.sh

Start

/root/scripts/response.sh

output:

Kill Old lmtpd
Start New One
PID:  10785

Auto Run

/etc/rc.local

# for e-mail auto reply
/root/scripts/response.sh > /dev/null 2>&1

Remark

在舊版 Centos 上要 hardcode 用 python6

vi /opt/response/response-lmtpd

#!/usr/bin/env python26

Testing

Log:

/var/log/maillog

Dec 27 13:27:13 mail response[22829]: response-lmtpd version 0.8 starting up... (loglevel: WARNING)
Dec 27 13:27:13 mail response[22831]: Daemon PID=22831

# 當一切沒有問題就可拿走 "/etc/init.d/response-lmtpd" 內的 –debug

DAEMON_ARGS="--debug --syslog --syslog-facility=MAIL"

telnet test:

telnet localhost 10027

220 server_hostname 0.8

 


Cron jobs

 

cd /opt/response

cp -a examples/crontab /etc/cron.d/response

/etc/cron.d/response 的內容

PATH=/opt/response:/usr/bin

# 每 5 min auto reply 一次, 每次只 reply 10 個人
*/5  *      *   *   *   response    response-notify --debug --syslog -L 10 &> /dev/null

0,30 *      *   *   *   response    response-cleanup --debug --syslog --disable-expired-configs &> /dev/null
12   1      *   *   *   response    response-cleanup --debug --syslog --delete-old-response-records &> /dev/null
12   2      *   *   *   response    response-cleanup --debug --syslog --delete-unused-response-records &> /dev/null

chmod 644 response

Jul 17 12:17:01 mail crond[29649]: (root) BAD FILE MODE (/etc/cron.d/response)

/etc/init.d/crond reload

Testing

log:

sudo -u response /opt/response/response-notify --debug

Dec 17 13:21:33 mail response[11581] (response-notify:113) [WARNING]: response-notify version 0.8 starting up... (loglevel: DEBUG)
Dec 17 13:21:33 mail response.pidfile[11581] (pidfile.py:67) [DEBUG]: Writing pidfile /var/run/response/notify.pid with pid 11581
Dec 17 13:21:33 mail response[11581] (response-notify:128) [WARNING]: Running with PID=11581
Dec 17 13:21:33 mail response[11581] (response-notify:139) [WARNING]: Initializing...
Dec 17 13:21:33 mail response[11581] (response-notify:140) [WARNING]: Upper limit of generated response mails: 100
Dec 17 13:21:33 mail response[11581] (response-notify:143) [WARNING]: Connecting to backend...
Dec 17 13:21:33 mail response.backend[11581] (backend.py:136) [INFO]: MySQL: Asking pool for a connection
Dec 17 13:21:33 mail response.backend[11581] (backend.py:136) [DEBUG]: MySQL: Successfully aquired connection from pool
Dec 17 13:21:33 mail response.backend[11581] (backend.py:136) [DEBUG]: MySQL: Opening cursor for connection
Dec 17 13:21:33 mail response[11581] (response-notify:163) [INFO]: Not creating any successive autoresponse for ...
Dec 17 13:21:33 mail response.backend[11581] (backend.py:136) [DEBUG]: MySQL: Executing query: SELECT `record`.`id` AS `id` ...
Dec 17 13:21:33 mail response[11581] (response-notify:167) [WARNING]: No pending responses found.
Dec 17 13:21:33 mail response[11581] (response-notify:323) [WARNING]: Doing a graceful shutdown...
Dec 17 13:21:33 mail response[11581] (response-notify:326) [INFO]: Closing SMTP connection
Dec 17 13:21:33 mail response.backend[11581] (backend.py:136) [DEBUG]: MySQL: Closing cursor for connection
Dec 17 13:21:33 mail response.backend[11581] (backend.py:136) [INFO]: MySQL: Releasing connection
Dec 17 13:21:33 mail response.backend[11581] (backend.py:136) [INFO]: MySQL: Disposing connection pool...
Dec 17 13:21:33 mail response[11581] (response-notify:340) [DEBUG]: Cleaning up...
Dec 17 13:21:33 mail response.pidfile[11581] (pidfile.py:77) [DEBUG]: Deleting pidfile /var/run/response/notify.pid
Dec 17 13:21:33 mail response[11581] (response-notify:343) [WARNING]: Quit.

Opts:

–debug                                                           # 當一切沒有問題就不用加

-L LIMIT, --limit-response-mails=LIMIT               # never create more than this amount of response mails, default: 10

Cron Log

Message from syslogd@mail at Dec 27 16:01:02 ...
 ?<20>response[23434] (response-notify:222) [WARNING]: [1] [email protected] -> <[email protected]> (record id: 1)

Troubleshoot

Dec 17 18:43:53 mail crond[25547]: (root) BAD FILE MODE (/etc/cron.d/response)

 


Postfix configuration

 

/etc/postfix/master.cf

response  unix  -       -       n       -       4       lmtp
    -o disable_dns_lookups=yes

/etc/postfix/transport_map_response

response.internal               response:[127.0.0.1]:10027

postmap /etc/postfix/transport_map_response

/etc/postfix/recipient_bcc_map_response.cf

cd  /etc/postfix

touch  recipient_bcc_map_response.cf

chmod  640 recipient_bcc_map_response.cf

chown  root.postfix  recipient_bcc_map_response.cf

內容:

hosts = 127.0.0.1
user = response
password = FIXME
dbname = response

query = SELECT '%u#%[email protected]'
        FROM `autoresponse_config`
        WHERE `address` = '%s'
        AND `enabled` = 1

/etc/postfix/main.cf

# concurrency per domain --> concurrency per recipient
response_destination_recipient_limit = 1

# Register our internal only response domain for the transport
transport_maps =  hash:/etc/postfix/transport_map_response ........


proxy_read_maps = .............
 $recipient_bcc_maps
 .............

# for auto reponse
recipient_bcc_maps = proxy:mysql:/etc/postfix/recipient_bcc_map_response.cf

最後 reload Postfix

postfix reload

 


Usage

 

TABLE `autoresponse_config`

`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`address` varchar(255) NOT NULL UNIQUE,                              <--- [email protected] (它是在 alias table 前的 !!)
`enabled` bool NOT NULL,
`changed` datetime NOT NULL,
`expires` datetime NOT NULL,                                                 <--- DATETIME 'YYYY-MM-DD HH:MM:SS'
`subject` varchar(255) NOT NULL,
`message` longtext NOT NULL                                                <--- 比對方的內容

TABLE `autoresponse_record`

`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`sender_id` integer NOT NULL,
`recipient` varchar(255) NOT NULL,
`hit` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',           <-- 最後一次收 sender(recipient) 的信的時間
`sent` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',         <-- 何時 auto reply 了
UNIQUE (`sender_id`, `recipient`)

 


roundcubemail Plugin

 

Tested Package:

  • rc-vacation-master.zip
  • roundcubemail-1.0.3.tar.gz

Download:

https://github.com/bhuisgen/rc-vacation

unzip rc-vacation-master.zip

mv rc-vacation-master vacation

DB:

GRANT SELECT , INSERT , DELETE ON  `response` . * TO  'responserc'@'localhost';

SQL:

// database DSN
$rcmail_config['vacation_sql_dsn'] =
        'mysql://user:password@localhost/postfix';

// read data queries
$rcmail_config['vacation_sql_read'] =
        array("SELECT subject AS vacation_subject, message AS vacation_message, " .
                  "enabled AS vacation_enable FROM response.autoresponse_config " .
              "WHERE address=%username;"
             );

// write data queries
$rcmail_config['vacation_sql_write'] =
        array(
        "DELETE FROM response.autoresponse_record WHERE sender_id IN (SELECT id FROM response.autoresponse_config WHERE 
         address=%email);",
        "DELETE FROM response.autoresponse_config WHERE address=%email;",
        "INSERT INTO response.autoresponse_config (address,subject,message,changed,expires,enabled) VALUES 
        (%email,%vacation_subject,%vacation_message,NOW(),ADDDATE( NOW( ) , 31 ),%vacation_enable);"
);

roundcube

config/main.inc.php

$rcmail_config['plugins'] = array('vacation');

P.S.

/usr/share/roundcubemail/plugins/vacation Folder 的 PHP 一定要叫 vacation.php

%username           <-- 成個 login name (由於 login name 是成個 domain, 所以用它亦可)

%email_domain      <-- email_domain

 


watchdog

 

By monit

/etc/monit.d/response.conf

check process response-lmtpd with pidfile /var/run/response/lmtpd.pid
    start program = "/etc/scripts/response.sh" as uid "response" and gid "response" with timeout 60 seconds
    stop program  = "/bin/sh -c 'kill -9 `cat /var/run/response/lmtpd.pid`'"
    if failed port 10027 then restart
    if 2 restarts within 3 cycles then alert

By hourly cron job

response_watchdog.sh

#!/bin/bash
#
# Function: restart response & notify admin when it fail
#

pidfile="/var/run/response/lmtpd.pid"
prog="/root/scripts/response.sh"
admin="[email protected]"

function mail2admin {
        echo "Send mail to admin"
        echo `date` | mail -s "auto response fail" $admin
}

function checkpid {
  if [ -f $pidfile ]; then
      pid=`cat $pidfile`
      kill -0 $pid &> /dev/null
      if [ $? != 0 ]; then
        echo "program crash, start new one"
        rm $pidfile
        bash $prog
        mail2admin
      else
        echo "porgram working fine"
    fi
  else
        echo "without pid file, start new one"
        bash $prog
        mail2admin
  fi
  sleep 1
}

checkpid

 


DOC

在 examples Folder 內

  • crontab  
  • DATABASE.mysql  
  • debian-initscript  
  • POSTFIX.conf

 

Creative Commons license icon Creative Commons license icon