#!/usr/bin/perl -w # Websieve Cyrus Mail Account Management Tool by Alain Turbide # $version="0.63a"; use CGI qw(:standard :html3); use CGI::Carp qw(fatalsToBrowser set_message); #predeclare variables from websieve.conf use vars qw($sieveport $imapport $defaultscript $allowadvanced $header1); use vars qw($maildomain $mailhostappend $problem_email @namespaces $includepublic); use vars qw($usereply $usereject $useacl $usediscard $usevariablefield); use vars qw($useregex $usevacation $usereply $shortacl $usemulti $usematches); use vars qw($usesearchflg $usecustom $keepredirect $quotemailbox $tb $cb $bg); use vars qw($showmenu $showhome $showserver $nobyline $expires $OLDMODIFY); use vars qw($LOGOUTURL $HOMEURL $HELPURL $VIEWRULESURL $SETVACATIONURL); use vars qw($SETACLURL $ADDRULEURL $SETPASSWORDURL $ADVANCEDURL $ADMINMENUURL); use vars qw($FORWARDALLURL $useforwardall $IMAPERROR $SIEVEERROR $imap); use vars qw($server_hosts $useserverselect $useimapSSL $usesieveSSL); use vars qw($returntoview $usesize $err @list %vacation %modevals @serverlist); use vars qw($uid $res $scriptname $scriptdef $pseudo $mode $sieve); use vars qw($imapserver $pass $op $msgdest $namespace $regexflg $regexbit); use vars qw($sizeflg $copyflg $copybit $searchbit $tmp $matchflg $version); use vars qw($sizebit $change $line $script $oldscript $oldmode $rules); use vars qw($useauth %scripts $rulelist $rulesorig $delimiter $skey); use vars qw($useservercookie $alt_namespace $vacation_prelude $userc4 $maxrules); use vars qw($useldapextras $gomodifyit $ldappassattr $LDAP_SERVER); use vars qw($LDAP_BASEDN $ENCRYPT_PASS $selectbyacl $partition); use vars qw($keepbit $keepflg $ismanager $cyrusadminuid $unixhiersep); use vars qw($sendcmd $touser $fromuser $useprocmail ); $unixhiersep="\." if !$unixhiersep; if( $useldapextras ) { use vars qw($NEWUSERURL $NEWGROUPURL $LDAPSEARCHURL $manageruid); use vars qw(%ldapdefgroupatts %ldapdefpersonatts @ldappersonatts); use vars qw($ldapmemberatt $ldapgroup_ou $ldapperson_ou $mgrrecmail); use vars qw(%donotdisplay $suggestpass $allowchghost $mailhostatt); } #default to using RC4 encryption for cookies of $userc4 not defined $userc4=1 if !defined $userc4; $maxrules=400; BEGIN { sub handle_errors { my $msg =shift; if ($msg=~/login|unknown/i) { &incorrect_login; } else { print"

Received a program error!

Error: $msg"; } } set_message(\&handle_errors); $program_url= url(-absolute=>1) if !$program_url; require './funclib.pl'; require './websieve.conf'; # get the list of available imap servers @serverlist=keys %server_hosts; if ($useauth) { require './auth.pl';} if ($useldapextras) { require './ldapextras.conf'; require './ldapextras.pl'; } } if ($useprocmail) { $allowadvanced=0; $useregex=0; $usesearchflg=0; $usemulti=0; } $remote_host=remote_host(); if (!$skey) { print header,"

Variable \$skey in websieve.conf NOT set!
You MUST set this variable to a random string of characters for encryption of Cookie data" ; exit; } my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $skey=$yday.$skey.$yday; $session_exp='1800' if !$session_exp; $notflghash=''; $copybit=1; $sizebit=2; $searchbit=4; $keepbit=8; $regexbit=128; $error=''; $sencode_params=''; %modevals = ( "on","Yes", "off","No"); $op='' if !$op; if (param('op')) { if (param('op') eq 'logout' || param('op') eq 'login') { $auth_params{'uid'}='clear'; $auth_params{'pass'}='clear'; $encode_params=&encode_list(%auth_params); $encode_params=&Encrypt($encode_params,$skey) if !$userc4; $encode_params=&encrypt_rc4($skey,$encode_params) if $userc4; $encode_params=&encode_base64($encode_params) if $userc4; $auth_cookie=cookie(-name => 'websieve', -value=>$encode_params, -path=>"$program_url", -expires => 'now'); print header(-cookie=> $auth_cookie); param('op',''); print hidden('op'); &web_authenticate; &byline; &closeimap; &closesieve; exit; } } $gotcookie=''; $encode_params=cookie('websieve'); if (!$encode_params) { $encode_params=param('s') if param('s'); } if (!$encode_params && !param('login') ) { print header; &web_authenticate; &byline; exit; } else { if (param('login')) { $uid = param('login'); $pass = param('password'); } else { $gotcookie=1; $encode_params=&Decrypt($encode_params,$skey) if !$userc4; $encode_params=&decode_base64($encode_params) if $userc4; $encode_params=&encrypt_rc4($skey,$encode_params) if $userc4; %auth_params=&decode_list($encode_params); $uid=$auth_params{'uid'}; $pass=$auth_params{'pass'}; if ($uid eq 'clear') { print header; &web_authenticate; &byline; exit; } my $authhost=$auth_params{'remotehost'} if $auth_params{'remotehost'}; my $etime=$auth_params{'exp'} if $auth_params{'exp'}; if ((time - $etime) > $session_exp) { print header,"
Your Session has expired!

"; &web_authenticate; &byline; exit; } if ($authhost && $authhost ne $remote_host) { print header,"
Remote host does not match Session host!

