Benutzer-Werkzeuge

Action disabled: source

autoresponder mit postfix

Für dovecot-sieve gibt es mit vacation ein Plugin, welches Abwesenheitsmeldungen erstellt und verschickt. „Leider“ ist vacation so geschrieben, dass maximal einmal pro Tag eine Mail pro Sender rausgeht. Will man also z.B. für eine info-Adresse jede Mail mit einer Meldung bestätigen, geht dies mit vacation nicht ohne den Quelltext zu verändern.

Zum Glück gibt es eine sehr einfache Möglichkeit einen autoresponder direkt am Postfix-Server einzurichten. Dazu muss man Anpassungen in zwei Konfigfiles machen und ein Script haben, welches das Beantworten übernimmt

Konfiguration

virtual

In der Datei virtual legt man pro Adresse, die autoresponder haben sollen, einen Eintrag in der folgenden Form an

postmaster@domain.tld user@domain.tld,user@domain.tld@autoreply.domain.tld

Mails für postmaster@domain.tld werden hierbei an den user@domain.tld geschickt. Zusätzlich geht die Mail an die zweite Adresse, welche den autoresponder von postfix verarbeitet.
autoreply.domain.tld darf keinesfalls unter mydestination oder virtual_mailbox_domains in der main.cf aufgeführt sein!

Danach die Datei mittels postmap für postfix lesbar machen

postmap /path/to/virtual

transport

In der Datei transport wird auf Basis der Domain der Empfangsadresse der „Lieferweg“ festgelegt. Hier drin legen wir einen Eintrag für die autoreply-Adresse an und weisen diesem einen Postfix-Handler zu (auch diese Datei muss mittels postmap kovertiert werden)

autoreply.domain.tld autoreply:

Wenn also eine Mail an die autoreply-Domain geschickt wird, dann wird der Postfix-Handler autoreply aufgerufen. Diesen müssen wir erst noch defnieren.

master.cf

In master.cf werden die „Dienste“ von Postfix definiert und konfiguriert. Hier müssen wir für autoreply einen Handler erstellen. Dieser kann so ausschauen

autoreply	unix	-	n	n	-	-	pipe
 flags= user=nobody argv=/opt/etc/postfix/autoreply ${sender} ${mailbox}

ma Wenn also autoreply aufgerufen wird, dann „piped“ Postfix die Mail an das angegebene Script. Neben dem Inhalt der Mail via stdin übergibt Postfix 2 Parameter an das Script. Damit das Script weiss von wem die Mail ist und wohin die Meldung geschickt werden soll.

main.cf

Jetzt muss man nur noch in main.cf virtual resp transport aktivieren

transport_maps = hash:/path/to/transport
virtual_alias_maps = hash:/path/to/virtual

Danach ein

postfix stop
postfix start

autoresponder Script

Hier kommt das unter autoreply festgelegt Script. Es handelt sich hierbei um ein einfaches Shellscript, welches den Inhalt der Mail (inkl aller Mailheader) via stdin übergeben bekommt. Zusätzlich erwartet das Script den Sender und den Originalempfänger der E-Mail als Parameter.

Das Script prüft ob die Mail von einer Mailingliste kommt oder sonstige Bedingungen nicht erfüllt. In diesen Fällen wird keine Mail versendet. Bei den Bedingungen habe ich mich bei vacation orientiert

  • Auto-Submitted: header exists with any value except „no“
  • Precedence: header exists with value „junk“, „bulk“ or „list“
  • The envelope sender
    • begins with „MAILER-DAEMON“ (case-insensitive)
    • begins with „LISTSERV“ (case-insensitive)
    • begins with „majordomo“ (case-insensitive)
    • begins with „owner-“ (case-sensitive)
    • contains the string „-request“ anywhere within it (case-sensitive)
  • The envelope sender and envelope recipient are the same
  • The envelope recipient is not found in the message To:, Cc: or Bcc: fields.
  • The envelope sender is not found in From-Header

Code

autoreply

Der aktuellste Code kann hier im Trac gefunden werden

#!/bin/bash
 
######################################################################
#                                                                    #
# autoreply script for integration into postfix server process       #
#                                                                    #
# Author:     tobi <tobster@brain-force.ch>                          #
# Version:    0.3.1 rc                                               #
# Date:       05/09/11                                               #
# License:    GPL Version 3 (contact author prior to commercial use) #
# Depends:    bash (get it via ipkg)                                 #
#             egrep (should be in ipkg coreutils or similar)         #
#                                                                    #
# Important:  You probably need to adjust chmod on the log file.     #
#             This script SHOULD NEVER run as root and therefore the #
#             logfile needs to be created manually by root. The user #
#             running autoreply need write access on that logfile.   #
#                                                                    #
#             Check all paths in the script as the default paths are #
#             for a debian. Change them to your enviroment!          #
#                                                                    #
#             create autoreply.txt and autoreply.html manually.      #
#             these files expect the content as valid (ex correct    #
#             mime headers and transfer-encodings) mime parts        #
#             see enclosed example files to see the structure        #
#                                                                    #
#             this script uses bash specific stuff so it wont run    #
#             on other shells without adjustment to the code.        #
#             especially the methods for string replacement are      #
#             bash specific                                          #
#                                                                    #
# History:    * 04/08/10 initial version 0.1 as beta                 #
#             * 06/08/10 minor bug fixes                             #
#             * 10/08/10 support for template files added            #
#             * 11/08/10 version 0.2 as stable                       #
#             * 05/09/11 minor changes. trim.php no longer needed    #
#             * 05/09/11 original msg as rfc attachment              #
#             * 05/09/11 version 0.3 as beta                         #
#             * 06/09/11 bug in rfc attachment fixed                 #
#             * 29/11/11 minor code optimations                      #
#             * 29/11/11 variables substitution for templates        #
#             * 29/11/11 version 0.3 as stable                       #
#             * 29/11/11 additional checks implemented               #
#             * 30/11/11 msg ID read from maillog                    #
#             * 30/11/11 version 0.3.1 as rc (should be stable)      #
#                                                                    #
# ToDo:       * support for txt and html templates (added in 0.2)    #
#             * original message as rfc822 compatible attachment     #
#               (added in 0.3)                                       #
#             * implement an exclude list (added in 0.3.1 rc)        #
#                                                                    #
# Summary:    A small autoreply script that sends messages on every  #
#             mail received ex if you use a info address and want to #
#             confirm every message that is sent there.              #
#             Some tests are performed before sending the mail:      #
#                                                                    #
#              * is the mail coming from a mailing list?             #
#              * are there typical headers for bulk messages?        #
#              * can the rcpt address been found in msg headers?     #
#                                                                    #
# Usage:      echo msg | autreply sender reciever                    #
# * sender:   sender of the original msg. The one who will receive   #
#             the autoreply                                          #
# * receiver: the receiver of the original msg. Will be used as      #
#             sender of the autoreply message                        #
# * stdin:    on stdin the content of the original msg is expected   #
#                                                                    #
######################################################################
 
# config variables
 
# logpath MUST be writable for the user running autoreply (check master.cf where the user can be specified)
# the script tries to create the file but depending from the specified position it will be impossible
# for the script to create it.
# The easiest way is to manually create the file and chmod it so the user running autoreply has write privileges on the file
LOG=/var/log/autoreply.log
 
# exclude list for autoreply. must be valid syntax for <egrep>
# if the sender of the mail or the receiver of the autoreply match expression then NO autoreply will be sent
EXCLUDE=brain-force.ch\|hunde-gassi.ch\|tobisworld.homeip.net
 
# path to sendmail program
# for diskstation users /usr/syno/mailstation/sbin/sendmail
MAIL=/usr/sbin/sendmail
 
# installation path of the script itself and its template files
# note: the trailing slash is VERY important!!
I_PATH=/etc/postfix/autoreply/
 
