#!/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
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.

")); } 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.

")); } else { print $q->p (esmith::cgi::genSmallRedCell ($q, "Mail is being selectivly delivered to Zarafa.

")); } } print $q->p ($q->td ($q->a ({href => $q->url (-absolute => 1) . "?state=globalEnableProc"}, 'Modify'), " global mailfiltering rules and system settings.

")); #------------------------------------------------------------ # 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.
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.

")); } else { print $q->Tr ($q->td ($q->a ({href => $q->url (-absolute => 1) . "?state=showhide&action=yes"}, 'Show'), "the . and _ Pseudonyms.

")); } print ""; 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, '
'); } 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, '
'); } } } } } 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 '
'; }#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 here'); print ""; 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 '
'; } #------------------------------------------------------------ # 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 ""; 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 '
'; } 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 ''; print ''; 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 ''; print ''; 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 ''; print ''; 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 ""; #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 (' '), $q->td (' ')); #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 '
'; } 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],
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 ''; print ''; 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,
Each user enables and configures TMDA at domainname/tmda
'. "$acct has $status enabled tmda at /tmda

". 'Then set TMDA as enabled in the SME Accounts database
this sets the users .qmail file up the SME way.
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 ""; #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 (' '), $q->td (' ')); 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 '
'; 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 ''; } 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, "; $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 ''; } 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 ('configure 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 ''; print ''; 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 ''; print ''; 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 () { print "$_
\n"; } close INF; } if ( -e "$file" ) { open (INF,"$file") or die ("can't open $file to read: $1. "); while () { print "$_
\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 ('

* Global rules
* Individual accounts
* Delivery options
* Mail Rules

Global rules

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

Individual accounts

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

Delivery options

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 smeserver-mailsorting Provides configuration files to create mail rules that are processed by either procmail or maildrop smeserver-vacation Provides for a vacation message to be sent, for example the user is out of the office dungog-tmda-cgi 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

Mail Rules

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 ('Review qmail/current or Review 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; }