"; &web_authenticate; &byline; exit; } } # else param('login') if (param('viewscript')) { $viewscript=param('viewscript'); $gotcookie=''; } else { $viewscript=$auth_params{'script'}; } param('viewscript',$viewscript); if (param('server') ) { $userserver=param('server'); $gotcookie=''; } else { $userserver=$auth_params{'server'} if $auth_params{'server'}; } if ($useauth && !$userserver) { # get imapserver address from auth database $userserver=&auth_getuserserver; } $userserver=&getserverdata($userserver); $auth_params{'uid'}=$uid; $auth_params{'pass'}=$pass; $auth_params{'server'}=$userserver; $auth_params{'script'}=$viewscript; $auth_params{'remotehost'}=$remote_host; $auth_params{'exp'}=time; $encode_params=&encode_list(%auth_params); $encode_params=&Encrypt($encode_params,$skey) if !$userc4; $encode_params=&encrypt_rc4($skey,$encode_params) if $userc4; $encode_params=&encode_base64($encode_params) if $userc4; $auth_cookie=cookie(-name => 'websieve', -value=>$encode_params, -path=>"$program_url", -expires => $expires); if ($uid ne "" && $pass ne "") { if (&bind < 0) { print header; &incorrect_login; } } else { print header; &incorrect_login; } if (!$allowadvanced) { foreach $advanceduser (@advanceduser) { $allowadvanced=1 if $uid=~/^$advanceduser/i; } } $sencode_params=&URLEncode($encode_params) if $useservercookie; # $sencode_params=&URLEncode($encode_params) if !$gotcookie; &addservercookie($sencode_params) if !$gotcookie; # $useservercookie=1 if !$gotcookie; if (!$gotcookie && !$useservercookie) { print header(-cookie=> $auth_cookie); } else { print header; } $ismanager=1 if (($uid eq $manageruid) || ($uid eq $cyrusadminuid)); undef $gotcookie; &modify_screen; &closeimap; &closesieve; print hr if $op ; &byline if ($op ne 'ldapsearch'); exit; } sub addservercookie { my ($cookie) =@_; $VIEWRULESURL=~s/>/&s=$cookie>/; $FORWARDALLURL=~s/>/&s=$cookie>/; $SETVACATIONURL=~s/>/&s=$cookie>/; $SETACLURL=~s/>/&s=$cookie>/; $ADDRULEURL=~s/>/&s=$cookie>/; $SETPASSWORDURL=~s/>/&s=$cookie>/; $ADVANCEDURL=~s/>/&s=$cookie>/; $ADMINMENUURL=~s/>/&s=$cookie>/; } sub initscripts { my ($scriptname,$scriptdef,$mode,$viewscript,$scriptsave,$deletescript,$scriptlist); my (%scripts)=@_; $scriptdef=$scripts{'scriptdef'}; $mode=$scripts{'mode'}; $scriptlist=$scripts{'scriptlist'}; $viewscript=$scripts{'viewscript'}; $scriptname=$viewscript; $deletescript=''; my @scriptlist; @scriptlist=split (/ /,$scriptlist); if ($scripts{'active'} && $viewscript eq $scripts{'active'}) { $scriptdef='on'; } $scriptdef='on' if !$usemulti; param("lastviewscr",$viewscript); print hidden("lastviewscr",$viewscript); param("viewscript",$viewscript); param("scriptname",$scriptname); param("deletescript",$deletescript); if ($op eq 'advanced') { print "
"; print "
"; print "
Advanced Settings
"; print "
"; } if ($usemulti && $op eq 'advanced') { print ""; param("scriptdef",$scriptdef); print ""; print "\n"; print ""; } else { print hidden("scriptdef",$scriptdef); print hidden("viewscript",$viewscript); print hidden("scriptname",$scriptname); } if ($usemulti && $op eq 'advanced') { print "\n"; } if ($allowadvanced && $op eq 'advanced') { param("mode",$mode); print "\n"; } else { param("mode",$mode); print hidden("mode"); } print "
Current Scripts:",$scriptlist," (currently active script shown with *)
Activate Script?: ",radio_group("scriptdef",['off','on'],$scriptdef,'',\%modevals),"
Edit script name: ",textfield("viewscript",$viewscript,12,""),"
Save to script name: ",textfield("scriptname",$scriptname,12,""),"
Delete script name: ",textfield("deletescript",$deletescript,12,""),"
Script Mode: ",radio_group("mode",['basic','advanced'],$mode,'',''),"
"; print "NOTE: You will lose ALL changes made to a script in advanced mode if you switch back to basic mode." if ($mode eq 'advanced' && $op eq 'advanced'); } sub printpass { print "
"; print "
Change Password","
"; print "
"; print "\n" if ($ismanager && $useauth); print " \n"; print " \n"; print "
User ID:",textfield('authuser'),"
New Password:",password_field('pass1'),"
New Password (again):",password_field('pass2'),"
\n"; print "
"; } sub modifyacl { my $mbx=""; my $err=""; return if (defined param('Select')); return if (defined param('Save Changes')); return if (param('action') && param('action') eq 'confirmmbxdel'); $mbx=param("mbx") if defined param("mbx"); my $partition = param('partition') if param('partition'); my $acl=''; my $generalrights=''; $generalrights=param('rights') if defined param('rights'); $acl=join('',param('acl')) if defined param("acl"); $acl=$generalrights.$acl; my ($useracl)=""; $useracl=param('acluser') if defined param('acluser'); my $maxquota; $maxquota=param('aclmaxquota') if defined param('aclmaxquota'); my ($newmbx)=""; $newmbx=param('newmbx') if defined param('newmbx'); $mbx=~s/^ +//g; $mbx=~s/ +$//g; my $mbxorig=$mbx; $userspace=1; # check if folder is in an additional namespace if (param('Select Folder')) { my $selected=param('selectedmbx'); $selected=~/^\[([^\]^\[]*)\]/; $selected=$1; param('mbx',$selected.'*'); return; } if (param('Select Server')) { my $imapserver=param('server'); return; } if (param('Up One Level')) { my $selected=param('selectedmbx'); $selected=~/^\[(.*?)\]/; $selected=$1; $selected=~s/$unixhiersep?[^.]+$//; param('mbx',$selected.'*'); param('selectedmbx',''); return; } foreach $namespace (@namespaces) { if ($newmbx) { if ($newmbx=~/^$namespace./i) { $mbx="$newmbx"; $userspace=0; last; # stop checking } } elsif ($mbx=~/^$namespace./i) { $userspace=0; last; # stop checking } } if ($userspace) { if ($alt_namespace) { if ($mbx) { $newmbx=$unixhiersep.$newmbx if $newmbx; } $mbx="".$mbx.$newmbx.""; } else { ## $mbx=~s/^INBOX/user$unixhiersep$uid/i; $newmbx=$unixhiersep.$newmbx if $newmbx; $mbx="".$mbx.$newmbx.""; } } if ($ismanager && !$newmbx) { $mbx=$mbxorig; } elsif ($ismanager) { $mbx=$newmbx; $mbx=~s/^$unixhiersep//; } my $change; #print br,"mbx=$mbx, newmbx=$newmbx",br;return; if ($newmbx && param('Create Mailbox')) { $err=&createmailfolder($mbx,$partition); if ($err) { print hr,"Createmailbox Error: $err
"; return; } else { $change=1 ; if ($ismanager) { param('mbx',$mbx); print hidden('mbx'); } } } if (!$mbx || !(( $acl && $useracl) || $maxquota)) { return; } if (param('Set Acl')) { $mbx="\"$mbx\"" if ($quotemailbox==1); if ( $mbx && !&listmailbox($mbx)) { $err="Mailbox does not exist!"; } else { $err=&setacl($mbx,$useracl,$acl); $change=1; } } if ($maxquota && param('Set Quota')) { $err=&setquota($mbx,$maxquota); $change=1; } if ($err) { print hr,"Error modifying $mbx, Err: $err\n",br; return; } print hr,"Mailbox modification successful..
" if $change; return; } #### View ACL's sub viewacl { my ($tmp,@acl); my (%aclhash) =( "l"=>"[l]ook", "r"=>"[r]ead", "s"=>"[s]een", "w"=>"[w]rite", "i"=>"[i]nsert", "p"=>"[p]ost", "c"=>"[c]reate", "d"=>"[d]elete", "a"=>"[a]dmin", #"none"=>"No Access" ); my $mbx; $mbx=param('mbx') if param('mbx'); if ($ismanager) { #$mbx="INBOX*" if !$mbx; $mbx="user".$unixhiersep.$uid.$unixhiersep."*" if !$mbx; @mailboxes=&listmailbox($mbx) ; } if (param('Delete This Mailbox') && param('delmailbox')) { param('Delete This Mailbox',''); param('action','confirmmbxdel'); &confirmmbxdelete; print hidden('action'); print end_form; print end_html; exit; } my $subtext="Folder"; $subtext="Mailbox" if $ismanager; my (%rightshash)=( "lrs"=>"Read (lrs)", "lrsp"=>"Post (lrsp)", "lrswipcd"=>"Write (lrswipcd)", "lrsip"=>"Append (lrsip)", "lrswipcda"=>"All (lrswipcda)", "lrswipd"=>"Write-no create(lrswipd)", "none"=>"Remove access (none)" ); my (@rights)=("lrs","lrsp","lrswipcd","lrsip","lrswipcda","lrswipd","none"); my (@acls)=("l","r","s","w","i","p","c","d","a","none"); print "",hr; print "
"; my (@tmpmbx,$eachmbx,$eachfolder); my ($user,$useracl); print "
ACL View for user mailbox","
"; print ""; print ""; if ($shortacl ) { print ""; } else { print ""; } @tmpmbx=@mailboxes; undef @acl; my (@tmp,$acl_tmp,$user_tmp); while (@tmpmbx) { $eachmbx=shift(@tmpmbx); next if ($eachmbx!~/\S/); $eachfolder="$eachmbx"; # check if folder is in an additional namespace foreach $namespace (@namespaces) { if ($eachmbx=~/^$namespace./i) { $eachfolder="$eachmbx"; last; # stop checking } } $eachfolder="\"$eachfolder\"" if ($quotemailbox==1); @tmpacl=&getacl($eachfolder) if $eachfolder; # print "tmpacl=$eachfolder==@tmpacl
"; $tmp=join(' ',@tmpacl); #remove stray mailbox names that have spaces $tmp=~s/^.*?" *//; @tmp=split(/ /,$tmp); # print "tmp2acl=$tmp
"; $tmp=''; while (@tmp) { $user_tmp=shift(@tmp); next if !$user_tmp; $acl_tmp="[".shift(@tmp)."]" if @tmp; $tmp.=", " if $tmp; $tmp.="$user_tmp=$acl_tmp"; } if ($shortacl) { if (!$tmp) { $tmp=''; } $tmp="[$eachmbx]---->".$tmp; push (@aclview,$tmp); } else { print ""; } } @tmpbox=@mailboxes; push (@tmpbox," ") if $alt_namespace; print "" if ($shortacl && $ismanager); print "
[$subtext]-->UserID [acl]
Folder NameUserID [acl]
$eachmbx$tmp
",popup_menu('selectedmbx',[@aclview],' ') if ($shortacl); print "  ".submit('Select Folder')." ".submit('Up One Level')."
"; print "
"; print br,"
"; $mbx=shift(@tmpbox); param('mbx',$mbx); param('acluser',''); param('newmbx',''); param('acl',''); param('rights','-'); print "
Access Control List Entry: $uid","
" if !$ismanager; print "
Mailbox ACL and Quota Management
" if $ismanager; print ""; print ""; } else { print textfield("mbx","",48)."   ".submit("Select","Select $subtext")."  (Wildcards allowed [*])"; } print ""; print ""; print ""; print ""; if ($ismanager) { my @imapquota=&getquota($mbx) if ($havequota || !$useprocmail); param('aclmaxquota',''); param('aclmaxquota',$imapquota[2]); print ""; } print "
$subtext:"; if (!$ismanager) { print popup_menu('mbx',[@tmpbox],' ')."
Foreign User ID:".textfield("acluser")." (User ID to assign access rights)  ".submit("Set Acl")."
General Rights:".radio_group('rights',[@rights],"-",'',\%rightshash)."
Specific Rights:".checkbox_group('acl',[@acls],'','',\%aclhash)."
<$cb>Disk Quota Limit (KB):"; print textfield('aclmaxquota',$imapquota[2],20,40); print "  Disk Quota Used (KB):  ".$imapquota[1]."  ".submit("Set Quota")."
"; print "
",br; print "
"; print "
New Folder Creation
" if !$ismanager; print "
$subtext Creation
" if $ismanager; print ""; param('delmailbox',''); param('newmbx',''); param('partition',''); print ""; print "" if $ismanager; print "" if $ismanager; print "
$subtext to Create:".textfield("newmbx")."  "; print "Partition: ",textfield("partition") if $ismanager; print"  ". submit('Create Mailbox',"Create $subtext")."  
$subtext to Delete:".textfield("delmailbox")."   ".submit("Delete This Mailbox","Delete $subtext")."
Mail Server: ",popup_menu("server",[@serverlist],$imapserver,\%serverdisplay) . "   ".submit("Select Server","Select Server")."
"; print "
"; } sub getuserinfo { my ($res,$script,$mode,$pseudo,$oldmode); my (@tmpboxes,@tmprules,@tmpscr); my (@scriptlist,$scriptlist,$scriptname,$scriptdef); undef @rules; undef @mailboxes; undef @quota; undef %vacation; undef %scripts; #creates global variables $mode,@rules,@mailboxes,@quota and %vacation; # get quota @quota=&getquota("INBOX") if ($havequota || !$useprocmail); if ($IMAPERROR !~ /no errors/i && !$ismanager && $IMAPERROR) { $error=$IMAPERROR; &closeimap; &closesieve; &incorrect_login; exit; } #print "quota=@quota"; # get mailboxes @tmpboxes=&listmailbox("*") if (!$ismanager); # remove "user.userid" prefix #place empty element in @mailboxes for display purposes push (@mailboxes,' '); while (@tmpboxes) { $tmpline=shift(@tmpboxes); chomp($tmpline); $tmpline=~s/\r//g; if ($alt_namespace) { $tmpline=~s/^ *user$unixhiersep$uid$unixhiersep* * /INBOX$unixhiersep/i; } else { $tmpline=~s/^ *user$unixhiersep$uid$unixhiersep* *//i; } #thiswill be set true if "anyone" identifier has any privs # for the folder defined by $tmpline my $public=1; #this will be set true if this user has admin privs for #this folder my $ownedbyuser = 0; #Display all folders if Manager is user $includepublic=1 if $ismanager; if ($selectbyacl) { my @tmpacl = &getacl($tmpline); #following 5 lines fix returned acl values when folders contain # spaces when using IMAP::Admin $tmp=join(' ',@tmpacl); #remove stray mailbox names that have spaces $tmp=~s/^.*?" *//; @acl=split(/ /,$tmp); $tmp=''; while(@acl) { my $line=shift(@acl); $public = 1 if ($line=~ /anyone/i); if ($line=~/$uid/i) { my $useracl=shift(@acl); $ownedbyuser=1 if ($useracl=~/a/i); } } $tmpline = "" if (($public)&&(!$ownedbyuser)&&(!$includepublic)); } else { if (($tmpline!~/^INBOX|$uid/i) && (!$includepublic)) { $tmpline=""; } } push (@mailboxes,$tmpline) if ($tmpline=~/\S/); } # get mailboxes from other namespaces foreach $namespace(@namespaces) { push (@mailboxes,&listmailbox("$namespace.*")); } #get scriptlists if (!$useprocmail) { &opensieve($uid,$pass,$sieveport,$imapserver) if (!$sieve); if (!$sieve) { print start_html(-title=>'Error login in to Sieve Server',-BGCOLOR=>'red'), h2("Error login in to Sieve Server: $imapserver
"), "There is a problem accessing the Sieve Server, click HERE and try again.\n"; &closesieve; &closeimap; exit; } @scriptlist=&listscripts; while (@scriptlist) { $_=shift(@scriptlist); if (/\*|ACTIVE/) { $defaultscript=$_; $defaultscript=~s/\*| *ACTIVE//g; $_="".$defaultscript."*"; $scripts{'active'}=$defaultscript; } if ($scriptlist) {$scriptlist.=', ';} $scriptlist.=$_; } if (!param('viewscript')) { $scriptname=$defaultscript; $viewscript=$defaultscript; $scriptdef='off'; } else { $scriptname=param('scriptname'); $viewscript=param('viewscript'); $scriptdef=param('scriptdef'); } } # if not useprocmail # get sieve scripts if (!$useprocmail) { $pseudo=&getscript($viewscript."_pseudo"); $script=&getscript($viewscript); $script=$script.$pseudo; } else { $script=&auth_getattrib($matchingrules); } if ( $SIEVEERROR && $SIEVEERROR !~ /No Error/i && $SIEVEERROR !~ /doesn.t exist/i) { print "Error: getscript->".$SIEVEERROR."
"; } #combined script and pseudo files to enable easy compatibility with old method #of having rules in same file as script @tmprules=split(/\n/,$script) if ($script); @tmpscr=grep !/#rule|#mode|#vacation|##pseudo/i,@tmprules; #remove pseudo rules and CR's from main script $script=join("\n",@tmpscr); @tmprules=grep /^ *\#\#pseudo|^ *#rule|^ *#mode|^ *#vacation/i, @tmprules; $pseudo=join("\n",@tmprules); while (@tmprules) { $_=shift(@tmprules); if (s/^ *#rule&& *//i) { s/\r//g; push(@rules,$_); } elsif (/^ *#vacation&&(.*)&&(.*)&&(.*)&&(.*)/i) { $vacation{'days'}=$1; $vacation{'addresses'}="$2"; $vacation{'text'}=$3; $vacation{'mode'}=$4; $vacation{'addresses'}=~s/\\@/\@/g; $vacation{'addresses'}=~s/\"//g; } elsif (/^ *#mode&&(.*)/) { $mode=$1; $oldmode=$mode; } } if ( !defined %vacation) { $vacation{'mode'}='off'; $vacation{'days'}='1'; $vacation{'text'}='On vacation for the next week'; } if (!$vacation{'addresses'}) { $vacation{'addresses'}="$uid\@$maildomain $uid\@$mailhostappend"; } if ($allowadvanced && param('mode') && (param('viewscript') eq param('scriptname'))) { $mode=param('mode'); } elsif (!$allowadvanced || !$mode) { $mode='basic'; } $scripts{'script'}=$script if $script; $scripts{'pseudo'}=$pseudo; $scripts{'mode'}=$mode; $scripts{'oldmode'}=$oldmode; $scripts{'scriptname'}=$scriptname; $scripts{'viewscript'}=$viewscript; $scripts{'scriptlist'}=$scriptlist; $scripts{'scriptdef'}=$scriptdef; $scripts{'deletescript'}=param('deletescript'); return %scripts; } sub printscript { my ($script)=@_; param("script",$script); print "
"; print ""; print "
Sieve Script Edit
",textarea("script",$script,30,100,"","wrap=virtual"),"
"; } # print web form and display all current rules # also display form to accept a new rule sub printrules { # my (@fieldlist)=("subject","from","to"); my (%actions,%contain); my (@ruletype)=('DISABLED','ENABLED','DELETE','MODIFY'); my (@desttype)=("folder","address"); my ($fieldname,$fieldval,$sdest,$sdest1,$sto,$sfrom,$ssubject,$destt,$sdest2,$sdest3,$check1,$check2,$check3,$check4,$check5,$joinop,$size); my ($applyall,$searchflg); my ($sfield,$svalues,$scopyflg,$sregexflg,$sfieldname,$sfieldval,$ssize,$skeepflg); $ssize=$sfieldname=$sfieldval=$sfrom=$sto=$ssubject=$sdest=$sdest0=$sdest1=$sdest3=$check3=$check4=''; $sflg=$ssizeflg=0; push (@desttype,' '); # retrieve rules string from global hash %record where key is matchingrules #convert rules string to an array $sdest=$svalues=$sfield; $scopyflg=''; $sregexflg=''; $skeepflg=''; my ($sdestt)='folder'; %actions = ( "folder","File Into", "address","Forward To", "reply","Reply with", "reject","Reject", "discard","Discard" ); my (@flgsts)=(0,1); %notflghash=( 0,"contains", 1,"does not contain", ); %searchflghash = ( 0," all of ", 1," any of " ); %sizeflghash = ( 0," less ", 2," greater " ); %copyhash = ( 'keep',"Keep a copy in your Inbox", 'copy',"Continue checking other rules after applying this rule", 'regex',"Use regular expressions" ); my ($toggle,$priority,$line,$dest,$field,$flg,$copyflg,$sizeflg,$keepflg); my ($rulecount)=0; my ($pcount)=1; # insert view rules here.. if ($op eq 'viewrules' ) { print hr,"
"; print "
Viewing Rules for: $uid","
"; print "
"; print ""; # only print if viewing... } # if viewrules @tmprules=@rules; $modrule=""; while (@tmprules) { $line=shift(@tmprules); chomp($line); $line=~s/\s*//; $line=~s/\s$//; $line=~s/\r//g; ($priority,$ruletype,$from,$to,$subject,$destt,$dest,$flg,$fieldname,$fieldval,$size)=split('&&',$line); if ((!($from || $to || $subject || $size || ($fieldname&&$fieldval)) || !$ruletype) && !$dest) { next; } #this line to support old version of websieve scripts if ($flg=~/copy/i) { $flg=$copybit; } $flg=0 if !$flg; $copyflg= ($flg & $copybit); $searchflg=($flg & $searchbit); $searchflg=0 if !$searchflg; $sizeflg=($flg & $sizebit); $regexflg=($flg & $regexbit); $keepflg=($flg & $keepbit); $priority=$pcount; $applyall=''; $applyall=1 if (!($to | $from | $subject | $fieldname | $fieldval | $size) && $dest); # if it is a modify rule then save this rule for modify later if (($ruletype=~/modify/i || ($applyall && $op eq 'forward' && $destt eq 'address')) && !($sto || $sfrom || $ssubject || $sdest || $ssize)) { # can use 'DELETE' but data loss in form submit might cause a new rule to be lost if using IE $ruletype=$OLDMODIFY; $sto=$to; $sfrom=$from; $ssubject=$subject; $modrule="1"; $spriority=$priority-1; $sdestt=$destt; $sdest=$dest; $scopyflg=$copyflg; $ssizeflg=$sizeflg; $skeepflg=$keepflg; $sflg=$flg; $sregexflg=$regexflg ; $ssearchflg=$searchflg; $sfieldname=$fieldname ; $sfieldval=$fieldval ; $ssize=$size; # save values for modify later } param("rules.priority.$rulecount","$priority"); param("rules.ruletype.$rulecount",$ruletype); param("rules.searchflg.$rulecount",$searchflg); if ($op eq 'forward' && $ruletype=~/DELETE/i) { print hidden("rules.priority.$rulecount"); print hidden("rules.ruletype.$rulecount"); } if ($op eq 'viewrules' ) { # only print if viewer print "\n"; print ""; print "\n"; print ""; # only if viewing.. } #if viewrules $rulecount++; $pcount+=2; } # while if (!defined($spriority)) {$spriority=$pcount-1;} $savedcount=$rulecount; $sdest0=' '; # set up variables for modify operation on a rule $check1=''; $check2=''; $check0=''; $check5=''; my $customrule=''; if (!$sdest) {$sdest=' ';} if ($sdestt=~/address/i) { $sdest1=$sdest; $check1='checked'; } elsif ($sdestt=~/reply/i) { $sdest2=$sdest; $sdest2=~s/\\n/\r\n/g; $check2='checked'; } elsif ($sdestt=~/folder/i) { $sdest0=$sdest; $check0='checked'; } elsif ($sdestt=~/reject/i) { $check3='checked'; $sdest3=$sdest; $sdest3=~s/\\n/\r\n/g; } elsif ($sdestt=~/discard/i) { $check4='checked'; } elsif ($sdestt=~/custom/i) { $customrule=1; $check5='checked'; $sdest5=$sdest; $sdest5=~s/\\n/\n/g; } if ($op eq 'viewrules' ) { print "
[Rule#] Priority - StatusCurrent Rules
[$rulecount] ",textfield("rules.priority.$rulecount",$priority,2), popup_menu("rules.ruletype.$rulecount",[@ruletype],$ruletype),""; if ($destt ne 'custom' ) { print "IF " if !$applyall; print "[Unconditional Rule] " if $applyall; $searchflg=0; $searchflg=1 if ($flg & $searchbit); # only if viewing my ($wc)=''; my %contains; if ($regexflg) { $contains{'to'}=$contains{'from'}=$contains{'subject'}=$contains{'field'}='matches regex'; } else { $contains{'to'}=$contains{'from'}=$contains{'subject'}=$contains{'field'}='contains'; $contains{'to'}='matches' if $to=~/\*|\?/; $contains{'to'}.='{not} ' if $to=~/^\s*!/; $contains{'from'}='matches' if $from=~/\*|\?/; $contains{'from'}.='{not} ' if $from=~/^\s*!/; $contains{'subject'}='matches' if $subject=~/\*|\?/; $contains{'subject'}.='{not} ' if $subject=~/^\s*!/; $contains{'field'}='matches' if $fieldval=~/\*|\?/; $contains{'field'}='{not} matches' if $fieldval=~/^\s*!/; $contains{'size'}='msg size less than'; $contains{'size'}='msg size greater than' if $sizeflg; } $joinop='AND'; $joinop='OR' if $searchflg; if ($from) { print "\'From\' $contains{'from'} \'",$wc.$from.$wc,"\' "; } if ($to) { if ($from) {print " $joinop field: ";} print "\'To\' $contains{'to'} \'",$wc.$to.$wc,"\'"; } if ($subject) { if ($to | $from) {print " $joinop field: ";} print "\'Subject\' $contains{'subject'} \'",$wc.$subject.$wc,"\'"; } if ($fieldname) { if ($to | $from | $subject) {print " $joinop field: ";} print "\'$fieldname\' $contains{'field'} \'",$wc.$fieldval.$wc,"\'"; } if ($size) { my $kb='K'; $kb="K" if $size=~s/k//gi; if ($to | $from | $subject | $fieldname) {print " $joinop ";} print " $contains{'size'} \'$size"."$kb\'"; } #$dest=~s/^(.{40}).*/$1->(more)/; $dest=~s/\\n/
/g; print " THEN " if !$applyall; print "$actions{$destt} "," \'",$dest,"\'"; } # if !$custom else { # $dest=~s/^(.{40}).*/$1->(more)/; $dest=~s/\\n/
/g; print "Custom Rule: $dest"; } if ($copyflg) { print " - [Continue]"; } if ($keepflg) { print " - [Keep a copy]"; } print "
"; print "
"; if (!$rulecount) { print " [No Rules avalailable]
"; } print "
",submit('Save Changes'),"  ",submit("Refresh"),"  ",reset("Reset Values"),"
"; } # if viewrules if (($op eq 'addrule' || $modrule) && ($op ne 'forward')) { $modrule=""; #### New Rule Entry my ($wild)="Hint: Use * or ? for wildcards
To invert a rule use ! as the first character of your search string" ; print hr,"
"; print "
New Rule Entry for user: $uid
"; print ""; print ""; my @checked; my @checkvalues=("copy","keep"); push @checkvalues,"regex" if $useregex; if ($scopyflg) { push @checked,"copy"; } if ($skeepflg) { push @checked,"keep"; } if ($sregexflg) { push @checked,"regex"; } param("rules.copy.$rulecount",@checked); print "\n"; param("rules.ruletype.$rulecount",'ENABLED'); param("rules.priority.$rulecount","$spriority"); print "
Rule#: [$rulecount]"; print "  Priority: ",textfield("rules.priority.$rulecount",$spriority,2); print "  Status: ",popup_menu("rules.ruletype.$rulecount",[@ruletype],'ENABLED'),"
"; print "",checkbox_group(-name=>"rules.copy.$rulecount", -values=>\@checkvalues, -defaults=>\@checked, -linebreak=>'true', -labels=>\%copyhash),""; while (($rulecount==$savedcount) && ($rulecount<$maxrules)) { print "

"; print ""; ############# TO field print ""; print ""; ########### SUBJECT field print ""; print ""; $usesize=1 if !defined $usesize; if ($usesize) { ##### Size of message rule print ""; print ""; } if ($usevariablefield) { ##### Variable field 'field' print ""; print ""; } ######## THEN ####### Action FILEINTO print ""; print ""; ############## Action REDIRECT param("rules.forward.$rulecount","$sdest1"); print ""; ############### Action REPLY WITH if ($usereply) { param("rules.reply.$rulecount","$sdest2") if (defined $sdest2); print ""; } ############## Action Reject if ($usereject) { param("rules.reject.$rulecount","$sdest3"); print ""; } ############## Action Discard if ($usediscard) { print ""; } ############### Action CustomCode if ($usecustom ) { print ""; param("rules.custom.$rulecount","$sdest5") if (defined $sdest5); print ""; # print textfield("rules.forward.$rulecount",$sdest1,35),""; } #### END of Actions $rulecount++; } print "
"; param("rules.desttype.$rulecount","$sdestt"); ###### FROM field print "IF "; if ($usesearchflg) { $ssearchflg=0; $ssearchflg=1 if ($sflg & $searchbit); param("rules.searchflg.$rulecount","$ssearchflg"); print popup_menu("rules.searchflg.$rulecount",[@flgsts],$ssearchflg,\%searchflghash); } print " field(s):  'from' contains ", ""; param("rules.from.$rulecount","$sfrom"); print textfield("rules.from.$rulecount","$sfrom",50),"
 "; print "  'to' contains ", ""; param("rules.to.$rulecount","$sto"); print textfield("rules.to.$rulecount","$sto",50),"
 "; print "  'subject' contains ", ""; param("rules.subject.$rulecount","$ssubject"); print textfield("rules.subject.$rulecount","$ssubject",50),"
