X-Git-Url: http://git.rot13.org/?p=BackupPC.git;a=blobdiff_plain;f=bin%2FBackupPC_sendEmail;h=c20c6ccfcfbb65db3ab5842f084a726d5d82c6ce;hp=2a7184c0154648e496bb9071d70caf61ea4ef3dc;hb=c615e1bfc6f2b0604a2658996f5dd6b6cfa9469c;hpb=e9453b7611be63303572ae443d5fb56b73364678 diff --git a/bin/BackupPC_sendEmail b/bin/BackupPC_sendEmail index 2a7184c..c20c6cc 100755 --- a/bin/BackupPC_sendEmail +++ b/bin/BackupPC_sendEmail @@ -1,4 +1,4 @@ -#!/bin/perl -T +#!/usr/bin/perl #============================================================= -*-perl-*- # # BackupPC_sendEmail: send status emails to users and admins @@ -13,7 +13,7 @@ # Craig Barratt # # COPYRIGHT -# Copyright (C) 2001 Craig Barratt +# Copyright (C) 2001-2009 Craig Barratt # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -31,147 +31,190 @@ # #======================================================================== # -# Version 1.6.0_CVS, released 10 Dec 2002. +# Version 3.2.0, released 31 Jul 2010. # # See http://backuppc.sourceforge.net. # #======================================================================== use strict; +no utf8; use lib "/usr/local/BackupPC/lib"; use BackupPC::Lib; use BackupPC::FileZIO; +use Encode; use Data::Dumper; use Getopt::Std; use DirHandle (); +use vars qw($Lang $TopDir $BinDir $LogDir %Conf $Hosts); die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) ); -my $TopDir = $bpc->TopDir(); -my $BinDir = $bpc->BinDir(); -my %Conf = $bpc->Conf(); +$TopDir = $bpc->TopDir(); +$LogDir = $bpc->LogDir(); +$BinDir = $bpc->BinDir(); +%Conf = $bpc->Conf(); +$Lang = $bpc->Lang(); +$Hosts = $bpc->HostInfoRead(); $bpc->ChildInit(); use vars qw(%UserEmailInfo); -do "$TopDir/log/UserEmailInfo.pl"; +do "$LogDir/UserEmailInfo.pl"; my %opts; -getopts("t", \%opts); -if ( @ARGV != 0 ) { - print("usage: $0 [-t]\n"); - exit(1); -} +if ( !getopts("ctu:", \%opts) || @ARGV != 0 ) { + print <ServerConnect($Conf{ServerHost}, $Conf{ServerPort}); -if ( $err ) { - print("Can't connect to server ($err)\n"); - exit(1); -} -my $reply = $bpc->ServerMesg("status hosts"); -$reply = $1 if ( $reply =~ /(.*)/s ); -my(%Status, %Info, %Jobs, @BgQueue, @UserQueue, @CmdQueue); -eval($reply); + -t display the emails that would be sent, without sending them -########################################################################### -# Generate sysadmin warning messages -########################################################################### -my $mesg = ""; - -my @badHosts = (); -foreach my $host ( sort(keys(%Status)) ) { - next if ( $Status{$host}{reason} ne "backup failed" - || $Status{$host}{error} =~ /^lost network connection to host/ ); - push(@badHosts, "$host ($Status{$host}{error})"); -} -if ( @badHosts ) { - my $badHosts = join("\n - ", sort(@badHosts)); - $mesg .= < 0 ) { - my $n = $Info{DUDailySkipHostCntPrev}; - my $m = $Conf{DfMaxUsagePct}; - $mesg .= <new("$TopDir/pc") or die("Can't read $TopDir/pc: $!"); -my @oldDirs = (); -my @files = $d->read; -$d->close; -foreach my $host ( @files ) { - next if ( $host eq "." || $host eq ".." || defined($Status{$host}) ); - push(@oldDirs, "$TopDir/pc/$host"); +foreach my $user ( keys(%UserEmailInfo) ) { + foreach my $host ( keys(%{$UserEmailInfo{$user}}) ) { + next if ( defined($Hosts->{$host}) ); + delete($UserEmailInfo{$user}{$host}); + } + next if ( $UserEmailInfo{$user} ); + delete($UserEmailInfo{$user}); } -if ( @oldDirs ) { - my $oldDirs = join("\n - ", sort(@oldDirs)); - $mesg .= <ServerConnect($Conf{ServerHost}, $Conf{ServerPort}); +if ( $err ) { + if ( $opts{c} && $Conf{EMailAdminUserName} ne "" ) { + my $headers = $Conf{EMailHeaders}; + $headers .= "\n" if ( $headers !~ /\n$/ ); + my $mesg = <ServerMesg("status hosts info"); +$reply = $1 if ( $reply =~ /(.*)/s ); +my(%Status, %Info, %Jobs, @BgQueue, @UserQueue, @CmdQueue); +eval($reply); -if ( $mesg ne "" && $Conf{EMailAdminUserName} ne "" ) { - $mesg = <HostInfoRead(); +my @AdminBadHosts = (); foreach my $host ( sort(keys(%Status)) ) { - next if ( $Hosts->{$host}{user} eq "" ); # # read any per-PC config settings (allowing per-PC email settings) # $bpc->ConfigRead($host); %Conf = $bpc->Conf(); my $user = $Hosts->{$host}{user}; - next if ( time - $UserEmailInfo{$user}{lastTime} - < $Conf{EMailNotifyMinDays} * 24*3600 ); + + next if ( $user eq "" ); + + # + # Accumulate host errors for the admin email below + # + if ( ($Status{$host}{reason} eq "Reason_backup_failed" + || $Status{$host}{reason} eq "Reason_restore_failed") + && $Status{$host}{error} !~ /^lost network connection to host/ + && !$Conf{BackupsDisable} + ) { + push(@AdminBadHosts, "$host ($Status{$host}{error})"); + } + + next if ( time - $UserEmailInfo{$user}{$host}{lastTime} + < $Conf{EMailNotifyMinDays} * 24*3600 + || $Conf{XferMethod} eq "archive" + || $Conf{BackupsDisable} + || $Hosts->{$host}{user} eq "" + ); my @Backups = $bpc->BackupInfoRead($host); my $numBackups = @Backups; if ( $numBackups == 0 ) { - my $subj = "BackupPC: no backups of $host have succeeded"; - sendUserEmail($user, $host, $Conf{EMailNoBackupEverMesg}, $subj, { + my $subj = defined($Conf{EMailNoBackupEverSubj}) + ? $Conf{EMailNoBackupEverSubj} + : $Lang->{EMailNoBackupEverSubj}; + my $mesg = defined($Conf{EMailNoBackupEverMesg}) + ? $Conf{EMailNoBackupEverMesg} + : $Lang->{EMailNoBackupEverMesg}; + sendUserEmail($user, $host, $mesg, $subj, { userName => user2name($user) }) if ( !defined($Jobs{$host}) ); next; @@ -182,6 +225,11 @@ foreach my $host ( sort(keys(%Status)) ) { my $numBadOutlook = 0; for ( my $i = 0 ; $i < @Backups ; $i++ ) { my $fh; + # + # ignore partials -> only fulls and incrs should be used + # in figuring out when the last good backup was + # + next if ( $Backups[$i]{type} eq "partial" ); $lastNum = $Backups[$i]{num} if ( $lastNum < $Backups[$i]{num} ); if ( $Backups[$i]{type} eq "full" ) { $lastFull = $Backups[$i]{startTime} @@ -208,8 +256,8 @@ foreach my $host ( sort(keys(%Status)) ) { while ( 1 ) { my $s = $fh->readLine(); last if ( $s eq "" ); - if ( $s =~ /^Error reading file.*\.pst : ERRDOS - ERRlock/ - || $s =~ /^Error reading file.*\.pst\. Got 0 bytes/ ) { + if ( $s =~ /^\s*Error reading file.*\.pst : (ERRDOS - ERRlock|NT_STATUS_FILE_LOCK_CONFLICT)/ + || $s =~ /^\s*Error reading file.*\.pst\. Got 0 bytes/ ) { $badOutlook = 1; last; } @@ -222,11 +270,16 @@ foreach my $host ( sort(keys(%Status)) ) { } } if ( time - $last > $Conf{EMailNotifyOldBackupDays} * 24*3600 ) { - my $subj = "BackupPC: no recent backups on $host"; + my $subj = defined($Conf{EMailNoBackupRecentSubj}) + ? $Conf{EMailNoBackupRecentSubj} + : $Lang->{EMailNoBackupRecentSubj}; + my $mesg = defined($Conf{EMailNoBackupRecentMesg}) + ? $Conf{EMailNoBackupRecentMesg} + : $Lang->{EMailNoBackupRecentMesg}; my $firstTime = sprintf("%.1f", (time - $Backups[0]{startTime}) / (24*3600)); my $days = sprintf("%.1f", (time - $last) / (24 * 3600)); - sendUserEmail($user, $host, $Conf{EMailNoBackupRecentMesg}, $subj, { + sendUserEmail($user, $host, $mesg, $subj, { firstTime => $firstTime, days => $days, userName => user2name($user), @@ -239,35 +292,118 @@ foreach my $host ( sort(keys(%Status)) ) { * 24 * 3600 ) { my($days, $howLong); if ( $lastGoodOutlook == 0 ) { - $howLong = "not been backed up successfully"; + $howLong = eval("qq{$Lang->{howLong_not_been_backed_up}}"); } else { $days = sprintf("%.1f", (time - $lastGoodOutlook) / (24*3600)); - $howLong = "not been backed up for $days days"; + $howLong = eval("qq{$Lang->{howLong_not_been_backed_up_for_days_days}}"); } - my $subj = "BackupPC: Outlook files on $host need to be backed up"; + my $subj = defined($Conf{EMailOutlookBackupSubj}) + ? $Conf{EMailOutlookBackupSubj} + : $Lang->{EMailOutlookBackupSubj}; + my $mesg = defined($Conf{EMailOutlookBackupMesg}) + ? $Conf{EMailOutlookBackupMesg} + : $Lang->{EMailOutlookBackupMesg}; my $firstTime = sprintf("%.1f", (time - $Backups[0]{startTime}) / (24*3600)); my $lastTime = sprintf("%.1f", (time - $Backups[$#Backups]{startTime}) / (24*3600)); - sendUserEmail($user, $host, $Conf{EMailOutlookBackupMesg}, $subj, { + sendUserEmail($user, $host, $mesg, $subj, { + days => $days, firstTime => $firstTime, lastTime => $lastTime, numBackups => $numBackups, userName => user2name($user), howLong => $howLong, + serverHost => $Conf{ServerHost}, }) if ( !defined($Jobs{$host}) ); } } + +########################################################################### +# Generate sysadmin warning message +########################################################################### +my $adminMesg = ""; + +if ( @AdminBadHosts ) { + my $badHosts = join("\n - ", sort(@AdminBadHosts)); + $adminMesg .= < 0 ) { + my $n = $Info{DUDailySkipHostCntPrev}; + my $m = $Conf{DfMaxUsagePct}; + $adminMesg .= <new("$TopDir/pc") or die("Can't read $TopDir/pc: $!"); +my @oldDirs = (); +my @files = $d->read; +$d->close; +foreach my $host ( @files ) { + next if ( $host =~ /^\./ || defined($Status{$host}) ); + push(@oldDirs, "$TopDir/pc/$host"); +} +if ( @oldDirs ) { + my $oldDirs = join("\n - ", sort(@oldDirs)); + $adminMesg .= <Dump( [\%UserEmailInfo], [qw(*UserEmailInfo)]); - if ( open(HOST, ">$TopDir/log/UserEmailInfo.pl") ) { + if ( open(HOST, ">", "$LogDir/UserEmailInfo.pl") ) { + binmode(HOST); print(HOST $dumpStr); close(HOST); } } +exit(0); sub user2name { @@ -281,32 +417,45 @@ sub user2name sub sendUserEmail { my($user, $host, $mesg, $subj, $vars) = @_; - $vars->{user} = $user; - $vars->{host} = $host; - $vars->{subj} = $subj; - $mesg =~ s/\$(\w+)/defined($vars->{$1}) ? $vars->{$1} : \$$1/eg; - if ( $opts{t} ) { - print("#" x 75, "\n"); - print $mesg; - } else { - SendMail($mesg); - } - $UserEmailInfo{$user}{lastTime} = time; - $UserEmailInfo{$user}{lastSubj} = $subj; - $UserEmailInfo{$user}{lastHost} = $host; + return if ( $Conf{BackupsDisable} ); + + $vars->{user} = $user; + $vars->{host} = $host; + $vars->{headers} = $Conf{EMailHeaders}; + $vars->{headers} .= "\n" if ( $vars->{headers} !~ /\n$/ ); + $vars->{domain} = $Conf{EMailUserDestDomain}; + $vars->{CgiURL} = $Conf{CgiURL}; + $subj =~ s/\$(\w+)/defined($vars->{$1}) ? $vars->{$1} : "\$$1"/eg; + $vars->{subj} = encode('MIME-Header', $subj); + $mesg =~ s/\$(\w+)/defined($vars->{$1}) ? $vars->{$1} : "\$$1"/eg; + SendMail($mesg); + $UserEmailInfo{$user}{$host}{lastTime} = time; + $UserEmailInfo{$user}{$host}{lastSubj} = $subj; } sub SendMail { my($mesg) = @_; - my($from) = $Conf{EMailFromUserName}; + my $from = $Conf{EMailFromUserName}; + my $utf8 = 1 + if ( $Conf{EMailHeaders} =~ /Content-Type:.*charset="utf-?8"/i ); local(*MAIL); + if ( $opts{t} ) { + binmode(STDOUT, ":utf8") if ( $utf8 ); + + print("#" x 75, "\n"); + print $mesg; + return; + } $from = "-f $from" if ( $from ne "" ); + print("Sending test email using $Conf{SendmailPath} -t $from\n") + if ( $opts{u} ne "" ); if ( !open(MAIL, "|$Conf{SendmailPath} -t $from") ) { printf("Can't run sendmail ($Conf{SendmailPath}): $!\n"); return; } + binmode(MAIL, ":utf8") if ( $utf8 ); print MAIL $mesg; close(MAIL); }