Abwesenheitsmeldungen mit postfix

Aus
Die druckbare Version wird nicht mehr unterstützt und kann Darstellungsfehler aufweisen. Bitte aktualisiere deine Browser-Lesezeichen und verwende stattdessen die Standard-Druckfunktion des Browsers.

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 (mehr zu vacation und dovecot-sieve)

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}

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 an 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.

autoreply

#!/bin/sh
 
######################################################################
#                                                                    #
# autoreply script for integration into postfix server process       #
#                                                                    #
# Author:     tobi <tobster@brain-force.ch>                          #
# Version:    0.2                                                    #
# Date:       11/08/10                                               #
# License:    GPL Version 3                                          #
#             Free for personal use                                  #
#             Contact the author for commercial usage                #
#                                                                    #
# 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 using orginial content and subject          #
#             * 11/08/10 version 0.2 as stable                       #
#             * 12/08/10 rfc822 type attachment of original msg      #
#                                                                    #
# ToDo:       * support for txt and html templates (added in 0.2)    #
#             * use original message and subject (added in 0.2)      #
#             * support for attachments in autoreply mail            #
#             * original msg as rfc822 attachment (added in 0.2)     #
#                                                                    #
# 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   #
#                                                                    #
######################################################################
 
if test "$1" = "-h"; then
 echo "*************************************************************"
 echo "*                                                           *"
 echo "* Usage:    autoreply sender reciever                       *"
 echo "* sender:   the original sender of the mail                 *"
 echo "* reciever: the original reciever of the mail               *"
 echo "* stdin:    on stdin the content of the mail is expected    *"
 echo "*                                                           *"
 echo "*************************************************************"
 exit
fi
 
msg=""
log=/opt/var/log/autoreply.log
err=''
touch $log
 
while read x1
do
 msg="$msg\n$x1"
done
 
sendReply ()
{
 mail=/usr/syno/mailstation/sbin/sendmail
 #text=$(echo -e "$msg" | /opt/etc/postfix/split.php)
 #subject=$(echo -e "$msg" | grep ^Subject: | cut -c9-)
 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 "t=\"$(cat /opt/etc/postfix/autoreply.txt)\""
 str=$str"\n--alternative\n"
 str=$str$t
 str=$str"\n\n--alternative\n"
 eval "t=\"$(cat /opt/etc/postfix/autoreply.html)\""
 str=$str$t"\n\n--alternative--\n\n--grenze\n"
 rfc=$(echo -e "$msg" | /opt/etc/postfix/trim.php)
 str=$str"Content-Type: message/rfc822\nContent-Disposition: attachment;filename=message.eml;\nContent-Transfer-Encoding: 7bit\n\n$rfc\n\n--grenze--"
 echo -e "$str" | $mail -f "$2" -t "$1"
 #echo -e $(date +"%b %_d %T")"\tMessage sent: $1\t$2" >> /opt/var/log/autoreply.log
 #echo -e "$str"
 exit
}
 
err=$(echo -e $msg | grep -i ^Auto-Submitted: | grep -iv "no" )
t=$?
if test $t -eq 0 ; then
 echo -e $(date +"%b %_d %T")"\tMessage has Auto-Submitted Headers with a value other than \"no\"\n$1\t$2" >> $log
 exit
fi
 
err=$(echo -e $msg | grep -i ^Precedence: | grep -i "junk")
t=$?
if test $t -eq 0 ; then
 echo -e $(date +"%b %_d %T")"\tMessages has Precedence \"junk\" header\n$1\t$2" >> $log
 exit
fi
 
err=$(echo -e $msg | grep -i ^Precedence: | grep -i "bulk")
t=$?
if test $t -eq 0 ; then
 echo -e $(date +"%b %_d %T")"\tMessages has Precedence header \"bulk\"\n$1\t$2" >> $log
 exit
fi
 
err=$(echo -e $msg | grep -i ^Precedence: | grep -i "list")
t=$?
if test $t -eq 0 ; then
 echo -e $(date +"%b %_d %T")"\tMessage has Precedence header with \"list\"\n$1\t$2" >> $log
 exit
fi
 
err=$(echo $1 | egrep -i mailer-daemon\|listserv\|majordomo\|owner-\|\-request)
t=$?
if test $t -eq 0 ; then
 echo -e $(date +"%b %_d %T")"\tMessage seems to be from a mailing list\n$1\t$2" >> $log
 #echo "$msg\n$1\n$2" > /opt/var/log/autoreply.log
 exit
fi
 
if test "$1" = "$2" ; then
 echo -e $(date +"%b %_d %T")"\tFehler: Sender und Empfaenger sind gleich\n$1\t$2" >> $log
 exit
fi
 
err=$(echo -e $msg | grep -i ^To: | grep "$2")
t=$?
if test $t -eq 0; then
 sendReply $1 $2 "$msg"
fi
 
err=$(echo -e $msg | grep -i ^Cc: | grep "$2")
t=$?
if test $t -eq 0; then
 sendReply $1 $2 "$msg"
fi
 
err=$(echo -e $msg | grep -i ^Bcc: | grep "$2")
t=$?
if test $t -eq 0; then
 sendReply $1 $2 "$msg"
fi
echo -e $(date +"%b %_d %T")"\trcpt not found in headers (To, Cc or Bcc)\n$1\t$2" >> $log

split.php

#!/usr/bin/php
<?php
$fp=fopen('php://stdin','r');
$str = array();
while($line=fgets($fp,4096)){
 $t = trim($line);
 if(!empty($t)) {
  $bool = true;
 }
 if($bool === true){ 
  $str[] = trim($line);
 }
}
echo $str[array_search('',$str)+1];
?>

trim.php

#!/usr/bin/php
<?php
$fp=fopen('php://stdin','r');
$str = '';
while($line=fgets($fp,4096)){
 $str .= $line;
}
echo trim($str);
?>