Msg size"; param("rules.sizeflg.$rulecount","$ssizeflg"); print popup_menu("rules.sizeflg.$rulecount",[(0,2)],$ssizeflg,\%sizeflghash); print " than "; print ""; param("rules.size.$rulecount","$ssize") ; print textfield("rules.size.$rulecount","$ssize",15)," (K)ilobytes
Field name"; param("rules.fieldname.$rulecount","$sfieldname"); print textfield("rules.fieldname.$rulecount",$sfieldname,10); print " contains ",""; param("rules.fieldval.$rulecount","$sfieldval") ; print textfield("rules.fieldval.$rulecount","$sfieldval",50),"
THEN File Into "; param("rules.mailbox.$rulecount","$sdest0"); if (!$ismanager) { print popup_menu("rules.mailbox.$rulecount",[@mailboxes],"$sdest0"); } else { print textfield("rules.mailbox.$rulecount","$sdest0",50); } print " (Mail Folder)
  Forward To "; print textfield("rules.forward.$rulecount",$sdest1,50)," (Email Address)
  Reply With "; print textarea("rules.reply.$rulecount",$sdest2,2,43)," (Text Message)
  Reject "; print textarea("rules.reject.$rulecount",$sdest3,2,43)," (Text Message)
  Discard  
ORCustom Rule
(Sieve Script)
"; print textarea("rules.custom.$rulecount",$sdest5,5,52),"
";print "
"; print hr,"
$wild
"; $rulecount--; print hr,"
",submit("Save Rule "),"  ",reset('Clear'),"
"; } # if addrule ##### Forward all operation if ($op eq 'forward') { param("rules.priority.$rulecount","$spriority"); param("rules.ruletype.$rulecount","ENABLED"); param("rules.forward.$rulecount","$sdest1"); param("rules.desttype.$rulecount",'address'); param("rules.to.$rulecount",''); param("rules.from.$rulecount",''); param("rules.subject.$rulecount",''); param("rules.fieldname.$rulecount",''); param("rules.fieldval.$rulecount",''); # this prevents warnings further on print hidden("rules.priority.$rulecount"), hidden("rules.ruletype.$rulecount"), hidden("rules.desttype.$rulecount"), hidden("rules.to.$rulecount"), hidden("rules.from.$rulecount"), hidden("rules.subject.$rulecount"), hidden("rules.fieldname.$rulecount"), hidden("rules.fieldval.$rulecount"); print ""; print hr, "
"; print "
Forward all mail from: $uid","
"; print "
Forward Mail To: "; print textfield("rules.forward.$rulecount",$sdest1,52); print "
"; print "NOTE: If you want to keep a copy of messages that ", "you are
forwarding, don't use this screen. Create a", " new filter rule to
redirect your mail instead.
"; print "
"; } param('rulescount',$rulecount); print hidden('rulescount'); } sub printinfo { my $percent='0.00'; $percent= sprintf "%2.2d",$quota[1]/$quota[2]*100 if ($quota[2]); print "
\n"; print ""; print ""; } else { print ""; }; if ($usemulti && !$useprocmail) { print "" } print "
Server: $imapserverUserid: $uidUsed Quota: "; if ($percent ne "" && ($havequota || !$useprocmail)) { print "[$quota[1] kbytes used / $quota[2] kbytes available.($percent\% usage)]$quota[1] No limitsScript: [$viewscript]
"; } sub byline { return if $nobyline; print "


