diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3aa8108 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.rpm +*.log +*spec-20* +*.tgz diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9346c57 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +# Makefile for source rpm: smeserver-email-management +# $Id: Makefile,v 1.1 2020/06/10 08:56:01 brianr Exp $ +NAME := smeserver-email-management +SPECFILE = $(firstword $(wildcard *.spec)) + +define find-makefile-common +for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done +endef + +MAKEFILE_COMMON := $(shell $(find-makefile-common)) + +ifeq ($(MAKEFILE_COMMON),) +# attept a checkout +define checkout-makefile-common +test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2 +endef + +MAKEFILE_COMMON := $(shell $(checkout-makefile-common)) +endif + +include $(MAKEFILE_COMMON) diff --git a/README.md b/README.md index 1e278e5..62e9807 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,15 @@ -# smeserver-email-management +# smeserver-email-management -SMEServer Koozali developed git repo for smeserver-email-management smecontribs \ No newline at end of file +SMEServer Koozali developed git repo for smeserver-email-management smecontribs + +## Wiki +
https://wiki.koozali.org/Email-Management + +## Bugzilla +Show list of outstanding bugs: [here](https://bugs.koozali.org/buglist.cgi?component=smeserver-email-management&product=SME%20Contribs&query_format=advanced&limit=0&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=CONFIRMED) + +## Description + +
*This description has been generated by an LLM AI system and cannot be relied on to be fully correct.* +*Once it has been checked, then this comment will be deleted* +
diff --git a/additional/COPYING b/additional/COPYING new file mode 100644 index 0000000..196760e --- /dev/null +++ b/additional/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/contriborbase b/contriborbase new file mode 100644 index 0000000..9b7fd51 --- /dev/null +++ b/contriborbase @@ -0,0 +1 @@ +contribs10 diff --git a/createlinks b/createlinks new file mode 100644 index 0000000..53319da --- /dev/null +++ b/createlinks @@ -0,0 +1,19 @@ +#!/usr/bin/perl -w + +use esmith::Build::CreateLinks qw(:all); +use File::Basename; +use File::Path; + +#wrong way +#safe_symlink("/etc/e-smith/web/functions/wrapper","root/etc/e-smith/web/panels/manager/cgi-bin/user-email"); +#real way +panel_link("user-email","manager"); + +#-------------------------------------------------- +# actions for smeserver-durep-update: +#-------------------------------------------------- +my $event = "smeserver-email-management-update"; + +# yum plugin already call this +#event_link("navigation-conf", $event, "50"); + diff --git a/root/etc/e-smith/events/smeserver-email-management-update/.gitignore b/root/etc/e-smith/events/smeserver-email-management-update/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/e-smith/web/functions/user-email b/root/etc/e-smith/web/functions/user-email new file mode 100755 index 0000000..03654a7 --- /dev/null +++ b/root/etc/e-smith/web/functions/user-email @@ -0,0 +1,2019 @@ +#!/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; +} + diff --git a/root/etc/e-smith/web/panels/manager/cgi-bin/user-email b/root/etc/e-smith/web/panels/manager/cgi-bin/user-email new file mode 120000 index 0000000..c31c040 --- /dev/null +++ b/root/etc/e-smith/web/panels/manager/cgi-bin/user-email @@ -0,0 +1 @@ +../../../functions/user-email \ No newline at end of file diff --git a/smeserver-email-management.spec b/smeserver-email-management.spec new file mode 100644 index 0000000..6c7e53a --- /dev/null +++ b/smeserver-email-management.spec @@ -0,0 +1,266 @@ +# $Id: smeserver-email-management.spec,v 1.3 2021/02/23 03:52:15 jpp Exp $ +# Authority: dungog +# Name: Stephen Noble + +Summary: modify and monitor maildelivery for all users +%define name smeserver-email-management +Name: %{name} +%define version 1.3 +%define release 6 +Version: %{version} +Release: %{release}%{?dist} +License: GPL +URL: http://www.dungog.net/sme +Group: SMEserver/addon +Source: %{name}-%{version}.tar.xz + +BuildArchitectures: noarch +BuildRoot: /var/tmp/%{name}-%{version} +Provides: dungog-email = %{version}-%{release} +Requires: e-smith-release >= 9.0, +Requires: smeserver-vacation +Requires: smeserver-mailsorting +#Requires: smeserver-userpanel, userpanel causes endless problems +BuildRequires: e-smith-devtools >= 1.13.1-03 +AutoReqProv: no + +%description +SME Server panel to allow admin to enable and configure procmail, +maildrop, vacation or forwarding for users, +see all users mail delivery methods in a table. +Admin can add global rules and apply them to all users, +set advanced mail properties. +Original work of Stephen Noble dungog.net. + +%prep +%setup +mkdir -p root/etc/e-smith/events/smeserver-email-management-update + +%build +perl createlinks + +#LEXICONS=$(find root/etc/e-smith/{locale/,web/functions/} -type f ) +#for lexicon in $LEXICONS +#do +# /sbin/e-smith/validate-lexicon $lexicon +#done + +%install +rm -rf $RPM_BUILD_ROOT +(cd root ; find . -depth -print | cpio -dump $RPM_BUILD_ROOT) +rm -f %{name}-%{version}-filelist +/sbin/e-smith/genfilelist $RPM_BUILD_ROOT > %{name}-%{version}-filelist +echo "%doc COPYING" >> %{name}-%{version}-filelist + +%clean +%pre +%preun +%post +%postun + +%files -f %{name}-%{version}-filelist +%defattr(-,root,root) + +%changelog +* Sat Sep 07 2024 cvs2git.sh aka Brian Read 1.3-6.sme +- Roll up patches and move to git repo [SME: 12338] + +* Sat Sep 07 2024 BogusDateBot +- Eliminated rpmbuild "bogus date" warnings due to inconsistent weekday, + by assuming the date is correct and changing the weekday. + +* Mon Feb 22 2021 Jean-Philipe Pialasse 1.3-5.sme +- fix wrong link in function [SME: 11373] +- add event to avoid reboot [SME: 10951] + +* Fri Oct 23 2020 Brian Read 1.3-4.sme +- Initial import to SME10 tree [SME: 10951] + +* Sat Feb 02 2019 Jean-Philipe Pialasse 1.3-3.sme +- fix not able to display log and config files for users [SME: 10731] + +* Mon May 29 2017 Jean-Philipe Pialasse 1.3-2.sme +- add support for admin account [SME: 9737] + +* Mon Aug 08 2016 Jean-Philipe Pialasse 1.3-1.sme +- initial import to SME 9 + +* Wed Jul 21 2010 Stephen Noble 1.2-12 +- fix remember destination when modifying + +* Tue Jun 09 2009 Stephen Noble 1.2-11 +- fix path for ssl template expansion + +* Sat Mar 07 2009 Stephen Noble 1.2-10 +- Configure user settings for zarafa + +* Tue Oct 31 2006 Stephen Noble 1.2-9 +- MaxScannerSize added + +* Tue Oct 31 2006 Stephen Noble 1.2-8 +- qmail settings added + +* Mon Oct 30 2006 Stephen Noble +- qpsmtpd settings available in globals page +- [1.2-7] + +* Sat Oct 28 2006 Stephen Noble +- review domain mailserver delegation +- review group Visible property +- set qpsmtpd Bcc setting for mail archiving +- [1.2-6] + +* Wed Aug 23 2006 Stephen Noble +- remove strict check on mailrule criterion +- [1.2-5] + +* Thu May 04 2006 Stephen Noble +- TMDA support added +- [1.2-4] + +* Wed Apr 05 2006 Stephen Noble +- cosmetic, comment fixed +- [1.2-3] + +* Fri Mar 24 2006 Stephen Noble +- maildrop forwarding note added +- vacation system call changed to actions/qmail-update-user +- spamboss note added +- [1.2-2] + +* Thu Sep 22 2005 Stephen Noble +- simplified and updated for sme7 +- [1.2-1] + +* Fri Jul 01 2005 Stephen Noble +- removed requirement for perl-Unicode-IMAPUtf7 +- [1.0-6] + +* Tue Apr 26 2005 Stephen Noble +- removed junkfilter option for simplification +- corrected messages due to changes in other rpms +- mailblocking and pattern matching msg removed +- [1.0-5] + +* Sat Jan 29 2005 Stephen Noble +- supports spamassassin ver.3 / sme-spamfilter +- fixed global systemdefault spam sorting +- modify user TMDA usage +- [1.0-4] + +* Tue Dec 07 2004 Stephen Noble +- shows TMDA usage +- [1.0-3] + +* Mon Oct 18 2004 Stephen Noble +- cosmetic changes, refreshes correctly, log filter rblsd changed to rbls +- [1.0-2] + +* Thu Aug 12 2004 Stephen Noble +- rpm renamed dungog-email +- function processmail renamed dungog-email, will affect any userpanel delegations +- display users MailDomains & MailLocal settings from dungog-mailblocking +- display each users pseudonyms, option to hide . and _ versions +- display 'virtual domain' pseudonyms and domain delegations from dungog-vdomain +- display admin in user table +- antivirus and filtering status consolidated into one sub panel +- make admin aware of the pattern matching rpms +- junkfilter userpanel removed +- [1.0-1] + +* Wed Jul 28 2004 Stephen Noble +- removed tmda +- you now modify junkfilter rules from the command line +- [0.2-11] + +* Wed Jul 28 2004 Stephen Noble +- cosmetic, altered comment about spamassassin +- [0.2-10] + +* Wed Apr 07 2004 Stephen Noble +- smtp/rbls settings saved correctly +- individual email forwarding address shown on summary page +- [0.2-9] + +* Sun Mar 28 2004 Stephen Noble +- requires sme 6.0 +- smtp settings added + rbls, max message size +- updates userpanel panel links on install and uninstall +- [0.2-8] + +* Fri Mar 05 2004 Stephen Noble +- procmail forward to user fixed +- procmail says folder not in correct format fixed +- userpanel-procmail-pro moved to GPL userpanel +- [0.2-7] + +* Thu Dec 04 2003 Stephen Noble +- individual setting = systemdefault unless set otherwise +- dovecoat imap folders fixed in procmail dropdown lists +- rbls only works on 5.6, custom fragments added + requires e-smith-mailfront-1.0.0-02rbl.noarch.rpm +- spamassasin sme5/sme6 differences added + +- [0.2-7] + +* Thu Dec 04 2003 Stephen Noble +- individual setting = systemdefault unless set otherwise +- dovecoat imap folders fixed in procmail dropdown lists +- rbls only works on 5.6, custom fragments added + requires e-smith-mailfront-1.0.0-02rbl.noarch.rpm +- spamassasin sme5/sme6 differences added +- [0.2-6] + +* Mon Sep 08 2003 Stephen Noble +- larger text field for rbls entry +- logic improved deciding between individual and global delivery + will use individual setting until individual setting is systemdefault +- logic improved in creating .procmailrc + if you have both junkfilter and spamassassin installed +- [0.2-5] + +* Thu Aug 21 2003 Stephen Noble +- SME 6.0 support, servermanager navigation & shows tables correctly +- minor bug fixes +- [0.2-4] + +* Sun Aug 03 2003 Stephen Noble +- mail sent with offline dialup server with rbls installed but off is not delayed +- new delivery action option, tag spam but leave for mail client to sort +- [0.2-3] + +* Mon Jun 02 2003 Stephen Noble +- added notes, where to get spamassassin, contibs.org +- a filtering spamboss needs this procmail rule 'custom headers' "spamboss@" > 'spamfolder' +- [0.2-2] + +* Thu May 29 2003 Stephen Noble +- lots of changes, test before using on production machine +- improved display on dungog > emailfiltering panel + shows individual override on spamfilter + shows which global spamfilter and the sort/delete/fwd action +- uses tmda-0.78, + and tmda-cgi-0.9 for user interface, NB tmda-cgi-0.9 is later than 0.71 + www.servername/tmda, authenticates against users system password + admin or user still has to enable tmda with panels +- adds userpanel-procmail-pro, + adds second test for procmail, if x & if y then... + restricts characters in criterion to avoid broken rules, it may be too strict + email characters you want added to the allowed list +- incorporates better notification and seperate control of spamassassin + deliver tagged spamassassin spam to folder/spammboss/delete it + junkfilter spam folder changed to junkmail to be consistant with spamassassin +- server-manager > emailfiltering > global > filters + choose between junkfilter or spammassassin or use both + tmda runs before/without procmail and stops 99.9%% + function added to reset individual overrides to null + the default in now 'null' but was 'disabled' + this was a bug as the individual setting overrides the global setting + userpanel-procmail-pro is fixed, userpanel-procmail will be in userpanel.v12 +- [0.2-1] + +* Tue Jul 23 2002 Stephen Noble +- initial release +- [0.1-1] +