initial commit of file from CVS for smeserver-unjunkmgr on Sat Sep 7 21:11:06 AEST 2024
This commit is contained in:
396
root/usr/local/unjunkmgr/spamreminder.pl
Executable file
396
root/usr/local/unjunkmgr/spamreminder.pl
Executable file
@@ -0,0 +1,396 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
#############################################################################
|
||||
#
|
||||
# This script provides weekly overview of email stored in the junkmail
|
||||
# folder and allows for unjunking. When an email is being unjunked the
|
||||
# baysian filter in SpamAssassin is trained as ham.
|
||||
#
|
||||
# This script has been developed
|
||||
# by Jesper Knudsen at http://sme.swerts-knudsen.dk
|
||||
#
|
||||
# Revision History:
|
||||
#
|
||||
# August 24, 2008: Initial version
|
||||
#############################################################################
|
||||
|
||||
# internal modules (part of core perl distribution)
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
use POSIX qw/strftime floor/;
|
||||
use Time::Local;
|
||||
use Date::Manip;
|
||||
use strict;
|
||||
use MIME::Lite;
|
||||
|
||||
use esmith::db;
|
||||
use esmith::ConfigDB;
|
||||
use esmith::AccountsDB;
|
||||
|
||||
#############################################################################
|
||||
# Configuration
|
||||
#############################################################################
|
||||
|
||||
# The address which will be copied on the weekly summary emails (default: none)
|
||||
my $admin_email_addr = '';
|
||||
|
||||
my $domain_name = esmith::ConfigDB->open()->get('DomainName')->value;
|
||||
my $unjunkhost = $domain_name;
|
||||
my $enabled;
|
||||
my $useremails = 'yes';
|
||||
|
||||
my $db = esmith::ConfigDB->open()
|
||||
|| die "Unable to open configuration dbase.";
|
||||
my %db_conf = $db->get('unjunkmgr')->props;
|
||||
|
||||
while ( my ( $parameter, $value ) = each(%db_conf) ) {
|
||||
if ( $parameter eq 'enabled' ) {
|
||||
$enabled = $value;
|
||||
}
|
||||
if ( $parameter eq 'adminemails' and uc($value) eq 'YES' ) {
|
||||
$admin_email_addr = 'admin';
|
||||
}
|
||||
if ( $parameter eq 'unjunkhost' ) {
|
||||
$unjunkhost = $value;
|
||||
}
|
||||
if ( $parameter eq 'useremails' ) {
|
||||
$useremails = $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# The address from which the weekly summary comes from
|
||||
my $spamfilter_addr = 'Admin Junk Summary <UnJunkManager>';
|
||||
|
||||
# Which stylesheet to use for the summary email
|
||||
my $css_file = '/usr/local/unjunkmgr/unjunkmgr.css';
|
||||
|
||||
# Debug enabled? - will send all reports to $admin_email_addr
|
||||
my $debug = 0;
|
||||
#############################################################################
|
||||
|
||||
# Parameters for the Junkmail Summary functionality
|
||||
|
||||
my $root_url = sprintf( "https://%s/unjunkmgr", $unjunkhost );
|
||||
|
||||
my $path = "/home/e-smith/files/users/";
|
||||
|
||||
my $end_path_cur = "/Maildir/.junkmail/cur";
|
||||
my $end_path_new = "/Maildir/.junkmail/new";
|
||||
|
||||
my $sa_dbase = '/home/e-smith/db/configuration';
|
||||
my $dbh = esmith::ConfigDB->open($sa_dbase)
|
||||
|| die "Unable to open spamassassin configuration dbase.";
|
||||
my %sa_conf = $dbh->get('spamassassin')->props;
|
||||
|
||||
my $disabled = 0;
|
||||
my $days_to_keep = 5;
|
||||
my $spam_mark = 7;
|
||||
my $spam_discard = 10;
|
||||
|
||||
my $parameter = "";
|
||||
my $value = "";
|
||||
while ( ( $parameter, $value ) = each(%sa_conf) ) {
|
||||
if ( $parameter eq 'status' and not $value eq 'enabled' ) {
|
||||
$disabled = 1;
|
||||
}
|
||||
if ( $parameter eq 'MessageRetentionTime' ) {
|
||||
$days_to_keep = $value;
|
||||
}
|
||||
if ( $parameter eq 'TagLevel' ) {
|
||||
$spam_mark = $value;
|
||||
}
|
||||
if ( $parameter eq 'RejectLevel' ) {
|
||||
$spam_discard = $value;
|
||||
}
|
||||
}
|
||||
|
||||
#printf("Enabled = %s\n",$disabled);
|
||||
#printf("Retention = %s\n",$days_to_keep);
|
||||
#printf("TagLevel = %s\n",$spam_mark);
|
||||
#printf("RejectLevel = %s\n",$spam_discard);
|
||||
|
||||
if ( uc($useremails) eq 'YES' or lc($admin_email_addr) eq 'admin' ) {
|
||||
Junkmail_Reminder();
|
||||
}
|
||||
|
||||
#All done
|
||||
exit 0;
|
||||
|
||||
#############################################################################
|
||||
# Subroutines ###############################################################
|
||||
#############################################################################
|
||||
|
||||
########################################
|
||||
# Process parms #
|
||||
########################################
|
||||
sub parse_arg {
|
||||
my $startdate = shift;
|
||||
my $enddate = shift;
|
||||
my $secsinday = 86400;
|
||||
my $time = 0;
|
||||
my $start = UnixDate( $startdate, "%s" );
|
||||
my $end = UnixDate( $enddate, "%s" );
|
||||
|
||||
if ( !$start && !$end ) {
|
||||
$end = time;
|
||||
$start = $end - $secsinday;
|
||||
return ( $start, $end );
|
||||
}
|
||||
|
||||
if ( !$start ) {
|
||||
$start = $end - $secsinday;
|
||||
return ( $start, $end );
|
||||
}
|
||||
|
||||
if ( !$end ) {
|
||||
$end = $start + $secsinday;
|
||||
return ( $start, $end );
|
||||
}
|
||||
|
||||
if ( $start > $end ) {
|
||||
return ( $end, $start );
|
||||
}
|
||||
|
||||
return ( $start, $end );
|
||||
|
||||
}
|
||||
|
||||
sub get_email_details {
|
||||
my $entry = shift;
|
||||
my $score;
|
||||
my $spam;
|
||||
my $spamlimit;
|
||||
my $spam_string = 'Unknown';
|
||||
my $subject = 'Unknown';
|
||||
my $from = 'Unknown';
|
||||
my $to = 'Unknown';
|
||||
|
||||
open( ORIGINAL, "$entry" ); #OPEN FILE FOR READING
|
||||
my @original = <ORIGINAL>; #READ FILE INTO AN ARRAY
|
||||
|
||||
#PROCESS THE ARRAY
|
||||
|
||||
foreach my $x (@original) {
|
||||
if ( $x =~ m/^Subject:/ ) {
|
||||
($subject) = $x =~ m/^Subject: (.*)$/;
|
||||
if ( not defined($subject) ) {
|
||||
$subject = 'Unknown';
|
||||
}
|
||||
else {
|
||||
$subject =~ s/^[ \t]//g;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $x =~ m/^To:/ ) {
|
||||
($to)
|
||||
= $x
|
||||
=~ m/([a-zA-Z0-9._\%\+\-]+\@[a-zA-Z0-9\.\-]+\.[a-zA-Z]{2,4})/;
|
||||
if ( not defined($to) ) {
|
||||
$to = 'Unknown';
|
||||
}
|
||||
}
|
||||
if ( $x =~ m/^From:/ ) {
|
||||
($from)
|
||||
= $x
|
||||
=~ m/([a-zA-Z0-9._\%\+\-]+\@[a-zA-Z0-9\.\-]+\.[a-zA-Z]{2,4})/;
|
||||
if ( not defined($from) ) {
|
||||
$from = 'Unknown';
|
||||
}
|
||||
}
|
||||
|
||||
if ( $x =~ m/^X-Spam-Status:/ ) {
|
||||
( $spam, $score, $spamlimit )
|
||||
= $x
|
||||
=~ m/^X-Spam-Status: ([^\,]+)\, hits=([^\ ]+)\ required=(.*)/;
|
||||
if ( defined($spamlimit) ) {
|
||||
if ( $spam eq 'Yes'
|
||||
and $score > $spamlimit
|
||||
and $score < $spam_discard )
|
||||
{
|
||||
$spam_string = sprintf( "Likely Spam (%s)", $score );
|
||||
}
|
||||
else {
|
||||
$spam_string = sprintf( "Spam (%s)", $score );
|
||||
}
|
||||
}
|
||||
else {
|
||||
$spam_string = 'Unknown';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
close(ORIGINAL);
|
||||
|
||||
return ( $subject, $from, $to, $spam_string );
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# The function serializes a complex datastructure into a safe and compact
|
||||
# single line string.
|
||||
################################################################################
|
||||
|
||||
sub serialize_cmd {
|
||||
my $cmd = shift;
|
||||
|
||||
my $out = $cmd;
|
||||
|
||||
# replace all newlines, CR and % with CGI-style encoded sequences
|
||||
$out =~ s/([\;%\r\n])/sprintf("%%%02X", ord($1))/ge;
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
sub Junkmail_Reminder {
|
||||
|
||||
my $found;
|
||||
my $entry;
|
||||
my $subject;
|
||||
my $to;
|
||||
my $from;
|
||||
my $real_name;
|
||||
my $name;
|
||||
my $to_email;
|
||||
my $score;
|
||||
my $spamlist;
|
||||
my $spamcount = 0;
|
||||
|
||||
my ( $oneweekago, $noew ) = parse_arg( "last week", "" );
|
||||
|
||||
my $adb = esmith::AccountsDB->open_ro()
|
||||
|| die "Couldnt' open AccountsDB\n";
|
||||
my @accounts;
|
||||
push @accounts, $adb->users;
|
||||
|
||||
foreach my $account (@accounts) {
|
||||
|
||||
$name = $account->key;
|
||||
$spamcount = 0;
|
||||
$spamlist = undef;
|
||||
$found = 0;
|
||||
|
||||
$real_name = sprintf( "%s %s",
|
||||
$account->prop('FirstName'),
|
||||
$account->prop('LastName') );
|
||||
if ( $debug == 1 ) {
|
||||
printf( "User : %s (%s)\n", $real_name, $name );
|
||||
}
|
||||
|
||||
my @junkmail_dirs;
|
||||
push @junkmail_dirs, "$path$name$end_path_new";
|
||||
push @junkmail_dirs, "$path$name$end_path_cur";
|
||||
|
||||
foreach my $junkmail_dir (@junkmail_dirs) {
|
||||
|
||||
# Now get the content list for the directory.
|
||||
opendir( QDIR, "$junkmail_dir" )
|
||||
or die "Couldn't read directory $junkmail_dir";
|
||||
|
||||
my @sorted_dates = map $_->[1], sort { $b->[0] <=> $a->[0] }
|
||||
map -f "$junkmail_dir/$_" ? [ ( stat _ )[9], $_ ] : (),
|
||||
readdir(QDIR);
|
||||
closedir(QDIR);
|
||||
|
||||
foreach $entry (@sorted_dates) {
|
||||
next if $entry =~ /^\./;
|
||||
$entry = $junkmail_dir . '/' . $entry;
|
||||
my $modifytime = ( stat($entry) )[9];
|
||||
|
||||
# Now only report new emails..
|
||||
if ( -f $entry and ( $modifytime > $oneweekago ) ) {
|
||||
$found++;
|
||||
( $subject, $from, $to, $score )
|
||||
= get_email_details($entry);
|
||||
|
||||
# printf("Found Spam email: %s with score %s (%s)",$from, $score,$spamcount);
|
||||
$spamlist->[$spamcount]{'user'} = $name;
|
||||
$spamlist->[$spamcount]{'realname'} = $real_name;
|
||||
$spamlist->[$spamcount]{'file'} = $entry;
|
||||
$spamlist->[$spamcount]{'subject'} = $subject;
|
||||
$spamlist->[$spamcount]{'from'} = $from;
|
||||
$spamlist->[$spamcount]{'to'} = $to;
|
||||
$spamlist->[ $spamcount++ ]{'score'} = $score;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $spamcount > 0 and not $disabled ) {
|
||||
|
||||
my $email_msg;
|
||||
|
||||
$email_msg .= "<HTML><HEAD><TITLE>UnJunk Manager</TITLE>";
|
||||
|
||||
if ( open( CSS, "$css_file" ) ) {
|
||||
my @css = <CSS>;
|
||||
$email_msg .= "<style type=\"text/css\">";
|
||||
foreach my $cssline (@css) {
|
||||
$email_msg .= $cssline;
|
||||
}
|
||||
$email_msg .= "</style>";
|
||||
}
|
||||
|
||||
$email_msg .= "</HEAD>";
|
||||
$email_msg
|
||||
.= sprintf "<H1>Junk Emails Blocked for %s: %s</H1><br>",
|
||||
$real_name, $spamcount;
|
||||
$email_msg .= sprintf
|
||||
"The emails listed below have been placed in your personal Junk Box since your last Junk Box Summary and will be<br>";
|
||||
$email_msg .= sprintf
|
||||
"deleted after $days_to_keep days. To receive any of these messages, click UnJunk and the message will be delivered to your inbox.<br>";
|
||||
$email_msg
|
||||
.= sprintf "<table border=\"1\" width=\"900\"><tr>";
|
||||
$email_msg .= sprintf
|
||||
'<td width="600" align="left" valign="top" bgcolor="#C0C0C0" colspan=4>';
|
||||
$email_msg
|
||||
.= sprintf
|
||||
"<b><font face=\"Verdana\"><H2>Emails sent to %s</H2></font></b></td></tr>",
|
||||
$real_name;
|
||||
$email_msg .= sprintf
|
||||
"<td bgcolor=\"#C0C0C0\"><font size=\"2\">Action</td><td bgcolor=\"#C0C0C0\"><font size=\"2\">From</td><td bgcolor=\"#C0C0C0\"><font size=\"2\">Subject</td><td bgcolor=\"#C0C0C0\"><font size=\"2\">Threat</td></tr>";
|
||||
|
||||
foreach my $email ( @{$spamlist} ) {
|
||||
my $spamchanger = $root_url . '/spamchanger.pl';
|
||||
my $url
|
||||
= sprintf "%s?user=%s&email=%s&subject=%s&from=%s",
|
||||
$spamchanger, $email->{'user'}, $email->{'file'},
|
||||
$email->{'subject'}, $email->{'from'};
|
||||
$email_msg
|
||||
.= sprintf
|
||||
"<td><font size=\"2\"><a href=\"%s\">UnJunk</a></td>",
|
||||
serialize_cmd($url);
|
||||
$email_msg
|
||||
.= sprintf
|
||||
"<td><font size=\"2\">%-40.40s</td><td><font size=\"2\">%-50.50s</td><td><font size=\"2\">%s</td></tr>",
|
||||
$email->{'from'}, $email->{'subject'},
|
||||
$email->{'score'};
|
||||
}
|
||||
|
||||
$email_msg .= sprintf "</table>";
|
||||
|
||||
# create a new MIME Lite based email
|
||||
my $msg = MIME::Lite->new(
|
||||
Subject =>
|
||||
sprintf(
|
||||
"Summary of junk emails blocked - %s Junk Emails Blocked",
|
||||
$spamcount ),
|
||||
From => $spamfilter_addr,
|
||||
To => uc($useremails) eq 'YES'
|
||||
? $name
|
||||
: $admin_email_addr,
|
||||
|
||||
# To => $debug == 1 ? $admin_email_addr : $name,
|
||||
# No cc email if debug..
|
||||
# Cc => $admin_email_addr eq 'admin' ? $admin_email_addr : '',
|
||||
Cc => (
|
||||
$admin_email_addr eq 'admin'
|
||||
and uc($useremails) eq 'YES'
|
||||
) ? $admin_email_addr : '',
|
||||
Type => 'text/html',
|
||||
Data => $email_msg
|
||||
);
|
||||
|
||||
$msg->send();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user