2025-04-04 18:02:23 +01:00
|
|
|
#
|
|
|
|
# Generated by SM2Gen version:0.9(20Jan2025) Chameleon version:4.5.4 On Python:3.12.3 at 2025-04-04 12:46:00
|
|
|
|
#
|
|
|
|
#
|
|
|
|
# Routines to be edited by the developer to provide content and validation for parameters
|
|
|
|
# and provison of the control data for table(s)
|
|
|
|
#
|
|
|
|
use esmith::util;
|
|
|
|
use esmith::util::network;
|
|
|
|
use esmith::ConfigDB;
|
|
|
|
use esmith::HostsDB;
|
|
|
|
use esmith::AccountsDB;
|
|
|
|
use esmith::NetworksDB;
|
|
|
|
use esmith::DomainsDB;
|
|
|
|
|
2025-04-06 07:58:24 +01:00
|
|
|
use POSIX 'strftime';
|
|
|
|
|
2025-04-04 18:02:23 +01:00
|
|
|
use constant FALSE => 0;
|
|
|
|
use constant TRUE => 1;
|
|
|
|
|
|
|
|
|
|
|
|
#The most common ones
|
|
|
|
#my $cdb
|
|
|
|
#my $adb
|
|
|
|
#my $ndb
|
|
|
|
#my $hdb
|
|
|
|
#my $ddb
|
|
|
|
|
|
|
|
# Validation routines - parameters for each panel
|
|
|
|
|
|
|
|
sub validate_TABLE {
|
|
|
|
my $c = shift;
|
|
|
|
my $prefix_data = shift; #Data hash as parameter
|
|
|
|
# Validation for each field
|
|
|
|
my $ret = "";
|
|
|
|
|
|
|
|
if (! TRUE) #validate $c->param('StatsDate')
|
|
|
|
{$ret .= 'Validation for StatsDate failed';}
|
|
|
|
if ($ret eq "") {$ret = 'ok';}
|
|
|
|
return $ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub validate_CONFIG {
|
|
|
|
my $c = shift;
|
|
|
|
my $prefix_data = shift; #Data hash as parameter
|
|
|
|
# Validation for each field
|
|
|
|
my $ret = "";
|
|
|
|
|
|
|
|
if (! TRUE) #validate $c->param('TextorHTML')
|
|
|
|
{$ret .= 'Validation for TextorHTML failed';}
|
|
|
|
if (! TRUE) #validate $c->param('Email')
|
|
|
|
{$ret .= 'Validation for Email failed';}
|
|
|
|
if (! TRUE) #validate $c->param('EmailHost')
|
|
|
|
{$ret .= 'Validation for EmailHost failed';}
|
|
|
|
if (! TRUE) #validate $c->param('EmailUser')
|
|
|
|
{$ret .= 'Validation for EmailUser failed';}
|
|
|
|
if (! TRUE) #validate $c->param('DBSave')
|
|
|
|
{$ret .= 'Validation for DBSave failed';}
|
|
|
|
if (! TRUE) #validate $c->param('DBHost')
|
|
|
|
{$ret .= 'Validation for DBHost failed';}
|
|
|
|
if (! TRUE) #validate $c->param('DBUser')
|
|
|
|
{$ret .= 'Validation for DBUser failed';}
|
|
|
|
if (! TRUE) #validate $c->param('CountrySelect')
|
|
|
|
{$ret .= 'Validation for CountrySelect failed';}
|
|
|
|
if (! TRUE) #validate $c->param('AccumCountryCodes')
|
|
|
|
{$ret .= 'Validation for AccumCountryCodes failed';}
|
|
|
|
if (! TRUE) #validate $c->param('EnableRHSBL')
|
|
|
|
{$ret .= 'Validation for EnableRHSBL failed';}
|
|
|
|
if (! TRUE) #validate $c->param('EnableRHSBL')
|
|
|
|
{$ret .= 'Validation for EnableRHSBL failed';}
|
|
|
|
if (! TRUE) #validate $c->param('RBLLIST')
|
|
|
|
{$ret .= 'Validation for RBLLIST failed';}
|
|
|
|
if (! TRUE) #validate $c->param('SBLLIST')
|
|
|
|
{$ret .= 'Validation for SBLLIST failed';}
|
|
|
|
if (! TRUE) #validate $c->param('UBLLIST')
|
|
|
|
{$ret .= 'Validation for UBLLIST failed';}
|
|
|
|
if ($ret eq "") {$ret = 'ok';}
|
|
|
|
return $ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Get singleton data for each panel
|
|
|
|
|
|
|
|
sub get_data_for_panel_TABLE {
|
|
|
|
# Return a hash with the fields required which will be loaded into the shared data
|
|
|
|
my $c = shift;
|
|
|
|
my %ret = (
|
|
|
|
'Data1'=>'Data for TABLE', #Example
|
|
|
|
# fields from Inputs in TABLE $fields['TABLE']
|
|
|
|
'StatsDate'=>'StatsDate contents',
|
|
|
|
|
|
|
|
);
|
|
|
|
return %ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub get_data_for_panel_CONFIG {
|
|
|
|
# Return a hash with the fields required which will be loaded into the shared data
|
|
|
|
my $c = shift;
|
2025-04-06 07:58:24 +01:00
|
|
|
my $cdb = esmith::ConfigDB->open() || die("Couldn't open config db");
|
|
|
|
my $key = 'mailstats';
|
2025-04-04 18:02:23 +01:00
|
|
|
my %ret = (
|
|
|
|
'Data1'=>'Data for CONFIG', #Example
|
|
|
|
# fields from Inputs in CONFIG $fields['CONFIG']
|
2025-04-06 07:58:24 +01:00
|
|
|
'TextorHTML'=>$cdb->get_prop($key,'TextorHTML') || 'HTML',
|
|
|
|
'Email'=>$cdb->get_prop($key,'Email') || 'admin',
|
|
|
|
'EmailHost'=>$cdb->get_prop($key,'EmailHost') || 'localhost',
|
|
|
|
'EmailPort'=>$cdb->get_prop($key,'EmailPORT') || '25',
|
|
|
|
'EmailUser'=>$cdb->get_prop($key,'EmailUser') || 'admin',
|
|
|
|
'DBSave'=>$cdb->get_prop($key,'SaveDataToMySQL') || 'yes',
|
|
|
|
'DBHost'=>$cdb->get_prop($key,'DBHost') || 'localhost',
|
|
|
|
'DBUser'=>$cdb->get_prop($key,'DBUser') || 'admin',
|
|
|
|
'DBPort'=>$cdb->get_prop($key,'DBPort') || '3306',
|
|
|
|
#'CountrySelect'=>'CountrySelect ',
|
|
|
|
'AccumCountryCodes'=>$cdb->get_prop('qpsmtpd','BadCountries'),
|
|
|
|
'EnableRHSBL'=>$cdb->get_prop('qpsmtpd','RHSBL'),
|
|
|
|
'EnableDNSBL'=>$cdb->get_prop('qpsmtpd','DNSBL'),
|
|
|
|
'EnableURIBL'=>$cdb->get_prop('qpsmtpd','URIBL'),
|
|
|
|
'RBLList'=>$cdb->get_prop('qpsmtpd','RBLList'),
|
|
|
|
'SBLList'=>$cdb->get_prop('qpsmtpd','SBLList'),
|
|
|
|
'UBLList'=>$cdb->get_prop('qpsmtpd','UBLList'),
|
|
|
|
'LevelPort'=>$cdb->get_prop('spamassassin','TagLevel') || '5',
|
|
|
|
'RejectLevel'=>$cdb->get_prop('spamassassin','RejectLevel') || '12'
|
|
|
|
|
2025-04-04 18:02:23 +01:00
|
|
|
|
|
|
|
);
|
|
|
|
return %ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get control data for table(s)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Return hash with values from row in which link clicked on table
|
|
|
|
|
|
|
|
sub get_selected_TABLE {
|
|
|
|
my $c = shift;
|
|
|
|
my $selected = shift; #Parameter is name of selected row.
|
|
|
|
my $is_new_record = shift; #Indicates new record required (defaults)
|
|
|
|
my %ret = {};
|
|
|
|
return %ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub get_selected_CONFIG {
|
|
|
|
my $c = shift;
|
|
|
|
my $selected = shift; #Parameter is name of selected row.
|
|
|
|
my $is_new_record = shift; #Indicates new record required (defaults)
|
|
|
|
my %ret = {};
|
|
|
|
return %ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#after sucessful modify or create or whatever and submit then perfom (if the params validate)
|
|
|
|
|
|
|
|
sub perform_TABLE {
|
|
|
|
my $c = shift;
|
|
|
|
my $prefix_data = shift; #Data hash as parameter
|
|
|
|
my $ret = "";
|
|
|
|
my $db = $cdb; #maybe one of the others
|
|
|
|
my $dbkey = 'ChangeThis';
|
|
|
|
# To make it write to DB as comment, delete this (regex) string in each if statement "TRUE\) \#copy or perform with value: .* e.g."
|
|
|
|
|
|
|
|
if (! TRUE) #copy or perform with value: StatsDate e.g. $db->set_prop($dbkey,'StatsDate',$c->param('StatsDate'),type=>'service'))
|
|
|
|
{$ret .= 'Perform/save failed for StatsDate';}
|
|
|
|
if ($ret eq "") {$ret = 'ok';}
|
|
|
|
return $ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub perform_CONFIG {
|
|
|
|
my $c = shift;
|
|
|
|
my $prefix_data = shift; #Data hash as parameter
|
|
|
|
my $ret = "";
|
2025-04-06 07:58:24 +01:00
|
|
|
my $cdb = esmith::ConfigDB->open() || die("Couldn't open config db");
|
2025-04-04 18:02:23 +01:00
|
|
|
my $db = $cdb; #maybe one of the others
|
2025-04-06 07:58:24 +01:00
|
|
|
my $dbkey = 'mailstats';
|
2025-04-04 18:02:23 +01:00
|
|
|
# To make it write to DB as comment, delete this (regex) string in each if statement "TRUE\) \#copy or perform with value: .* e.g."
|
|
|
|
|
2025-04-06 07:58:24 +01:00
|
|
|
if (! $db->set_prop($dbkey,'TextorHTML',$c->param('TextorHTML'),type=>'service'))
|
2025-04-04 18:02:23 +01:00
|
|
|
{$ret .= 'Perform/save failed for TextorHTML';}
|
2025-04-06 07:58:24 +01:00
|
|
|
if (! $db->set_prop($dbkey,'Email',$c->param('Email'),type=>'service'))
|
2025-04-04 18:02:23 +01:00
|
|
|
{$ret .= 'Perform/save failed for Email';}
|
2025-04-06 07:58:24 +01:00
|
|
|
if (! $db->set_prop($dbkey,'EmailHost',$c->param('EmailHost'),type=>'service'))
|
2025-04-04 18:02:23 +01:00
|
|
|
{$ret .= 'Perform/save failed for EmailHost';}
|
2025-04-06 07:58:24 +01:00
|
|
|
if (! $db->set_prop($dbkey,'EmailPort',$c->param('EmailPort'),type=>'service'))
|
|
|
|
{$ret .= 'Perform/save failed for EmailPort';}
|
|
|
|
if (! $db->set_prop($dbkey,'EmailUser',$c->param('EmailUser'),type=>'service'))
|
2025-04-04 18:02:23 +01:00
|
|
|
{$ret .= 'Perform/save failed for EmailUser';}
|
2025-04-06 07:58:24 +01:00
|
|
|
if (! $db->set_prop($dbkey,'SaveDataToMySQL',$c->param('DBSave'),type=>'service'))
|
2025-04-04 18:02:23 +01:00
|
|
|
{$ret .= 'Perform/save failed for DBSave';}
|
2025-04-06 07:58:24 +01:00
|
|
|
if (! $db->set_prop($dbkey,'DBHost',$c->param('DBHost'),type=>'service'))
|
2025-04-04 18:02:23 +01:00
|
|
|
{$ret .= 'Perform/save failed for DBHost';}
|
2025-04-06 07:58:24 +01:00
|
|
|
if (! $db->set_prop($dbkey,'DBUser',$c->param('DBUser'),type=>'service'))
|
2025-04-04 18:02:23 +01:00
|
|
|
{$ret .= 'Perform/save failed for DBUser';}
|
2025-04-06 07:58:24 +01:00
|
|
|
if (! $db->set_prop($dbkey,'DBPort',$c->param('DBPort'),type=>'service'))
|
|
|
|
{$ret .= 'Perform/save failed for DBPort';}
|
|
|
|
#if (! $db->set_prop($dbkey,'CountrySelect',$c->param('CountrySelect'),type=>'service'))
|
|
|
|
# {$ret .= 'Perform/save failed for CountrySelect';}
|
|
|
|
if (! $db->set_prop('qpsmtpd','BadCountries',$c->param('AccumCountryCodes'),type=>'service'))
|
2025-04-04 18:02:23 +01:00
|
|
|
{$ret .= 'Perform/save failed for AccumCountryCodes';}
|
2025-04-06 07:58:24 +01:00
|
|
|
if (! $db->set_prop('qpsmtpd','RHSBL',$c->param('EnableRHSBL'),type=>'service'))
|
2025-04-04 18:02:23 +01:00
|
|
|
{$ret .= 'Perform/save failed for EnableRHSBL';}
|
2025-04-06 07:58:24 +01:00
|
|
|
if (! $db->set_prop('qpsmtpd','DNSBL',$c->param('EnableDNSBL'),type=>'service'))
|
|
|
|
{$ret .= 'Perform/save failed for EnableDNSBL';}
|
|
|
|
if (! $db->set_prop('qpsmtpd','URIBL',$c->param('EnableURIBL'),type=>'service'))
|
|
|
|
{$ret .= 'Perform/save failed for EnableURIBL';}
|
|
|
|
if (! $db->set_prop('qpsmtpd','RBLList',$c->param('RBLList'),type=>'service'))
|
2025-04-04 18:02:23 +01:00
|
|
|
{$ret .= 'Perform/save failed for RBLLIST';}
|
2025-04-06 07:58:24 +01:00
|
|
|
if (! $db->set_prop('qpsmtpd','SBLList',$c->param('SBLList'),type=>'service'))
|
2025-04-04 18:02:23 +01:00
|
|
|
{$ret .= 'Perform/save failed for SBLLIST';}
|
2025-04-06 07:58:24 +01:00
|
|
|
if (! $db->set_prop('qpsmtpd','UBLList',$c->param('UBLList'),type=>'service'))
|
2025-04-04 18:02:23 +01:00
|
|
|
{$ret .= 'Perform/save failed for UBLLIST';}
|
2025-04-06 07:58:24 +01:00
|
|
|
if (! $db->set_prop('spamassassin','TagLevel',$c->param('TagLevel'),type=>'service'))
|
|
|
|
{$ret .= 'Perform/save failed for TagLevel';}
|
|
|
|
if (! $db->set_prop('spamassassin','RejectLevel',$c->param('RejectLevel'),type=>'service'))
|
|
|
|
{$ret .= 'Perform/save failed for RejectLevel';}
|
2025-04-04 18:02:23 +01:00
|
|
|
if ($ret eq "") {$ret = 'ok';}
|
|
|
|
return $ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub create_link{
|
|
|
|
# WIP
|
|
|
|
my ($c,$route, $panel, $index) = @_;
|
|
|
|
my $link = "$route?trt=$panel&Selected=$index";
|
|
|
|
return $link;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub get_StatsDate{
|
|
|
|
return ['yesterday']
|
|
|
|
}
|
|
|
|
|
2025-04-06 07:58:24 +01:00
|
|
|
sub get_CountryCodes {
|
|
|
|
return [
|
|
|
|
['Afghanistan' => 'AF'], # Frequent political/malware spam
|
|
|
|
['Argentina' => 'AR'], # 52% spam call rate (highest globally)
|
|
|
|
['Brazil' => 'BR'], # Top spam call origin
|
|
|
|
['China' => 'CN'], # High spam volume
|
|
|
|
['France' => 'FR'], # 43% spam call rate, top email spam source
|
|
|
|
['Germany' => 'DE'], # Significant email spam volume
|
|
|
|
['India' => 'IN'], # High spam call/text volume
|
|
|
|
['Indonesia' => 'ID'], # 51.5% spam call rate
|
|
|
|
['Italy' => 'IT'], # 35.1% spam call rate, email spam source
|
|
|
|
['Malaysia' => 'MY'], # 63% scam calls
|
|
|
|
['Mexico' => 'MX'], # Emerging spam source
|
|
|
|
['Nigeria' => 'NG'], # "Nigerian prince" scams
|
|
|
|
['Pakistan' => 'PK'], # Phishing campaigns
|
|
|
|
['Peru' => 'PE'], # Emerging spam source
|
|
|
|
['Russia' => 'RU'], # Cybercrime associations
|
|
|
|
['Saudi Arabia' => 'SA'], # High spam volume
|
|
|
|
['Spain' => 'ES'], # 43.9% spam call rate, email spam
|
|
|
|
['Turkey' => 'TR'], # Significant spam activity
|
|
|
|
['Ukraine' => 'UA'], # Spam proxy servers
|
|
|
|
['United States' => 'US'], # High email spam volume
|
|
|
|
['Viet Nam' => 'VN'] # Phishing/malware origins
|
|
|
|
];
|
2025-04-04 18:02:23 +01:00
|
|
|
}
|
2025-04-06 07:58:24 +01:00
|
|
|
|
|
|
|
|
|
|
|
sub get_RBL_lists{
|
|
|
|
return (
|
|
|
|
# Other Major Providers
|
|
|
|
"zen.spamhaus.org", # Combines SBL, XBL, and PBL
|
|
|
|
'bl.spamcop.net', # SpamCop Blocklist (user-reported spam)
|
|
|
|
'cbl.abuseat.org', # Composite Blocking List (bot-infected hosts)
|
|
|
|
'b.barracudacentral.org', # Barracuda Reputation Blocklist
|
|
|
|
|
|
|
|
# Specialized Lists
|
|
|
|
'dun.dnsrbl.net', # DNSRBL (DNS-based blacklist)
|
|
|
|
'psbl.surriel.com', # Passive Spam Block List (passive spam traps)
|
|
|
|
'backscatterer.org', # Backscatter/Out-of-Bounce spam sources
|
|
|
|
'dronebl.org', # Drones/Proxy/DDoS sources
|
|
|
|
'dnsbl-1.uceprotect.net',# UCEPROTECT Level 1 (entry-level blocking)[User Query]
|
|
|
|
'dnsbl-2.uceprotect.net' # UCEPROTECT Level 2 (more aggressive)[User Query]
|
|
|
|
);}
|
|
|
|
|
|
|
|
sub get_SBL_list{
|
|
|
|
return (
|
|
|
|
"sbl.spamhaus.org", # Spamhaus Blocklist
|
|
|
|
"xbl.spamhaus.org", # eXploits Blocklist
|
|
|
|
"pbl.spamhaus.org", # Policy Blocklist
|
|
|
|
"auth.spamhaus.org", # Auth Blocklist
|
|
|
|
"multi.surbl.org", # SURBL's multi-level URI checker (domains in email content)
|
|
|
|
"rhsbl.sorbs.net" # Right-Hand Side Blocklist (domain-based, not IP-based)
|
|
|
|
);}
|
|
|
|
|
|
|
|
sub get_URIBL_list{
|
|
|
|
return my @uribl_lists = (
|
|
|
|
"uribl.com", # Primary URIBL service
|
|
|
|
"multi.uribl.com", # Combined URIBL checks
|
|
|
|
"black.uribl.com", # Aggressive blocking list
|
|
|
|
"grey.uribl.com", # Suspicious URI list
|
|
|
|
"white.uribl.com" # Verified safe URI list
|
|
|
|
);}
|
|
|
|
|
|
|
|
sub get_mailstat_dates {
|
|
|
|
my ($directory) = '/opt/mailstats/html';
|
|
|
|
my @date_pairs;
|
|
|
|
|
|
|
|
# Find all matching files in directory
|
|
|
|
opendir(my $dh, $directory) or die "Can't open directory: $!";
|
|
|
|
|
|
|
|
while (my $file = readdir($dh)) {
|
|
|
|
next unless $file =~ /mailstats_for_(\d{4}-\d{2}-\d{2})\.html$/;
|
|
|
|
my $date = $1;
|
|
|
|
|
|
|
|
if ($date =~ /^(\d{4})-(\d{2})-(\d{2})$/) {
|
|
|
|
my $formatted_date = strftime("%B %-d %Y", 0, 0, 0, $3, $2-1, $1-1900);
|
|
|
|
push @date_pairs, [$formatted_date, $date];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
closedir($dh);
|
|
|
|
|
|
|
|
# Sort dates chronologically
|
|
|
|
@date_pairs = sort { $a->[1] cmp $b->[1] } @date_pairs;
|
|
|
|
|
|
|
|
return \@date_pairs;
|
|
|
|
}
|
|
|
|
|
2025-04-04 18:02:23 +01:00
|
|
|
1;
|