1#!/usr/bin/perl 2 3require '/var/www/cgi-bin/auth.pl'; 4 5my $version="0.61i"; 6my $adminuid="admin"; 7my $adminpass="secret"; 8$LDAP_SERVER='imap1'; 9$LDAP_BASEDN='o=your org,c=ca'; 10my $maildomain="toshiba.ca"; 11my $vacationfile="/var/imap/procmail/vacationmsg"; 12my $replyfile="/var/imap/procmail/reply"; 13my $vacationdb="/var/imap/procmail/vacationdb"; 14my $rulefile="/var/imap/procmail/procmailrc"; 15my $rejectfile="/var/imap/procmail/rejectfile"; 16my $header="X-Customfilter:"; 17 18 19sub updateprocmail { 20 my ($filterval,$uid) =@_; 21 my (@mbxlist,$rulesyes,$vacationyes,$usereject); 22%fields=( 23 "subject",'^Subject:', 24 "to2",'(^Cc:|^CC:|^To:|^TO:|^Sender:)', 25 "to",'^TO_', 26 "contain",'* ', 27 "not contain",'* !', 28 "from",'^From:', 29 "address","* !^X-Loop: \$CYUSER\@$maildomain\n| \$FORMAIL -A\"X-Loop: \$CYUSER\@$maildomain\" | \$SENDMAIL ", 30 "folder",'| $DELIVERTO $USERINBOX.', 31 "nocopy",':0', 32 "copy",':0 ic', 33 "reply",':0 hc', 34 "vacation",':0 Whc: locfile' 35 ); 36 37$copybit=1; 38$sizebit=2; 39$searchbit=4; 40$keepbit=8; 41$regexbit=128; 42 my %matchtype=( 43 "0","allof", 44 $searchbit,"anyof" 45 ); 46 47 my (@lrules)=split('\n',$filterval); 48 my ($keep,$copystat,$procr,$extradefs) = ""; 49 my $proc=""; 50 my $not=""; 51 $copystat=""; 52 $procr=""; 53 $rulesyes=0; 54 $vacationyes=0; 55 my ($fieldn,$field,$wc); 56 my $regexused; 57 my %vacation; 58 #remove old files; 59 my @remove=glob("$replyfile.*.$uid"); 60 while ($_=shift(@remove)) { 61 unlink $_; 62 } 63 unlink "$vacationdb.$uid"; 64 unlink "$vacationfile.$uid"; 65 66 while (@lrules) { 67 my $tmp=''; 68 $line=shift(@lrules); 69 if ($line=~/^ *#vacation&&(.*)&&(.*)&&(.*)&&(.*)/i) { 70 $vacation{'days'}=$1; 71 $vacation{'addresses'}="$2"; 72 $vacation{'text'}=$3; 73 $vacation{'mode'}=$4; 74 $vacation{'addresses'}=~s/\\@/\@/g; 75 $vacation{'addresses'}=~s/\"//g; 76 $usevacation=1; 77 next; 78 79 } 80 81 chomp($line); 82 my ($tag,$priority,$ruletype,$from,$to,$subject,$desttype,$dest,$flg,$fieldname,$fieldval,$size) = split("&&",$line); 83 next if !$desttype; 84 next if $tag=~/mode/i; 85 $priority=~s/^ +//; 86 $priority=~s/ +$//; 87 $dest=~s/\r//g; 88 $dest=~s/\\n/\r\n/g; 89 if ($flg=~/copy/i) { 90 $copyflg='copy'; 91 } 92 else { 93 $copyflg= ($flg & $copybit); 94 } 95 if ($copyflg) { 96 $copyflg='copy'; 97 } 98 else { 99 $copyflg='nocopy'; 100 } 101 $matchflg=($flg & $searchbit); 102 $keepflg=($flg & $keepbit); 103 $keepflg=0 if (!$keepflg); 104 $matchflg=0 if (!$matchflg); 105 $sizeflg=($flg & $sizebit); 106 $sizeflg=0 if (!$sizeflg); 107 $regexflg=($flg & $regexbit); 108 $regexused ||=$regexflg; 109 if ($ruletype !~/ENABLED|\d/i) {next}; 110 if ($desttype=~/folder/i) { 111 next if !$dest; 112 $dest=~s/^INBOX.INBOX/INBOX/; 113 if (($dest =~s/^INBOX\.(.+)/$1/)||($alt_namespace)) { 114 $msgdest=$dest; 115 } 116 else { 117 $msgdest="$dest"; 118 } 119 # check if folder is in an addtional namespace 120 foreach $namespace (@namespaces) { 121 if ($dest=~/^$namespace./i) { 122 $msgdest="$dest"; 123 last; # stop checking 124 } 125 } 126 } 127 elsif ($desttype=~/discard/) { 128 $msgdest="/dev/null"; 129 } 130 elsif ($desttype=~/address/i) { 131 if ($dest =~/\w+\@\w+\.\w+/) { 132 $msgdest=$dest; 133 } 134 else { 135 next; 136 } 137 next if !$dest; 138 139 } 140 141 else {$msgdest='';} 142 $rulesyes=1; 143 144 $fieldn='0'; 145 $field=''; 146 $not=''; 147 148 if ($to) { 149 150 $not="!" if $to=~s/^\s*!//; 151 $to=".*$to.*"; 152 $field.=$not.$fields{'contain'}.$fields{'to'}."$to\n"; 153 $fieldn++; 154 } 155 $not=''; 156 if ($from) { 157 $not="!" if $from=~s/^\s*!//; 158 $from=".*$from.*"; 159 $field.=$not.$fields{'contain'}.$fields{'from'}."$from\n"; 160 $fieldn++; 161 } 162 $not=''; 163 if ($subject) { 164 $not="!" if $subject=~s/^\s*!//; 165 $subject=".*$subject.*"; 166 $field.=$not.$fields{'contain'}.$fields{'subject'}."$subject\n"; 167 $fieldn++; 168 169 } 170 $not=''; 171 if ($size) { 172 $contains='< '; 173 $contains='> ' if $sizeflg; 174 $not="!" if $size=~s/^\s*!//; 175 $size=~/([0-9]+)/; 176 $kb=''; 177 $size=$1; 178 $size='' if !$size; 179 $field.=$not.$contains.$size."$kb\n"; 180 $fieldn++; 181 } 182 183 $not=''; 184 if ($fieldname && $fieldval) { 185 $not="!" if $fieldval=~s/^\s*!//; 186 $fieldval=".*$fieldval.*"; 187 $field.=$not.$fields{'contain'}."^".$fieldname.": "."$fieldval\n"; 188 $fieldn++; 189 190 } 191 192 193 if (!($to || $from || $subject || $size || $fieldname || $fieldval ) && $desttype ne 'custom') { 194 $tmp=''; # for now 195 $copystat=''; 196 } 197 elsif ($desttype=~/reject/) { 198 $msgdest="* !^X-Loop: $uid\@$maildomain\n* !^FROM_DAEMON\n"; 199 $msgdest.="| (\$FORMAIL -r -I\"Precedeence: junk\" -A\""; 200 $msgdest.="X-Loop: $uid\@$maildomain\";/bin/cat $rejectfile; /bin/echo \"-- \";) | \$SENDMAIL ;"; 201 $tmp=":0 h"."\n".$field."$msgdest\n\n"; 202 203 } 204 elsif ($desttype=~/reply/i) { 205 $msgdest="* !^X-Loop: $uid\@$maildomain\n* !^FROM_DAEMON\n"; 206 $msgdest.="| (\$FORMAIL -r -I\"Precedeence: junk\" -A \""; 207 $msgdest.="X-Loop: $uid\@$maildomain\";/bin/cat $replyfile.$priority.$uid ; /bin/echo \"-- \";) | \$SENDMAIL ;"; 208 $tmp=$fields{$copyflg}."\n".$field."$msgdest\n\n"; 209 open (REP,">$replyfile.$priority.$uid"); 210 print REP "$dest\n"; 211 close REP; 212 next if !$dest; 213 } 214 215 elsif ($desttype eq 'custom') { 216 $tmp=$dest."\n\n"; 217 next if $tmp!~/^\s*:0/; 218 } 219 else { 220 $tmp=$fields{$copyflg}."\n".$field.$fields{lc($desttype)}."\'$msgdest\'\n\n"; 221 } 222 $proc.=$tmp; 223 $change=1; 224 } #while @lrules 225 $vacationyes=1 if ($vacation{'mode'}=~/on|active|yes|1/i); 226 $proch="# Mail rules for user $uid\n# Created by Websieve version $version\n\n"; 227 228 $proc=$proch.$proc; 229 230 if($vacation{'mode'}=~/on|active|yes|1/i) { 231 $vacation{'text'}=~s/\\n/\r\n/g; 232 if ($vacation{'text'}) { 233 $msgdest="* !^X-Loop: $uid\@$maildomain\n* !^FROM_DAEMON\n"; 234 $msgdest.="| \$FORMAIL -rD 8192 $vacationdb.$uid\n\n"; 235 $msgdest.=":0 ehc\n| (\$FORMAIL -r -I\"Precedence: junk\" -A\"X-Loop: $uid\@$maildomain\" ; /bin/cat $vacationfile.$uid; ) | \$SENDMAIL; "; 236 $proc.=":0 Whc: $vacationdb.$uid.lock"."\n"."$msgdest\n\n"; 237 open (VAC,">$vacationfile.$uid"); 238 print VAC $vacation{'text'}."\n"; 239 close VAC; 240 open (VACDB,">$vacationdb.$uid"); 241 close VACDB; 242 $rulesyes=1; 243 } 244 else { 245 $vacation{'mode'}='off'; 246 } 247 248 } 249 else { 250 unlink "$vacationfile.$uid"; 251 unlink "$vacationdb.$uid"; 252 } 253# if (!$rulesyes ) { 254# $proc=$proch; 255# $rulesyes=1; 256# } 257 258 259 $change=1; 260 if ($rulesyes) { 261# print "proc=\n$proc\npseudo=\n$pseudo\n"; 262 open (OUT,">$rulefile.$uid"); 263 print OUT "$proc\n"; 264 close OUT; 265 return; 266 } # if rulesyes 267 else { 268 unlink "$rulefile.$uid"; 269 } 270 271} 272sub parseinput { 273 while (<>) { 274 print $_; 275 if (/^$header +(\w+) (\S+)/) { 276 ($uid, $adminsecret)=($1,$2); 277 last; 278 } 279 280 } 281 return $uid; 282} 283 284#main 285 286$uid=&parseinput; 287$uid= $ARGV[0] if $ARGV[0]; 288$ld=&auth_connect($adminuid,$adminpass); 289$dn=&auth_getdn($ld,$uid); 290$rules=&auth_getatt($ld,$dn,'matchingrules'); 291&updateprocmail($rules,$uid) if $rules; 292 293