der-merlin
New Member
Hallo,
ich habe mir ein Script gebastelt, das eine Benachrichtuigung an den Absender generiert, wenn die Mail an den entfernten Absender nach mehreren Stunden nicht versandt wurde. Das läuft auch zufriedenstellend per stündlichen Cronjob und ich hab das hier unten angefügt.
Ich möchte nun auch die Fehlerursache mit angeben und habe ein Problem mit dem ich nicht weiter komme und auch Google hat mich mehr verwirrt als geholfen, deshalb, mit Bitte um "Input":
Bei der Auswertung des Log qmail/send habe ich die richtigen Meldungen zur Mail extrahiert. Ich bekomme pro "offener" Mail in der
"starting-Schleife" die entfernte Mailadresse und die Tasknummer ausgelesen und in der "delivery-Schleife" die Tasknummer und die Server-Fehlermeldung
Ich komme nun nicht weiter, wie ich mit Listen-Arrays/Hash (ohne SQL, nur perl) das so aufbauen kann, dass ich bei starting:
den Mailempfänger und dazu den Task ablege
und dann bei delivery:
anhand des Task die Fehlermeldung dem Empfänger zuordne
(Die Werte habe ich in Variablen, aber wohin damit
Problem dabei ist:
Da Qmail mehrfach versucht die Mails zu senden, habe ich mehrere Task für einen Empfänger (mit immer der gleichen Fehlermeldung)
UND
Wenn mehrere Empfänger angegeben sind, muss ich das für mehrere Adressen zuordnen.
Die Ausgabe soll dann so in eine Variable erfolgen, dass jeder Mailempfänger mit einer (der letzen) Fehlermeldung 1 mal angezeigt wird.
...
Hier erstmal das "fast-fertige" (funktionierende) Script
ich habe mir ein Script gebastelt, das eine Benachrichtuigung an den Absender generiert, wenn die Mail an den entfernten Absender nach mehreren Stunden nicht versandt wurde. Das läuft auch zufriedenstellend per stündlichen Cronjob und ich hab das hier unten angefügt.
Ich möchte nun auch die Fehlerursache mit angeben und habe ein Problem mit dem ich nicht weiter komme und auch Google hat mich mehr verwirrt als geholfen, deshalb, mit Bitte um "Input":
Bei der Auswertung des Log qmail/send habe ich die richtigen Meldungen zur Mail extrahiert. Ich bekomme pro "offener" Mail in der
"starting-Schleife" die entfernte Mailadresse und die Tasknummer ausgelesen und in der "delivery-Schleife" die Tasknummer und die Server-Fehlermeldung
Code:
starting delivery 7665: msg 2326553 to remote sumsi@t-onlie.de
delivery 7665: deferral: Sorry,_I_wasn't_able_to_establish_an_SMTP_connection._(#4.4.1)/
...
starting delivery 7669: msg 2326553 to remote sumsi@t-onlie.de
delivery 7669: deferral: Sorry,_I_wasn't_able_to_establish_an_SMTP_connection._(#4.4.1)/
Ich komme nun nicht weiter, wie ich mit Listen-Arrays/Hash (ohne SQL, nur perl) das so aufbauen kann, dass ich bei starting:
den Mailempfänger und dazu den Task ablege
und dann bei delivery:
anhand des Task die Fehlermeldung dem Empfänger zuordne
(Die Werte habe ich in Variablen, aber wohin damit
Problem dabei ist:
Da Qmail mehrfach versucht die Mails zu senden, habe ich mehrere Task für einen Empfänger (mit immer der gleichen Fehlermeldung)
UND
Wenn mehrere Empfänger angegeben sind, muss ich das für mehrere Adressen zuordnen.
Code:
( aus der $mtext{$rmsg} )
starting delivery 7436: msg 2326550 to remote test@t-onlie.de
starting delivery 7437: msg 2326550 to remote test2@t-onlie.de
starting delivery 7438: msg 2326550 to remote test@onlie.de
delivery 7438: failure: 83.243.43.224_does_not_like_recipient./Remote_host_said:_554_5.7.1_<test@onlie.de>:_Relay_access_denied/Giving_up_on_83.243.43.224./
delivery 7436: deferral: Sorry,_I_wasn't_able_to_establish_an_SMTP_connection._(#4.4.1)/
delivery 7437: deferral: Sorry,_I_wasn't_able_to_establish_an_SMTP_connection._(#4.4.1)/
Die Ausgabe soll dann so in eine Variable erfolgen, dass jeder Mailempfänger mit einer (der letzen) Fehlermeldung 1 mal angezeigt wird.
...
Hier erstmal das "fast-fertige" (funktionierende) Script
Code:
#!/usr/bin/perl
#
# catch remote adress and mail from qmail-queue for info to sender
# works with qmail and netqmail
# use crontab to start it
#
# Jürgen Augustinat 11/2008 "ja at regionalnetz de"
# thanks to Michele Beltrame "mb at italpro net" for qmHandle
#
# Install:
# copy the script to path, set premission 4755
# edit cronfile e.g.: 55 * * * * /path/queuemail2
# have fun
#
# you can use it for test only, if you change the T0: in "Print Mail..." at the end of the script
use strict;
use warnings;
use diagnostics;
my $version = '2.20'; # can run in cronjob every hour, write delaytime to mail
# ... start userconfig ...
my ($queue) = '/var/qmail/queue/';
my $lastfile = '/var/run/queuetime';
# set mailprogram
my $Sendmail_Prog = "/usr/sbin/sendmail";
# your service-mailadress
my $mailfrom = 'service@yourdomain.tld';
# please set delay hours (h*60min*60sec) 4-12-24-48-72
# last can set greater as queuelifetime :-)
my $delhr1 = 4;
my $delhr2 = 12;
my $delhr3 = 24;
my $delhr4 = 48;
my $delhr5 = 72;
# ... end userconfig ...
my $summary = 0;
my @array = ();
my $lastrun = 0;
my $mytime = time();
## START build lastfile !could uncomment after the first go-off !
if (-e $lastfile){}
else{
open(LAST, ">$lastfile") || die "error write lastrun\n";
print LAST $mytime-3600;
close (LAST);
}
## END
my $deltime1 = $delhr1*3600;
my $deltime2 = $delhr2*3600;
my $deltime3 = $delhr3*3600;
my $deltime4 = $delhr4*3600;
my $deltime5 = $delhr5*3600;
# read lifetime
my $day = 0;
my $lifetime = '/var/qmail/control/queuelifetime';
if (-e $lifetime){
open(DAYS, $lifetime);
$day = <DAYS>/86400;
close(DAYS);
}
else{
$day = 7;
}
# lastrun = read file and write time!
open(LAST, $lastfile) || die "error read lastrun\n";
$lastrun = <LAST>;
close (LAST);
open(LAST, ">$lastfile") || die "error write lastrun\n";
print LAST $mytime;
close (LAST);
# START #
# Create a message list for remote queues
my (@msglist) = ();
my (%delhr) = ();
foreach my $currentqueue ("remote") {
opendir(DIR,"${queue}$currentqueue");
my (@dirlist) = grep !/\./, readdir DIR;
closedir DIR;
foreach my $dir (@dirlist) {
opendir (SUBDIR,"${queue}${currentqueue}/$dir");
my (@files) = grep !/\./, map "$dir/$_", readdir SUBDIR;
foreach my $file (@files) {
my $Datei = "${queue}${currentqueue}/$file";
my $letsgo = '';
my @info = stat($Datei);
my $expiry = $info[9];
# set the notify delay
my $expiry1 = $expiry+$deltime1;
my $expiry2 = $expiry+$deltime2;
my $expiry3 = $expiry+$deltime3;
my $expiry4 = $expiry+$deltime4;
my $expiry5 = $expiry+$deltime5;
if ($expiry1 > $mytime) {
next;
}
if ($expiry1 > $lastrun && $expiry1 <= $mytime) {
push @msglist, "$file";
$delhr{"$file"} = $delhr1;
next;
}
if ($expiry2 > $lastrun && $expiry2 <= $mytime) {
push @msglist, "$file";
$delhr{"$file"} = $delhr2;
next;
}
if ($expiry3 > $lastrun && $expiry3 <= $mytime) {
push @msglist, "$file";
$delhr{"$file"} = $delhr3;
next;
}
if ($expiry4 > $lastrun && $expiry4 <= $mytime ) {
push @msglist, "$file";
$delhr{"$file"} = $delhr4;
next;
}
if ($expiry5 > $lastrun && $expiry5 <= $mytime ) {
push @msglist, "$file";
$delhr{"$file"} = $delhr5;
next;
}
}
closedir SUBDIR;
}
}
# read for remote message list
my ($q) = shift;
my (%ret, %date, %from, %subj, %to, %allto);
if ($summary == 0) {
foreach my $msg(@msglist) {
# Read return path
open (MSG, "${queue}info/$msg");
$ret{$msg} = <MSG>;
substr($ret{$msg}, 0, 1) = '';
chop ($ret{$msg});
close (MSG);
# Read all remote (D=Done,T=Todo)
open (MSG, "${queue}remote/$msg");
$allto{$msg} = <MSG>;
chop ($allto{$msg});
close (MSG);
# Read something from message header (sender, receiver, subject, date)
open (MSG, "${queue}mess/$msg");
while (<MSG>) {
if ($_ =~ /^Date: /) {
$date{$msg} = $';
chop ($date{$msg});
}
elsif ( $_ =~ /^From: /) {
$from{$msg} = $';
chop ($from{$msg});
}
elsif ( $_ =~ /^Subject: /) {
$subj{$msg} = $';
chop ($subj{$msg});
}
elsif ( $_ =~ /^To: /) {
$to{$msg} = $';
chop ($to{$msg});
}
elsif ( $_ eq "\n") {
last;
}
}
close (MSG);
}
}
# lets go to send the mails
{
# first read the todo recipients only
foreach my $msg(@msglist) {
my $Stop = 0;
my @Reci = ();
my $to = "";
my $todo = "";
my ($dir, $rmsg) = split (/\//, $msg);
if ($summary == 0) {
@array=split(/\0/,$allto{$msg});
foreach (@array){
$todo = $_ ;
if ($todo =~ /^T/) {
substr($todo, 0, 1) = '';
push (@Reci,"$todo\n");
}
}
# use $Stop because no $ret im mail from postmaster/mailer, use for no info e.g. .local
$Stop = index ($ret{$msg},"@");
#if ($from{$msg}=~ /\.local/){
# $Stop= 0;
# }
if ($Stop > 0){
$to=$from{$msg};
if ($from{$msg}=~ /.*<(.*)>/){
$to=$1;
}
open(MAIL,"|$Sendmail_Prog -t") || print STDERR "Mailprogramm error, not started \n";
print MAIL "From: $mailfrom\n";
print MAIL "To: $to\n"; # use "To: $mailfrom\n"; for test only
print MAIL "Subject: eMail $subj{$msg} \n\n";
## in german:
print MAIL "Die Mail von $ret{$msg}\n"; # set to RETURNPATH for info the sender e.g. if from wwwrun
print MAIL "gesendet am $date{$msg}, mit dem \n";
print MAIL "Betreff: $subj{$msg} \n";
print MAIL "konnte seit über $delhr{$msg} Stunden nicht an folgende Empfänger zugestellt werden: \n\n";
print MAIL "@Reci \n" ;
print MAIL "Diese Infomail erhalten Sie max. $day Tage lang!\n";
print MAIL "Mehr Infos unter http://seite_auf_server.tld/xyz.html !\n";
## english version follows:
# print MAIL "The mail from $ret{$msg} sending on $date{$msg} with the \n";
# print MAIL "Subject: $subj{$msg} \n";
# print MAIL "could not carried forward since $delhr{$msg} hours to the recipient: \n\n";
# print MAIL "@Reci \n\n" ;
# print MAIL "We will send this info $day days long\n";
# print MAIL "For more informations visit http://whatyouthink.yourdomain.com/xyz.html \n";
##
close(MAIL);
}
}
}
}
Last edited by a moderator: