initial commit of file from CVS for smeserver-unjunkmgr on Sat Sep 7 21:11:06 AEST 2024
This commit is contained in:
parent
14a99ec4d0
commit
320f4a90e3
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*.rpm
|
||||
*.log
|
||||
*spec-20*
|
||||
*.tgz
|
21
Makefile
Normal file
21
Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
# Makefile for source rpm: smeserver-unjunkmgr
|
||||
# $Id: Makefile,v 1.1 2020/11/16 11:07:56 brianr Exp $
|
||||
NAME := smeserver-unjunkmgr
|
||||
SPECFILE = $(firstword $(wildcard *.spec))
|
||||
|
||||
define find-makefile-common
|
||||
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
|
||||
endef
|
||||
|
||||
MAKEFILE_COMMON := $(shell $(find-makefile-common))
|
||||
|
||||
ifeq ($(MAKEFILE_COMMON),)
|
||||
# attept a checkout
|
||||
define checkout-makefile-common
|
||||
test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2
|
||||
endef
|
||||
|
||||
MAKEFILE_COMMON := $(shell $(checkout-makefile-common))
|
||||
endif
|
||||
|
||||
include $(MAKEFILE_COMMON)
|
15
README.md
15
README.md
@ -1,3 +1,16 @@
|
||||
# smeserver-unjunkmgr
|
||||
# <img src="https://www.koozali.org/images/koozali/Logo/Png/Koozali_logo_2016.png" width="25%" vertical="auto" style="vertical-align:bottom"> smeserver-unjunkmgr
|
||||
|
||||
SMEServer Koozali developed git repo for smeserver-unjunkmgr smecontribs
|
||||
|
||||
## Wiki
|
||||
<br />https://wiki.koozali.org/Unjunkmgr
|
||||
<br />https://wiki.koozali.org/Sme-unjunkmgr
|
||||
|
||||
## Bugzilla
|
||||
Show list of outstanding bugs: [here](https://bugs.koozali.org/buglist.cgi?component=smeserver-unjunkmgr&product=SME%20Contribs&query_format=advanced&limit=0&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=CONFIRMED)
|
||||
|
||||
## Description
|
||||
|
||||
<br />*This description has been generated by an LLM AI system and cannot be relied on to be fully correct.*
|
||||
*Once it has been checked, then this comment will be deleted*
|
||||
<br />
|
||||
|
1
contriborbase
Normal file
1
contriborbase
Normal file
@ -0,0 +1 @@
|
||||
contribs10
|
63
createlinks
Normal file
63
createlinks
Normal file
@ -0,0 +1,63 @@
|
||||
#!/usr/bin/perl -w
|
||||
use esmith::Build::CreateLinks qw(:all);
|
||||
# our event specific for updating with yum without reboot
|
||||
$event = 'smeserver-unjunkmgr-update';
|
||||
#add here the path to your templates needed to expand
|
||||
#see the /etc/systemd/system-preset/49-koozali.preset should be present for systemd integration on all you yum update event
|
||||
|
||||
foreach my $file (qw(
|
||||
/etc/systemd/system-preset/49-koozali.preset
|
||||
/etc/httpd/conf/httpd.conf
|
||||
/etc/crontab
|
||||
))
|
||||
{
|
||||
templates2events( $file, $event );
|
||||
}
|
||||
#action needed in case we have a systemd unit
|
||||
event_link('systemd-default', $event, '10');
|
||||
event_link('systemd-reload', $event, '50');
|
||||
#action specific to this package
|
||||
#event_link('action', $event, '30');
|
||||
#services we need to restart
|
||||
safe_symlink('restart',"root/etc/e-smith/events/$event/services2adjust/httpd-e-smith");
|
||||
#and Server Manager panel link
|
||||
#panel_link('somefunction', 'manager');
|
||||
|
||||
|
||||
|
||||
use esmith::Build::CreateLinks qw(:all);
|
||||
|
||||
# Start and stop links
|
||||
|
||||
#--------------------------------------------------
|
||||
# functions for manager panel
|
||||
#--------------------------------------------------
|
||||
my $panel = "manager";
|
||||
|
||||
panel_link( "unjunkmgr", $panel );
|
||||
|
||||
# Events links
|
||||
|
||||
my $event = 'unjunkmgr-conf';
|
||||
|
||||
# Templates
|
||||
|
||||
foreach (qw(
|
||||
/etc/httpd/conf/httpd.conf
|
||||
/etc/crontab
|
||||
))
|
||||
{
|
||||
templates2events( "$_", qw(
|
||||
unjunkmgr-conf
|
||||
console-save
|
||||
bootstrap-console-save
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
# Actions
|
||||
|
||||
# Services
|
||||
safe_symlink( "sigusr1",
|
||||
"root/etc/e-smith/events/$event/services2adjust/httpd-e-smith" );
|
||||
|
@ -0,0 +1 @@
|
||||
yes
|
@ -0,0 +1 @@
|
||||
no
|
@ -0,0 +1 @@
|
||||
yes
|
@ -0,0 +1 @@
|
||||
enabled
|
@ -0,0 +1 @@
|
||||
central.swerts-knudsen.dk
|
@ -0,0 +1 @@
|
||||
1112
|
@ -0,0 +1 @@
|
||||
service
|
@ -0,0 +1 @@
|
||||
yes
|
28
root/etc/e-smith/templates/etc/crontab/unjunk
Normal file
28
root/etc/e-smith/templates/etc/crontab/unjunk
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
use esmith::ConfigDB;
|
||||
|
||||
my $dbh = esmith::ConfigDB->open()
|
||||
|| die "Unable to open configuration dbase.";
|
||||
my %sa_conf = $dbh->get('unjunkmgr')->props;
|
||||
|
||||
while ( my ( $parameter, $value ) = each(%sa_conf) ) {
|
||||
if ( $parameter eq 'enabled' ) {
|
||||
$enabled = $value;
|
||||
}
|
||||
if ( $parameter eq 'useremails' ) {
|
||||
$user_emails = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$OUT = "";
|
||||
if ( uc($enabled) eq 'YES' ) {
|
||||
$OUT .= "# Schedule the UnJunk every 5 minutes\n";
|
||||
$OUT
|
||||
.= "0-59/5 * * * * root /usr/local/unjunkmgr/spamchanger.pl -file=/tmp/unjunk.file\n";
|
||||
$OUT .= "\n";
|
||||
$OUT
|
||||
.= "# Schedule the weekly Blocked Junk Summary to arrive at 1PM Friday\n";
|
||||
$OUT .= "0 13 * * 5 root /usr/local/unjunkmgr/spamreminder.pl\n";
|
||||
}
|
||||
}
|
||||
|
33
root/etc/e-smith/templates/etc/crontab/unjunkstats
Normal file
33
root/etc/e-smith/templates/etc/crontab/unjunkstats
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
use esmith::ConfigDB;
|
||||
|
||||
my $dbh = esmith::ConfigDB->open()
|
||||
|| die "Unable to open configuration dbase.";
|
||||
my %sa_conf = $dbh->get('unjunkmgr')->props;
|
||||
|
||||
while ( my ( $parameter, $value ) = each(%sa_conf) ) {
|
||||
if ( $parameter eq 'enabled' ) {
|
||||
$enabled = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$OUT = "";
|
||||
if ( uc($enabled) eq 'YES' ) {
|
||||
|
||||
my $random_hour = 5 + int( rand(50) );
|
||||
$OUT .= "# Hourly Antivirus stats (random minute)\n";
|
||||
$OUT .= $random_hour . " * * * * root /usr/local/unjunkmgr/spamfilter-statsclient.pl viruswebstats hour\n";
|
||||
$OUT .= "# The last 24 hour Antivirus stats (random minute)\n";
|
||||
$OUT .= $random_hour . " * * * * root /usr/local/unjunkmgr/spamfilter-statsclient.pl viruswebstats day\n";
|
||||
$OUT .= "# Hourly Spam stats (random minute)\n";
|
||||
$OUT .= $random_hour . " * * * * root /usr/local/unjunkmgr/spamfilter-statsclient.pl spamwebstats hour\n";
|
||||
$OUT .= "# The last 24 hour Spam stats (random minute)\n";
|
||||
$OUT .= $random_hour . " * * * * root /usr/local/unjunkmgr/spamfilter-statsclient.pl spamwebstats day\n";
|
||||
|
||||
$OUT .= "\n";
|
||||
$OUT .= "# Now get the MRTG stats run\n";
|
||||
$OUT .= $random_hour . ' * * * * root /usr/bin/mrtg /etc/mrtg/unjunkstats.cfg >/dev/null 2>&1';
|
||||
$OUT .= "\n";
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
{
|
||||
use esmith::NetworksDB;
|
||||
use esmith::ConfigDB;
|
||||
|
||||
my $ndb = esmith::NetworksDB->open_ro();
|
||||
|
||||
$localAccess = $ndb->local_access_spec();
|
||||
$localAccess =~ s#/255\.255\.255\.255##g;
|
||||
|
||||
my $dbh = esmith::ConfigDB->open() || die "Unable to open configuration dbase.";
|
||||
my %sa_conf = $dbh->get('unjunkmgr')->props;
|
||||
|
||||
while (my ($parameter,$value) = each(%sa_conf)) {
|
||||
if ($parameter eq 'LocalOnly') {
|
||||
$local = $value;
|
||||
}
|
||||
if ($parameter eq 'enabled') {
|
||||
$enabled = $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$OUT = "";
|
||||
if (not (uc($enabled) eq 'YES')) {
|
||||
return;
|
||||
}
|
||||
$OUT .= "# This is the location of the UnJunk web interface\n";
|
||||
|
||||
$OUT .= "AddHandler cgi-script .pl\n";
|
||||
$OUT .= "Alias /unjunkmgr /usr/local/unjunkmgr\n";
|
||||
$OUT .= "<Directory /usr/local/unjunkmgr>\n";
|
||||
$OUT .= " Options +FollowSymLinks +ExecCGI\n";
|
||||
$OUT .= " AllowOverride All\n";
|
||||
$OUT .= " <FilesMatch \.php\$\>\n";
|
||||
$OUT .= " SetHandler \"proxy:unix:/var/run/php-fpm/php$version.sock|fcgi://localhost\"\n";
|
||||
$OUT .= " </FilesMatch>\n";
|
||||
|
||||
if (uc($local) eq 'YES') {
|
||||
$OUT .= " Require ip $localAccess\n";
|
||||
} else {
|
||||
$OUT .= " Require all granted\n";
|
||||
}
|
||||
|
||||
$OUT .= "</Directory>\n";
|
||||
}
|
||||
|
28
root/etc/e-smith/web/functions/unjunkmgr
Normal file
28
root/etc/e-smith/web/functions/unjunkmgr
Normal file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/perl
|
||||
#----------------------------------------------------------------------
|
||||
# heading : Administration
|
||||
# description : Unjunkmgr
|
||||
# navigation : 4000 4200
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
use strict;
|
||||
use CGI ':all';
|
||||
use CGI::Carp qw(fatalsToBrowser);
|
||||
|
||||
BEGIN {
|
||||
$ENV{'PATH'} = '/bin:/usr/bin:/sbin';
|
||||
$ENV{'SHELL'} = '/bin/bash';
|
||||
delete $ENV{'ENV'};
|
||||
}
|
||||
|
||||
my $q = new CGI;
|
||||
my $content
|
||||
= "0; url=https://" . $ENV{'HTTP_X_FORWARDED_HOST'} . "/unjunkmgr";
|
||||
$q->default_dtd('-//W3C//DTD XHTML 1.0 Transitional//EN');
|
||||
|
||||
print $q->header('text/html');
|
||||
print $q->start_html(
|
||||
-head => meta( { -http_equiv => 'refresh', -content => $content } ) );
|
||||
|
||||
print $q->end_html;
|
||||
|
40
root/etc/mrtg/unjunkstats.cfg
Normal file
40
root/etc/mrtg/unjunkstats.cfg
Normal file
@ -0,0 +1,40 @@
|
||||
workdir: /usr/local/unjunkmgr/
|
||||
|
||||
interval: 60
|
||||
#---------------------------------------------------------------
|
||||
|
||||
Target[spam]: `/usr/local/unjunkmgr/spamfilter-statsclient.pl spam hour`
|
||||
AddHead[spam]: <link rel="stylesheet" type="text/css" href="unjunkmgr.css">
|
||||
MaxBytes[spam]: 100000
|
||||
Options[spam]: gauge,nopercent,dorelpercent,nobanner,nolegend
|
||||
Title[spam]: Spam Statistics
|
||||
PageTop[spam]: <H1> Email Spam Statistics</H1>
|
||||
WithPeak[spam]: dwmy
|
||||
YLegend[spam]: messages
|
||||
ShortLegend[spam]: messages
|
||||
LegendI[spam]: Spam:
|
||||
LegendO[spam]: Scanned:
|
||||
Legend1[spam]: Spam:
|
||||
Legend2[spam]: Scanned:
|
||||
Legend3[spam]:
|
||||
Legend4[spam]:
|
||||
Legend5[spam]: Spam Percent:
|
||||
Colours[spam]: RED#FF0000,DARK GREEN#23D016,WHITE#FFFFFF,WHITE#FFFFFF,RED#FF0000
|
||||
|
||||
Target[virus]: `/usr/local/unjunkmgr/spamfilter-statsclient.pl virus hour`
|
||||
AddHead[virus]: <link rel="stylesheet" type="text/css" href="unjunkmgr.css">
|
||||
MaxBytes[virus]: 100000
|
||||
Options[virus]: gauge,nopercent,dorelpercent,nobanner,nolegend
|
||||
Title[virus]: Virus Statistics
|
||||
PageTop[virus]: <H1> Email Virus Statistics</H1>
|
||||
WithPeak[virus]: dwmy
|
||||
YLegend[virus]: messages
|
||||
ShortLegend[virus]: messages
|
||||
LegendI[virus]: Virus:
|
||||
LegendO[virus]: Scanned:
|
||||
Legend1[virus]: Virus:
|
||||
Legend2[virus]: Scanned:
|
||||
Legend3[virus]:
|
||||
Legend4[virus]:
|
||||
Legend5[virus]: Virus Percent:
|
||||
Colours[virus]: RED#FF0000,DARK GREEN#23D016,WHITE#FFFFFF,WHITE#FFFFFF,RED#FF0000
|
443
root/usr/local/unjunkmgr/index.php
Normal file
443
root/usr/local/unjunkmgr/index.php
Normal file
@ -0,0 +1,443 @@
|
||||
<?php
|
||||
include ("jpgraph/jpgraph.php");
|
||||
include ("jpgraph/jpgraph_pie.php");
|
||||
|
||||
// These are called from the HTML further down due to the way Jpgraph renders
|
||||
// Check for a type. This is not called on the first run through
|
||||
$parm1 = $_GET['type'];
|
||||
|
||||
// For tests
|
||||
// printf("TYPE=%s - %s\n",$type,$parm1);
|
||||
// So we only run these if we are called with a type. Which is what happens in the html further down.
|
||||
if ($parm1 == 'spamhour') {
|
||||
read_and_print_spam_log('/usr/local/unjunkmgr/spamfilterstats.spam.hour', 'last hour', 'graph');
|
||||
} elseif ($parm1 == 'spamday') {
|
||||
read_and_print_spam_log('/usr/local/unjunkmgr/spamfilterstats.spam.day', 'last 24 hours', 'graph');
|
||||
}
|
||||
?>
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Corporate Virus and Spam Statistics</title>
|
||||
<meta http-equiv="Refresh" content="300">
|
||||
<meta http-equiv="Pragma" content="no-cache">
|
||||
<meta http-equiv="Expires" content="Mon, 19 Aug 2002 07:47:20 GMT">
|
||||
<link rel="stylesheet" type="text/css" href="unjunkmgr.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<center>
|
||||
<table border="3" width="940">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<h1>Corporate Spam and Virus Statistics</h1><br>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<table border="0" width="920" align="center">
|
||||
<tr>
|
||||
<!-- Top row 24 hours Spam & Virus stats -->
|
||||
<td width="25%" align="center">
|
||||
<h2 style="word-spacing: 0; margin-top: 0; margin-bottom: 0" align="center">Hourly Spam Statistics over last 24 hours</h2>
|
||||
<h2 style="word-spacing: 0; margin-top: 0; margin-bottom: 0"><a href="spam.html"><img border="1" src="spam-day.png" width="450" height="121"></a></h2>
|
||||
</td>
|
||||
<td width="25%" align="center">
|
||||
<h2 style="word-spacing: 0; margin-top: 0; margin-bottom: 0" align="center">Hourly Virus Statistics over last 24 hours</h2>
|
||||
<h2 style="word-spacing: 0; margin-top: 0; margin-bottom: 0"><a href="virus.html"><img border="1" src="virus-day.png" width="450" height="121"></a></h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td colspan="2"> </td></tr>
|
||||
<tr>
|
||||
<!-- Second row last hour/24 hours Spam Pie charts-->
|
||||
<!-- this is where we call the script again to draw the Pie Charts-->
|
||||
<td align="center"><img src="index.php?type=spamhour"></td>
|
||||
<td align="center"><img src="index.php?type=spamday"></td>
|
||||
|
||||
</tr>
|
||||
<tr><td colspan=2> </td></tr>
|
||||
<!-- This does the Virus stats charts -->
|
||||
<tr>
|
||||
<td align="center">
|
||||
<?php
|
||||
read_and_print_virus_log('/usr/local/unjunkmgr/spamfilterstats.virus.hour', 'hour', 'table'); ?>
|
||||
</td>
|
||||
<td align="center">
|
||||
<?php
|
||||
read_and_print_virus_log('/usr/local/unjunkmgr/spamfilterstats.virus.day', '24 hours', 'table'); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td colspan=2> </td></tr>
|
||||
<!-- This does the Spam pie charts -->
|
||||
<tr>
|
||||
<td align="center">
|
||||
<?php //read_and_print_spam_log('/usr/local/unjunkmgr/spamfilterstats.spam.hour', 'hour', 'table');
|
||||
|
||||
?>
|
||||
</td>
|
||||
<td align="center">
|
||||
<?php //read_and_print_virus_log('/usr/local/unjunkmgr/spamfilterstats.spam.day', '24 hours', 'table');
|
||||
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td colspan=2> </td></tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<?php
|
||||
function read_and_print_virus_log($log_filename, $text, $style)
|
||||
{
|
||||
|
||||
if (!file_exists($log_filename) || !is_readable($log_filename) || !$fd = fopen($log_filename, "r")) {
|
||||
print ('<td width="10%" align="left"><H3 style="word-spacing: 0; margin-top: 2; margin-bottom: 2; margin-left: 2" colspan=2>');
|
||||
print ('Statistics database not found');
|
||||
print ('</td>');
|
||||
return;
|
||||
}
|
||||
//print ('get data virus_log');
|
||||
flock($fd, 1); // get a shared lock
|
||||
$linecount = 0;
|
||||
while (!feof($fd)) {
|
||||
$line = fgets($fd);
|
||||
if ($line) {
|
||||
|
||||
// printf("line = %s\n",$line);
|
||||
// $keys = split ("\|", $line) ;
|
||||
$keys = preg_split("/\|/", $line);
|
||||
|
||||
$list = array();
|
||||
foreach ($keys as $item) {
|
||||
// $key = split ("\=", $item);
|
||||
$key = preg_split("/\=/", $item);
|
||||
// printf("key = %s\n",$key);
|
||||
if ($key[0] == 'SCANNED') {
|
||||
$scanned = $key[1];
|
||||
}
|
||||
if ($key[0] == 'BAD') {
|
||||
$bad = $key[1];
|
||||
}
|
||||
if ($key[0] == 'NAME') {
|
||||
$name = $key[1];
|
||||
} elseif ($key[0] == 'COUNT') {
|
||||
$count = $key[1];
|
||||
$list['count'] = $count;
|
||||
} elseif ($key[0] == 'LATEST') {
|
||||
$latest = $key[1];
|
||||
$list['latest'] = $latest;
|
||||
}
|
||||
}
|
||||
|
||||
if ($name) {
|
||||
$list = array(
|
||||
'name' => $name,
|
||||
'count' => $count,
|
||||
'latest' => $latest
|
||||
);
|
||||
$print_list[$linecount++] = $list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flock($fd, 3); // release the lock
|
||||
fclose($fd);
|
||||
|
||||
// Now print out results if they exist
|
||||
if (isset($print_list)) {
|
||||
$sorted_list = msort($print_list, "count", false);
|
||||
}
|
||||
|
||||
// print_r($sorted_list);
|
||||
print ('<table border="2" align="center"width="98%">');
|
||||
// This will always be table - used to have 'oldstyle'
|
||||
if ($style == 'table') {
|
||||
print ('<tr><td width="100%" align="center" valign="top" colspan=2 bgcolor=#888888>');
|
||||
print ('<H2 style="word-spacing: 0; margin-top: 0; margin-bottom: 2; margin-left: 2">');
|
||||
|
||||
printf("Virus Threats last %s ", $text);
|
||||
print ('</td>');
|
||||
print ('<tr><td width="70%" align="left" valign="top"><H3 style="word-spacing: 0; margin-top: 0; margin-bottom: 2; margin-left: 2">');
|
||||
printf("Emails Scanned for Virus");
|
||||
print ('</td>');
|
||||
print ('<td align="right"><H3 style="word-spacing: 0; margin-top: 0; margin-bottom: 2; margin-left: 2">');
|
||||
printf("%s", number_format($scanned, 0, 0, '.'));
|
||||
print ('</td>');
|
||||
print ('</tr>');
|
||||
print ('<tr><td width="50%" align="left"><H3 style="word-spacing: 0; margin-top: 0; margin-bottom: 2; margin-left: 2">');
|
||||
printf("Infected with Virus");
|
||||
print ('</td>');
|
||||
print ('<td align="right"><H3 style="word-spacing: 0; margin-top: 0; margin-bottom: 2; margin-left: 2">');
|
||||
if ($scanned > 0) printf("%s (%.2f %%)", number_format($bad, 0, 2, '.') , number_format(($bad / $scanned) * 100, 2, '.', ''));
|
||||
print ('</td>');
|
||||
print ('</tr>');
|
||||
}
|
||||
|
||||
if (isset($sorted_list)) {
|
||||
// This will print emails if there are any
|
||||
if ($linecount > 0) {
|
||||
$linecount = 0;
|
||||
|
||||
print ('<tr><H3><td width="100%" align="left" valign="top" colspan=2 bgcolor=#888888>');
|
||||
print ('<H4 style="word-spacing: 0; margin-top: 0; margin-bottom: 2; margin-left: 2">');
|
||||
// Always table ??
|
||||
if ($style == 'table') {
|
||||
print ('Top Blocked Virus Threats');
|
||||
} else {
|
||||
printf("Top Spammed Emails last %s", $text);
|
||||
}
|
||||
print ('</td>');
|
||||
print ('</tr>');
|
||||
print ('<tr><td width="70%" align="left" bgcolor=#BBBBBB><H5 style="word-spacing: 0; margin-top: 0; margin-bottom: 2; margin-left: 2">');
|
||||
// Always table ??
|
||||
if ($style == 'table') {
|
||||
print ('Name');
|
||||
} else {
|
||||
print ('Email address');
|
||||
}
|
||||
print ('</td>');
|
||||
print ('<td align="right" bgcolor=#BBBBBB><H5 style="word-spacing: 0; margin-top: 0; margin-bottom: 2; margin-left: 2">');
|
||||
print ('Count');
|
||||
print ('</td>');
|
||||
print ('</tr>');
|
||||
|
||||
foreach ($sorted_list as $item) {
|
||||
|
||||
print ('<tr><td width="70%" align="left"><H5 style="word-spacing: 0; margin-top: 2; margin-bottom: 2; margin-left: 2">');
|
||||
printf("%s", $item['name']);
|
||||
print ('</td>');
|
||||
print ('<td align="right"><H5 style="word-spacing: 0; margin-top: 2; margin-bottom: 2; margin-left: 2">');
|
||||
printf("%s", $item['count']);
|
||||
print ('</td>');
|
||||
print ('</tr>');
|
||||
|
||||
$linecount++;
|
||||
|
||||
// Only show top 10...
|
||||
if ($linecount >= 10) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // End isset
|
||||
print ('</table>');
|
||||
return;
|
||||
}
|
||||
|
||||
function read_and_print_spam_log($log_filename, $text, $style)
|
||||
{
|
||||
|
||||
if (!file_exists($log_filename) || !is_readable($log_filename) || !$fd = fopen($log_filename, "r")) {
|
||||
print ('<td width="10%" align="left"><H3 style="word-spacing: 0; margin-top: 2; margin-bottom: 2; margin-left: 2" colspan=2>');
|
||||
print ('Statistics database not found');
|
||||
print ('</td>');
|
||||
return;
|
||||
}
|
||||
//print ('get data spam_log');
|
||||
flock($fd, 1); // get a shared lock
|
||||
$linecount = 0;
|
||||
while (!feof($fd)) {
|
||||
$line = fgets($fd);
|
||||
if ($line) {
|
||||
// printf("line = %s\n",$line);
|
||||
// $keys = split ("\|", $line) ;
|
||||
$keys = preg_split("/\|/", $line);
|
||||
$list = array();
|
||||
foreach ($keys as $item) {
|
||||
// $key = split ("\=", $item);
|
||||
$key = preg_split("/\=/", $item);
|
||||
// printf("key = %s\n",$key);
|
||||
if ($key[0] == 'SCANNED') {
|
||||
$scanned = $key[1];
|
||||
}
|
||||
if ($key[0] == 'REJECT') {
|
||||
$reject = $key[1];
|
||||
}
|
||||
if ($key[0] == 'TAGGED') {
|
||||
$tagged = $key[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flock($fd, 3); // release the lock
|
||||
fclose($fd);
|
||||
|
||||
//if ($style == 'oldstyle') {
|
||||
// print('<table border="2" align="center" width="98%">');
|
||||
//
|
||||
// print('<tr><td width="70%" align="left"><H3 style="word-spacing: 0; margin-top: 2; margin-bottom: 2; margin-left: 2">');
|
||||
// printf("Scanned for Spam");
|
||||
// print('</td>');
|
||||
// print('<td align="right"><H3 style="word-spacing: 0; margin-top: 2; margin-bottom: 2; margin-left: 2">');
|
||||
// printf("%s",number_format($scanned,0,0,'.'));
|
||||
// print('</td>');
|
||||
// print('</tr>');
|
||||
//
|
||||
// print('<tr><td width="70%" align="left" valign="top"><H3 style="word-spacing: 0; margin-top: 0; margin-bottom: 2; margin-left: 2">');
|
||||
// printf("Good");
|
||||
// print('</td>');
|
||||
// print('<td align="right"><H3 style="word-spacing: 0; margin-top: 0; margin-bottom: 2; margin-left: 2">');
|
||||
// $good_emails = $scanned-($reject+$tagged);
|
||||
// printf("%s (%.2d %%)",number_format($good_emails,0,0,'.'),($good_emails/$scanned)*100);
|
||||
// print('</td>');
|
||||
// print('</tr>');
|
||||
//
|
||||
//
|
||||
// print('<tr><td width="50%" align="left"><H3 style="word-spacing: 0; margin-top: 2; margin-bottom: 2; margin-left: 2">');
|
||||
// printf("Rejected as Spam");
|
||||
// print('<td align="right"><H3 style="word-spacing: 0; margin-top: 2; margin-bottom: 2; margin-left: 2">');
|
||||
// printf("%s (%.2d %%)",number_format($reject,0,0,'.'),($reject/$scanned)*100);
|
||||
// print('</td>');
|
||||
// print('</tr>');
|
||||
//
|
||||
// print('<tr><td width="50%" align="left"><H3 style="word-spacing: 0; margin-top: 2; margin-bottom: 2; margin-left: 2">');
|
||||
// printf("Accepted but Tagged as Spam");
|
||||
// print('<td align="right"><H3 style="word-spacing: 0; margin-top: 2; margin-bottom: 2; margin-left: 2">');
|
||||
// printf("%s (%.2d %%)",number_format($tagged,0,0,'.'),($tagged/$scanned)*100);
|
||||
// print('</td>');
|
||||
// print('</tr>');
|
||||
// print('<br>');
|
||||
// print('</table>');
|
||||
//
|
||||
//} else {
|
||||
$good_emails = $scanned - ($reject + $tagged);
|
||||
|
||||
// what if no emails went through??
|
||||
if ($scanned == 0) {
|
||||
|
||||
include "jpgraph/jpgraph_canvas.php";
|
||||
include "jpgraph/jpgraph_canvtools.php";
|
||||
|
||||
$g = new CanvasGraph(450, 260, 'auto');
|
||||
$scale = new CanvasScale($g);
|
||||
$scale->Set(0, 27, 0, 53);
|
||||
$g->SetMargin(1, 2, 1, 2);
|
||||
$g->SetColor('white');
|
||||
$g->SetMarginColor("black");
|
||||
$g->InitFrame();
|
||||
|
||||
$t = new CanvasRectangleText();
|
||||
|
||||
$t->SetFillColor('');
|
||||
$t->SetFontColor('black');
|
||||
$t->SetColor('');
|
||||
$t->SetShadow('');
|
||||
$t->SetFont(FF_ARIAL, FS_BOLD, 14);
|
||||
$t->Set('No emails scanned for spam last hour', 8, 1, 8);
|
||||
$t->Stroke($g->img, $scale);
|
||||
|
||||
$g->Stroke();
|
||||
return;
|
||||
}
|
||||
|
||||
// Some data
|
||||
$data = array(
|
||||
$good_emails,
|
||||
$tagged,
|
||||
$reject
|
||||
);
|
||||
|
||||
// A new pie graph
|
||||
$graph = new PieGraph(450, 260, 'auto');
|
||||
|
||||
// Setup title
|
||||
$graph->title->Set("Spam Statistics " . $text);
|
||||
$graph->title->SetFont(FF_ARIAL, FS_BOLD, 14);
|
||||
$graph->title->SetMargin(3); // Add a little bit more margin from the top
|
||||
$graph->footer->center->Set("Generated " . date('l jS \of F Y h:i:s A'));
|
||||
|
||||
// Create the pie plot
|
||||
$p1 = new PiePlotC($data);
|
||||
// $p1->value->SetColor("navy");
|
||||
$p1->SetCenter(0.35, 0.50);
|
||||
|
||||
$p1->SetLegends(array(
|
||||
"Good (" . number_format($good_emails, 0, 0, '.') . ")",
|
||||
"Tagged (" . number_format($tagged, 0, 0, '.') . ")",
|
||||
"Rejected (" . number_format($reject, 0, 0, '.') . ")",
|
||||
));
|
||||
|
||||
$graph->legend->Pos(0.10, 0.30);
|
||||
$graph->legend->SetLayout(LEGEND_VERT);
|
||||
|
||||
$p1->SetSliceColors(array(
|
||||
"green",
|
||||
"orange",
|
||||
"red"
|
||||
));
|
||||
|
||||
// Create the extra text box to show scanned emails number
|
||||
// $txt = new Text();
|
||||
// $txt->Set("Total scanned " . number_format($scanned,0,0,'.'));
|
||||
// $txt->ParagraphAlign('right');
|
||||
// $txt->Show();
|
||||
// $txt->SetFont(FF_VERDANA,FS_NORMAL,8);
|
||||
// $txt->Pos(0.82,0.5,'center','bottom');
|
||||
// $txt->SetBox('gray9','black','gray9',0,2);
|
||||
// $txt->SetShadow();
|
||||
// $graph->AddText($txt);
|
||||
// $p1->Explode(array(0,15,15,25,15));
|
||||
// Set size of pie
|
||||
$p1->SetSize(0.32);
|
||||
|
||||
// Label font and color setup
|
||||
$p1->value->SetFont(FF_VERDANA, FS_BOLD, 10);
|
||||
$p1->value->SetColor('black');
|
||||
|
||||
// Setup the title on the center circle
|
||||
$p1->midtitle->Set("Total of\n" . number_format($scanned, 0, 0, '.') . "\nscanned");
|
||||
$p1->midtitle->SetFont(FF_VERDANA, FS_NORMAL, 10);
|
||||
|
||||
// Set color for mid circle
|
||||
$p1->SetMidColor('yellow');
|
||||
|
||||
// Use percentage values in the legends values (This is also the default)
|
||||
$p1->SetLabelType(PIE_VALUE_PER);
|
||||
// $p1->SetLabelPos(0.8);
|
||||
// Add plot to pie graph
|
||||
$graph->Add($p1);
|
||||
|
||||
// .. and send the image on it's merry way to the browser
|
||||
$graph->Stroke();
|
||||
|
||||
//}
|
||||
return;
|
||||
}
|
||||
|
||||
function msort($array, $id = "id", $sort_ascending = true)
|
||||
{
|
||||
$temp_array = array();
|
||||
while (count($array) > 0) {
|
||||
$lowest_id = 0;
|
||||
$index = 0;
|
||||
foreach ($array as $item) {
|
||||
if (isset($item[$id])) {
|
||||
if ($array[$lowest_id][$id]) {
|
||||
if ($item[$id] < $array[$lowest_id][$id]) {
|
||||
$lowest_id = $index;
|
||||
}
|
||||
}
|
||||
}
|
||||
$index++;
|
||||
}
|
||||
$temp_array[] = $array[$lowest_id];
|
||||
$array = array_merge(array_slice($array, 0, $lowest_id) , array_slice($array, $lowest_id + 1));
|
||||
}
|
||||
if ($sort_ascending) {
|
||||
return $temp_array;
|
||||
} else {
|
||||
return array_reverse($temp_array);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
|
127
root/usr/local/unjunkmgr/spamchanger.pl
Executable file
127
root/usr/local/unjunkmgr/spamchanger.pl
Executable file
@ -0,0 +1,127 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
#############################################################################
|
||||
#
|
||||
# This script provides a weekly overview of email stored in the junkmail
|
||||
# folder and allows for unjunking. When an email is being unjunked the
|
||||
# bayesian 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
|
||||
#############################################################################
|
||||
|
||||
use Cwd "realpath";
|
||||
use File::Basename;
|
||||
use English;
|
||||
use strict;
|
||||
use CGI qw(:standard);
|
||||
use File::Copy;
|
||||
use File::Spec;
|
||||
|
||||
## If we are called as Perl Script then we are in "Move files" mode. The commandline then has the path
|
||||
## to the unjunk file in the option file=<unjunk file>
|
||||
|
||||
if ( defined param('-file') ) {
|
||||
printf( "UnJunk File = %s\n", param('-file') )
|
||||
if ( defined( param('-verbose') ) );
|
||||
|
||||
my $LogFile = param('-file');
|
||||
if ( not open( UNJUNK, "+< $LogFile" ) ) {
|
||||
exit 0;
|
||||
}
|
||||
my @logfile = <UNJUNK>;
|
||||
|
||||
# Now truncate the file...
|
||||
truncate( UNJUNK, 0 );
|
||||
close(UNJUNK);
|
||||
|
||||
foreach my $email (@logfile) {
|
||||
my ( $user, $file ) = $email =~ m/^USER:([^:]+):(.*)$/;
|
||||
if ( defined($user) and defined($email) ) {
|
||||
printf( "UnJunking file %s for user %s\n", $file, $user )
|
||||
if ( defined( param('-verbose') ) );
|
||||
|
||||
# Now Move the file to /home/e-smith/files/users/<user>/Maildir/cur
|
||||
my ( $name, $path, $suffix )
|
||||
= File::Basename::fileparse( $file, '\..*' );
|
||||
my $new_location
|
||||
= sprintf( "/home/e-smith/files/users/%s/Maildir/cur/%s%s",
|
||||
$user, $name, $suffix );
|
||||
|
||||
# If UnJunking a file lets learn as ham
|
||||
my $result = `su - root -c "/usr/bin/sa-learn --ham $file"`;
|
||||
if ( defined( param('-verbose') ) ) {
|
||||
printf( "Result of sa-learn: %s\n", $result );
|
||||
}
|
||||
|
||||
printf( "New location = %s\n", $new_location )
|
||||
if ( defined( param('-verbose') ) );
|
||||
|
||||
if ( not rename( $file, $new_location ) ) {
|
||||
printf( "Move was not successfull : %s\n", $! )
|
||||
if ( defined( param('-verbose') ) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("Incorrect UnJunk file!!\n")
|
||||
if ( defined( param('-verbose') ) );
|
||||
}
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
|
||||
####################################################################
|
||||
## If we end here we are in the web mode and should output HTML data
|
||||
####################################################################
|
||||
|
||||
print header; #<-- prints the http header using the CGI module
|
||||
my $user = param('user');
|
||||
my $from = param('from');
|
||||
my $subject = param('subject');
|
||||
my $email = param('email');
|
||||
|
||||
# Print header info
|
||||
print "<HTML><HEAD><TITLE>UnJunk Manager</TITLE>\n";
|
||||
printf
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/unjunkmgr/unjunkmgr.css\">\n";
|
||||
print "</HEAD>\n";
|
||||
|
||||
if ( not defined($user) or not defined($email) ) {
|
||||
print "<H2>Incorrect UnJunk Link</H2><br>\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my $email_msg .= sprintf "<table border=\"1\" width=\"900\"><tr>";
|
||||
$email_msg .= sprintf
|
||||
'<td width="600" align="left" valign="top" bgcolor="#C0C0C0" colspan=3>';
|
||||
$email_msg
|
||||
.= sprintf
|
||||
"<b><H2>The following email has been scheduled for UnJunk</b></H2></td></tr>",
|
||||
$user;
|
||||
|
||||
$email_msg .= sprintf
|
||||
"<td bgcolor=\"#C0C0C0\"><font size=\"2\" face=\"Verdana\">From</td><td bgcolor=\"#C0C0C0\"><font face=\"Verdana\" size=\"2\">Subject</td></tr>";
|
||||
$email_msg
|
||||
.= sprintf
|
||||
"<td><font face=\"Verdana\" size=\"2\">%-30.30s</td><td><font face=\"Verdana\" size=\"2\">%-40.40s</td></tr>",
|
||||
$from, $subject;
|
||||
$email_msg .= sprintf "</table>";
|
||||
|
||||
printf $email_msg;
|
||||
|
||||
my $LogFile = "/tmp/unjunk.file";
|
||||
|
||||
if ( not open( WRITE, ">> $LogFile" ) ) {
|
||||
printf('<H2>Unable to write to the UnJunk schedular file</b></H2>');
|
||||
}
|
||||
else {
|
||||
printf WRITE "USER:%s:%s\n", $user, $email;
|
||||
close(WRITE);
|
||||
}
|
||||
|
||||
exit 0;
|
||||
|
853
root/usr/local/unjunkmgr/spamfilter-statsclient.pl
Executable file
853
root/usr/local/unjunkmgr/spamfilter-statsclient.pl
Executable file
@ -0,0 +1,853 @@
|
||||
#!/usr/bin/perl -w
|
||||
#############################################################################
|
||||
#
|
||||
# This script provides daily SpamFilter statistics.
|
||||
#
|
||||
# Default configuration is:
|
||||
# /sbin/e-smith/db config setprop unjunkmgr statsclient enabled
|
||||
# /sbin/e-smith/db config setprop unjunkmgr statsclientport 1111
|
||||
# /sbin/e-smith/db config setprop unjunkmgr statsclienthost central.swerts-knudsen.dk
|
||||
|
||||
# This script has been developed
|
||||
# by Jesper Knudsen at http://sme.swerts-knudsen.dk
|
||||
#
|
||||
# Revision History:
|
||||
#
|
||||
# August 15, 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 Cwd "realpath";
|
||||
use File::Basename;
|
||||
use English;
|
||||
use CGI qw(:standard);
|
||||
use File::Copy;
|
||||
use File::Spec;
|
||||
use Data::Dumper;
|
||||
use IO::Socket::INET;
|
||||
use Carp;
|
||||
|
||||
use esmith::db;
|
||||
use esmith::ConfigDB;
|
||||
use esmith::AccountsDB;
|
||||
|
||||
#Behaving oddly, but seems to work...
|
||||
if ( ( $#ARGV != 1 )
|
||||
or ( $ARGV[0] !~ /spam|virus|webstats/ )
|
||||
or ( ( $ARGV[1] !~ /hour|day/ ) ) )
|
||||
{
|
||||
die "\nUsage: $0 [spam|virus|viruswebstats|spamwebstats] [hour|day]\n";
|
||||
}
|
||||
|
||||
my $type = $ARGV[0];
|
||||
my $duration = $ARGV[1];
|
||||
my $master_host_name;
|
||||
my $master_host_port;
|
||||
|
||||
# Temp. log location
|
||||
my $log_location = '/usr/local/unjunkmgr/';
|
||||
|
||||
# Initialize timezone
|
||||
my $timezone = `date +%z`;
|
||||
Date_Init("TZ=$timezone");
|
||||
|
||||
my ( $checked, $found ) = Corporate_Statistics($duration);
|
||||
|
||||
if ( not( $type eq 'viruswebstats' or $type eq 'spamwebstats' ) ) {
|
||||
printf( "%s\n%s\n\n", $found, $checked );
|
||||
}
|
||||
|
||||
exit 1;
|
||||
|
||||
########################################
|
||||
# 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 Corporate_Statistics {
|
||||
|
||||
my $duration = shift;
|
||||
|
||||
my $release_version;
|
||||
|
||||
my $enabled;
|
||||
my $statsclient;
|
||||
|
||||
my $dbh = esmith::ConfigDB->open()
|
||||
|| die "Unable to open configuration dbase.";
|
||||
my %sa_conf = $dbh->get('unjunkmgr')->props;
|
||||
|
||||
while ( my ( $parameter, $value ) = each(%sa_conf) ) {
|
||||
if ( $parameter eq 'enabled' ) {
|
||||
$enabled = $value;
|
||||
}
|
||||
if ( $parameter eq 'statsclient' ) {
|
||||
$statsclient = $value;
|
||||
}
|
||||
if ( $parameter eq 'statsclientport' ) {
|
||||
$master_host_port = $value;
|
||||
}
|
||||
if ( $parameter eq 'statsclienthost' ) {
|
||||
$master_host_name = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ( not( uc($enabled) eq 'YES' ) ) {
|
||||
return ( 0, 0 );
|
||||
}
|
||||
|
||||
%sa_conf = $dbh->get('sysconfig')->props;
|
||||
|
||||
while ( my ( $parameter, $value ) = each(%sa_conf) ) {
|
||||
if ( $parameter eq 'ReleaseVersion' ) {
|
||||
$release_version = $value;
|
||||
}
|
||||
}
|
||||
|
||||
my $SME_version;
|
||||
|
||||
# printf("SME Release Version %s\n",$release_version);
|
||||
#if ( $release_version =~ m/[78]/ ) {
|
||||
# $SME_version = 7;
|
||||
#}
|
||||
#else {
|
||||
# $SME_version = 6;
|
||||
#}
|
||||
|
||||
$SME_version = 10;
|
||||
|
||||
my $spam_reject_level;
|
||||
my $spam_tag_level;
|
||||
|
||||
# Now get the spamassassin configuration
|
||||
#if ( $SME_version == 6 ) {
|
||||
#
|
||||
# my $sa_dbase = '/home/e-smith/spamassassin_V3';
|
||||
# my $sa_dbh = esmith::ConfigDB->open($sa_dbase)
|
||||
# || die "Unable to open spamassassin configuration dbase.";
|
||||
# my %sa_conf = $sa_dbh->get('conf.global')->props;
|
||||
#
|
||||
# my $parameter = "";
|
||||
# my $value = "";
|
||||
# while ( ( $parameter, $value ) = each(%sa_conf) ) {
|
||||
# if ( $parameter eq 'required_hits' ) {
|
||||
# $spam_tag_level = $value;
|
||||
# }
|
||||
# if ( $parameter eq 'auto_delete' ) {
|
||||
# $spam_reject_level = $value;
|
||||
# }
|
||||
# if ( $parameter eq 'statsclientport' ) {
|
||||
# $master_host_port = $value;
|
||||
# }
|
||||
# if ( $parameter eq 'statsclienthost' ) {
|
||||
# $master_host_name = $value;
|
||||
# }
|
||||
# if ( $parameter eq 'statsclient' ) {
|
||||
# if ( not( $value eq 'enabled' ) ) {
|
||||
#
|
||||
# # disabled - get out of here.
|
||||
# return ( 0, 0 );
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# }
|
||||
#}
|
||||
#elsif ( $SME_version == 7 ) {
|
||||
$spam_reject_level
|
||||
= esmith::ConfigDB->open_ro->get('spamassassin')->prop('RejectLevel');
|
||||
$spam_tag_level
|
||||
= esmith::ConfigDB->open_ro->get('spamassassin')->prop('TagLevel');
|
||||
|
||||
#}
|
||||
|
||||
my $logfile;
|
||||
my $spamstring;
|
||||
my $checkstring;
|
||||
my $virusstring;
|
||||
my $virusfoundstring;
|
||||
my $spamclean;
|
||||
|
||||
# efficiency; don't rebuild the (constant) hash every loop iteration
|
||||
my %month_list = (
|
||||
'Jan' => 0,
|
||||
'Feb' => 1,
|
||||
'Mar' => 2,
|
||||
'Apr' => 3,
|
||||
'May' => 4,
|
||||
'Jun' => 5,
|
||||
'Jul' => 6,
|
||||
'Aug' => 7,
|
||||
'Sep' => 8,
|
||||
'Oct' => 9,
|
||||
'Nov' => 10,
|
||||
'Dec' => 11
|
||||
);
|
||||
|
||||
#if ( $SME_version == 7 ) {
|
||||
|
||||
# SME 7x
|
||||
$logfile = '/var/log/qpsmtpd/current';
|
||||
$spamstring = 'check_spam: Yes';
|
||||
$checkstring = 'check_spam:';
|
||||
$virusstring = 'clamscan results';
|
||||
|
||||
#}
|
||||
#else {
|
||||
# if ( $type eq 'virus' or $type eq 'viruswebstats' ) {
|
||||
# $logfile = '/var/log/amavis-ng/amavis-ng.log';
|
||||
# }
|
||||
# else {
|
||||
# $logfile = '/var/log/maillog';
|
||||
# }
|
||||
#
|
||||
# $spamstring = 'identified spam';
|
||||
# $spamclean = 'clean message';
|
||||
# $checkstring = 'spamd: result:';
|
||||
# $virusfoundstring = 'CLAMD found:';
|
||||
# $virusstring = 'Starting AMaViS';
|
||||
#}
|
||||
|
||||
my $virus_list;
|
||||
my $virus_count = 0;
|
||||
my $virus_scan_count = 0;
|
||||
|
||||
my $spam_tagged = 0;
|
||||
my $spam_rejected = 0;
|
||||
my $spam_checked = 0;
|
||||
my $spam_email_list;
|
||||
|
||||
my $YEAR = ( localtime(time) )[5]; # this is years since 1900
|
||||
my $start;
|
||||
my $end;
|
||||
|
||||
if ( $duration eq 'day' ) {
|
||||
( $start, $end ) = parse_arg( "yesterday", "" );
|
||||
}
|
||||
else {
|
||||
( $start, $end ) = parse_arg( "1 hour ago", "" );
|
||||
}
|
||||
|
||||
my $spams_found = 0;
|
||||
|
||||
# Its faster to pipe through grep for the right string....
|
||||
if ( $type eq 'spam' or $type eq 'spamwebstats' ) {
|
||||
|
||||
#if ( $SME_version == 7 ) {
|
||||
|
||||
# if (not open(LOG,"/usr/local/bin/tai64nlocal < $logfile | /bin/grep $checkstring|")) {
|
||||
if ( not open( LOG, "/usr/local/bin/tai64nlocal < $logfile |" ) ) {
|
||||
printf(
|
||||
"Error opening logfile (%s) for corporate spam reports - %s\n",
|
||||
$logfile, $! );
|
||||
return;
|
||||
}
|
||||
|
||||
#}
|
||||
#else {
|
||||
# if ( not open( LOG, "/usr/local/bin/tai64nlocal < $logfile|" ) ) {
|
||||
# printf(
|
||||
# "Error opening logfile (%s) for corporate spam reports - %s\n",
|
||||
# $logfile, $! );
|
||||
# return;
|
||||
# }
|
||||
#}
|
||||
}
|
||||
else {
|
||||
if ( not open( LOG, "/usr/local/bin/tai64nlocal < $logfile |" ) ) {
|
||||
|
||||
# if (not open(LOG,"/usr/local/bin/tai64nlocal < $logfile | /bin/grep -A 1 \'$virusstring\'|")) {
|
||||
printf(
|
||||
"Error opening logfile (%s) for corporate spam reports - %s\n",
|
||||
$logfile, $! );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
my $virusmatch = 0;
|
||||
|
||||
foreach my $line (<LOG>) {
|
||||
|
||||
$line =~ s/[ \t\n]*$//;
|
||||
|
||||
# printf("Line = %s\n",$line);
|
||||
my ( $year, $month, $day, $hour, $min, $sec, $rest );
|
||||
my ( $abstime, $abshour );
|
||||
|
||||
#if ( $SME_version == 7 ) {
|
||||
|
||||
( $year, $month, $day, $hour, $min, $sec, $rest )
|
||||
= $line
|
||||
=~ m/^([^-]+)-([^-]+)-([^ ]+) ([^:]+):([^:]+):([^.]+).(.*)/;
|
||||
|
||||
if ( not defined($year) ) {
|
||||
|
||||
# printf("Match = %s-%s-%s - %s:%s:%s\n",$year,$month,$day,$hour,$min,$sec);
|
||||
next;
|
||||
}
|
||||
|
||||
# Convert to absolute time
|
||||
$abstime = timelocal( $sec, $min, $hour, $day, $month - 1, $YEAR );
|
||||
$abshour = floor( $abstime / 3600 ); # Hours since the epoch
|
||||
|
||||
#}
|
||||
#else {
|
||||
#
|
||||
# # SME 6x format of log
|
||||
# ( $month, $day, $hour, $min, $sec, $rest )
|
||||
# = $line =~ m/^([^ ]+) ([^ ]+) ([^:]+):([^:]+):([^ ]+) (.*)/;
|
||||
# if ( not defined($month) ) {
|
||||
#
|
||||
# # printf("Match = %s-%s - %s:%s:%s\n",$month,$day,$hour,$min,$sec);
|
||||
# next;
|
||||
# }
|
||||
#
|
||||
# # Convert to absolute time
|
||||
# $abstime
|
||||
# = timelocal( $sec, $min, $hour, $day, $month_list{$month},
|
||||
# $YEAR );
|
||||
# $abshour = floor( $abstime / 3600 ); # Hours since the epoch
|
||||
#}
|
||||
|
||||
#If date specified, only process lines matching date
|
||||
next if ( $abstime < $start );
|
||||
|
||||
# We can assume that logs are chronological
|
||||
last if ( $abstime > $end );
|
||||
|
||||
if ($virusmatch) {
|
||||
my ($virusname) = $line =~ m/\]\: (.*)/;
|
||||
|
||||
# Make sure its found and not OK
|
||||
if ($virusname) {
|
||||
$virusname =~ s/[ \t\n]*$//;
|
||||
$virus_count++;
|
||||
|
||||
$virus_list->{$virusname}{'date'} = $abstime;
|
||||
$virus_list->{$virusname}{'count'}++;
|
||||
|
||||
# printf("Found Virus = \"%s\"\n",$virusname);
|
||||
}
|
||||
$virusmatch = 0;
|
||||
}
|
||||
|
||||
# Count Virus Results
|
||||
my $virusname;
|
||||
|
||||
# I am not sure about this - I thkink it can go
|
||||
#if ( $SME_version == 6 and $line =~ m/$virusfoundstring/ ) {
|
||||
#
|
||||
# # Have to get the name from next line - set flag
|
||||
# # printf("Match...\n");
|
||||
# $virusmatch = 1;
|
||||
# next;
|
||||
#}
|
||||
|
||||
if ( $line =~ m/$virusstring/ ) {
|
||||
$virus_scan_count++;
|
||||
|
||||
#if ( $SME_version == 7 ) {
|
||||
($virusname) = $line =~ m/$virusstring\: (.*)/;
|
||||
|
||||
# Make sure its found and not OK
|
||||
if ( defined($virusname) and not $virusname =~ m/: OK/ ) {
|
||||
|
||||
# Lets not count various errors from Clam...
|
||||
if ( lc($virusname) =~ m/warning/
|
||||
or lc($virusname) =~ m/error/ )
|
||||
{
|
||||
next;
|
||||
}
|
||||
|
||||
# Get rid of trailing spaces...
|
||||
$virusname =~ s/[ \t\n]*$//;
|
||||
$virus_count++;
|
||||
|
||||
$virus_list->{$virusname}{'date'} = $abstime;
|
||||
$virus_list->{$virusname}{'count'}++;
|
||||
|
||||
# printf("Found Virus = \"%s\"\n",$virusname);
|
||||
}
|
||||
|
||||
#}
|
||||
}
|
||||
|
||||
# Now count checked Spam
|
||||
if ( $line =~ m/$checkstring/ ) {
|
||||
$spam_checked++;
|
||||
}
|
||||
|
||||
# Find emails hit by spam
|
||||
if ( $line =~ m/logging::logterse plugin:/ ) {
|
||||
|
||||
# printf("Found logterse entry = %s\n",$line);
|
||||
|
||||
my @logentry = split( /\t/, $line );
|
||||
|
||||
# printf("Found entry6 = %s\n",$logentry[6]);
|
||||
# printf("Found entry7 = %s\n",$logentry[7]);
|
||||
# printf("Found entry8 = %s\n",$logentry[8]);
|
||||
|
||||
# Check if it got to SA scanning
|
||||
if ( defined( $logentry[8] ) ) {
|
||||
|
||||
# Now get email address if it was spam/rejected
|
||||
if ( $logentry[8] =~ m/^Yes/ or $logentry[6] =~ m/^90/ ) {
|
||||
my @emails = split( /,/, $logentry[4] );
|
||||
|
||||
# printf("Reject Reason = %s - %s\n",$logentry[8],$logentry[4]);
|
||||
|
||||
# Count rejected emails that didn't reach max score but was
|
||||
# rejected before queuing.
|
||||
if ( not( $logentry[8] =~ m/^Yes/ )
|
||||
and $logentry[6] =~ m/^90/ )
|
||||
{
|
||||
$spam_rejected++;
|
||||
$spams_found++;
|
||||
$spam_checked++;
|
||||
}
|
||||
|
||||
foreach my $email (@emails) {
|
||||
$email =~ s/[<>]//g;
|
||||
|
||||
# printf("Email = \"%s\"\n",$email);
|
||||
|
||||
$spam_email_list->{$email}++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
# Match identified Spam
|
||||
if ( $line =~ m/$spamstring/ ) {
|
||||
$spams_found++;
|
||||
|
||||
# printf("Line = %s\n",$line);
|
||||
my ( $score, $taglevel, $rest );
|
||||
if ( $SME_version == 6 ) {
|
||||
( $score, $taglevel, $rest )
|
||||
= $line =~ m/identified spam \(([^\/]+)\/([^\)]+)\)(.*)/;
|
||||
}
|
||||
elsif ( $SME_version == 7 ) {
|
||||
( $score, $taglevel, $rest )
|
||||
= $line =~ m/hits=([^\,]+)\, required=([^\,]+)\,(.*)/;
|
||||
}
|
||||
if ( defined($score) ) {
|
||||
|
||||
# printf("Score = %s (%s)\n",$score,$taglevel);
|
||||
if ( $score > $spam_tag_level
|
||||
and $score < $spam_reject_level )
|
||||
{
|
||||
$spam_tagged++;
|
||||
}
|
||||
elsif ( $score > $spam_reject_level ) {
|
||||
$spam_rejected++;
|
||||
}
|
||||
else {
|
||||
# this can only happen if configuration were changed in the last period - discard them..
|
||||
# printf("Configuration changed in last period - discarding item.....\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# printf ("Spam Emails found = %s out of %s emails\n",$spams_found,$spam_checks);
|
||||
close(LOG);
|
||||
|
||||
# printf(Dumper($spam_email_list));
|
||||
|
||||
if ( $type eq 'viruswebstats' ) {
|
||||
my $LogFile = sprintf( "%s/spamfilterstats.virus.%s", $log_location,
|
||||
$duration );
|
||||
if ( open( WRITE, "+> $LogFile" ) ) {
|
||||
|
||||
# printf WRITE ("START=%s|",$start);
|
||||
# printf WRITE ("END=%s|",$end);
|
||||
printf WRITE ( "SMEVERSION=%s|", $release_version );
|
||||
|
||||
printf WRITE ( "SCANNED=%s|", $virus_scan_count );
|
||||
printf WRITE ( "BAD=%s|", $virus_count );
|
||||
|
||||
foreach my $virus ( keys %{$virus_list} ) {
|
||||
|
||||
# First write virus name
|
||||
printf WRITE ( "NAME=%s|", $virus );
|
||||
printf WRITE ( "COUNT=%s|",
|
||||
$virus_list->{$virus}->{'count'} );
|
||||
printf WRITE ( "LATEST=%s|",
|
||||
$virus_list->{$virus}->{'date'} );
|
||||
printf WRITE ("\n");
|
||||
}
|
||||
close(WRITE);
|
||||
}
|
||||
|
||||
# Now send the statistics to the Statistice Server
|
||||
if ( $duration eq 'hour' and uc($statsclient) eq 'ENABLED' ) {
|
||||
ConnectAndSend( CreateStatisticsMsg('virus') );
|
||||
}
|
||||
|
||||
}
|
||||
if ( $type eq 'spamwebstats' ) {
|
||||
my $LogFile = sprintf( "%s/spamfilterstats.spam.%s", $log_location,
|
||||
$duration );
|
||||
if ( open( WRITE, "+> $LogFile" ) ) {
|
||||
|
||||
# printf WRITE ("START=%s|",$start);
|
||||
# printf WRITE ("END=%s|",$end);
|
||||
printf WRITE ( "SMEVERSION=%s|", $release_version );
|
||||
|
||||
printf WRITE ( "SCANNED=%s|", $spam_checked );
|
||||
printf WRITE ( "REJECT=%s|", $spam_rejected );
|
||||
printf WRITE ( "TAGGED=%s|", $spam_tagged );
|
||||
|
||||
foreach my $email ( keys %{$spam_email_list} ) {
|
||||
|
||||
# First write virus name
|
||||
printf WRITE ( "NAME=%s|", $email );
|
||||
printf WRITE ( "COUNT=%s|", $spam_email_list->{$email} );
|
||||
printf WRITE ("\n");
|
||||
}
|
||||
|
||||
close(WRITE);
|
||||
}
|
||||
|
||||
# Now send the statistics to the Statistice Server
|
||||
if ( $duration eq 'hour' and uc($statsclient) eq 'ENABLED' ) {
|
||||
ConnectAndSend( CreateStatisticsMsg('spam') );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( $type eq 'virus' ) {
|
||||
return ( $virus_scan_count, $virus_count );
|
||||
}
|
||||
elsif ( $type eq 'spam' ) {
|
||||
return ( $spam_checked, $spams_found );
|
||||
}
|
||||
else {
|
||||
return ( 0, 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
sub CreateStatisticsMsg {
|
||||
|
||||
my $stattype = shift;
|
||||
|
||||
# General
|
||||
my $duration = 'hour';
|
||||
my $encryption = 'NO';
|
||||
my $compression = 'NO';
|
||||
my $version = 1;
|
||||
|
||||
# Prepare Header
|
||||
my $msg
|
||||
= sprintf(
|
||||
"COMMAND=LOGGING\nTYPE=%s\nCOMPRESSION=%s\nENCRYPTION=%s\nVERSION=%s\n",
|
||||
uc($stattype), $compression, $encryption, $version );
|
||||
|
||||
$msg .= 'DATA=';
|
||||
|
||||
# printf("MSGHDR=%s\n",$msg);
|
||||
|
||||
my $LogFile = sprintf( "%s/spamfilterstats.%s.%s",
|
||||
$log_location, $stattype, $duration );
|
||||
|
||||
if ( open( LOG, "< $LogFile" ) ) {
|
||||
foreach my $line (<LOG>) {
|
||||
$msg .= $line;
|
||||
}
|
||||
close(LOG);
|
||||
}
|
||||
|
||||
# printf("MSG=%s",$msg);
|
||||
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub ConnectAndSend() {
|
||||
|
||||
my $command = shift;
|
||||
|
||||
my $return_value = undef;
|
||||
my $retry_attempts = 3;
|
||||
|
||||
my $socket
|
||||
= job_start_client( $master_host_name, $master_host_port, 120 );
|
||||
|
||||
if ( not defined($socket) ) {
|
||||
return $return_value;
|
||||
}
|
||||
|
||||
TRY_AGAIN:
|
||||
|
||||
# printf("Initiating Contact with statistics server \"%s\" (%s)\n",$master_host_name,$retry_attempts);
|
||||
|
||||
my $message = sprintf( "ACCOUNT=%s\|\n", GetMacAddress() );
|
||||
|
||||
# printf("Tx Msg = %s",$message);
|
||||
job_send_data( $socket, $message );
|
||||
|
||||
my $msg = <$socket>;
|
||||
|
||||
if ( not defined($msg) ) {
|
||||
if ( $retry_attempts-- > 0 ) {
|
||||
|
||||
# Wait a little while before trying again if system seems ill....
|
||||
sleep( int( rand(10) ) );
|
||||
|
||||
# debug(5,"Need a retry - %s retries left,",$retry_attempts);
|
||||
goto TRY_AGAIN;
|
||||
}
|
||||
else {
|
||||
job_stop_client($socket);
|
||||
|
||||
# printf("Timed out connecting to master");
|
||||
return $return_value;
|
||||
}
|
||||
}
|
||||
|
||||
my $deserialized = deserialize_cmd($msg);
|
||||
$msg = $deserialized;
|
||||
|
||||
$msg =~ s/[\r\n]*$//;
|
||||
|
||||
# printf("Rx Msg = %s\n",$msg);
|
||||
|
||||
my ( $status, $rest ) = $msg =~ m/STATUS=([^\|]+)\|(.*)/;
|
||||
|
||||
if ( not( $status eq 'OK' ) ) {
|
||||
job_stop_client($socket);
|
||||
|
||||
# printf("Received not OK message from master (%s)",$msg);
|
||||
return $return_value;
|
||||
}
|
||||
|
||||
$message = sprintf( "%s\n", $command );
|
||||
|
||||
# printf("Message = %s",$message);
|
||||
job_send_data( $socket, $message );
|
||||
|
||||
$msg = <$socket>;
|
||||
|
||||
if ( not defined($msg) ) {
|
||||
job_stop_client($socket);
|
||||
|
||||
# printf("Timed out connecting to master to send command");
|
||||
return $return_value;
|
||||
}
|
||||
|
||||
$deserialized = deserialize_cmd($msg);
|
||||
$msg = $deserialized;
|
||||
|
||||
$msg =~ s/[\r\n]*$//;
|
||||
|
||||
# printf("Rx Cmd Msg = %s\n",$msg);
|
||||
|
||||
( $status, $rest ) = $msg =~ m/STATUS=([^\|]+)\|(.*)/;
|
||||
|
||||
if ( not( $status eq 'OK' ) ) {
|
||||
job_stop_client($socket);
|
||||
|
||||
# printf("Received not OK message from master (%s)\n",$msg);
|
||||
return $return_value;
|
||||
}
|
||||
|
||||
job_stop_client($socket);
|
||||
|
||||
# printf("Statistics uploaded successfully\n");
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
sub GetMacAddress {
|
||||
|
||||
# This could fail
|
||||
my $ifconfigin = `/sbin/ifconfig eth0`;
|
||||
my @ifeth = split( /\n/, $ifconfigin );
|
||||
my ( $junk, $macaddr ) = split( / HWaddr /, $ifeth[0] );
|
||||
|
||||
# remove the ":" and spaces
|
||||
$macaddr =~ s/[\: ]//g;
|
||||
|
||||
# printf "MAC=\"$macaddr\"\n";
|
||||
return $macaddr;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
################################################################################
|
||||
|
||||
sub job_start_client {
|
||||
|
||||
my $master_host_name = shift;
|
||||
my $master_host_port = shift;
|
||||
my $timeout = shift;
|
||||
my $silent = shift;
|
||||
|
||||
$timeout = 60 if ( not defined($timeout) );
|
||||
$silent = 0 if ( not defined($silent) );
|
||||
|
||||
my $arp_refresh = 1;
|
||||
if ($arp_refresh) {
|
||||
|
||||
# Suspecting ARP cache timeout and subsequent connect failures as cause for
|
||||
# failures with "No Route to Host" error message
|
||||
# Hack it by massaging the ARP into clients ARP table with 3 pings.
|
||||
|
||||
# debug(2,"JOB: Doing ping to host %s to refresh ARP cache...",$master_host_name);
|
||||
my $system_cmd = sprintf( "ping -c 3 %s > %s 2>&1",
|
||||
$master_host_name, "/dev/null" );
|
||||
my $execute = `$system_cmd`;
|
||||
if ( $? == -1 ) {
|
||||
|
||||
# debug(2,"ARP ping failed to exec: %s", $!);
|
||||
}
|
||||
elsif ( $? >> 8 ) {
|
||||
|
||||
# debug(2,"ARP ping exited with value %d\n", $? >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
my $socket = IO::Socket::INET->new(
|
||||
PeerAddr => $master_host_name,
|
||||
PeerPort => $master_host_port,
|
||||
Proto => "tcp",
|
||||
Type => SOCK_STREAM,
|
||||
Timeout => $timeout
|
||||
);
|
||||
|
||||
if ( not defined($socket) ) {
|
||||
if ( not $silent ) {
|
||||
|
||||
# printf("Couldn't connect to Job Master = %s (TCP Port=%s) : %s\n",$master_host_name ,$master_host_port,$!);
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
else {
|
||||
# Set timeout for socket
|
||||
$socket->timeout($timeout);
|
||||
}
|
||||
return $socket;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
################################################################################
|
||||
|
||||
sub job_stop_client {
|
||||
|
||||
my $client = shift;
|
||||
|
||||
close($client) if ( defined($client) );
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# The function serializes a complex datastructure into a safe and compact
|
||||
# single line string.
|
||||
################################################################################
|
||||
|
||||
sub serialize_cmd {
|
||||
my $cmd = shift;
|
||||
|
||||
# replace all newlines, CR and % with CGI-style encoded sequences
|
||||
$cmd =~ s/([%\r\n])/sprintf("%%%02X", ord($1))/ge;
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# The function deserializes the input string into a complex datastructure.
|
||||
################################################################################
|
||||
sub deserialize_cmd {
|
||||
my $serialized = shift;
|
||||
|
||||
# convert back escapes to the original chars
|
||||
$serialized =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/ge;
|
||||
|
||||
return $serialized;
|
||||
|
||||
}
|
||||
|
||||
################################################################################
|
||||
################################################################################
|
||||
|
||||
sub job_send_data {
|
||||
|
||||
my $socket = shift;
|
||||
my $message = shift;
|
||||
|
||||
my $status = 0;
|
||||
if ( defined($socket) ) {
|
||||
my $msg = serialize_cmd($message);
|
||||
my $r = print $socket "$msg\n";
|
||||
|
||||
# printf("Socket write error msg \'%s\' - %s",$msg,$!) if (!defined($r));
|
||||
$status = 1;
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
################################################################################
|
||||
|
||||
sub job_receive_data {
|
||||
|
||||
my $socket = shift;
|
||||
my $timeout = shift;
|
||||
|
||||
$timeout = 1 if ( not defined($timeout) );
|
||||
|
||||
my $msg = undef;
|
||||
if ( defined($socket) ) {
|
||||
|
||||
# Set timeout for socket
|
||||
$socket->timeout($timeout);
|
||||
|
||||
# Now wait timeout time for someone to send something
|
||||
my $client = $socket->accept();
|
||||
if ( defined($client) ) {
|
||||
$msg = <$client>;
|
||||
my $deserialized = deserialize_cmd($msg);
|
||||
return ( $client, $deserialized );
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
242
root/usr/local/unjunkmgr/unjunkmgr.css
Normal file
242
root/usr/local/unjunkmgr/unjunkmgr.css
Normal file
@ -0,0 +1,242 @@
|
||||
BODY{
|
||||
background: #e6ecf8;
|
||||
color: #000000;
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
font-size: 12px;
|
||||
height: 100%;
|
||||
margin: 5px;
|
||||
padding: 0px;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
a { color: #000000 }
|
||||
|
||||
DIV.menu_bg{ z-index: 0; position: fixed; top: 0px; left: 0px; width: 162px; height: 100%; background-color: #eeeeee; }
|
||||
DIV.titre{ z-index: 1; position: absolute; top: 0px; left: 0px; width: 100%; height: 68px; background: #cccccc; margin: 0px 0px 1px 0px; }
|
||||
DIV.t_logo{ z-index: 1; position: absolute; top: 0px; left: 0px; }
|
||||
DIV.t_barre_orange{ z-index: 1; position: absolute; top: 41px; left: 0px; width: 100%; background: #ffc50a; border-color: #888888; border-style: solid; border-width: 1px 0px 1px 0px; }
|
||||
DIV.t_email{ z-index: 1; position: absolute; top: 50px; left: 0px; width: 240px; }
|
||||
DIV.t_liens{ z-index: 1; position: absolute; top: 50px; right: 0px; height: 14px; text-align: right; }
|
||||
DIV.t_barre_grise{ z-index: 1; position: absolute; top: 64px; left: 0px; width: 100%; background: #888888;}
|
||||
DIV.menu{ z-index: 1; position: absolute; top: 68px; left: 0px; width: 160px; padding: 0px 0px 0px 2px; }
|
||||
DIV.page{ z-index: 0; position: absolute; top: 68px; left: 162px; bottom: -1px; }
|
||||
DIV.contenu{ padding: 0px 20px 5px 5px; }
|
||||
|
||||
DIV.vert{ border-color: #006600; border-width: 1px; border-style: solid; color: #006600; padding: 2px; margin: 0px 20px 0px 20px; }
|
||||
DIV.rouge{ border-color: #ff0000; border-width: 1px; border-style: solid; color: #ff0000; padding: 2px; margin: 0px 20px 0px 20px; }
|
||||
DIV.vert a{ color: #006600; font-weight: bold; }
|
||||
DIV.rouge a{ color: #ff0000; font-weight: bold; }
|
||||
|
||||
FIELDSET{
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
FONT.copyleft{
|
||||
color: #777777;
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
FORM{
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
H1{
|
||||
color: #333333;
|
||||
font-size: 18px;
|
||||
margin-bottom: 4px;
|
||||
margin-top: 12px;
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
H2{
|
||||
color: #333333;
|
||||
font-size: 14px;
|
||||
margin-bottom: 3px;
|
||||
margin-top: 12px;
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
H3{
|
||||
color: #333333;
|
||||
font-size: 12px;
|
||||
/* margin-bottom: 3px;
|
||||
margin-top: 12px; */
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
H4{
|
||||
color: #333333;
|
||||
font-size: 12px;
|
||||
margin-bottom: 3px;
|
||||
margin-top: 12px;
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
H5{
|
||||
color: #333333;
|
||||
font-size: 10px;
|
||||
/* margin-bottom: 3px;
|
||||
margin-top: 12px; */
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HR{
|
||||
color: #666666;
|
||||
background-color: #666666;
|
||||
height: 1px;
|
||||
width: 80%;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
HR.copyleft{
|
||||
color: #dddddd;
|
||||
background-color: #dddddd;
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
OL, UL, LI{
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
UL{
|
||||
list-style-type: circle;
|
||||
}
|
||||
|
||||
P{
|
||||
margin-bottom: 2px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
PRE{
|
||||
margin: 3px 0px 3px 0px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
TABLE{
|
||||
border-collapse : collapse;
|
||||
empty-cells: show;
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
font-size: 12px;
|
||||
background-color: #e6ecf8;
|
||||
}
|
||||
|
||||
TABLE.bordure{
|
||||
border: 2px solid #cccccc;
|
||||
margin: 5px 5px 5px 2px;
|
||||
}
|
||||
|
||||
TD{
|
||||
font-size: 11px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
TD.header{
|
||||
border: 1px solid #cccccc;
|
||||
padding: 3px 2px 3px 2px;
|
||||
}
|
||||
|
||||
TH{
|
||||
font-size: 11px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
TH.bordure{
|
||||
background-color: #dddddd;
|
||||
border: 1px solid #cccccc;
|
||||
padding: 3px 2px 3px 2px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
TH.presse{
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
TH.bouton{
|
||||
border: 1px solid #dddddd;
|
||||
background-color: #eeeeee;
|
||||
padding: 4px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
TR{
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.cmdline{
|
||||
color: #00ffff;
|
||||
}
|
||||
|
||||
.xterm{
|
||||
background-color: #000000;
|
||||
border: 3px inset #999999;
|
||||
color: #ffffff;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.section{
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
padding-bottom: 2px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
a1:link, a1:visited, a1:hover, a1:active{
|
||||
border: 1px solid #000000;
|
||||
# border: 1px solid #cccccc;
|
||||
color: #000000;
|
||||
# margin: 0px;
|
||||
# padding: 0px 0px 0px 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover{
|
||||
background: #25bd25;
|
||||
border-color: #C0C0C0;
|
||||
}
|
||||
|
||||
a:active{
|
||||
background: #000000;
|
||||
border-color: #000000;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
a.choix, a.selection{
|
||||
border: 1px solid #eeeeee;
|
||||
color: #000000;
|
||||
display: block;
|
||||
# margin: 0px 0px 0px 0px;
|
||||
# padding: 0px 10px 2px 10px;
|
||||
text-align: left;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.choix:hover, a.selection:hover{
|
||||
background: #cccccc;
|
||||
border-color: #888888;
|
||||
}
|
||||
|
||||
a.choix:active, a.selection:active{
|
||||
background: #000000;
|
||||
border-color: #000000;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
a.selection:link, a.selection:visited, a.selection:active, a.selection:hover{
|
||||
border-color: #888888;
|
||||
}
|
||||
|
||||
a.selection:hover{
|
||||
background: #ffffff;
|
||||
border-color: #888888;
|
||||
}
|
136
smeserver-unjunkmgr.spec
Normal file
136
smeserver-unjunkmgr.spec
Normal file
@ -0,0 +1,136 @@
|
||||
# $Id: smeserver-unjunkmgr.spec,v 1.10 2022/08/02 01:49:38 jpp Exp $
|
||||
# Authority: jesperknudsen
|
||||
# Name: Jesper Knudsen
|
||||
|
||||
Summary: SME Server UnJunk Manager
|
||||
%define name smeserver-unjunkmgr
|
||||
%define version 3.1
|
||||
%define release 7
|
||||
Name: %{name}
|
||||
Version: %{version}
|
||||
Release: %{release}%{?dist}
|
||||
License: GPL
|
||||
Group: SME Server/addon
|
||||
Source: %{name}-%{version}.tar.xz
|
||||
#Patch1: smeserver-unjunkmgr-bzxxxxx-fix-stuff.patch
|
||||
|
||||
BuildRoot: /var/tmp/%{name}-%{version}-%{release}-buildroot
|
||||
BuildArch: noarch
|
||||
BuildRequires: e-smith-devtools
|
||||
Requires: smeserver-release >= 10.0
|
||||
Requires: e-smith-apache >= 2.6.0-19
|
||||
Requires: perl-MIME-Lite => 3
|
||||
Requires: perl-DateManip => 5.40
|
||||
Requires: mrtg
|
||||
Requires: perl-Email-Date-Format
|
||||
Requires: jpgraph
|
||||
Obsoletes: sme-unjunkmgr
|
||||
|
||||
%changelog
|
||||
* Sat Sep 07 2024 cvs2git.sh aka Brian Read <brianr@koozali.org> 3.1-7.sme
|
||||
- Roll up patches and move to git repo [SME: 12338]
|
||||
|
||||
* Sat Sep 07 2024 BogusDateBot
|
||||
- Eliminated rpmbuild "bogus date" warnings due to inconsistent weekday,
|
||||
by assuming the date is correct and changing the weekday.
|
||||
|
||||
* Mon Aug 01 2022 Jean-Philippe Pialasse <tests@pialasse.com> 3.1-6.sme
|
||||
- update to httpd 2.4 access syntax [SME: 12063]
|
||||
thanks to Vasarhelyi Zsolt
|
||||
|
||||
* Sat Nov 06 2021 Jean-Philippe Pialasse <tests@pialasse.com> 3.1-5.sme
|
||||
- fix unjunk links failing [SME: 11737]
|
||||
|
||||
* Tue Jun 01 2021 Jean-Philippe Pialasse <tests@pialasse.com> 3.1-4.sme
|
||||
- fix missing curly bracket and indentation [SME: 11178]
|
||||
|
||||
* Thu Apr 01 2021 Brian Read <brianr@bjsystems.co.uk> 3.1-3.sme
|
||||
- Add Update event to createlinks [SME: 11178]
|
||||
|
||||
* Thu Apr 01 2021 BogusDateBot
|
||||
- Eliminated rpmbuild "bogus date" warnings due to inconsistent weekday,
|
||||
by assuming the date is correct and changing the weekday.
|
||||
|
||||
* Tue Nov 24 2020 John Crisp <jcrisp@safeandsoundit.co.uk> 3.1-2.sme
|
||||
- Add cleaned up and fixed index.php that I forgot
|
||||
|
||||
* Tue Nov 24 2020 John Crisp <jcrisp@safeandsoundit.co.uk> 3.1-1.sme
|
||||
- Remove jpgraph to its own rpm
|
||||
- cleanup of various files
|
||||
- remove references to old SME versions
|
||||
|
||||
* Wed Nov 18 2020 Brian Read <brianr@bjsystems.co.uk> 3.0-2.sme
|
||||
- Fix SME Version check in perl stats prgram [SME: 11178]
|
||||
|
||||
* Wed Nov 18 2020 John Crisp <jcrisp@safeandsoundit.co.uk> 3.0-1.sme
|
||||
- Completely update jpgraph to 4.3.4
|
||||
- clean up various files and incorporate patches [SME: 11178]
|
||||
|
||||
* Tue Nov 17 2020 Brian Read <brianr@bjsystems.co.uk> 2.1-5.sme
|
||||
- Update jpgraph and fix php references in httpd.conf [SME: 11178]
|
||||
|
||||
* Mon Nov 16 2020 Brian Read <brianr@bjsystems.co.uk> 2.1-4.sme
|
||||
- Initial import to SME10 tree [SME: 11178]
|
||||
|
||||
* Fri Apr 4 2014 stephane de Labrusse <stephdl@de-labrusse.fr> 2.1-3.sme
|
||||
- added a unjunkmgr menu entry in the server-manager [sme : 8307]
|
||||
|
||||
* Thu Jun 27 2013 JP Pialasse <tests@pialasse.com> 2.1-2.sme
|
||||
- Add Update event to createlinks some php deprecated and PHP warning
|
||||
- patch1
|
||||
|
||||
* Wed Jun 26 2013 JP Pialasse <tests@pialasse.com> 2.1-1.sme
|
||||
- update JpGraph to fix deprecated messages
|
||||
- added perl-Email-Date-Format requirement for sme8 as per wiki
|
||||
- patch ttfpatch
|
||||
|
||||
* Tue Jun 25 2013 JP Pialasse <tests@pialasse.com> 2.0-4.sme
|
||||
- Add Update event to createlinks db default [SME: 7701]
|
||||
- patch0
|
||||
- added createlink in spec file
|
||||
|
||||
* Wed Jun 02 2010 Shad L. Lords <slords@mail.com> 2.0-1.sme
|
||||
- Clean up spec for importing into CVS
|
||||
|
||||
* Thu Jun 4 2009 Jesper Knudsen <jesper@swerts-knudsen.dk> 1.1.3-1
|
||||
- Added top spammed email stats in GUI and updated CSS to show nicely in IE
|
||||
- Fixed problem using unjunkhost confg parameter
|
||||
|
||||
* Fri Apr 3 2009 Jesper Knudsen <jesper@swerts-knudsen.dk> 1.1.0-2
|
||||
- Fixed error in spamreminder.pl line 112
|
||||
|
||||
* Thu Apr 2 2009 Jesper Knudsen <jesper@swerts-knudsen.dk> 1.1.0-1
|
||||
- Updated to submit statistics more randomly over the hour to avoid congestion on central
|
||||
- Add pie charts on stats
|
||||
- Add more configuration options
|
||||
|
||||
* Thu Aug 28 2008 Jesper Knudsen <jesper@swerts-knudsen.dk> 1.0.1-1
|
||||
- Updated spamreminder.pl to allow non-exisitng Subject fields
|
||||
- Made dependency of MRTG for RPM
|
||||
- Make sure to cleanup during un-install
|
||||
|
||||
* Fri Aug 22 2008 Jesper Knudsen <jesper@swerts-knudsen.dk> 1.0.0-1
|
||||
- First release
|
||||
|
||||
%description
|
||||
SME Server UnJunk Manager which scan the individual users junkmail folders and
|
||||
sends out a weekly summary where they can unjunk the emails
|
||||
|
||||
%prep
|
||||
%setup
|
||||
#%patch1 -p1
|
||||
|
||||
%build
|
||||
perl createlinks
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
(cd root ; find . -depth -print | cpio -dump $RPM_BUILD_ROOT)
|
||||
/sbin/e-smith/genfilelist $RPM_BUILD_ROOT > %{name}-%{version}-filelist
|
||||
echo "%doc " >> %{name}-%{version}-filelist
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files -f %{name}-%{version}-filelist
|
||||
%defattr(-,root,root)
|
Loading…
Reference in New Issue
Block a user