Websieve
"; print "Mail Account Management Tool Version: $version
Written by: Alain Turbide
"; print '
aturbide@toshiba.ca

'; return; } sub incorrect_login { print start_html(-title=>'Login Error!',-BGCOLOR=>'yellow'), h2('Login Error'), "There was an error in loging you in to the server. Please ", "click HERE and try again.\n"; if ($error !~ /sieve/i) { print "

System Error: $error"; print "
User server=$userserver
"; } else { print "

Wrong Password! "; } print end_html; exit; } sub web_authenticate { my @slist=@serverlist; my %serverdisplay; while ($_=shift @slist) { $serverdisplay{$_}=$server_hosts{$_}[0] if $_; } print start_html(-title=>$header1,-BGCOLOR=>$bg), "

",h1($header1), "For Problems with this service, please email $problem_email
",$HOMEURL,"
", start_form,"
", "", ""; if ($useserverselect) { print "
","Login: ",textfield('login'),"
Password: ",password_field('password'),"
Mail Server: ",popup_menu("server",[@serverlist],$imapserver,\%serverdisplay); } print "
",br, submit('Login'),"
", hidden('op'); print "
Your \"Login\" is the same as the part of your e-mail
address that goes before the \@ symbol.
"; print end_form; } sub bind { &openimap($uid,$pass,$imapserver,$imapport,$useimapSSL,$unixhiersep); if (!$imap || $IMAPERROR=~/NO login/i) { $error=$IMAPERROR."
"; &closeimap; return -1; # Return Failure } if (!$useprocmail) { &opensieve($uid,$pass,$sieveport,$imapserver,$usesieveSSL); if (!$sieve || $SIEVEERROR) { $error.=$SIEVEERROR."
"; &closeimap; &closesieve; return -1; } } return 0; # Return Success } sub modify_screen { # Print WWW Header my $header2="Mail Server: $userserver" if $showserver; $header2=" " if !$header2; my $err; print start_html(-title=>"$header1 for '$uid' on $userserver",-BGCOLOR=>$bg, -LINK=>"black", -VLINK=>"black"), "
",h2("$header1 $header2"),"
"; %scripts=&getuserinfo; $mode=$scripts{'mode'}; $op=''; $op=param('op') if param('op'); if ($mode =~ /advanced/i && !$op) { $op = 'viewrules'; } if ($showmenu||$showhome) { print ""; if ($useldapextras) { print ""; if ($ismanager) { print ""; print ""; $showmenu = $mgrrecmail; } } } print "
",tablebutton($HOMEURL); print "",tablebutton($LOGOUTURL),"",tablebutton($LDAPSEARCHURL),"",tablebutton($NEWUSERURL),"",tablebutton($NEWGROUPURL),"
"; print "
"; print "" if $useauth; print "" if ($usevacation && $mode ne 'advanced'); print "" if ($useforwardall && $mode ne 'advanced'); print ""; print "" if ($mode ne 'advanced'); if ($useacl && !$ismanager) { print "" ; } elsif ($ismanager) { print ""; } print "" if ($allowadvanced || $usemulti); print "
",tablebutton($SETPASSWORDURL),"",tablebutton($SETVACATIONURL),"",tablebutton($FORWARDALLURL),"",tablebutton($VIEWRULESURL),"",tablebutton($ADDRULEURL),"",tablebutton($SETACLURL),"",tablebutton($ADMINMENUURL),"",tablebutton($ADVANCEDURL),"
"; &printinfo; # Draw up the Web Form print start_form(-action=>$program_url); $gomodifyit = 'yes'; print hidden('s',$sencode_params) if $useservercookie; print "
",submit('Save Changes'),"  ",submit("Refresh"),"  ",reset('Reset Values'),"
" if $op; param('op',$op); if (param('action') && param('action') eq 'deletembx') { &deleteimapmailbox; } #Call ldapextras functons if configured to do so $res = &ldapextras if ($useldapextras); print hidden('gomodifyit',$gomodifyit); if (param('gomodifyit')) { &gomodifyit; %scripts=&getuserinfo; } if ($op eq 'addrule' && $returntoview) { param('op','viewrules'); } print hidden('op'); &initscripts(%scripts); if ($op eq 'setacl') { &viewacl if $useacl; print "
",submit('Save Changes'),"  ",submit("Refresh"),"  ",reset('Reset Values'),"
"; } if ($mode =~ /basic/i && $op ne 'setacl') { &printrules if ($op eq 'addrule' || $op eq 'viewrules' || $op eq 'forward'); if ($op eq 'setvacation') { &printvacation if $usevacation; } } elsif (($op ne 'setpass' && $op ne 'setacl' && $op eq 'viewrules' && $op ne 'forward') ) { # print "printing $op
"; &printscript($scripts{'script'}) ; print "
",submit('Save Changes'),"  ",submit("Refresh"),"  ",reset('Reset Values'),"
"; } if ($op eq 'setpass') { print hr; &printpass if $useauth; } #print ""; end_form; return; } sub checkrules { my ($linecount,$destt,$priority,$rulecount,$linecount2,@rulelist,$oldrules,$onerule,$copyflg,$sizeflg,$keepflg,$size); $copyflg=''; $dest=''; $linecount=$rulecount=0; $delimiter='&&'; $dest=""; my (@rulea,@tmprules); $linecount2=param("rulescount"); @tmprules=@rules; # start of current rule check # only priority and ruletype can be changed here if (!defined $linecount2) { $rules=join("\n",@tmprules); return ($rules); } $rulesorig=''; while (@tmprules) { $line=shift(@tmprules); $rulesorig.=$line; chomp($line); $line=~s/^ +//; $line=~s/ +$//; ($priority,$ruletype,$from,$to,$subject,$destt,$dest,$flg,$fieldname,$fieldval,$size)=split('&&',$line); if ($flg=~/copy/i) { $flg=$copybit; } $size='' if !$size; $flg=0 if !$flg; $copyflg=($flg & $copybit); $sizeflg=($flg & $sizebit); $keepflg=($flg & $keepbit); my ($pruletype)=""; $pruletype=param("rules.ruletype.$linecount") if param("rules.ruletype.$linecount"); # if delete or not valid data in fields, skip rule (delete it) # if (($pruletype=~/^delete/i) || ($ruletype=~/delete/i) || (!($to || $from || $subject || $size || ($fieldname && $fieldval) || $pruletype)) ) { # $linecount++; # next; # # } if ($pruletype=~/^delete/i || $ruletype=~/delete/i ) { $linecount++; next; } my ($pr1,$rt1)=""; if (defined(param("rules.priority.$linecount"))) { $pr1 =param("rules.priority.$linecount"); $rt1 =param("rules.ruletype.$linecount"); } else { $rt1=$ruletype; $pr1 =$priority; } $rt1=~s/ +//g; $pr1=~s/ +//g; $size=~/([0-9kK]+)/; $size=$1; $size='' if !$size; #check for valid data passed in form (ruletype and priority) #if not use original values from saved script if (($pr1!~/\W+/) && ($pr1=~/\d+/)) { $priority=$pr1; } #check for valid ruletype passed in form #print "rt1=$rt1, ruletype=$ruletype
"; if ($rt1=~/\W+/ ) { $rtype=$ruletype; } else { $rtype=$rt1; } if (!$rtype) { $rtype="DISABLED"; } $rule=$priority.$delimiter.$rtype.$delimiter.$from.$delimiter.$to.$delimiter.$subject.$delimiter.$destt.$delimiter.$dest.$delimiter.$flg.$delimiter.$fieldname.$delimiter.$fieldval.$delimiter.$size."\n"; # save checked rule and increment linecount push (@rulea,$rule); $linecount++; } # while $linecount=param("rulescount"); # start checking new rule entry for validity and parse it # New or modified rule is checked here # this loop should only run once while ($linecount==param("rulescount")){ # check for valid data - else skip rule if (!param("rules.to.$linecount") && !param("rules.from.$linecount") && !param("rules.subject.$linecount") && !(param("rules.fieldname.$linecount") && param("rules.fieldval.$linecount")) && !param("rules.size.$linecount") && !param("rules.custom.$linecount") && !param("rules.forward.$linecount") && !param("rules.ruletype.$linecount")) { $linecount++; next; } $destt=param("rules.desttype.$linecount"); if ($destt=~/folder/i) { if(param("rules.mailbox.$linecount")!~/\S/) { $linecount++; next; } $dest=param("rules.mailbox.$linecount"); } elsif ($destt=~/address/i) { if(param("rules.forward.$linecount")!~/\S/) { $linecount++; next; } $dest=param("rules.forward.$linecount"); } elsif ($destt=~/reply/i) { if(param("rules.reply.$linecount")!~/\S/) { $linecount++; next; } $dest=param("rules.reply.$linecount"); $dest=~s/\n/\\n/g; $dest=~s/\r//g; } elsif ($destt=~/custom/i) { if(param("rules.custom.$linecount")!~/\S/) { $linecount++; next; } $dest=param("rules.custom.$linecount"); $dest=~s/\n/\\n/g; $dest=~s/\r//g; } elsif ($destt=~/reject/i) { if(param("rules.reject.$linecount")!~/\S/) { $linecount++; next; } $dest=param("rules.reject.$linecount"); $dest=~s/\n/\\n/g; $dest=~s/\r//g; } else { $dest=''; } $copyflg=''; $keepflg=''; # $copyflg=param("rules.copy.$linecount"); my @checked=param("rules.copy.$linecount"); $copyflg=$copybit if (grep /copy/i, @checked); $keepflg=$keepbit if (grep /keep/i, @checked); $regexflg=$regexbit if (grep /regex/i,@checked); # $regexflg=param("rules.regex.$linecount"); if (param("rules.sizeflg.$linecount")) { $sizeflg=$sizebit; } else { $sizeflg=0; } if (param("rules.searchflg.$linecount")) { $searchflg=$searchbit; } else { $searchflg=0; } if (!$sizeflg) {$sizeflg=0}; if (!$copyflg) {$copyflg=0}; if (!$regexflg) {$regexflg=0}; if (!$keepflg) {$keepflg=0}; $flg=$keepflg | $copyflg | $searchflg | $regexflg | $sizeflg; # OR other flgs here $onerule=param("rules.priority.$linecount").$delimiter."ENABLED".$delimiter.param("rules.from.$linecount").$delimiter.param("rules.to.$linecount").$delimiter.param("rules.subject.$linecount").$delimiter. param("rules.desttype.$linecount").$delimiter.$dest.$delimiter.$flg.$delimiter.param("rules.fieldname.$linecount").$delimiter.param("rules.fieldval.$linecount").$delimiter.param("rules.size.$linecount")."\n"; $linecount++; }#while push (@rulea,$onerule) if $onerule; @rulea=sort {($a=~/(\d+)/)[0] <=> ($b=~/(\d+)/)[0]} @rulea; $rulelist="@rulea"; if ($rulesorig ne $rulelist) { return $rulelist; } return ""; } sub checkvacation { my (@tmp,$tmp,$t1,$t2); if (!defined param('vacationmode')) { $tmp=$vacation{'addresses'}; } else { $vacation{'days'}=param('vacationdays'); $tmp=param('vacaddresses'); $vacation{'mode'}=param('vacationmode'); $vacation{'text'}=param('vacationtext'); } $tmp=~s/\"//g; $tmp=~s/\@/\\@/g; $tmp=~s/\r//g; $tmp=~s/,+|:+|;+|\n/ /g; $tmp=~s/ +/ /g; $vacation{'addresses'}=$tmp; if ($vacation{'addresses'}) { $vacation{'addresses'}=~s/\\@/\@/g; @tmp=split(",| +",$vacation{'addresses'}); while (@tmp) { $t1.=', ' if $t1; $t1.="\"".shift(@tmp)."\""; } $vacation{'addresses'}=$t1 if $t1; } $vacation{'addresses'}="\"$uid\@$maildomain\", \"$uid\@$mailhostappend\"" if ($vacation{'addresses'}!~/\w+/); $vacation{'days'}="1" if ($vacation{'days'}!~/\d/); return; } sub gomodifyit { my (%tmpscr,$mode,@pseudo,$tmp,$modchange,$pseudonew,$delete,$save,$pseudo,$err); # process the sieve or procmail pseudo rulesets $change=0; $err=''; if (param('Refresh')) { print "Screen Refreshed"; return; } %tmpscr=%scripts; $oldscript=$tmpscr{'script'}; $scriptname=$tmpscr{'scriptname'}; $scriptdef=$tmpscr{'scriptdef'}; $script=param('script'); $oldmode=$tmpscr{'oldmode'}; $mode=param('mode'); $pseudo=$tmpscr{'pseudo'}; $delete=$tmpscr{'deletescript'}; # from auth.pl $res.=&auth_changepass if $useauth; return if $op eq 'setpass'; &modifyacl if ($useacl && $op eq 'setacl'); return if $op eq 'setacl'; print hr; if ($delete && !$useprocmail) { &opensieve($uid,$pass,$sieveport,$imapserver) if !$sieve; if ($scriptdef!~/yes|on|active/i && $viewscript eq $scripts{'active'}) { $res.=&setactive(""); } $res.=&deletescript($delete); if ($res) { print "\n",br,"Delete Script Error: $res...\n",br; return; } return; } if ($scriptdef!~/yes|on|active/i && $viewscript eq $scripts{'active'} && !$useprocmail) { $res.=&setactive(""); } &checkvacation if ($usevacation || $usereply); if (($oldmode ne $mode) && (param('viewscript') eq param('lastviewscr'))) { $modchange=1; print "Warning! Now in $mode mode...
" if $mode; print "Any changes made in advanced mode have now been overwritten.
" if $mode eq 'basic'; print "If you switch from advanced mode to basic you will lose any changes made to this script.
" if $mode eq 'advanced' } #print "mode=$mode oldmode=$oldmode
"; # check if viewing new script - no save then if (param('viewscript') eq param('lastviewscr')) { if ($mode =~ /basic/i || $modchange) { $rules=&checkrules; if ($useprocmail) { my $prules; my @rules=split(/\n/,$rules); while ($_=shift(@rules)) { $prules.="#rule&&".$_."\n"; } $change=1; my $vtext=$vacation{'text'}; $vtext=~s/\n/\\n/g; $vtext=~s/\r//g; $prules.="#vacation&&".$vacation{'days'}."&&".$vacation{'addresses'}."&&".$vtext."&&".$vacation{'mode'}."\n"; $prules.="#mode&&basic\n"; &auth_saveattrib($matchingrules,$prules) if defined &auth_saveattrib; &mailruleupd($uid); } elsif ($res.=&updatesieve($rules,%tmpscr)) { print "\n",br,"Updatesieve Error: Cant' update script...",br; print "Returned Error: $res $SIEVEERROR
"; print "You can click on your browser's Back button to "; print "go back and try your entry again.
"; # return; print hr; &byline; exit; } } else { $script=$oldscript if (!$script && $scriptdef !~/yes|on|active/i); if ($script && ($script=~/\w+/) && ($scriptname)) { @pseudo=split("\n",$pseudo); while (@pseudo) { $tmp=shift(@pseudo); $tmp=~s/^ *#mode.*$//ig; next if ($tmp!~/\S/); $pseudonew.=$tmp."\n"; } $vacation{'text'}=~s/\n/\\n/g; $vacation{'text'}=~s/\r//g; $pseudonew.="\n#mode&&advanced\n"; if (($script ne $oldscript) || ($pseudo ne $pseudonew) || ($scriptname ne $tmpscr{'viewscript'}) || $mode ne $oldmode) { $change=1; &opensieve($uid,$pass,$sieveport,$imapserver) if !$sieve; #$script.="\n".$pseudonew; $script=~s/\r\n/\n/mg; $res.=&putscript($scriptname,$script); $res.=&putscript($scriptname."_pseudo",$pseudonew); } } # if script =~/\w if ($scriptdef=~/yes|on|active/i && $scriptname && !$useprocmail) { &opensieve($uid,$pass,$sieveport,$imapserver) if !$sieve; $res.=&setactive($scriptname); print "Script $scriptname now active..
"; } } } # if param(viewscript) else { param('scriptdef','off'); } # Success! if (!$res ) { print "Update successful..." if $change; print "No changes.." if !$change; return; } else { print "Failure
Returned Error:
$res
"; return; } } sub updatesieve { my ($filterval,%scripts) =@_; $scriptdef=$scripts{'scriptdef'}; $scriptname=$scripts{'scriptname'}; if (!$scriptname) { $scriptname=$scripts{'viewscript'}; } my (@mbxlist,$rulesyes,$vacationyes,$usereject); my %fields=( "subject",'"subject" ', "to",'["Cc","CC","To","TO"] ', "contain",':contains ', "from",'["from"] ', "address",'redirect ', "folder",'fileinto ', "reject",'reject ', "reply",'vacation :days '.$vacation{'days'}.' ', "discard",'discard ' ); my %matchtype=( "0","allof", $searchbit,"anyof" ); # $fields{'contain'}=':matches ' if ($usematches); my (@lrules)=split('\n',$filterval); my ($keep,$copyrules,$copystat,$procreq,$procr,$extradefs) = ""; my $proch=""; my $proc=""; my $not=""; $copystat=""; $usereject=0; $procr=""; $copyrules=""; $procreq=""; $rulesyes=0; $vacationyes=0; my ($fieldn,$field,$wc); my $regexused; my $noelse; while (@lrules) { my $tmp=''; $line=shift(@lrules); chomp($line); my ($priority,$ruletype,$from,$to,$subject,$desttype,$dest,$flg,$fieldname,$fieldval,$size) = split("&&",$line); next if !$desttype; $procr.="#rule&&"."$line\n"; $dest=~s/\r//g; $dest=~s/\\n/\r\n/g; if ($flg=~/copy/i) { $copyflg=$copybit; } else { $copyflg= ($flg & $copybit); } $keep=""; $matchflg=($flg & $searchbit); $keepflg=($flg & $keepbit); $keepflg=0 if (!$keepflg); $matchflg=0 if (!$matchflg); $sizeflg=($flg & $sizebit); $sizeflg=0 if (!$sizeflg); $regexflg=($flg & $regexbit); $regexused ||=$regexflg; # if ((!($to|$from|$subject|($fieldname && $fieldval)) | !$fields{$desttype}) && (!($dest && $desttype eq 'custom')) && !$dest) {next}; if ($ruletype !~/ENABLED|\d/i) {next}; $keep=" keep;\n" if $keepflg; if ($desttype=~/folder/i) { #@mbxlist=&listmailbox("user.$uid.$dest"); #if (!@mbxlist) { # print "Folder $uid.$dest does not exist ..\n"; # next}; next if !$dest; $dest=~s/^INBOX.INBOX/INBOX/; if (($dest =~/^INBOX/)||($alt_namespace)) { $msgdest=$dest; } else { $msgdest="INBOX.$dest"; } # check if folder is in an addtional namespace foreach $namespace (@namespaces) { if ($dest=~/^$namespace./i) { $msgdest="$dest"; last; # stop checking } } } elsif ($desttype=~/address|reply|reject/i) { $msgdest=$dest; if ($desttype=~/address/i && $dest!~/\w+\@\w+\.\w+/) { next; } $usereject=1 if $desttype=~/reject/i; $vacationyes=1 if $desttype=~/reply/i; if (($keepredirect ) && ($desttype=~/address/i)) { $keep=" keep;\n"; } next if !$dest; } else {$msgdest='';} $rulesyes=1; if ($copyflg==$copybit) { $copystat=''; } else { $copyflg=''; } $fieldn='0'; $field=''; $wc=''; $fields{'contain'}=':matches ' if ($usematches); $not=''; if ($to) { if ($regexflg) { $fields{'contain'}=':regex '; $wc=''; } else { if ($to=~/\*|\?/) { $fields{'contain'}=':matches '; $wc='*' if (!$usematches); } elsif (!$usematches) { $fields{'contain'}=':contains '; $wc=''; } } $not="not " if $to=~s/^\s*!//; $field.=$not."address ".$fields{'contain'}.$fields{'to'}."\"$wc$to$wc\""; $fieldn++; } $not=''; if ($from) { if ($regexflg) { $fields{'contain'}=':regex '; $wc=''; } else { if ($from=~/\*|\?/) { $fields{'contain'}=':matches '; $wc='*' if (!$usematches); } elsif (!$usematches) { $fields{'contain'}=':contains '; $wc=''; } } $not="not " if $from=~s/^\s*!//; if ($field) {$field.=", ";} $field.=$not."address ".$fields{'contain'}.$fields{'from'}."\"$wc$from$wc\""; $fieldn++; } $not=''; if ($subject) { if ($regexflg) { $fields{'contain'}=':regex '; $wc=''; } else { if ($subject=~/\*|\?/) { $fields{'contain'}=':matches '; $wc='*' if (!$usematches); } elsif (!$usematches) { $fields{'contain'}=':contains '; $wc=''; } } $not="not " if $subject=~s/^\s*!//; if ($field) {$field.=", ";} $field.=$not."header ".$fields{'contain'}.$fields{'subject'}."\"$wc$subject$wc\""; $fieldn++; } $not=''; if ($size) { $fields{'contain'}=':under '; $fields{'contain'}=':over ' if $sizeflg; $not="not " if $size=~s/^\s*!//; my $kb='K'; $kb='K' if $size=~s/k//gi; $size=~/([0-9]+)/; $size=$1; $size='' if !$size; if ($field) {$field.=", ";} $field.=$not."size ".$fields{'contain'}.$size.$kb; $fieldn++; } $not=''; if ($fieldname && $fieldval) { if ($regexflg) { $fields{'contain'}=':regex '; $wc=''; } else { if ($fieldval=~/\*|\?/) { $fields{'contain'}=':matches '; $wc='*' if (!$usematches); } elsif (!$usematches) { $fields{'contain'}=':contains '; $wc=''; } } $not="not " if $fieldval=~s/^\s*!//; if ($field) {$field.=", ";} $field.=$not."header ".$fields{'contain'}." \"".$fieldname."\""." \"$wc$fieldval$wc\""; $fieldn++; } if ($desttype=~/reply/i) { $extradefs=":addresses [$vacation{'addresses'}] "; } else { $extradefs="";} if ($desttype=~/reply|reject/i) { $msgdest="text:\r\n".$msgdest."\r\n\.\r\n" if $msgdest; } else { $msgdest="\"".$msgdest."\"" if $msgdest; } # print "copystat=$copystat matchtype=$matchtype{$matchflg} fields=$field fields2=$fields{lc($desttype)} extra=$extradefs msgdest=$msgdest keep=$keep
"; if (!($to || $from || $subject || $size || $fieldname || $fieldval ) && $desttype ne 'custom') { $tmp=$fields{lc($desttype)}.$extradefs.$msgdest.";\n$keep\n\n" if ($desttype && $msgdest); $noelse=1; $copystat=''; $copyflg=$copybit; } elsif ($desttype eq 'custom') { $tmp=$dest."\n\n"; if ($tmp!~s/^\s*if /if /i && $tmp!~s/^\s*elsif /if /i) { $noelse=1; $copyflg=$copybit; } else { $tmp=$copystat.$tmp; $noelse=''; } } else { $copystat='' if ($noelse || $copyflg); $tmp=$copystat."if ".$matchtype{$matchflg}." \($field\) {\n ".$fields{lc($desttype)}.$extradefs.$msgdest.";\n$keep}\n\n"; $noelse=''; } # print $proc; if (!$copyflg) { $proc.=$tmp; } else { $copyrules.=$tmp; } $copystat='els' if $proc; $change=1; } #while @lrules $vacationyes=1 if ($vacation{'mode'}=~/on|active|yes|1/i); $proch="# Mail rules for user $uid\n# Created by Websieve version $version\n"; if ($rulesyes | $vacationyes | $usereject | $regexused) { $procreq="require [\"fileinto\""; if ($vacationyes) { $procreq.=",\"vacation\""; } if ($usereject) { $procreq.=",\"reject\""; } if ($regexused) { $procreq.=",\"regex\""; } $procreq.="];\n\n"; } $proc=$proch.$procreq.$copyrules.$proc; $proc.="else {\n keep;\n}\n\n" if ($rulesyes && !($op eq 'forward') && !$noelse) ; if($vacation{'mode'}=~/on|active|yes|1/i) { # this forces the script active when vacation is on $scriptdef='on' if $mode ne 'advanced'; # print "vacation=".$vacation{'text'}."
"; $vacation{'text'}=~s/\\n/\r\n/g; $vacation{'addresses'}=~s/\n/,/g; if ($vacation{'text'} && $vacation{'days'}) { # print "Sieve vacation active
"; # print "\nvacation :days ".$vacation{'days'}." :addresses [".$vacation{'addresses'}."] "."text:\r\n".$vacation_prelude.$vacation{'text'}."\r\n\.\r\n".";\n"; $proc.="\nvacation :days ".$vacation{'days'}." :addresses [".$vacation{'addresses'}."] "."text:\r\n".$vacation_prelude.$vacation{'text'}."\r\n\.\r\n".";\n"; $rulesyes=1; } else { $vacation{'mode'}='off'; } } if (!$rulesyes ) { $proc=$proch; $rulesyes=1; } $change=1; if ($rulesyes) { &opensieve($uid,$pass,$sieveport,$imapserver) if !$sieve; $pseudo.="\n\n##PSEUDO script start\n".$procr; # append #rule lines to end of script # append vacation pseudo lines $vacation{'text'}=~s/\n/\\n/g; # $vacation{'addresses'}=~s/\"//g; $vacation{'text'}=~s/\r//g; $pseudo.="#vacation&&".$vacation{'days'}."&&".$vacation{'addresses'}."&&".$vacation{'text'}."&&".$vacation{'mode'}."\n" if $usevacation; $pseudo.="#mode&&$mode\n"; &auth_saveattrib($matchingrules,$pseudo) if ($updatepseudo && defined &auth_saveattrib); #$proc.=$pseudo; #print "name=$scriptname
proc=$proc"; # debug # &savetext($scriptname,$proc); # debug test &putscript($scriptname,$proc); if (&putscript($scriptname."_pseudo",$pseudo)) { if ($SIEVEERROR =~ /exist/i) { return ''; } else { return $SIEVEERROR; } } if($vacation{'mode'}=~/on|active|yes|1/i) { print "Sieve vacation active
"; } if ($scriptdef && $scriptdef=~/yes|on|active/i && !$useprocmail) { print "Script $scriptname active..
"; $res=&setactive($scriptname); return $SIEVEERROR if $res; } return; } # if rulesyes } sub printvacation { my ($tmpvacadd); $tmpvacadd=$vacation{'addresses'}; %modevals = ( "on","Yes", "off","No"); $vacation{'text'}=~s/\\n/\r\n/g; print hr,"
"; print "
Vacation Mode status for: $uid","
"; print ""; param("vacationmode",$vacation{'mode'}); print "\n"; param("vacationtext",$vacation{'text'}); print "\n"; if (!$useprocmail) { param("vacationdays",$vacation{'days'}); print "\n"; param("vacaddresses",$tmpvacadd); print "\n"; } # if !$useprocmail print "
Vacation Active?: ",radio_group("vacationmode",['off','on'],$vacation{'mode'},'',\%modevals),"
Vacation Text: ",textarea("vacationtext",$vacation{'text'},5,50,"","wrap=virtual"),"
Repeat Days: ",textfield("vacationdays",$vacation{'days'},2,"")," (How many days before sending vacation notice again in reply to same user.)
Vacation Addresses: ",textarea("vacaddresses",$tmpvacadd,2,50,"","wrap=virtual")," (Your email addresses that you receive mail on)
"; } sub createmailfolder { my ($mbx,$partition)=@_; my @list=&listmailbox($mbx); my $err; if (!(@list)) { $err=&createmailbox($mbx,$partition); } else { $err="$mbx already exists!"; } if ($err) { return $err; } print "$mbx created successfully.
"; return ""; } ############################################# sub encode_list { return undef unless @_; my $out=''; foreach (@_) { $out .= 'G'.pack('c', 65 + int(rand(6))) if $out; $out .= reverse(uc(unpack('H'.(length)*2, $_))) if $_; } return $out.'='; # looks like some recognizable format } sub decode_list { return undef unless $_[0]; my @out; foreach ( split(/G[A-F]/, substr($_[0],0,-1)) ) { push @out, pack('H'.(length), scalar reverse $_); } return @out; } ############################################## # Encryption routines for cookie # from EZCrypt v2.0 (c) 2000 Croesus Design and Promotion # Developed by Jason C. Fleming # Base64 routines Copyright 1995-1997 Gisle Aas. # This library is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. sub Encrypt { my ($plaintext,$key) = @_; #get message and key from user if (!$key) { print "\$skey not set!!!
"; } my ($cr,$index,$char,$key_char,$encrypted); $plaintext = &rot13($plaintext); #garble source by swapping alphabet $cr = '``'; #carriage return character unlikely to occur in text $plaintext =~ s/[\n\f\t]//g; #remove whitespace chars $plaintext =~ s/[\r]/$cr/g; #swap cr with our token while ( length($key) < length($plaintext) ) { $key .= $key } #pad private key $key=substr($key,0,length($plaintext)); #set key to same length as source $index=0; while ($index < length($plaintext)) { #go through each character and swap bits with key $char = substr($plaintext,$index,1); $key_char = substr($key,$index,1); $encrypted .= chr(ord($char) ^ ord($key_char)); #THE MEAT OF THE ENCRYPTION $index++; } $encrypted = encode_base64($encrypted); #convert xor encrypted string into printable blocks $encrypted; #send the cyphertext back to user } sub Decrypt { my ($encrypted, $key) = @_; $encrypted = decode_base64($encrypted); #convert encrypted blocks into xor code my ($cr,$index,$char,$key_char,$decrypted); while ( length($key) < length($encrypted) ) { $key .= $key } #pad key $key=substr($key,0,length($encrypted)); #set key to same length as source $index=0; while( $index < length($encrypted) ) { #swap bits with key $char = substr($encrypted,$index,1); $key_char = substr($key,$index,1); $decrypted .= chr(ord($char) ^ ord($key_char)); #THE MEAT OF THE ENCRYPTION $index++; } $cr = '``'; $decrypted =~ s/$cr/\r/g;#replace carriage returns my $list=&rot13( $decrypted ); #unswap alphabet } sub rot13{ #swaps low letters (a-m) with high letters (n-z) and visa versa my $source = shift (@_); $source =~ tr /[a-m][n-z]/[n-z][a-m]/; #performs rot13 swapping (lc) $source =~ tr /[A-M][N-Z]/[N-Z][A-M]/;#performs rot13 swapping (caps) $source = reverse($source); $source; } sub encode_base64 { my $res = ""; my $eol = $_[1]; $eol = "\n" unless defined $eol; pos($_[0]) = 0; # ensure start at the beginning while ($_[0] =~ /(.{1,45})/gs) { $res .= substr(pack('u', $1), 1); chop($res); } $res =~ tr|` -_|AA-Za-z0-9+/|; # `# help emacs # fix padding at the end my $padding = (3 - length($_[0]) % 3) % 3; $res =~ s/.{$padding}$/'=' x $padding/e if $padding; # break encoded string into lines of no more than 76 characters each if (length $eol) { $res =~ s/(.{1,76})/$1$eol/g; } $res; } sub decode_base64{ local($^W) = 0; # unpack("u",...) gives bogus warning in 5.00[123] my $str = shift; my $res = ""; $str =~ tr|A-Za-z0-9+=/||cd; # remove non-base64 chars #if (length($str) % 4) {die "Base64 decoder requires string length to be a multiple of 4"} $str =~ s/=+$//; # remove padding $str =~ tr|A-Za-z0-9+/| -_|; # convert to uuencoded format while ($str =~ /(.{1,60})/gs) { my $len = chr(32 + length($1)*3/4); # compute length byte $res .= unpack("u", $len . $1 ); # uudecode } $res; } # end of encrypt routines ### only used in debugging ##### sub savetext { my ($filename,$filetext)=@_; open OUT,">/tmp/$filename"; print OUT $filetext; close OUT; } sub URLEncode { my($url)=@_; my(@characters)=split(/(\%[0-9a-fA-F]{2})/,$url); foreach(@characters) { if ( /\%[0-9a-fA-F]{2}/ ) # Escaped character set ... { unless ( /(20|7f|[0189a-fA-F][0-9a-fA-F])/i || /2[2356fF]|3[a-fA-F]|40/i ) { s/\%([2-7][0-9a-fA-F])/sprintf "%c",hex($1)/e; } } else # Other stuff { s/([\000-\040\177-\377\074\076\042\+]) /sprintf "%%%02x",unpack("C",$1)/egx; } } return join("",@characters); } # RC4 perl encryption routine by Andy Welter May 2001 # Encrypt a buffer at a type. Encryption is a stateful # process, so we use the "@state" global variable to track # the state. sub rc4 { my ($buf) = @_; my ($ebuf, $char); my $x=0; my $y=0; for(unpack('C*',$buf)) { $x++; $y=($state[$x%=256]+$y)%256; @state[$x,$y]=@state[$y,$x]; $char= pack (C, $_^=$state[ ($state[$x] + $state[$y]) %256 ]); $ebuf= $ebuf . $char; }; return $ebuf; }; sub prepkey { # # Prepare the encryption key # my ($key)=@_; my @hexkey=unpack('C*',$key); my ($x, $y)=("0","0"); my @t; my @state; for(@t=@state=0..255){ $y=($hexkey[$_%@hexkey]+$state[$x=$_]+$y)%256; @state[$x,$y]=@state[$y,$x]; #&swap; } return @state; }; sub encrypt_rc4 { my ($key,$buf)=@_; local @state=&prepkey($key); return &rc4($buf); }; sub tablebutton { my ($text) = @_; return "
".$text."
\n"; } # this function will take a user's mail server host name and retrieve all port # and host data to connect to it if not default. sub getserverdata { my ($userserver)=@_; $imapserver=$userserver if $userserver; if (defined $server_hosts{$userserver}) { # $serverdisplay=$server_hosts{$userserver}[0] if $server_hosts{$userserver}[0]; $imapport=$server_hosts{$userserver}[1] if $server_hosts{$userserver}[1]; $sieveport=$server_hosts{$userserver}[2] if $server_hosts{$userserver}[2]; $maildomain=$server_hosts{$userserver}[3] if $server_hosts{$userserver}[3]; $mailhostappend=$server_hosts{$userserver}[4] if $server_hosts{$userserver}[4]; my $sslopts=$server_hosts{$userserver}[5]; if ($sslopts) { $useimapSSL=1 if ($sslopts=~/imap|both|all|^ssl$/i); $usesieveSSL=1 if ($sslopts=~/sieve|both|all|^ssl$/i); } } return ($imapserver); } sub confirmmbxdelete { if( !$ismanager ) { print "Access not allowed
"; return; } $mbx=param('delmailbox'); return if !$mbx; if ($mbx=~/\*/) { print "Warning! You are attempting a wildcard delete !!! Not allowed!
"; return; } param('delmailbox',$mbx); param( 'action', 'deletembx' ); print hidden('delmailbox'); print hidden('mbx'); print "

Confirm: Really delete $mbx from server $imapserver


"; print "
",submit("Confirm Delete"),"
"; print "
If so, press the 'Confirm Delete' button.\n"; print "
If not, press the back button in your browser.\n
"; return; } sub deleteimapmailbox { if( !$ismanager ) { print "Access not allowed
"; return; } $mbx=param('delmailbox'); return if !$mbx; if ($ismanager ) { my $err = setacl( $mbx , $uid, "lrswipcda" )."
"; } $err.= &deletemailbox($mbx); if ( $err ) { print hr,"DeleteMailbox Error: imapdelerr $err"; return; } else { print "Mailbox: $mbx deleted.
"; } } sub mailruleupd { my ($uid)=@_; open (MAIL, "|$sendcmd"); print MAIL "From: $fromaddr\n"; print MAIL "To: $toaddr\n"; print MAIL "Subject: Filter activation\n"; print MAIL "X-Customfilter: $uid $adminsecret\n"; print MAIL "\n"; print MAIL "Filter activation message for $uid"; close(MAIL); }