Shellscript für Ubuntu Postfix

Ich habe ein Shellscript geschrieben, welches per Cron einmal am Tag die Postfix-Queue checkt und falls da was hängt, eine Email schickt.
Das Script sieht so aus:

#!/bin/bash
queuelength=/usr/sbin/postqueue -p | tail -n1 | awk '{print $5}'
queuecontent=/usr/sbin/postqueue -p
queuecount=echo $queuelength | grep "[0-9]"
if ["$queuecount" == „“]; then
echo „Queue is empty“;
else
echo -e „\r\n$queuecontent“ | mail -s „$queuelength Mails in der Queue“ „[email protected]
fi

So weit so gut. Die Ausgabe sieht dann z.B. so aus:

-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
9668D131469E 642 Mon Mar 30 12:40:25 [email protected]
(host mx00.kundenserver.de[212.227.15.41] refused to talk to me: 554-kundenserver.de (mxeue006) Nemesis ESMTP Service not available 554-No SMTP service 554 invalid DNS PTR resource record, IP=85.214.18.22)
[email protected]

8317713146A7 642 Mon Mar 30 12:40:35 [email protected]
(host mx00.kundenserver.de[212.227.15.41] refused to talk to me: 554-kundenserver.de (mxeue004) Nemesis ESMTP Service not available 554-No SMTP service 554 invalid DNS PTR resource record, IP=85.214.18.22)
[email protected]

EE45D13146A4 642 Mon Mar 30 12:40:30 [email protected]
(host mx01.kundenserver.de[217.72.192.67] refused to talk to me: 554-kundenserver.de (mxeue103) Nemesis ESMTP Service not available 554-No SMTP service 554 invalid DNS PTR resource record, IP=85.214.18.22)
[email protected]

49A6A13146A6 642 Mon Mar 30 12:40:33 [email protected]
(host mx01.kundenserver.de[217.72.192.67] refused to talk to me: 554-kundenserver.de (mxeue105) Nemesis ESMTP Service not available 554-No SMTP service 554 invalid DNS PTR resource record, IP=85.214.18.22)
[email protected]

– 3 Kbytes in 4 Requests.

Auch super!
Jetzt bräuchte ich aber noch den Betreff zu den einzelnen Mails. Den Inhalt der Mails kann man ja mit postcat -q XXXXXXXX auslesen und das bringt mich an die Grenzen meiner Shellscript-Fähigkeiten. Wie kann ich nun also:

  1. Die ID’s aus dem String $queuecontent auslesen, so dass quasi ein neuer String entsteht, der z.B. so aussieht:

9668D131469E 
8317713146A7 
EE45D13146A4 
49A6A13146A6 

  1. Alle IDs aus diesem neuen String mit postcat -q abarbeiten, dort den Betreff und die ersten 200 Zeichen den Inhalts unter der bisherigen Mail ausgeben. So dass die bisherige Mail wie bisher ausgegeben wird (siehe oben) und dann aber noch darunter die Betreffzeile und die ersten 200 Zeichen dieser 4 Emails nacheinander angezeigt wird.
    Mit postcat -q sieht die Ausgabe z.B. so aus:

ENVELOPE RECORDS deferred/A/A7A8B13146C7
message_size: 1074 195 1 0 1074
message_arrival_time: Wed Apr 1 06:18:33 2015
create_time: Wed Apr 1 06:18:33 2015
named_attribute: rewrite_context=local
sender_fullname: www-data
sender: [email protected]
MESSAGE CONTENTS deferred/A/A7A8B13146C7
Received: by xxxxxx.stratoserver.net (Postfix, from userid 33)
id A7A8B13146C7; Wed, 1 Apr 2015 06:18:33 +0200 (CEST)
To: [email protected]
Subject: Freischaltung Ihrer Bewertung
X-PHP-Originating-Script: 10004:bewertung.php
From: [email protected]
X-PPP-Message-ID: <[email protected]>
X-PPP-Vhost: mail.de
Message-Id: <[email protected]>
Date: Wed, 1 Apr 2015 06:18:33 +0200 (CEST)

Hallo Marc,
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

Alles Liebe,
Dirk.
HEADER EXTRACTED deferred/A/A7A8B13146C7
original_recipient: [email protected]
recipient: [email protected]
MESSAGE FILE END deferred/A/A7A8B13146C7

Falls mir jemand dazu was schreiben kann, wäre das toll. Ich weiß, dass dies recht leicht mit awk, tail und grep zu realisieren ist, habe davon aber SEHR wenig Plan :wink:

Gruß,
Dirk.

Hallo,

mal ganz ins Unreine:

for MAILID in postqueue -p | perl -nle 'print $1 if /(^\w{12})/;'
do
echo „Mail with ID $MAILID in the queue:“
postcat -q $MAILID | tail -c 200
echo
done

Der Perl-Einzeiler holt die Message-IDs aus der Postqueue-Ausgabe und
macht dann eine Schleife über jede Mail in der Queue. Das Tail schneidet
nach den ersten 200 Zeichen ab.

