#!/usr/bin/php =3.0 ---------------------------------------------------------------------- */ /* ----------------------------------------------------------------- */ /** MAIN FUNCTION Read all the mail folders and search for .procmailrc's */ function procmail2sieve() { global $ROOT; $d=@opendir($ROOT); if ($d) { while ($c=readdir($d)) { if (substr($c,0,1)==".") continue; // skip hidden files if (is_dir($ROOT."/".$c)) { // Go to level 2. $e=@opendir($ROOT."/".$c); if ($e) { while ($f=readdir($e)) { if (substr($f,0,1)==".") continue; // skip hidden files if (is_file($ROOT."/".$c."/".$f."/.procmailrc")) { // We found one .procmailrc, let's parse it on behalf of his user... parseOneProcmail($f); /* ################## SUB FUNCTION ###################### */ } } closedir($e); } else { echo "ERROR: Cannot open ".$ROOT."/".$c."\n"; } } } closedir($d); } else { echo "FATAL: cannot open ".$ROOT."\n"; exit(); } } /* procmail2sieve */ /* ----------------------------------------------------------------- */ /** Parse ONE procmailrc, and write its sieve rules * @param string $user */ function parseOneProcmail($user) { global $SIEVEROOT; $email=preg_replace("#_([^_]*)$#","@$1",$user); if ($rules=readrules($user)) { /* ################## SUB FUNCTION ###################### */ for($i=0; $i 1, "minor"=>9, "release" => 9, "string" => "1.9.9"); fputs($f,'# This script has been automatically generated by avelsieve # (Sieve Mail Filters Plugin for Squirrelmail) # Warning: If you edit this manually, then the changes will not # be reflected in the users\' front-end! #AVELSIEVE_VERSION'.urlencode(base64_encode(serialize($avelsieveversion))).' #AVELSIEVE_CREATED'.time().' #AVELSIEVE_MODIFIED'.time().' require ["fileinto","envelope","reject","vacation","imap4flags","relational","comparator-i;ascii-numeric","regex","body","date"]; '); foreach($rules as $rule) { if ($rule["type"]==2) continue; // IGNORE "Filter the message through SpamAssassin" // Create the avelsieve array: $avelrule=array(); // And sieve script: $script="if "; $avelrule["condition"]="and"; $avelrule["type"]=1; if (!count($rule["conds"])) { // no conditions $script.="true\n"; $avelrule["cond"][]=array("kind" => "message", "type" => "all"); } else { // have conditions $script.="allof ("; $first=true; foreach($conds as $cond) { if (!$first) $script.=",\n"; $first=false; // What kind of condition? switch($cond[0]) { case 0: // subject $script.='header :contains "Subject" "'.str_replace('"','\\"',$cond[1]).'"'; $avelrule["cond"][]=array("kind" => "message", "type" => "header", "header" => "Subject", "matchtype" => "contains", "headermatch" => $cond[1] ); break; case 1: // sender $script.='header :contains "From" "'.str_replace('"','\\"',$cond[1]).'"'; $avelrule["cond"][]=array("kind" => "message", "type" => "header", "header" => "From", "matchtype" => "contains", "headermatch" => $cond[1] ); break; case 2: // recipient $script.='address :contains ["to", "cc"] "'.str_replace('"','\\"',$cond[1]).'"'; $avelrule["cond"][]=array("kind" => "message", "type" => "address", "address" => "toorcc", "matchtype" => "contains", "addressmatch" => $cond[1] ); break; case 3: // List-Post $script.='header :contains "List-Post" "'.str_replace('"','\\"',$cond[1]).'"'; $avelrule["cond"][]=array("kind" => "message", "type" => "header", "header" => "List-Post", "matchtype" => "contains", "headermatch" => $cond[1] ); break; case 4: // List-Id $script.='header :contains "List-Id" "'.str_replace('"','\\"',$cond[1]).'"'; $avelrule["cond"][]=array("kind" => "message", "type" => "header", "header" => "List-Id", "matchtype" => "contains", "headermatch" => $cond[1] ); break; case 5: // Spamassassin $script.='header :contains "X-Spam-Status" "Yes"'; $avelrule["cond"][]=array("kind" => "message", "type" => "header", "header" => "X-Spam-Status", "matchtype" => "contains", "headermatch" => "Yes" ); break; case 6: // Delivered-To $script.='envelope :contains "to" "'.str_replace('"','\\"',$cond[1]).'"'; $avelrule["cond"][]=array("kind" => "message", "type" => "envelope", "envelope" => "to", "matchtype" => "contains", "envelopematch" => $cond[1] ); break; } } $script.=")\n{\n"; } // Now the ACTION: switch($rule["type"]) { case 1: // move to $script.='fileinto "'.str_replace('"','\\"',$rule["actionparam"]).'"; stop; '; $avelrule["action"] = 5; $avelrule["folder"] = $rule["actionparam"]; $avelrule["stop"] = "on"; break; case 3: // Discard (for good) $script.='discard; stop; '; $avelrule["action"] = 2; $avelrule["stop"] = "on"; break; case 4: // Forward To (copy) $script.='redirect "'.str_replace('"','\\"',$rule["actionparam"]).'"; '; $avelrule["action"] = 4; $avelrule["redirectemail"] = $rule["actionparam"]; break; case 5: // Auto-Reply $script.='vacation :days 7 :addresses ["'.$email.'"@ :subject "Auto Reply" text: '.str_replace("\\'","'",@file_get_contents($ROOT."/".$u."/".$user."/".$user.".txt")).' . ; '; $avelrule["action"] = 6; $avelrule["vac_addresses"] = $email; $avelrule["vac_subject"] = "Auto Reply"; $avelrule["vac_days"] = 7; $avelrule["vac_message"] = @file_get_contents($ROOT."/".$u."/".$user."/".$user.".txt"); break; } $script.="}\n"; // Now put it into the script file : fputs($f,"#START_SIEVE_RULE".urlencode(base64_encode(serialize($avelrule)))."END_SIEVE_RULE\n"); fputs($f,$script); /* if allof (header :contains "From" "expediteur@coin.pan", header :contains "To" "destinataire@coin.pan") { fileinto "INBOX.test"; stop; } */ } /* for each rule */ fclose($f); // Then Move it to the right place @unlink($SIEVEROOT."/".$u."/".$user."/sieve/phpscript.sieve"); rename( $SIEVEROOT."/".$u."/".$user."/sieve/tmp/phpscript.sieve", $SIEVEROOT."/".$u."/".$user."/sieve/phpscript.sieve" ); chown($SIEVEROOT."/".$u."/".$user."/sieve/phpscript.sieve",$uid); chgrp($SIEVEROOT."/".$u."/".$user."/sieve/phpscript.sieve","vmail"); } } else { echo "ERROR: can't read rules for $user\n"; } } /* parseOneProcmauil */ /* ----------------------------------------------------------------- */ /** Read rules, fill an array from m_procmail.php original file yeah I know, ereg() is deprecated ;) */ function readrules($user="") { if (!$user) $user=$this->user; $u=substr($user,0,1); if (!file_exists(ALTERNC_MAIL."/$u/$user/.procmailrc")) { return false; } $f=fopen(ALTERNC_MAIL."/$u/$user/.procmailrc","rb"); $state=0; $rulenum=0; $ligne=0; $res=array(); while (!feof($f)) { $found=false; // found allow us to know if we found something for each loop $s=fgets($f,1024); $s=trim($s); if ($state==1 && !ereg("^# RuleEnd$",$s)) { $res[$rulenum]["rule"][$res[$rulenum]["count"]++]=$s; $found=true; } if ($state==1 && ereg("^# RuleEnd$",$s)) { $state=0; $rulenum++; $found=true; } if ($state==0 && ereg("^# RuleType ([0-9][0-9]) -- (.*)?$",$s,$r)) { $state=1; $res[$rulenum]["type"]=$r[1]; $res[$rulenum]["name"]=$r[2]; $res[$rulenum]["count"]=0; $found=true; } if (!$found && $state!=0) { return false; } $ligne++; } fclose($f); return $res; } /* ----------------------------------------------------------------- */ /** Take ONE rule array, extract properly returns one array with the conditions (which are arrays with Condition Type and Value) and the action parameter */ function describe($rule) { // Lecture des conditions : $cond=array(); switch ($rule["type"]) { case 5: $i=1; while ($rule["rule"][$i]!="* !^FROM_DAEMON" && $rule["rule"][$i]!="") { $cond[]=$rule["rule"][$i]; $i++; } break; default: $i=1; while (substr($rule["rule"][$i],0,1)=="*") { $cond[]=$rule["rule"][$i]; $i++; } break; } // $cond is an array of conditions // let's parse the condition : (see arrays at the top of this file) $conds=array(); for($i=0;$i "Le sujet du message contient ...", 1 => "L'expediteur du message est contient ...", 2 => "L'un des destinataires du message contient ...", 3 => "L'en-tete 'List-Post' du message est ...", 4 => "L'en-tete 'List-Id' du message est ...", 5 => "SpamAssassin considere qu'il s'agit d'un Spam", 6 => "L'en-tete 'Delivered-To' du message contient ...", ); $aactions=array( 1 => "Move the message to this folder", 2 => "Filter the message through SpamAssassin", 3 => "Discard the message (for good !)", 4 => "Forward the mail to", 5 => "Auto-reply", ); /* ----------------------------------------------------------------- */ // CONFIGURATION : include_once('/usr/share/alternc/panel/class/local.php'); $ROOT=$L_ALTERNC_MAIL; $SIEVEROOT="/var/lib/dovecot/sieve"; // GO ! procmail2sieve();