touch $LOG > /dev/null 2>&1
[[ $? -ne 0 || ! -w $LOG ]] && echo "$LOG could not be statet. Check path and permissions" && exit 1
 
case "$2" in
 'webmaster@MY_DOMAIN')
  NAME='Me the webmaster'
  COMPANY='MY COMPANY'
 ;;
 'autoreply-test@brain-force.ch')
  NAME='James Bond aka 007'
  COMPANY='MI6 Royalkillers Branch'
  ADDRESS='Swansey Road 110'
  TOWN='Not known'
  COUNTRY='Scotland'
 ;;
esac
 
while read x1
do
 MSG="$MSG\n$x1"
done
 
sendReply ()
{
 STR="From: $2 <$2>\n"
 STR=$STR"To: <"$1">\n"
 STR=$STR"Content-Type: multipart/mixed; boundary=\"grenze\"\n"
 STR=$STR"Subject: Ihre Anfrage an / Your request to "$2"\n\n"
 STR=$STR"--grenze\n"
 STR=$STR"Content-Type: multipart/alternative; boundary=\"alternative\"\n"
 eval "TEMPLATE=\"$(cat ${I_PATH}autoreply.txt)\""
 STR=$STR"\n--alternative\n"
 STR=$STR$TEMPLATE
 STR=$STR"\n\n--alternative\n"
 eval "TEMPLATE=\"$(cat ${I_PATH}autoreply.html)\""
 STR=$STR$TEMPLATE
 [[ ! "x$NAME" = 'x' && ! "x$COMPANY" = 'x' ]] && STR="${STR//'VAR_name '/$NAME}" && STR="${STR//VAR_company/ - $COMPANY}"
 [[ "x$NAME" = 'x' || "x$COMPANY" = 'x' ]] && STR="${STR//'VAR_name '/$NAME}" && STR="${STR//VAR_company/$COMPANY}"
 [[ "x$NAME" = 'x' && "x$COMPANY" = 'x' ]] && STR="${STR//'VAR_name '/$NAME}" && STR="${STR//'VAR_company'/$COMPANY}"
 [[ ! "x$ADDRESS" = 'x' && ! "x$TOWN" = 'x' ]] && STR="${STR//'VAR_address '/$ADDRESS}" && STR="${STR//VAR_town/, $TOWN}"
 [[ "x$ADDRESS" = 'x' ||  "x$TOWN" = 'x' ]] && STR="${STR//'VAR_address '/$ADDRESS}" && STR="${STR//VAR_town/$TOWN}"
 [[ "x$ADDRESS" = 'x' && "x$TOWN" = 'x' ]] && STR="${STR//'VAR_address '/$ADDRESS}" && STR="${STR//'VAR_town'/$TOWN}"
 STR="${STR//'VAR_country'/$COUNTRY}"
 STR=$STR"\n\n--alternative--\n\n--grenze\n"
 STR=$STR"Content-Type: message/rfc822\nContent-Disposition: attachment;filename=message.eml;\nContent-Transfer-Encoding: 7bit\n\n$MSG\n\n--grenze--"
 echo -e "$STR" | $MAIL -f "$2" -t "$1"
 if [ $? -eq 0 ] ; then
  SHOW=$(cat /var/log/mail.log | grep '<'$1'>' | awk '{print $6}' | awk -F: '{print $1}')
  OUT=$(echo $SHOW | awk '{print $NF}')
  IN=$(echo $SHOW | awk '{print $(NF-1)}')
  echo -e $(date +"%b %_d %T")" autoreply success: msg to $1 ("$OUT") in response to mail to $2 ("$IN") sent" >> $LOG  && exit 0
 fi
 echo -e $(date +"%b %_d %T")" autoreply error: msg to $1 in response to mail to $2 could NOT  be sent." >> $LOG && exit 1
}
[ ! "x$(echo -e $1 | egrep $EXCLUDE)" = 'x' ] && echo -e $(date +"%b %_d %T")" autoreply dunno: domain in exclude list found in sender-envelope sender=$1 rcpt=$2" >> $LOG 2>&1 && exit 1
[ ! "x$(echo -e $MSG | grep ^From: | egrep $EXCLUDE)" = 'x' ] && echo -e $(date +"%b %_d %T")" autoreply dunno: domain in exclude list found in From-header sender=$1 rcpt=$2" >> $LOG 2>&1 && exit 1
[ "$1" = "$2" ] && echo -e $(date +"%b %_d %T")" autoreply dunno: sender and receiver are the same sender=$1 rcpt=$2" >> $LOG && exit 1
[ "x$(echo -e $MSG | grep -i ^From: | grep $1)" = 'x' ] && echo -e $(date +"%b %_d %T")" autoreply dunno: envelop sender not found in From-header sender=$1 rcpt=$2" >> $LOG && exit 1
[ ! "x$(echo -e $MSG | grep -i ^Auto-Submitted: | grep -iv no)" = 'x' ] && echo -e $(date +"%b %_d %T")" autoreply dunno: msg has auto-submitted headers with a value other than \"no\" sender=$1 rcpt=$2" >> $LOG && exit 1
[ ! "x$(echo -e $MSG | grep -i ^Precedence: | grep -i junk)" = 'x' ] && echo -e $(date +"%b %_d %T")" autoreply dunno: msg has precedence \"junk\" header sender=$1 rcpt=$2" >> $LOG && exit 1
[ ! "x$(echo -e $MSG | grep -i ^Precedence: | grep -i bulk)" = 'x' ] &&  echo -e $(date +"%b %_d %T")" autorepy dunno: msg has precedence header \"bulk\" sender=$1 rcpt=$2" >> $LOG && exit 1
[ ! "x$(echo -e $MSG | grep -i ^Precedence: | grep -i list)" = 'x' ] && echo -e $(date +"%b %_d %T")" autoreply dunno: msg has precedence header with \"list\"sender=$1 rcpt=$2" >> $LOG && exit 1
[ ! "x$(echo $1 | egrep -i mailer-daemon\|listserv\|majordomo\|owner-\|\-request)" = 'x' ] &&  echo -e $(date +"%b %_d %T")" autoreply dunno: msg seems to be from a mailing list sender=$1 rcpt=$2" >> $LOG && exit 1
[ ! "x$(echo -e $MSG | grep -i ^To: | grep $2)" = 'x' ] &&  sendReply $1 $2 "$MSG"
[ ! "x$(echo -e $MSG | grep -i ^Cc: | grep $2)" = 'x' ] &&  sendReply $1 $2 "$MSG"
[ ! "x$(echo -e $MSG | grep -i ^Bcc: | grep $2)" = 'x' ] &&  sendReply $1 $2 "$MSG"
echo -e $(date +"%b %_d %T")" autoreply dunno: rcpt not found in headers (To, Cc or Bcc) sender=$1 rcpt=$2" >> $LOG && exit 1

autoreply.txt

Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Besten Dank fuer Ihre Anfrage
 Ihre Anfrage wird so schnell wie moeglich beantwortet

Thanks for your request,
 it will be answered asap

Gruss / Regards

VAR_name VAR_company
VAR_address VAR_town
VAR_country
$2

Anbei der Inhalt ihrer Anfrage / Following the content of your request

autoreply.html

Content-Type: text/html
Content-Transfer-Encoding: 7bit
 
<p>
Besten Dank f&uuml;r Ihre Anfrage, <br />
&nbsp;Ihre Anfrage ist angekommen und wird schnellstm&ouml;glich beantwortet
</p>
<p>
Thanks for your request,<br />
&nbsp;Your request has been received and will be answered asap
</p>
 
<p>Gruss / Regards<br /><br />
VAR_name VAR_company<br />
VAR_address VAR_town<br />
VAR_country<br />
<a href=\"mailto:"$2"\">"$2"</a><br /><br />Anbei der Inhalt ihrer Anfrage / Following the content of your request</p>
Melden Sie sich an, um einen Kommentar zu erstellen.

Seiten-Werkzeuge