Um solche Sachen zu teilen eignet sich übrigens Pastebin ganz gut, denn
dort entfällt die Formatierung, was es besser lesbar macht.

Gruß,
Steve

Oh, wow!
Danke!
Erstaunlich, wie einfach das geht - wenn man weiß wie :wink:

Kleines Problem noch: Tail macht die letzten 200 Zeichen. Natürlich könnte ich jetzt Head nehmen, aber dann kämen nur die ganzen Metas.

Hast Du noch einen Tip, wie ich den Code von Dir noch ergänzen kann, so dass folgendes Ausgegeben wird:

  • Die restliche Zeile ab "Subject: " bis zum Zeilenende (denn da steht der Betreff drin)
  • Die ersten 200 Zeichen des Emailcontents. Diese beginnen nach der Zeile „Date:“ Müsste also so etwas sein, wie: Da, wo "Date: " steht, noch zum Zeilenende springen und ab der nächsten Zeile dann die ersten 200 Zeichen ausgeben.

To: [email protected]
Subject: Freischaltung Ihrer Bewertung
X-PHP-Originating-Script: 10004:bewertung.php
From: [email protected]
X-PPP-Message-ID:
X-PPP-Vhost: xxxxxxx.de
Message-Id:
Date: Wed, 1 Apr 2015 06:18:33 +0200 (CEST)

Hallo Marc,
lkfjsl kdjflsk dlfkjsldkjf lskjdflskjdflksj ldfks d

Wäre super, wenn das iwie ginge.
Danke schonmal :smile:

Hallo,

ja, muss natürlich head statt tail heißen, ist noch zu früh…

Das Problem bei Headern ist, ist das sie in jeder Reihenfolge auftauchen können. Date kann also der letzte Header sein, muss aber nicht. Habe auf die schnelle keinen schönen Weg gefunden außer diesen.

Betreffzeile:
grep ^Subject: ${MAILID}

Ersten 10 Zeilen der Mail:
grep -A10 ‚^$‘ ${MAILID} | head -n 10

Grep liefert 10 Zeilen nach jeder leeren Zeile (Leere Zeile ist der Trenner zwischen Header und Content). Das anschließende Head liefert dann nur die ersten 10, da in Mails ja üblicherweise mehrere leere Zeilen vorkommen.

Gruß,
Steve

Zu früh… *lach*

Ja, super - das werde ich mal ausprobieren.
Stimmt - die Header sind nicht umbedingt immer in der gleichen Reihenfolge…
Danke!!!

So - dank Steve habe ich das Problem echt super lösen können. Falls es für andere interessant sein könnte - hier das komplette Script:

#!/bin/bash
queuelength=/usr/sbin/postqueue -p | tail -n1 | awk '{print $5}'
queuecontent=/usr/sbin/postqueue -p
queuecount=echo $queuelength | grep "[0-9]"
if ["$queuecount" == „“]; then
echo „Queue is empty“;
else
for MAILID in postqueue -p | perl -nle 'print $1 if /(^\w{12})/;'
do
a="$a \r\n-----------------------------------------\r\n$(echo „Mail mit ID $MAILID“)\r\n-----------------------------------------\r\n"
subj=$(postcat -q $MAILID | grep ^Subject:smile:
to=$(postcat -q $MAILID | grep ^To:smile:
from=$(postcat -q $MAILID | grep ^From:smile:
date=$(postcat -q $MAILID | grep ^Date:smile:
inhalt=$(postcat -q $MAILID | grep -A10 ‚^$‘ | head -n 20 | sed -n -e :a -e ‚1,4!{P;N;D;};N;ba‘)
b=$(postcat -q $MAILID |head -c 2000)
b=${b##**To: }
a="$a$to\r\n$from\r\n$date\r\n$subj\r\n$inhalt\r\n"
done
inhalt="\r\n$queuecontent\r\nhttps://xxx.stratoserver.net:8443/\r\nhttps://xxx.stratoserver.net:8443/admin/mail-settings/queue\r\n\r\n$a"
echo -e „$inhalt“ | mail -s „$queuelength Mails in der Queue“ „[email protected]
fi

kleiner Tipp noch
Dein Server hat keinen Reverse-DNS-Eintrag (PTR). Das gilt bei vielen Mailservern als Hinweis auf Spam(mer). Du solltest deinen Anbieter bitten, einen entsprechenden Eintrag anzulegen. Außerdem solltest du darauf achten, das sich dein Server im HELO/EHLO auch mit diesem Namen meldet.

Gruß,
Steve

Ja, Danke für den Hinweis.
Ich hatte das aber mit Absicht auf meinem Server so gesetzt, damit ich testen kann mit unzugestellten Emails in der Queue :wink:
Habe es wieder umgestellt, weil das Skript ja jetzt super funktioniert :smiley:

Liebe Grüße,
Dirk.

Einfacher wäre gewesen, über IPtables Port 25 ausgehend zu blockieren :wink:

Ah.
*räusper*
oder so…

-D

Das nächste mal über die iptables…