smeserver-email-management/root/etc/e-smith/web/functions/user-email

2020 lines
73 KiB
Perl
Executable File

#!/usr/bin/perl -wT
#----------------------------------------------------------------------
# heading : Configuration
# description : E-mail Management
# navigation : 6000 6701
#
# Author: Stephen Noble support@dungog.net
#
#----------------------------------------------------------------------
package esmith;
use strict;
use CGI ':all';
use CGI::Carp qw(fatalsToBrowser);
use esmith::cgi;
use esmith::config;
use esmith::util;
use esmith::db;
use File::Find; #find user Maildir's
sub showInitial ($$); #front
sub showHelp ($);
sub showGroup ($$);
sub performGroup ($);
#global
sub showGlobalEnable ($$); #Global Settings
sub showEdit ($); #Add or modify a Global procmail rule
sub performSave ($); #save global rule
sub performDelete ($); #delete global rule
sub performGlobalSave ($); #save globally
sub performShowHide ($); #show hide _. pseudonyms
#individual
sub showEnableProc ($$$); #Single user setup
sub showAdvancedRuleEdit ($); #Add or modify a users procmail rule
sub performEnableProc ($); #save single user
sub performSaveRule ($); #save single user rule
sub performDeleteSingle ($); #delete single user rule
sub performDeletelog ($); #delete user procmail.log
sub performViewlog ($); #view .procmailrc or procmail.log
sub GetDisplayName ($); # of the mailfolder
BEGIN
{
# Clear PATH and related environment variables so that calls to
# external programs do not cause results to be tainted. See
# "perlsec" manual page for details.
$ENV {'PATH'} = '/usr/bin';
$ENV {'SHELL'} = '/bin/bash';
delete $ENV {'ENV'};
}
esmith::util::setRealToEffective ();
$CGI::POST_MAX=1024 * 100; # max 100K posts
$CGI::DISABLE_UPLOADS = 1; # no uploads
my %conf;
tie %conf, 'esmith::config';
my %accounts;
tie %accounts, 'esmith::config', '/home/e-smith/db/accounts';
my %domains;
tie %domains, 'esmith::config', '/home/e-smith/db/domains';
my %processmail;
tie %processmail, 'esmith::config', '/home/e-smith/db/processmail';
my %dungog;
tie %dungog, 'esmith::config', '/home/e-smith/db/dungog';
#-------------------------
# global variables
#-------------------------
my %Label = ('TO_' => 'e-mail address To:&Cc:',
'From' => 'e-mail address From:',
'Subject' => 'the subject',
'>' => 'size greater than',
'<' => 'size less than',
'headers' => 'e-mail headers');
my %Labels = ('sort' => 'sort to mail folder',
'forward' => 'forward email',
'delete' => 'delete email',
'inbox' => 'send to my inbox');
#-------------------------
# examine state parameter
#-------------------------
my $q = new CGI;
if (! grep (/^state$/, $q->param))
{
showInitial ($q, '');
}
elsif ($q->param ('state') eq "help")
{
showHelp ($q);
}
elsif ($q->param ('state') eq "showGroup")
{
showGroup ($q, '');
}
elsif ($q->param ('state') eq "performGroup")
{
performGroup ($q);
}
elsif ($q->param ('state') eq "edit")
{
showEdit ($q);
}
elsif ($q->param ('state') eq "save")
{
performSave ($q);
}
elsif ($q->param ('state') eq "delete")
{
performDelete ($q);
}
elsif ($q->param ('state') eq "deleteSingle")
{
performDeleteSingle ($q);
}
elsif ($q->param ('state') eq "showhide")
{
performShowHide ($q);
}
elsif ($q->param ('state') eq "globalSave")
{
performGlobalSave ($q);
}
elsif ($q->param ('state') eq "enableProc")
{
showEnableProc ($q, '', '');
}
elsif ($q->param ('state') eq "globalEnableProc")
{
showGlobalEnable ($q, '');
}
elsif ($q->param ('state') eq "performEnableProc")
{
performEnableProc ($q);
}
elsif ($q->param ('state') eq "advmodifyRule")
{
showAdvancedRuleEdit ($q);
}
elsif ($q->param ('state') eq "saveRule")
{
performSaveRule ($q);
}
elsif ($q->param ('state') eq "deletelog")
{
performDeletelog ($q);
}
elsif ($q->param ('state') eq "viewlog")
{
performViewlog ($q);
}
else
{
esmith::cgi::genStateError ($q, \%conf);
}
exit (0);
#-----------------------------------
# and display the appropriate form
#-----------------------------------
sub showInitial ($$)
{
my ($q, $msg) = @_;
if ($msg eq '')
{
esmith::cgi::genHeaderNonCacheable
($q, \%conf, 'Email Management.');
}
else
{
esmith::cgi::genHeaderNonCacheable
($q, \%conf, 'Email Management.');
print $q->h4 ('Operation status report');
print $q->p ($msg);
print $q->hr;
}
unless (( -e "/etc/e-smith/web/functions/userpanel-vacation" ) &&
( -e "/etc/e-smith/web/functions/userpanel-mailsort" ))
{
print $q->p ('Extra functions are available, see https://wiki.koozali.org<br>
yum install smeserver-mailsorting smeserver-vacation');
}
#------------------------------------------------------------
# Global changes
#------------------------------------------------------------
print $q->h4 ('Global.');
my $FilterType = db_get_prop(\%conf, 'qmail', "FilterType") || '';
if ($FilterType eq 'maildrop')
{
print $q->p (esmith::cgi::genSmallRedCell ($q, 'Mail is being Sorted with Maildrop.'));
}
if ($FilterType eq 'procmail')
{
print $q->p (esmith::cgi::genSmallRedCell ($q, "Mail is being Sorted with Procmail.<p>"));
}
if ( -e "/usr/share/zarafa/VERSION" )
{
my $Gzar = db_get_prop(\%conf, 'zarafa-server', "GlobalForward") || '';
if ($Gzar eq 'enabled')
{ print $q->p (esmith::cgi::genSmallRedCell ($q, "Mail is being delivered globally to Zarafa.<p>")); }
else
{ print $q->p (esmith::cgi::genSmallRedCell ($q, "Mail is being selectivly delivered to Zarafa.<p>")); }
}
print $q->p ($q->td ($q->a ({href => $q->url (-absolute => 1) .
"?state=globalEnableProc"}, 'Modify'), " global mailfiltering rules and system settings.<p>"));
#------------------------------------------------------------
# accounts and user names
#------------------------------------------------------------
print $q->h4 ('Individual accounts.');
my @userAccounts = ();
foreach (sort keys %accounts)
{
push (@userAccounts, $_)
if (db_get_type(\%accounts, $_) eq "user");
}
my @Pseudonyms = ();
foreach (sort keys %accounts)
{
push (@Pseudonyms, $_)
if (db_get_type(\%accounts, $_) eq "pseudonym");
}
my $numAccts = @userAccounts +1;
if ($numAccts == 0)
{
print $q->h4 ('There are no user accounts in the system.');
}
else
{
print $q->p ('Review and modify a user\'s email delivery settings below.<br>
Details in the Help link below');
my $showPseudonym = db_get(\%processmail, 'showPseudonym') || 'no';
if ($showPseudonym eq 'yes')
{
print $q->Tr ($q->td ($q->a ({href => $q->url (-absolute => 1) . "?state=showhide"},
'Hide'),
"the . and _ Pseudonyms.<p>"));
}
else
{
print $q->Tr ($q->td ($q->a ({href => $q->url (-absolute => 1) . "?state=showhide&action=yes"},
'Show'),
"the . and _ Pseudonyms.<p> "));
}
print "<table border=1 cellspacing=1 cellpadding=4>";
print $q->Tr (esmith::cgi::genSmallCell ($q, $q->b ('Account')),
esmith::cgi::genSmallCell ($q, $q->b ('Name')),
esmith::cgi::genSmallCell ($q, $q->b ('Pseudonyms')),
esmith::cgi::genSmallCell ($q, $q->b ('delivery')),
esmith::cgi::genSmallCell ($q, $q->b ('forwarding')),
esmith::cgi::genSmallCell ($q, $q->b ('options')));
my $acct = '';
foreach $acct ('admin', @userAccounts)
{
my $EmailForward = db_get_prop(\%accounts, $acct, "EmailForward") || '';
my $ForwardAddress = db_get_prop(\%accounts, $acct, "ForwardAddress") || '';
my $fname = db_get_prop(\%accounts, $acct, "FirstName");
my $lname = db_get_prop(\%accounts, $acct, "LastName");
my $fullname = "$fname $lname";
my $userpath = ($acct eq 'admin')? "": "files/users/$acct";
#clean display
if ($EmailForward eq 'local')
{
$ForwardAddress = '';
}
#block external mail to this user
my $Visible ='';
if (defined(db_get_prop(\%accounts, $acct, "Visible")))
{
$Visible = db_get_prop(\%accounts, $acct, "Visible") || '';
if ($Visible ne 'internal') { $Visible = '';}
}
#mailfilter, bypass procmail/maildrop
my $MailFilter ='';
if (defined(db_get_prop(\%accounts, $acct, "MailFilter")))
{
$MailFilter = db_get_prop(\%accounts, $acct, "MailFilter") || '';
if ($MailFilter ne 'bypass') { $MailFilter = '';}
}
#vacation
my $vac ='';
if (defined(db_get_prop(\%accounts, $acct, "EmailVacation")))
{
$vac = db_get_prop(\%accounts, $acct, "EmailVacation") || '';
if ($vac eq 'yes') { $vac = 'vacation';}
if ($vac eq 'no') { $vac = '';}
}
#zarafa
my $zar ='';
my $Gzar = db_get_prop(\%conf, 'zarafa-server', "GlobalForward") || '';
if ($Gzar ne 'enabled')
{
if (defined(db_get_prop(\%accounts, $acct, "zarafa")))
{
$zar = db_get_prop(\%accounts, $acct, "zarafa") || '';
if ($zar eq 'enabled') { $zar = 'zarafa';}
if ($zar eq 'disabled') { $zar = '';}
}
}
my $tmda ='';
if ( -e "/etc/e-smith/templates/etc/crontab/25tmda-daily")
{
if (defined(db_get_prop(\%accounts, $acct, "tmda")))
{
$tmda = db_get_prop(\%accounts, $acct, "tmda") || '';
if ($tmda eq "on")
{
if (-e "/home/e-smith/$userpath/.tmda/config")
{
$tmda = 'tmda';
}
elsif (-e "/home/e-smith/$userpath/TMDA_restore.tgz")
{
$tmda = 'tmda!';
}
else
{
$tmda = 'tmda-';
}
}
else
{
if (-e "/home/e-smith/$userpath/.tmda/config")
{
$tmda = 'tmda*';
}
}
}
else
{
if (-e "/home/e-smith/$userpath/.tmda/config")
{
$tmda = 'tmda*';
}
}
if ($tmda eq 'off') { $tmda = '';}
}
#options
my $options = "$vac $Visible $MailFilter $tmda $zar";
#Pseudonyms
my @nyms = ();
foreach (@Pseudonyms)
{
my $Account = db_get_prop(\%accounts, $_, "Account");
if ($acct eq $Account)
{
if ($showPseudonym eq 'yes')
{
push (@nyms, $_);
push (@nyms, '<br>');
}
else
{
#lowercase
$fname =~ s/([^\W0-9_])/\l$1/g;
$lname =~ s/([^\W0-9_])/\l$1/g;
if ($_ ne $fname.".".$lname)
{
if ($_ ne $fname."_".$lname)
{
push (@nyms, $_);
push (@nyms, '<br>');
}
}
}
}
}
if ($acct eq 'admin')
{
$ForwardAddress = db_get_prop(\%accounts, 'admin', 'ForwardAddress') || '';
if ($ForwardAddress ne '')
{
$EmailForward = 'forward' || '';
}
}
print $q->Tr ( esmith::cgi::genSmallCell ($q, $q->a ({href => $q->url (-absolute => 1)
. "?state=enableProc&acct=" . $acct}, $acct)),
esmith::cgi::genSmallCell ($q, $fullname),
esmith::cgi::genSmallCell ($q, "@nyms"),
esmith::cgi::genSmallCell ($q, $EmailForward),
esmith::cgi::genSmallCell ($q, $ForwardAddress),
esmith::cgi::genSmallCell ($q, $options));
}#end of users
print '</table>';
}#end >0 users
#------------------------------------------------------------
# domains
#------------------------------------------------------------
if ( -e "/etc/e-smith/web/functions/dungog-domains")
{
my @domain = ();
foreach (sort keys %domains)
{
push (@domain, $_) if (db_get_type(\%domains, $_) eq "domain");
}
print $q->h4 ('Domains.');
print $q->p ('Modify with dungog-domain <a href="smeserver-domains">here</a>');
print "<table border=1 cellspacing=1 cellpadding=4>";
print $q->Tr (esmith::cgi::genSmallCell ($q, $q->b ('Domain')),
esmith::cgi::genSmallCell ($q, $q->b ('Description')),
esmith::cgi::genSmallCell ($q, $q->b ('Delegated to')));
foreach ( sort @domain)
{
my $Description = db_get_prop(\%domains, $_, "Description") || '';
my $MailServer = db_get_prop(\%domains, $_, "MailServer") || '';
print $q->Tr (esmith::cgi::genSmallCell ($q, $_),
esmith::cgi::genSmallCell ($q, $Description),
esmith::cgi::genSmallCell ($q, $MailServer));
}
print '</table>';
}
#------------------------------------------------------------
# groups
#------------------------------------------------------------
my @groups = ();
foreach (sort keys %accounts)
{
push (@groups, $_) if (db_get_type(\%accounts, $_) eq "group");
}
print $q->h4 ('Groups.');
my $numgroups = @groups;
if ($numgroups == 0)
{
print $q->h4 ('There are no groups in the system.');
}
else
{
print $q->p ('Modify group email delivery');
print "<table border=1 cellspacing=1 cellpadding=4>";
print $q->Tr (esmith::cgi::genSmallCell ($q, $q->b ('Group')),
esmith::cgi::genSmallCell ($q, $q->b ('Description')),
esmith::cgi::genSmallCell ($q, $q->b ('Visible')));
foreach ( sort @groups)
{
my $Description = db_get_prop(\%accounts, $_, "Description") || '';
my $Visible = db_get_prop(\%accounts, $_, "Visible") || 'external';
print $q->Tr (esmith::cgi::genSmallCell ($q, $q->a ({href => $q->url (-absolute => 1)
. "?state=showGroup&group=" . $_}, $_)),
esmith::cgi::genSmallCell ($q, $Description),
esmith::cgi::genSmallCell ($q, $Visible));
}
print '</table>';
}
print $q->endform;
print $q->p ($q->hr, $q->font ({size => "-1"}, "https://wiki.koozali.org",
$q->a ({href => $q->url (-absolute => 1) . "?state=help"}, 'Email help'), " ..."));
print '</FONT>';
print '</DIV>';
print $q->end_html;
}
#------------------------------------------------------------
# show modify or create global rule
#------------------------------------------------------------
sub showEdit ($)
{
my ($q) = @_;
my $pmRule = $q->param ('acct');
my $oldpmRule = "$pmRule";
if ($pmRule eq 'new')
{
my $random = int(rand(999999));
$pmRule = $random;
}
esmith::cgi::genHeaderNonCacheable
($q, \%conf, 'Add or modify a Global procmail rule.');
print $q->startform (-method => 'POST',
-action => $q->url (-absolute => 1));
print $q->table ({border => 0, cellspacing => 0, cellpadding => 4},
esmith::cgi::genTextRow ($q, $q->p ('Select the part of the email to be tested. The criterion
could be part of an email address, header or subject, or the email size.
The second test is optional.')),
esmith::cgi::genWidgetRow ($q, "First Test",
$q->popup_menu (-name => 'basis',
-values => ['Subject','TO_','From','headers','<','>'],
-default => db_get_prop(\%processmail, $pmRule, "basis") || '' ,
-labels => \%Label)),
esmith::cgi::genNameValueRow ($q,"First Criterion",
"criterion",
db_get_prop(\%processmail, $pmRule, "criterion") || '',),
esmith::cgi::genWidgetRow ($q, "Second Test",
$q->popup_menu (-name => 'basis2',
-values => ['','Subject','TO_','From','headers'],
-default => db_get_prop(\%processmail, $pmRule, "basis2") || '' ,
-labels => \%Label)),
esmith::cgi::genNameValueRow ($q,"Second Criterion",
"criterion2",
db_get_prop(\%processmail, $pmRule, "criterion2") || '',),
esmith::cgi::genTextRow ($q, $q->p ('What you are going to do with the message.')),
esmith::cgi::genWidgetRow ($q, "Action",
$q->popup_menu (-name => 'action',
-values => ['sort','forward','delete'],
-default => db_get_prop(\%processmail, $pmRule, "action") || '' ,
-labels => \%Labels)),
esmith::cgi::genNameValueRow ($q,"Folder or address",
"deliver",
db_get_prop(\%processmail, $pmRule, "deliver") || ''),
esmith::cgi::genTextRow ($q, $q->b ('Optional copy')),
esmith::cgi::genTextRow ($q, $q->p ("Keep a copy of the email, sort it, or send it to somewhere else.")),
esmith::cgi::genWidgetRow ($q, "Copy",
$q->popup_menu (-name => 'copy',
-values => ['no','yes'],
-default => db_get_prop(\%processmail, $pmRule, "copy") || '' )),
esmith::cgi::genWidgetRow ($q, "Action of copy",
$q->popup_menu (-name => 'action2',
-values => ['','inbox','sort','forward'],
-default => db_get_prop(\%processmail, $pmRule, "action2") || '',
-labels => \%Labels)),
esmith::cgi::genNameValueRow ($q, "Folder or address",
"deliver2",
db_get_prop(\%processmail, $pmRule, "deliver2") || ''),
esmith::cgi::genTextRow ($q, $q->b ('Priority')),
esmith::cgi::genTextRow ($q, $q->p ("Change the order ".
"in which global rules are evaluated by altering this value. ".
"Low numbers go first and values must be unique or you ".
"overwrite the other rule with that value.")),
esmith::cgi::genNameValueRow ($q, "Order of rule execution",
"pmRule",
"$pmRule",));
print $q->p (esmith::cgi::genButtonRow ($q,
$q->submit (-name => 'action',
-value => 'Save')));
print $q->hidden (-name => 'state', -override => 1, -default => 'save');
print $q->hidden (-name => 'pmRule', -override => 1, -default => $pmRule);
print $q->hidden (-name => 'oldpmRule', -override => 1, -default => $oldpmRule);
print $q->endform;
print $q->p ($q->hr, $q->font ({size => "-1"}, "dungog.net/wiki",
$q->a ({href => $q->url (-absolute => 1) . "?state=help"}, 'Email help'), " ..."));
print '</FONT>';
print '</DIV>';
print $q->end_html;
}
#------------------------------------------------------------
# show qmail settings
#------------------------------------------------------------
sub showGroup ($$)
{
my ($q) = @_;
my $group = $q->param ('group');
esmith::cgi::genHeaderNonCacheable ($q, \%conf, 'Group mail Settings');
print $q->startform (-method => 'POST',
-action => $q->url (-absolute => 1));
print $q->h4 ("Group Mail settings - $group");
print $q->p ("Disable external reciept of mail, ie. for the address $group, not the members of the group");
my $Visible = db_get_prop(\%accounts, $group, "Visible") || '';
print $q->p ("Group Email Delivery:",
$q->popup_menu (-name => 'Visible',
-values => ['external', 'internal'],
-default => $Visible));
print $q->p (esmith::cgi::genButtonRow ($q,
$q->submit (-name => 'action',
-value => 'Save')));
print $q->hidden (-name => 'state', -override => 1, -default => 'performGroup');
print $q->hidden (-name => 'group', -override => 1, -default => $group);
print $q->endform;
print $q->p ($q->hr, $q->font ({size => "-1"}, "https://wiki.koozali.org",
$q->a ({href => $q->url (-absolute => 1) . "?state=help"}, 'Email help'), " ..."));
print '</FONT>';
print '</DIV>';
print $q->end_html;
}
sub performGroup ($)
{
my ($q) = @_;
my $group = $q->param ('group');
my $Visible = $q->param ('Visible');
if ($Visible eq 'internal')
{
db_set_prop(\%accounts, $group, "Visible", 'internal');
}else{
db_delete_prop(\%accounts, $group, "Visible");
}
system ("/sbin/e-smith/signal-event", "email-update") == 0
or die ("Error occurred while globally updating.\n");
showInitial ($q, "settings saved.");
}
#------------------------------------------------------------
# show global update form
#------------------------------------------------------------
sub showGlobalEnable ($$)
{
my ($q) = @_;
esmith::cgi::genHeaderNonCacheable ($q, \%conf, 'Global Settings');
print $q->startform (-method => 'POST',
-action => $q->url (-absolute => 1));
print $q->h4 ('Zarafa');
# test if zarafa is installed
if ( -e "/usr/share/zarafa/VERSION" )
{
print $q->p ('Zarafa is an exchange replacment, see contribs.org/zarafa');
my $GlobalForward = db_get_prop(\%conf, 'zarafa-server', "GlobalForward") || 'disabled';
print $q->p ("Zarafa Global delivery",
$q->popup_menu (-name => 'GlobalForward',
-values => ['disabled','enabled'],
-default => $GlobalForward));
}
print $q->h4 ('Email Sorting');
# test if Mailfilter is installed
if ( -e "/etc/e-smith/web/functions/userpanel-mailsort" )
{
print $q->p ('Make a system wide change, enable procmail or maildrop,
Note, procmail and maildrop will deliver mail according to
the local, forward or both settings after any sorting');
my $FilterType = db_get_prop(\%conf, 'qmail', "FilterType") || '';
print $q->p ("Global Email Delivery",
$q->popup_menu (-name => 'FilterType',
-values => ['default', 'procmail', 'maildrop'],
-default => $FilterType));
print $q->h4 ('Global mail rules');
print $q->p ("Any rules you create will be placed before the users rules. ");
print $q->table ({border => 0, cellspacing => 0, cellpadding => 4});
my @pmRules = ();
foreach (sort keys %processmail)
{
push (@pmRules, $_)
if (db_get_type(\%processmail, $_) eq "pmGlobalRule");
}
#hide table if you have no rules
my $pmRules = @pmRules || 'no rules';
if ($pmRules eq 'no rules')
{
print $q->p ($q->a ({href => $q->url (-absolute => 1) . "?state=edit&acct=new"},
'Click here'),
'to define your first Global procmail rule.');
}
else
{
print $q->p ($q->a ({href => $q->url (-absolute => 1) . "?state=edit&acct=new"},
'Click here'),
"to add another procmail rule. You currently have $pmRules rules.");
print "<table border=1 cellspacing=1 cellpadding=4>";
#header
print $q->Tr (esmith::cgi::genSmallCell ($q, $q->b ('basis')),
esmith::cgi::genSmallCell ($q, $q->b ('criterion')),
esmith::cgi::genSmallCell ($q, $q->b ('basis2')),
esmith::cgi::genSmallCell ($q, $q->b ('criterion2')),
esmith::cgi::genSmallCell ($q, $q->b ('destination')),
esmith::cgi::genSmallCell ($q, $q->b ('copy')),
esmith::cgi::genSmallCell ($q, $q->b ('copy to')),
$q->td ('&nbsp;'),
$q->td ('&nbsp;'));
#held in /home/e-smith/db/processmail
my $pmRule;
foreach $pmRule (sort {$a <=> $b} @pmRules)
{
my $basis = db_get_prop(\%processmail, $pmRule, "basis") || '';
my $criterion = db_get_prop(\%processmail, $pmRule, "criterion") || '';
my $basis2 = db_get_prop(\%processmail, $pmRule, "basis2") || '';
my $criterion2 = db_get_prop(\%processmail, $pmRule, "criterion2") || '';
my $action = db_get_prop(\%processmail, $pmRule, "action") || '';
my $deliver = db_get_prop(\%processmail, $pmRule, "deliver") || '';
my $copy = db_get_prop(\%processmail, $pmRule, "copy") || '';
my $deliver2 = db_get_prop(\%processmail, $pmRule, "deliver2") || '';
my $action2 = db_get_prop(\%processmail, $pmRule, "action2") || '';
if ($copy eq 'yes' && $action2 eq 'inbox')
{
$copy = 'yes*';
}
foreach ($basis, $basis2)
{
if ($_ eq 'TO_')
{
$_ = 'To';
}
if ($_ eq '>')
{
$_ = 'greater than';
}
if ($_ eq '<')
{
$_ = 'less than';
}
}
if ($action eq 'delete')
{
print $q->Tr ( #esmith::cgi::genSmallCell ($q, $pmRule),
esmith::cgi::genSmallCell ($q, $basis),
esmith::cgi::genSmallCell ($q, $criterion),
esmith::cgi::genSmallCell ($q, $basis2),
esmith::cgi::genSmallCell ($q, $criterion2),
esmith::cgi::genSmallRedCell ($q, 'deleted'),
esmith::cgi::genSmallCell ($q, $copy),
esmith::cgi::genSmallCell ($q, $deliver2),
esmith::cgi::genSmallCell ($q,
$q->a ({href => $q->url (-absolute => 1)
. "?state=edit&acct="
. $pmRule}, 'Modify...')),
esmith::cgi::genSmallCell ($q,
$q->a ({href => $q->url (-absolute => 1)
. "?state=delete&acct="
. $pmRule}, 'Remove...')));
}
else
{
print $q->Tr ( #esmith::cgi::genSmallCell ($q, $pmRule),
esmith::cgi::genSmallCell ($q, $basis),
esmith::cgi::genSmallCell ($q, $criterion),
esmith::cgi::genSmallCell ($q, $basis2),
esmith::cgi::genSmallCell ($q, $criterion2),
esmith::cgi::genSmallCell ($q, $deliver),
esmith::cgi::genSmallCell ($q, $copy),
esmith::cgi::genSmallCell ($q, $deliver2),
esmith::cgi::genSmallCell ($q,
$q->a ({href => $q->url (-absolute => 1)
. "?state=edit&acct="
. $pmRule}, 'Modify...')),
esmith::cgi::genSmallCell ($q,
$q->a ({href => $q->url (-absolute => 1)
. "?state=delete&acct="
. $pmRule}, 'Remove...')));
}
}
}
print '</table>';
}
else
{
print $q->p ('Maildrop and procmail can be enabled more easily with smesmerver-mailfiltering
see https://wiki.koozali.org, yum install smesmerver-mailfiltering');
}
print $q->h4 ('Email/qmail settings');
print $q->p ('Enable archiving of email to and from the server to the user maillog [which must exist],<br>
cc adds a header for legal reasons, bcc does not');
print $q->p ("qpsmtpd Log Level:",
$q->popup_menu (-name => 'LogLevel',
-values => ['6', '8'],
-default => db_get_prop(\%conf, 'qpsmtpd', "LogLevel")));
print $q->p ("Double Bounces:",
$q->popup_menu (-name => 'DoubleBounceTo',
-values => ['postmaster','devnull'],
-default => db_get_prop(\%conf, 'qmail', "DoubleBounceTo")));
print $q->p ("Archive Email:",
$q->popup_menu (-name => 'BccMode',
-values => ['off', 'cc', 'bcc'],
-default => db_get_prop(\%conf, 'qpsmtpd', "BccMode")));
print $q->p ("RBL Blacklist:",
$q->popup_menu (-name => 'DNSBL',
-values => ['disabled', 'enabled'],
-default => db_get_prop(\%conf, 'qpsmtpd', "DNSBL")));
print $q->p (esmith::cgi::genNameValueRow ($q,
"RBL Blacklists",
"RBLList",
db_get_prop(\%conf, 'qpsmtpd', "RBLList")));
print $q->p ("SBL Blacklist:",
$q->popup_menu (-name => 'RHSBL',
-values => ['disabled', 'enabled'],
-default => db_get_prop(\%conf, 'qpsmtpd', "RHSBL")));
print $q->p (esmith::cgi::genNameValueRow ($q,
"SBL Blacklists",
"SBLList",
db_get_prop(\%conf, 'qpsmtpd', "SBLList")));
print $q->p (esmith::cgi::genNameValueRow ($q,
"Max size for attachment, in bytes",
"MaxMessageSize",
db_get_prop(\%conf, 'qmail', "MaxMessageSize")));
print $q->p (esmith::cgi::genNameValueRow ($q,
"Max size that is virus scanned, in bytes",
"MaxScannerSize",
db_get_prop(\%conf, 'qpsmtpd', "MaxScannerSize")));
print $q->p (esmith::cgi::genButtonRow ($q,
$q->submit (-name => 'action',
-value => 'Save')));
print $q->hidden (-name => 'state',
-override => 1,
-default => 'globalSave');
print $q->endform;
print $q->p ($q->hr, $q->font ({size => "-1"}, "https://wiki.koozali.org",
$q->a ({href => $q->url (-absolute => 1) . "?state=help"}, 'Email help'), " ..."));
print '</FONT>';
print '</DIV>';
print $q->end_html;
}
#------------------------------------------------------------
# save procmail rule to database
#------------------------------------------------------------
sub performSave ($)
{
my ($q) = @_;
my $oldpmRule = $q->param ('oldpmRule') || '';
my $pmRule = $q->param ('pmRule') || '';
my $basis = $q->param ('basis') || '';
my $criterion = $q->param ('criterion') || '';
my $basis2 = $q->param ('basis2') || '';
my $criterion2 = $q->param ('criterion2') || '';
my $deliver = $q->param ('deliver') || '';
my $deliver2 = $q->param ('deliver2') || '';
my $copy = $q->param ('copy') || '';
my $action = $q->param ('action') || '';
my $action2 = $q->param ('action2') || '';
my $changes = $q->param ('changes') || '';
if ($deliver eq '' && $action eq 'forward')
{
esmith::cgi::genHeaderNonCacheable ($q, \%conf, "Error: in destination.");
esmith::cgi::genResult ($q, "Error: You failed to enter a destination address");
return;
}
if ($deliver2 eq '' && $copy eq 'yes' && $action2 eq 'forward')
{
esmith::cgi::genHeaderNonCacheable ($q, \%conf, "Error: in destination.");
esmith::cgi::genResult ($q, "Error: You failed to enter a destination address for your copy");
return;
}
if ($criterion eq '')
{
esmith::cgi::genHeaderNonCacheable ($q, \%conf, "Error: in criterion.");
esmith::cgi::genResult ($q, "Error: you failed to enter a criterion value");
return;
}
if ($action ne 'delete' && $deliver eq '' )
{
esmith::cgi::genHeaderNonCacheable ($q, \%conf, "Error: in destination.");
esmith::cgi::genResult ($q, "Error: you failed to enter a destination value");
return;
}
if ($copy eq 'no')
{
$deliver2 = '';
$action2 = '';
}
db_delete(\%processmail, $oldpmRule);
db_set(\%processmail, $pmRule, 'pmGlobalRule');
db_set_prop(\%processmail, $pmRule, "basis", $basis);
db_set_prop(\%processmail, $pmRule, "criterion", $criterion);
db_set_prop(\%processmail, $pmRule, "basis2", $basis2);
db_set_prop(\%processmail, $pmRule, "criterion2", $criterion2);
db_set_prop(\%processmail, $pmRule, "deliver", $deliver);
db_set_prop(\%processmail, $pmRule, "deliver2", $deliver2);
db_set_prop(\%processmail, $pmRule, "action", $action);
db_set_prop(\%processmail, $pmRule, "action2", $action2);
db_set_prop(\%processmail, $pmRule, "copy", $copy);
system ("/sbin/e-smith/signal-event", "mailsorting-conf") == 0
or die ("Error occurred while globally updating mailfiltering.\n");
showGlobalEnable ($q, "Rules altered.");
}
#------------------------------------------------------------
# delete rule
#------------------------------------------------------------
sub performDelete ($)
{
my ($q) = @_;
my $acct = $q->param ('acct');
db_delete(\%processmail, "$acct");
system ("/sbin/e-smith/signal-event", "mailsorting-conf") == 0
or die ("Error occurred while globally updating mailfiltering.\n");
showGlobalEnable ($q, "Removed rule.");
}
#------------------------------------------------------------
# show or hide pseudonyms
#------------------------------------------------------------
sub performShowHide ($)
{
my ($q) = @_;
my $action = $q->param ('action');
if ($action eq 'yes')
{ db_set(\%processmail, 'showPseudonym', 'yes'); }
else
{ db_delete(\%processmail, "showPseudonym"); }
showInitial ($q, "");
}
#------------------------------------------------------------
# global update of all users .procmailrc/.qmail/.mailfilter files
#------------------------------------------------------------
sub performGlobalSave ($)
{
my ($q) = @_;
my $FilterType = $q->param ('FilterType') || 'default';
my $GlobalForward = $q->param ('GlobalForward') || '';
if (($FilterType eq 'procmail') || ($FilterType eq 'maildrop'))
{ db_set_prop(\%conf, 'qmail', 'FilterType', $FilterType); }
else
{ db_delete_prop(\%conf, 'qmail', 'FilterType'); }
if ($GlobalForward eq 'enabled')
{ db_set_prop(\%conf, 'zarafa-server', 'GlobalForward', 'enabled'); }
else
{ db_delete_prop(\%conf, 'zarafa-server', 'GlobalForward'); }
my $BccMode = $q->param ('BccMode') || '';
my $DNSBL = $q->param ('DNSBL') || '';
my $RHSBL = $q->param ('RHSBL') || '';
my $DoubleBounceTo = $q->param ('DoubleBounceTo') || '';
my $LogLevel = $q->param ('LogLevel') || '';
my $RBLList = $q->param ('RBLList') || '';
my $SBLList = $q->param ('SBLList') || '';
my $MaxScannerSize = $q->param ('MaxScannerSize') || '';
my $MaxMessageSize = $q->param ('MaxMessageSize') || '';
if ($BccMode eq 'cc' || $BccMode eq 'bcc')
{ db_set_prop(\%conf, 'qpsmtpd', 'Bcc', 'enabled');
db_set_prop(\%conf, 'qpsmtpd', 'BccMode', $BccMode); }
else
{ db_set_prop(\%conf, 'qpsmtpd', 'Bcc', 'disabled');
db_set_prop(\%conf, 'qpsmtpd', 'BccMode', $BccMode); }
if ($DoubleBounceTo eq 'devnull')
{ db_set_prop(\%conf, 'qmail', 'DoubleBounceTo', $DoubleBounceTo); }
else
{ db_delete_prop(\%conf, 'qmail', 'DoubleBounceTo'); }
db_set_prop(\%conf, 'qmail', 'MaxMessageSize', $MaxMessageSize);
db_set_prop(\%conf, 'qpsmtpd', 'MaxScannerSize', $MaxScannerSize);
db_set_prop(\%conf, 'qpsmtpd', 'DNSBL', $DNSBL);
db_set_prop(\%conf, 'qpsmtpd', 'RHSBL', $RHSBL);
db_set_prop(\%conf, 'qpsmtpd', 'LogLevel', $LogLevel);
db_set_prop(\%conf, 'qpsmtpd', 'RBLList', $RBLList);
db_set_prop(\%conf, 'qpsmtpd', 'SBLList', $SBLList);
#system ("/sbin/e-smith/signal-event", "mailsorting-conf") == 0
system ("/sbin/e-smith/signal-event", "email-update") == 0
or die ("Error occurred while signal-event email save.\n");
showInitial ($q, 'Setttings saved');
}
#------ SINGLE USER--------------------------------------
sub showEnableProc ($$$)
{
my ($q, $msg, $acctName) = @_;
my $FilterType = db_get_prop(\%conf, 'qmail', "FilterType") || '';
if ($msg eq '')
{
esmith::cgi::genHeaderNonCacheable
($q, \%conf, 'Single user setup');
}
else
{
esmith::cgi::genHeaderNonCacheable
($q, \%conf, 'Single user setup');
print $q->h4 ('Operation status report');
print $q->p ($msg);
print $q->hr;
}
print $q->startform
(-method => 'POST', -action => $q->url (-absolute => 1));
#get username from param, acctName is from deleteSingle
my $acct = '';
if ($acctName eq '')
{
$acct = $q->param ('acct');
}
else
{
$acct = $acctName;
}
if (db_get_type(\%accounts, $acct) eq "user" || $acct eq "admin")
{
my $name = db_get_prop(\%accounts, $acct, 'FirstName') . ' ' . db_get_prop(\%accounts, $acct, 'LastName');
my $userpath = ($acct eq 'admin')? "": "files/users/$acct";
print $q->p ('Email delivery for the user account "'
. $acct
. '" (user name "' . $name . '").');
print $q->h4 ("Email Delivery");
print $q->p ($q->a ({href => $q->url (-absolute => 1) . "?state=viewlog&file=.qmail&acct=$acct"},
'View'),
".qmail");
my %emailLabels = ('local' => 'Deliver email locally',
'forward' => 'Forward to address below',
'both' => 'Both deliver locally and forward');
my %visLabels = ('internal' => 'Internally visible only',
'external' => 'Unrestricted');
print $q->p (esmith::cgi::genWidgetRow ($q, "Email Delivery",
$q->popup_menu (-name => 'emailForward',
-values => ['local', 'forward', 'both'],
-default => db_get_prop(\%accounts, $acct, "EmailForward") || 'local',
-labels => \%emailLabels )));
my $forwardAddress = db_get_prop(\%accounts, $acct, 'ForwardAddress') || '';
print $q->p (esmith::cgi::genNameValueRow ($q,
"Forwarding address",
"forwardAddress",
$forwardAddress));
my $Visible = db_get_prop(\%accounts, $acct, "Visible") || '';
print $q->p (esmith::cgi::genWidgetRow ($q, "Visible ",
$q->popup_menu (-name => 'Visible',
-values => ['external', 'internal'],
-default => $Visible,
-labels => \%visLabels )));
########### test if zarafa is installed ####################
if ( -e "/usr/share/zarafa/VERSION" )
{
my %zarLabels = ('enabled' => 'Enabled',
'disabled' => 'Disabled',
'Genabled' => 'Zarafa is Globally enabled');
my $zar = db_get_prop(\%accounts, $acct, "zarafa") || '';
my $Gzar = db_get_prop(\%conf, 'zarafa-server', "GlobalForward") || '';
if ($Gzar eq 'enabled')
{ $zar = 'Genabled'; }
print $q->p (esmith::cgi::genWidgetRow ($q, "Deliver to Zarafa",
$q->popup_menu (-name => 'zarafa',
-values => ['enabled', 'disabled', 'Genabled'],
-default => $zar,
-labels => \%zarLabels )));
}
############# tmda ####################
# test if tmda is installed
if ( -e "/etc/e-smith/templates/etc/crontab/25tmda-daily")
{
my $tmda = defined(db_get_prop(\%accounts, $acct, "tmda")) ?
db_get_prop(\%accounts, $acct, "tmda") : '';
my $status = '';
unless (-e "/home/e-smith/$userpath/.tmda/config")
{
$status = 'NOT';
}
print $q->h4 ('TMDA settings');
print $q->p ('Enabling TMDA is a two stage process,<br>
Each user enables and configures TMDA at domainname/tmda<br>'.
"$acct has $status enabled tmda at /tmda<p>".
'Then set TMDA as enabled in the SME Accounts database<br>
this sets the users .qmail file up the SME way.<br>
the user can also do this himself at /user > tmda settings');
print $q->p ("TMDA Delivery:",
$q->popup_menu (-name => 'tmda',
-values => ['off', 'on'],
-default => $tmda));
}
############# Mailfilter ####################
# test if Mailfilter is installed
print $q->h4 ('Mailsorting rules');
if ( -e "/etc/e-smith/web/functions/userpanel-mailsort" )
{
my %filterLabels = ('on' => "Adopt system default: $FilterType",
'bypass' => "Bypass $FilterType");
my $MailFilter = db_get_prop(\%accounts, $acct, "MailFilter") || 'on';
print $q->p (esmith::cgi::genWidgetRow ($q, "Mailfilter",
$q->popup_menu (-name => 'MailFilter',
-values => ['on', 'bypass'],
-default => $MailFilter,
-labels => \%filterLabels )));
print $q->table ({border => 0, cellspacing => 0, cellpadding => 4});
#hide table if you have no rules
my @pmRules = ();
foreach (sort keys %processmail)
{
push (@pmRules, $_)
if (db_get_type(\%processmail, $_) eq "$acct");
}
my $pmRules = @pmRules || 'no rules';
if ($pmRules eq 'no rules')
{
print $q->p ($q->a ({href => $q->url (-absolute => 1) . "?state=advmodifyRule&acct=new&acctName=$acct"},
'Click here'),
'to define the first procmail rule.');
}
else
{
print $q->p ($q->a ({href => $q->url (-absolute => 1) . "?state=advmodifyRule&acct=new&acctName=$acct"},
'Click here'),
"to add another rule. You currently have $pmRules rules.");
print $q->p ;
print "<table border=1 cellspacing=1 cellpadding=4>";
#header
print $q->Tr ( #esmith::cgi::genSmallCell ($q, $q->b ('priority')),
esmith::cgi::genSmallCell ($q, $q->b ('basis')),
esmith::cgi::genSmallCell ($q, $q->b ('criterion')),
esmith::cgi::genSmallCell ($q, $q->b ('2nd basis')),
esmith::cgi::genSmallCell ($q, $q->b ('2nd criterion')),
esmith::cgi::genSmallCell ($q, $q->b ('destination')),
esmith::cgi::genSmallCell ($q, $q->b ('copy')),
esmith::cgi::genSmallCell ($q, $q->b ('copy to')),
$q->td ('&nbsp;'),
$q->td ('&nbsp;'));
my $pmRule;
foreach $pmRule (sort @pmRules)
{
my $basis = db_get_prop(\%processmail, $pmRule, "basis") || '';
my $criterion = db_get_prop(\%processmail, $pmRule, "criterion") || '';
my $basis2 = db_get_prop(\%processmail, $pmRule, "basis2") || '';
my $criterion2 = db_get_prop(\%processmail, $pmRule, "criterion2") || '';
my $action = db_get_prop(\%processmail, $pmRule, "action") || '';
my $deliver = db_get_prop(\%processmail, $pmRule, "deliver") || '';
my $copy = db_get_prop(\%processmail, $pmRule, "copy") || '';
my $deliver2 = db_get_prop(\%processmail, $pmRule, "deliver2") || '';
my $action2 = db_get_prop(\%processmail, $pmRule, "action2") || '';
foreach ($basis, $basis2)
{
if ($_ eq 'TO_')
{
$_ = 'Recipient';
}
if ($_ eq 'From')
{
$_ = 'Sender';
}
if ($_ eq '>')
{
$_ = 'greater than';
}
if ($_ eq '<')
{
$_ = 'less than';
}
}
if ($action eq 'delete')
{
print $q->Tr ( #esmith::cgi::genSmallCell ($q, $pmRule),
esmith::cgi::genSmallCell ($q, $basis),
esmith::cgi::genSmallCell ($q, $criterion),
esmith::cgi::genSmallCell ($q, $basis2),
esmith::cgi::genSmallCell ($q, $criterion2),
esmith::cgi::genSmallRedCell ($q, 'deleted'),
esmith::cgi::genSmallCell ($q, $copy),
esmith::cgi::genSmallCell ($q, $deliver2),
esmith::cgi::genSmallCell ($q,
$q->a ({href => $q->url (-absolute => 1)
. "?state=advmodifyRule&acctName=$acct&acct="
. $pmRule}, 'Modify...')),
esmith::cgi::genSmallCell ($q,
$q->a ({href => $q->url (-absolute => 1)
. "?state=deleteSingle&acctName=$acct&acct="
. $pmRule}, 'Remove...')));
}
else
{
print $q->Tr ( #esmith::cgi::genSmallCell ($q, $pmRule),
esmith::cgi::genSmallCell ($q, $basis),
esmith::cgi::genSmallCell ($q, $criterion),
esmith::cgi::genSmallCell ($q, $basis2),
esmith::cgi::genSmallCell ($q, $criterion2),
esmith::cgi::genSmallCell ($q, $deliver),
esmith::cgi::genSmallCell ($q, $copy),
esmith::cgi::genSmallCell ($q, $deliver2),
esmith::cgi::genSmallCell ($q,
$q->a ({href => $q->url (-absolute => 1)
. "?state=advmodifyRule&acctName=$acct&acct="
. $pmRule}, 'Modify...')),
esmith::cgi::genSmallCell ($q,
$q->a ({href => $q->url (-absolute => 1)
. "?state=deleteSingle&acctName=$acct&acct="
. $pmRule}, 'Remove...')));
}
}
}
print '</table>';
print $q->table ({border => 0, cellspacing => 1, cellpadding => 4});
#mailfilter files
print $q->Tr ($q->td ($q->a ({href => $q->url (-absolute => 1) . "?state=viewlog&file=.procmailrc&acct=$acct"},
'View'),
".procmailrc"),
$q->td ($q->a ({href => $q->url (-absolute => 1) . "?state=viewlog&file=.mailfilter&acct=$acct"},
'View'),
".mailfilter [maildrop]"));
print $q->Tr ($q->td ($q->a ({href => $q->url (-absolute => 1) . "?state=viewlog&file=procmail.log&acct=$acct"},
'View'),
"procmail.log"),
$q->td ($q->a ({href => $q->url (-absolute => 1) . "?state=viewlog&file=mailfilter.log&acct=$acct"},
'View'),
"mailfilter.log"));
print $q->Tr ($q->td ($q->a ({href => $q->url (-absolute => 1) . "?state=deletelog&file=procmail.log&acct=$acct"},
'Delete'),
'procmail.log'),
$q->td ($q->a ({href => $q->url (-absolute => 1) . "?state=deletelog&file=mailfilter.log&acct=$acct"},
'Delete'),
'mailfilter.log'));
print '</table>';
}
else
{
print $q->p ('Maildrop and procmail can be enabled more easily with smesmerver-mailfiltering
see https://wiki.koozali.org, yum install smesmerver-mailfiltering');
}
############# Vacation ####################
print $q->h4 ('Vacation message');
if ( -e "/etc/e-smith/web/functions/userpanel-vacation" )
{
my $enableVacation = db_get_prop(\%accounts, $acct, "EmailVacation");
if (defined ($enableVacation) && $enableVacation eq 'yes')
{
$enableVacation = 'yes';
}
else
{
$enableVacation = 'no';
}
my $fullname = db_get_prop(\%accounts, $acct, 'FirstName') . " " . db_get_prop(\%accounts, $acct, 'LastName');
my $vacationText = "From: \"$fullname\" \<$acct\@$conf{'DomainName'}\>\n".
"Subject: away from my email\n\n".
"I will not be reading my mail for a while. Your mail regarding\n\n".
" \"\$SUBJECT\"\n\n".
"will be read when I return.\n\n";
if ( -e "/home/e-smith/$userpath/.vacation.msg" )
{
open (VACATION, "</home/e-smith/$userpath/.vacation.msg")
or die "Error: Could not open file: /home/e-smith/$userpath/.vacation.msg\n";
my @vacationTemp = <VACATION>;
$vacationText = join ("", @vacationTemp);
close VACATION;
}
print $q->table ({border => 0, cellspacing => 0, cellpadding => 4},
esmith::cgi::genTextRow ($q,
"Enter a vacation message here. You can use the keyword \"\$SUBJECT\" ".
"anywhere in the text to be replaced with the subject line ".
"from the email that activated the auto-reply. ".
"All text up-to the first blank line will be part of the reply ".
"email's header so ensure to leave at leave one blank line ".
"before you start your reply message."),
esmith::cgi::genTextRow($q,
$q->textarea (-name => 'vacationText',
-override => 1,
-default => "$vacationText",
-rows => 10,
-columns => 64)),
$q->Tr (esmith::cgi::genCell ($q, "Enable Vacation Messages:"),
esmith::cgi::genCell ($q, $q->popup_menu (-name => 'enableVacation',
-values => ['yes', 'no'],
-default => "$enableVacation"))));
print '</table>';
}
else
{
print $q->p ('Vacation can be enabled more easily with smesmerver-vacation
see https://wiki.koozali.org, yum install smesmerver-vacation');
}
print $q->submit (-name => 'action', -value => 'Save');
print $q->hidden (-name => 'acctNAME', -override => 1, -default => $acct);
print $q->hidden (-name => 'state',
-override => 1,
-default => 'performEnableProc');
}
else
{
print $q->p (esmith::cgi::genTextRow ($q, "Admin can't modify any settings here."));
print $q->p ('<a href="emailsettings">configure</a> the admin settings in the E-mail panel');
}
print $q->endform;
print $q->p ($q->hr, $q->font ({size => "-1"}, "https://wiki.koozali.org",
$q->a ({href => $q->url (-absolute => 1) . "?state=help"}, 'Email help'), " ..."));
print '</FONT>';
print '</DIV>';
print $q->end_html;
return;
}
#------------------------------------------------------------
# advanced form to modify or create rule
#------------------------------------------------------------
sub showAdvancedRuleEdit ($)
{
my ($q) = @_;
my $acctName2 = $q->param ('acctName');
my $pmRule = $q->param ('acct');
my $oldpmRule = "$pmRule";
if ($pmRule eq 'new')
{
my $random = int(rand(999999));
$pmRule = $acctName2.$random;
}
#clear deliver field if using sort as we use the existing mbox list *nolonger
my $del = db_get_prop(\%processmail, $pmRule, "deliver") || '';
my $del2 = db_get_prop(\%processmail, $pmRule, "deliver2") || '';
esmith::cgi::genHeaderNonCacheable
($q, \%conf, 'Add or modify a users mail rule.');
print $q->startform (-method => 'POST',
-action => $q->url (-absolute => 1));
print $q->table ({border => 0, cellspacing => 0, cellpadding => 4},
esmith::cgi::genTextRow ($q, $q->p ('Select the part of the email to be tested. The criterion
could be part of an email address, header, subject, or the email size.
The second test is optional.')),
esmith::cgi::genWidgetRow ($q, "First Test",
$q->popup_menu (-name => 'basis',
-values => ['Subject','TO_','From','headers','<','>'],
-default => db_get_prop(\%processmail, $pmRule, "basis") || '' ,
-labels => \%Label)),
esmith::cgi::genNameValueRow ($q,"First Criterion",
"criterion",
db_get_prop(\%processmail, $pmRule, "criterion") || '',),
esmith::cgi::genWidgetRow ($q, "Second Test",
$q->popup_menu (-name => 'basis2',
-values => ['','Subject','TO_','From','headers'],
-default => db_get_prop(\%processmail, $pmRule, "basis2") || '' ,
-labels => \%Label)),
esmith::cgi::genNameValueRow ($q,"Second Criterion",
"criterion2",
db_get_prop(\%processmail, $pmRule, "criterion2") || '',),
esmith::cgi::genTextRow ($q, $q->p ("What you are going to do with your message.")),
esmith::cgi::genWidgetRow ($q, "Action",
$q->popup_menu (-name => 'action',
-values => ['sort','forward','delete'],
-default => db_get_prop(\%processmail, $pmRule, "action") || '' ,
-labels => \%Labels)),
esmith::cgi::genNameValueRow ($q,"Folder or address",
"deliver",
$del,),
esmith::cgi::genTextRow ($q, $q->b ('Optional copy')),
esmith::cgi::genTextRow ($q, $q->p ("Keep a copy of the email, sort it, or send it to somewhere else.")),
esmith::cgi::genWidgetRow ($q, "Copy",
$q->popup_menu (-name => 'copy',
-values => ['no','yes'],
-default => db_get_prop(\%processmail, $pmRule, "copy") || '' )),
esmith::cgi::genWidgetRow ($q, "Action of copy",
$q->popup_menu (-name => 'action2',
-values => ['','inbox','sort','forward'],
-default => db_get_prop(\%processmail, $pmRule, "action2") || '',
-labels => \%Labels)),
esmith::cgi::genNameValueRow ($q, "Folder or address",
"deliver2",
$del2,),
esmith::cgi::genTextRow ($q, $q->b ('Priority')),
esmith::cgi::genTextRow ($q, $q->p ("Change the order ".
"in which rules are evaluated by altering this value. ".
"Priority is determined by ascii value, and must be unique or you ".
"overwrite the other rule with that value. ".
"eg user101 goes first, then user5 then user99. because 1<5<9 ")),
esmith::cgi::genNameValueRow ($q,
"Order of rule execution",
"pmRule",
"$pmRule",));
print $q->p (esmith::cgi::genButtonRow ($q,
$q->submit (-name => 'action',
-value => 'Save')));
print $q->hidden (-name => 'state', -override => 1, -default => 'saveRule');
print $q->hidden (-name => 'pmRule', -override => 1, -default => $pmRule);
print $q->hidden (-name => 'oldpmRule', -override => 1, -default => $oldpmRule);
print $q->hidden (-name => 'acctName', -override => 1, -default => $acctName2);
print $q->endform;
print $q->p ($q->hr, $q->font ({size => "-1"}, "https://wiki.koozali.org",
$q->a ({href => $q->url (-absolute => 1) . "?state=help"}, 'Email help'), " ..."));
print '</FONT>';
print '</DIV>';
print $q->end_html;
return;
}
#----------PERFORM single user-------------------------------
sub performEnableProc ($)
{
my $acct = $q->param ('acctNAME');
my $loglevel = $q->param ('loglevel') || 'some';
my $emailForward = $q->param ('emailForward');
my $forwardAddress = $q->param ('forwardAddress');
my $Visible = $q->param ('Visible') || '';
my $MailFilter = $q->param ('MailFilter') || '';
my $tmda = $q->param ('tmda') || '';
my $zarafa = $q->param ('zarafa') || '';
if ($acct =~ /^([a-z][\-a-z0-9]*)$/)
{
$acct = $1;
}
my $userpath = ($acct eq 'admin')? "": "files/users/$acct";
if ($Visible eq 'internal')
{ db_set_prop(\%accounts, $acct, 'Visible', $Visible); }
else
{ db_delete_prop(\%accounts, $acct, 'Visible'); }
if ($MailFilter eq 'bypass')
{ db_set_prop(\%accounts, $acct, 'MailFilter', $MailFilter); }
else
{ db_delete_prop(\%accounts, $acct, 'MailFilter'); }
if ($zarafa eq 'enabled')
{ db_set_prop(\%accounts, $acct, 'zarafa', 'enabled'); }
elsif ($zarafa eq 'disabled')
{ db_delete_prop(\%accounts, $acct, 'zarafa'); }
if ($forwardAddress eq '') #blank
{
if (($emailForward eq 'forward') || ($emailForward eq 'both'))
{
showInitial ($q,
"Error: missing characters in email forwarding address: " .
"\"$forwardAddress\". Did not modify account.");
return;
}
}
elsif ($forwardAddress =~ /\s+/) #whitespace
{
showInitial ($q,
"Error: whitespace characters in email forwarding address: " .
"\"$forwardAddress\". Did not modify account.");
return;
}
elsif ($forwardAddress =~ /!^[a-zA-Z][a-zA-Z0-9\._\-\@]*$/) #not valid
{
showInitial ($q,
"Error: invalid characters in email forwarding address: " .
"\"$forwardAddress\". Did not modify account.");
return;
}
#in smeserver-vacation
if ( -e "/etc/e-smith/web/functions/userpanel-vacation" )
{
my $enableVacation = $q->param ('enableVacation');
my $vacationText = $q->param ('vacationText');
if ($vacationText eq '' && $enableVacation eq 'yes')
{
showEnableProc ($q, "Error: no vacation message was specified. $acct.", $acct);
return;
}
open (VACATION, ">/home/e-smith/$userpath/.vacation.msg")
or die ("Error opening vacation message file '/home/e-smith/files/$acct/.vacation.msg': $!\n");
print VACATION "$vacationText";
close VACATION;
db_set_prop(\%accounts, $acct, 'EmailVacation', "$enableVacation");
db_set_prop(\%accounts, $acct, 'EmailForward', $emailForward);
db_set_prop(\%accounts, $acct, 'ForwardAddress', $forwardAddress);
}
#in smeserver-mailfiltering
if ( -e "/etc/e-smith/web/functions/userpanel-mailsort" )
{
unless (exists $processmail {$acct})
{
db_set(\%processmail, $acct, 'settings');
}
db_set_prop(\%processmail, $acct, 'loglevel', $loglevel);
}
# in dungog-tmda-cgi
if ( -e "/etc/e-smith/web/functions/userpanel-tmda")
{
db_set_prop(\%accounts, $acct, 'tmda', $tmda);
}
system ("/sbin/e-smith/signal-event", "email-update", $acct) == 0
or die ("Error occurred email-update.\n");
showInitial ($q, "Settings altered for account $acct.");
#showEnableProc ($q, "Settings altered for account $acct.", $acct);
}
#------------------------------------------------------------
# save the rule for $user to the database
#------------------------------------------------------------
sub performSaveRule ($)
{
my ($q) = @_;
my $acctName = $q->param ('acctName') || '';
my $oldpmRule = $q->param ('oldpmRule') || '';
my $pmRule = $q->param ('pmRule') || '';
my $basis = $q->param ('basis') || '';
my $criterion = $q->param ('criterion') || '';
my $basis2 = $q->param ('basis2') || '';
my $criterion2 = $q->param ('criterion2') || '';
my $deliver = $q->param ('deliver') || '';
my $deliver2 = $q->param ('deliver2') || '';
my $copy = $q->param ('copy') || '';
my $action = $q->param ('action') || '';
my $action2 = $q->param ('action2') || '';
my $id = $q->param ('id') || '';
if ($acctName =~ /^([a-z][\.\-a-z0-9]*)$/)
{
$acctName = $1;
}
if ($deliver eq '' && $action eq 'forward')
{
esmith::cgi::genHeaderNonCacheable ($q, \%conf, "Error: in destination.");
esmith::cgi::genResult ($q, "Error: You failed to enter a destination address");
return;
}
if ($deliver2 eq '' && $copy eq 'yes' && $action2 eq 'forward')
{
esmith::cgi::genHeaderNonCacheable ($q, \%conf, "Error: in destination.");
esmith::cgi::genResult ($q, "Error: You failed to enter a destination address for your copy");
return;
}
if ($criterion eq '')
{
esmith::cgi::genHeaderNonCacheable ($q, \%conf, "Error: you failed to enter a criterion value.");
esmith::cgi::genResult ($q, "Error: you failed to enter a criterion value.");
return;
}
if ($copy eq 'no')
{
$deliver2 = '';
$action2 = '';
}
db_delete(\%processmail, $oldpmRule);
db_set(\%processmail, $pmRule, $acctName);
db_set_prop(\%processmail, $pmRule, "basis", $basis);
db_set_prop(\%processmail, $pmRule, "criterion", $criterion);
db_set_prop(\%processmail, $pmRule, "basis2", $basis2);
db_set_prop(\%processmail, $pmRule, "criterion2", $criterion2);
db_set_prop(\%processmail, $pmRule, "deliver", $deliver);
db_set_prop(\%processmail, $pmRule, "deliver2", $deliver2);
db_set_prop(\%processmail, $pmRule, "action", $action);
db_set_prop(\%processmail, $pmRule, "action2", $action2);
db_set_prop(\%processmail, $pmRule, "copy", $copy);
system ("/sbin/e-smith/signal-event", "mailsorting-conf", "$acctName") == 0
or die ("Error occurred while modifying user.\n");
showEnableProc ($q, "Rule saved for $acctName.",$acctName);
return;
}
#------------------------------------------------------------
# delete single rule
#------------------------------------------------------------
sub performDeleteSingle ($)
{
my ($q) = @_;
my $acct = $q->param ('acct'); #the rule number
my $acctName = $q->param ('acctName'); #the user
if ($acct =~ /^([a-z][\-a-z0-9]*)$/)
{
$acct = $1;
}
if ($acctName =~ /^([a-z][\-a-z0-9]*)$/)
{
$acctName = $1;
}
db_delete(\%processmail, "$acct");
system ("/sbin/e-smith/signal-event", "mailsorting-conf", "$acctName") == 0
or die ("Error occurred while modifying user.\n");
showEnableProc ($q, "Successfully removed rule.", $acctName);
}
sub performDeletelog ($)
{
my ($q) = @_;
my $acct = $q->param ('acct');
my $file = $q->param ('file');
if ($acct =~ /^([a-z][\-a-z0-9]*)$/)
{
$acct = $1;
}
my $userpath = ($acct eq 'admin')? "": "files/users/$acct";
if (-f "/home/e-smith/$userpath/$file")
{
system("/bin/rm -f /home/e-smith/$userpath/procmail.log");
}
if (-f "/home/e-smith/$userpath/$file")
{
system("/bin/rm -f /home/e-smith/$userpath/mailfilter.log");
}
showEnableProc ($q, "Deleted log file.", $acct);
}
sub performViewlog ($)
{
my ($q) = @_;
my $acct = $q->param ('acct');
my $file = $q->param ('file');
esmith::cgi::genHeaderNonCacheable
($q, \%conf, "$acct $file");
print $q->startform (-method => 'POST',
-action => $q->url (-absolute => 1));
print $q->table ({border => 0, cellspacing => 0, cellpadding => 4});
my $userpath = ($acct eq 'admin')? "": "files/users/$acct";
if ( -e "/home/e-smith/$userpath/$file" )
{
open (INF,"/home/e-smith/$userpath/$file")
or die ("can't open $file to read: $1. ");
while (<INF>)
{
print "$_<br>\n";
}
close INF;
}
if ( -e "$file" )
{
open (INF,"$file")
or die ("can't open $file to read: $1. ");
while (<INF>)
{
print "$_<br>\n";
}
close INF;
}
print $q->endform;
print $q->p ($q->hr, $q->font ({size => "-1"}, "https://wiki.koozali.org",
$q->a ({href => $q->url (-absolute => 1) . "?state=help"}, 'Email help'), " ..."));
print $q->end_html;
return;
}
sub GetDisplayName ($)
{
my $s = shift;
return $s;
}
sub showHelp ($)
{
my ($q) = @_;
esmith::cgi::genHeaderNonCacheable
($q, \%conf, 'Email Help');
print $q->startform (-method => 'POST',
-action => $q->url (-absolute => 1));
print $q->table ({border => 0, cellspacing => 0, cellpadding => 4},
esmith::cgi::genTextRow ($q, $q->p ('<pre>
* <a href="#global">Global rules</a>
* <a href="#individ">Individual accounts</a>
* <a href="#options">Delivery options</a>
* <a href="#rules">Mail Rules</a>
<a name="global"><h3>Global rules</h3></a>
If smeserver-mailsorting is installed you can enable all mail
to be directed through either procmail or maildrop.
Default leaves the system in the original state
When procmail or maildrop is enabled mail can be sorted according to
any rules created, if unsorted the mail is delivered according to the
standard email setting of the user ie local, forward or both.
Maildrop includes a rule to match content in the body of the email
for email smaller the 5000 bytes it compares the list of words
or regular expressions you create in the file /opt/wordfilter
<a name="individ"><h3>Individual accounts</h3></a>
The Individual accounts table of users provides an overview.
The Account name provies a link to individual settings.
Name shows the users real name.
Pseudomnys give additional email addresses that go to the account
Delivery is either
local - mail stays on server
forward - mail is forwarded to another address
both - keeps a copy and forwards the mail
The Forwarding address is show only if forwarding is enabled
<a name="options"><h3>Delivery options</h3></a>
Values in the options column may include:
internal, users can only recieve local mail
The following options require additional software.
bypass, exclude this user for global mailfiltering ie. procmail/maildrop
vacation, a vacation message reply is sent
tmda, challenge and response email system
zarafa, deliver to zarafa
<b>smeserver-mailsorting</b>
Provides configuration files to create mail rules
that are processed by either procmail or maildrop
<b>smeserver-vacation</b>
Provides for a vacation message to be sent,
for example the user is out of the office
<b>dungog-tmda-cgi</b>
tmda.net
A combination of challenge and responce, and tagged email address that reduces spam
Note. tmda needs two values set
> tmda : the sme setting is enabled and the user has enabled tmda at /tmda
> tmda* : the sme setting is NOT enabled but the user has enabled tmda at /tmda
> tmda- : the sme setting is enabled but the user never enabled tmda at /tmda
> tmda! : the user has disabled tmda at /tmda but not the sme setting
tmda
tmda is correctly configured
tmda*
tmda will work but without vacation, forwarding or procmail,
until .qmail file is recreated, then mail does not get sent to tmda.
tmda-
tmda setting is ignored
tmda!
/tmda was enabled but now is not, its likely mail will be lost
.qmail is sending mail to tmda, see the cron job below for a fix
To enable TMDA
1. enable and configure at /tmda
2. make SME aware of the change here
To disable TMDA
1. Tell SME we are no longer going to use TMDA
- once you have done that here SME has disabled tmda
[optional but recommended]
2. disable at /tmda to release pending mail
3. Tell SME again, to confirm current settings are restored
To Check users who may disable /tmda but not the SME setting
enable the cron job *Fix incorrect TMDA settings*
which is visible if you have dungog-cron
Admin can change the default domain for new tmda users
db dungog set tmdaDomain domain.net
expand-template /usr/lib/python2.3/site-packages/tmda-cgi/skel/install/.tmda/config
If you have procmail enabled the daily *TMDA pending summary*
will be deleted automatically if it is empty
<a name="rules"><h3>Mail Rules</h3></a>
Rules to match email then perform an action
Match against the emails size, To, From, or other headers
You can combine two elements before you call it a match
it may be helpful to view the headers of your emails to check if things
are not matching as expected,
to get an idea of the size of emails check the log file
when matched you can
sort to an existing mail folder
forward to another email address
or delete it
links are available to review the rules file,
you can review the log file to check which rules are matched
the log file is rotated weekly and kept for two weeks but you can delete it
if for example you are checking current activity and have a lot of information
')));
print $q->p ('<a href="viewlogfiles?filename=qmail/current&matchPattern=&highlightPattern=">Review</a> qmail/current or
<a href="viewlogfiles?filename=qpsmtpd/current&matchPattern=&highlightPattern=">Review</a> qpsmtpd/current in the View log files panel.');
print $q->endform;
print $q->p ($q->hr, $q->font ({size => "-1"}, "https://wiki.koozali.org",
$q->a ({href => $q->url (-absolute => 1) . ""}, 'Return to main'), " ..."));
print $q->end_html;
return;
}