root/alternc-procmail/tags/nightly_sarge/m_procmail.php

Revision 1272, 16.0 kB (checked in by benjamin, 4 years ago)

globaux oubli�s

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2 /*
3  $Id$
4  ----------------------------------------------------------------------
5  AlternC - Web Hosting System
6  Copyright (C) 2002 by the AlternC Development Team.
7  http://alternc.org/
8  ----------------------------------------------------------------------
9  Based on:
10  Valentin Lacambre's web hosting softwares: http://altern.org/
11  ----------------------------------------------------------------------
12  LICENSE
13
14  This program is free software; you can redistribute it and/or
15  modify it under the terms of the GNU General Public License (GPL)
16  as published by the Free Software Foundation; either version 2
17  of the License, or (at your option) any later version.
18
19  This program is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  GNU General Public License for more details.
23
24  To read the license please visit http://www.gnu.org/copyleft/gpl.html
25  ----------------------------------------------------------------------
26  Original Author of file: Benjamin Sonntag
27  Purpose of file: Build a .procmailrc file for a user.
28      Manage ldap aliases with pipes to procmail for a user.
29  ----------------------------------------------------------------------
30 */
31
32 bindtextdomain("procmail_builder", "/var/alternc/bureau/locales");
33
34 // Every plugin MUST start with that require to be able to access other classes :
35
36 class m_procmail {
37
38 var $clsid="procmail";    /* Every plugin has a distinct CLSID, corresponding to his error messages class. */
39 var $uid=0;         /* Membre actuellement connecté */
40 var $user;        /* pop Login name */
41
42 /*
43 How it works :
44 Normally, a pop mail entry is built as follow in the system db :
45     mail_domain (mail='friend@public.com'  alias='list of aliases+ friend_public.com'
46         uid=$cuid  pop=1 type=0 (standard mail ) )
47     mail_users (pop courier account) : alias = friend@public.com && alias = friend_public.com
48     mail_alias (postfix indirection) : mail = friend_public.com && alias = /var/alternc/mail...
49 with procmail_builder active, the entries are as follow :
50     mail_alias (postfix indirection) : mail = friend_public.com && alias = |/var/alternc/mail...
51 */
52
53 /*****************************************************************************
54 m_procmail() Constructeur de la classe m_procmail
55 *****************************************************************************/
56 function m_procmail($user="") {
57     $this->user=str_replace("@","_",$user);
58 }
59
60 /*****************************************************************************
61 get_status([$user]) retourne l'état de dérivation de la boite par procmail
62 de l'utilisateur $user (ou de l'utilisateur courant)
63 retourne 1 pour une boite dérivée, 0 pour une boite non dérivée, et false si
64 une erreur s'est produite
65 *****************************************************************************/
66 function get_status($user="") {
67     global $db;
68     if (!$user) $user=$this->user;
69
70     //    $db->query("INSERT INTO mail_domain (mail,alias,uid,pop,type) VALUES ('".$login."@".$domain."','".$login."_".$domain."','$cuid',0,1);");
71     //    $db->query("INSERT INTO mail_alias (mail,alias) VALUES ('".$login."_".$domain."','\"| $command\"');");
72
73     $db->query("SELECT alias FROM mail_alias WHERE mail='".$login."';");
74     if ($db->next_record()) {
75         if (substr($db->f("alias"),1,1)=="|") {
76             return 1;
77         }
78     }
79     return 0;
80 }
81
82 /*****************************************************************************
83 disable([$user]) Désactive procmail pour un utilisateur
84 Ne détruit pas le jeu de règles :)
85 Retourne True si tout s'est bien passé, false sinon.
86 *****************************************************************************/
87 function disable($user="") {
88     global $er,$db;
89     if (!$user) $user=$this->user;
90     $u=substr($user,0,1);
91     $db->query("UPDATE mail_alias SET alias='/var/alternc/mail/$u/$user/Maildir/' WHERE mail='$user';");
92     return true;
93 }
94
95 /*****************************************************************************
96 enable([$user]) Active procmail pour un utilisateur
97 Construit le jeu de règles par défaut si besoin :)
98 Retourne True si tout s'est bien passé, false sinon.
99 *****************************************************************************/
100 function enable($user="") {
101     global $er,$db;
102     if (!$user) $user=$this->user;
103     $u=substr($user,0,1);
104     // 1. on vérifie qu'un .procmailrc existe, sinon on crée le .procmailrc par défaut.
105     if (!file_exists("/var/alternc/mail/$u/$user/.procmailrc")) {
106         $f=fopen("/var/alternc/mail/$u/$user/.procmailrc","wb");
107         fputs($f,str_replace("%%HOME%%","/var/alternc/mail/$u/$user",join("",file("/var/alternc/bureau/class/procmail_builder/procmailrc.default"))));
108         fclose($f);
109     }
110     $db->query("UPDATE mail_alias SET alias='\"|/usr/bin/procmail -m /var/alternc/mail/$u/$user/.procmailrc\"' WHERE mail='$user';");
111     return true;
112 }
113
114
115 /*****************************************************************************
116 readrules([$user]) Lit le fichier procmailrc d'un utilisateur et retourne
117 les règles qu'il contient sous la forme d'un tableau ordonné de règle.
118 Chaque règle est un tableau associatif de la forme :
119 $c[$i]["type"]=Type de la règle (numéro)
120 $c[$i]["name"]=Nom de la règle (texte)
121 $c[$i]["count"]=Nombre de lignes dans la regle
122 $c[$i]["rule"][0-n]=Ligne de la règle
123 peut retourner un tableau vide (pas de règles) ou false si le fichier
124 .procmailrc n'existe pas ou est incorrectement formatté.
125     (note : contient un automate de lecture de .procmailrc.)
126 *****************************************************************************/
127 function readrules($user="") {
128     global $er;
129     if (!$user) $user=$this->user;
130     $u=substr($user,0,1);
131     if (!file_exists("/var/alternc/mail/$u/$user/.procmailrc")) {
132         $er->raise($this->clsid,6);
133         return false;
134     }
135     $f=fopen("/var/alternc/mail/$u/$user/.procmailrc","rb");
136     $state=0;    $rulenum=0;    $ligne=0;
137     $res=array();
138     while (!feof($f)) {
139         $found=false; // found permet de savoir si on a trouvé qqchose à chaque tour.
140         $s=fgets($f,1024);
141         $s=trim($s);
142         if ($state==1 && !ereg("^# RuleEnd$",$s)) {
143                         $res[$rulenum]["rule"][$res[$rulenum]["count"]++]=$s;
144                         $found=true;
145                 }
146                 if ($state==1 && ereg("^# RuleEnd$",$s)) { // $
147                         $state=0;
148                         $rulenum++;
149                         $found=true;
150                 }
151         if ($state==0 && ereg("^# RuleType ([0-9][0-9]) -- (.*)?$",$s,$r)) {
152             $state=1;
153             $res[$rulenum]["type"]=$r[1];
154             $res[$rulenum]["name"]=$r[2];
155             $res[$rulenum]["count"]=0;
156             $found=true;
157         }
158         if (!$found && $state!=0) {
159             $er->raise($this->clsid,5,$ligne);
160             return false;
161         }
162         $ligne++;
163     }
164     fclose($f);
165     return $res;
166 }
167
168 /*****************************************************************************
169 writerules($rule,[$user]) Ecrit le fichier procmailrc d'un utilisateur en prenant
170 le tableau de règle en paramètre. Remplit le .procmailrc avec le fichier
171 par défaut, suivi des règles dans l'ordre du tableau.
172 retourne false si le fichier .procmailrc n'existe pas déjà.
173 retourne true si tout va bien.
174 *****************************************************************************/
175 function writerules($res,$user="") {
176     global $er;
177     if (!$user) $user=$this->user;
178     $u=substr($user,0,1);
179     if (!file_exists("/var/alternc/mail/$u/$user/.procmailrc")) {
180         $er->raise($this->clsid,6);
181         return false;
182     }
183     $f=fopen("/var/alternc/mail/$u/$user/.procmailrc","wb");
184     fputs($f,str_replace("%%HOME%%","/var/alternc/mail/$u/$user",join("",file("/var/alternc/bureau/class/procmail_builder/procmailrc.default"))));
185     for($i=0;$i<count($res);$i++) {
186         $res[$i]["name"]=trim(str_replace("\r","",str_replace("\n","",$res[$i]["name"])));
187         fputs($f,"# RuleType ".sprintf("%02d",$res[$i]["type"])." -- ".$res[$i]["name"]."\n");
188         for($j=0;$j<$res[$i]["count"];$j++) {
189             fputs($f,$res[$i]["rule"][$j]."\n");
190         }
191         fputs($f,"# RuleEnd\n\n");
192     }
193     fclose($f);
194     return true;
195 }
196
197 /*****************************************************************************
198 addrule($rule,[$user]) Ajout la regle $rule au fichier procmailrc
199 d'un utilisateur retourne false si le fichier .procmailrc n'existe pas déjà.
200 retourne true si tout va bien.
201 *****************************************************************************/
202 function addrule($rule,$user="") {
203     global $er;
204     if (!$user) $user=$this->user;
205     $u=substr($user,0,1);
206     if (!file_exists("/var/alternc/mail/$u/$user/.procmailrc")) {
207         $er->raise($this->clsid,6);
208         return false;
209     }
210     $f=fopen("/var/alternc/mail/$u/$user/.procmailrc","ab");
211     $rule["name"]=trim(str_replace("\r","",str_replace("\n","",$rule["name"])));
212     fputs($f,"# RuleType ".sprintf("%02d",$rule["type"])." -- ".$rule["name"]."\n");
213     for($j=0;$j<$rule["count"];$j++) {
214         fputs($f,$rule["rule"][$j]."\n");
215     }
216     fputs($f,"# RuleEnd\n\n");
217     fclose($f);
218     return true;
219 }
220
221 /*****************************************************************************
222 buildrule($crit,$crittext,$raction,$foldertogo,$emailto,$autoreplytxt,[$user])
223 Construit la règle basée sur les critères de formulaire passés en paramètre.
224 *****************************************************************************/
225 function buildrule($rulename,$crit,$crittext,$raction,$foldertogo,$emailto,$autoreplytxt,$user="") {
226     global $er;
227     if (!$user) $user=$this->user;
228     $u=substr($user,0,1);
229     $mail=$user;
230     if ($c=strrpos($mail,"_")) {
231         $mail=substr($mail,0,$c)."@".substr($mail,$c+1);
232     }
233     // Vérification de la monovalence de Spam, Forward et AutoReply
234     if ($raction==2 || $raction==4 || $raction==5) {
235         $r=$this->readrules($user);
236         for($a=0;$a<count($r);$a++) {
237             if ($r[$a]["type"]==$raction) {
238                 $er->raise($this->clsid,9);
239                 return false;
240             }
241         }
242     }
243     $r=array();
244     $r["type"]=$raction;
245     $r["name"]=str_replace("\n","",trim($rulename));
246     if (!$r["name"]) $r["name"]="-";
247     $r["count"]=0;
248     switch ($raction) {
249     case 2:
250         $r["rule"][$r["count"]++]=":0 fw";
251         break;
252     case 4:
253         $r["rule"][$r["count"]++]=":0 c";
254         break;
255     case 5:
256         $r["rule"][$r["count"]++]=":0 Whc: /var/alternc/mail/$u/$user/$user.lock";
257         break;
258     default:
259         $r["rule"][$r["count"]++]=":0";
260         break;
261     }
262
263     for($j=0;$j<count($crit);$j++) {
264         $tt=str_replace(array("\n","?",".","*","+"),
265                                 array("","\\?","\\.","\\*", "\\+"),
266                             $crittext[$j]);
267
268         switch ($crit[$j]) {
269         case 0:
270             $s="* ^Subject.*$tt";
271             break;
272         case 1:
273             $s="* ^From.*$tt";
274             break;
275         case 2:
276             $s="* ^TO_$tt";
277             break;
278         case 3:
279             $s="* ^List-Post: $tt";
280             break;
281         case 4:
282             $s="* ^List-Id: $tt";
283             break;
284         case 5:
285             $s="* ^X-Spam-Status: Yes";
286             break;
287         case 6:
288             $s="* ^Delivered-To:.*$tt";
289             break;
290         }
291     $r["rule"][$r["count"]++]=$s;
292     } // for criteria.
293
294
295     switch ($raction) {
296     case 1:
297         //$r["rule"][$r["count"]++]=str_replace(" ","\\ ",substr($foldertogo,5))."/";
298         $r["rule"][$r["count"]++]=".".str_replace(array("\\\\"," "),array("\\","\\ "),addslashes(quotemeta(substr($foldertogo,6))))."/";
299         break;
300     case 2:
301         $r["rule"][$r["count"]++]="| /usr/bin/spamc";
302         break;
303     case 3:
304         $r["rule"][$r["count"]++]="/dev/null";
305         break;
306     case 4:
307         if (checkmail($emailto)) {
308             $er->raise($this->clsid,10);
309             return false;
310         }
311         $r["rule"][$r["count"]++]='|$SENDMAIL -oi '.$emailto;
312         break;
313     case 5:
314         $r["rule"][$r["count"]++]="* !^FROM_DAEMON";
315         $r["rule"][$r["count"]++]="* !^X-Loop: $mail";
316         $r["rule"][$r["count"]++]="| formail -rD 8192 /var/alternc/mail/$u/$user/$user.list";
317         $r["rule"][$r["count"]++]="";
318         $r["rule"][$r["count"]++]=":0 ehc";
319         $r["rule"][$r["count"]++]="| (formail -rtI\"Precedence: junk\" -I\"From: <$mail>\" -A\"X-Loop: $mail\" ; cat /var/alternc/mail/$u/$user/$user.txt) | ".'$'."SENDMAIL -oi -t";
320         $f=fopen("/var/alternc/mail/$u/$user/$user.txt","wb");
321         fputs($f,$autoreplytxt);
322         fclose($f);
323         @unlink("/var/alternc/mail/$u/$user/$user.list");
324         @unlink("/var/alternc/mail/$u/$user/$user.lock");
325     }
326     $r["rule"][$r["count"]++]="";
327     return $r;
328 }
329
330 /*****************************************************************************
331 uprule($rules,$i) Remonte d'un cran la $i-ème règle du tableau de
332 règle $rules retourne true si tout va bien. ($i>0)
333 *****************************************************************************/
334 function uprule($res,$i) {
335     global $er;
336     $i=intval($i);
337     if (count($res)<$i || $i==0) {
338         $er->raise($this->clsid,7);
339         return false;
340     }
341     $t=$res[$i];
342     $res[$i]=$res[$i-1];
343     $res[$i-1]=$t;
344     return $res;
345 }
346
347 /*****************************************************************************
348 downrule($rules,$i) Descend d'un cran la $i-ème règle du tableau de
349 règle $rules retourne true si tout va bien.
350 *****************************************************************************/
351 function downrule($res,$i) {
352     global $er;
353     $i=intval($i);
354     if ((count($res)-1)<$i) {
355         $er->raise($this->clsid,7);
356         return false;
357     }
358     $t=$res[$i];
359     $res[$i]=$res[$i+1];
360     $res[$i+1]=$t;
361     return $res;
362 }
363
364 /*****************************************************************************
365 describe($rule) Retourne un text dans la langue courante décrivant la règle
366 $rule passée en paramètre.
367 *****************************************************************************/
368 function describe($rule) {
369     $s="";
370
371     // Lecture des conditions :
372     $cond=array();
373     switch ($rule["type"]) {
374     case 5:
375         $i=1;
376         while ($rule["rule"][$i]!="* !^FROM_DAEMON" && $rule["rule"][$i]!="") {
377             $cond[]=$rule["rule"][$i];
378             $i++;
379         }
380         break;
381     default:
382         $i=1;
383         while (substr($rule["rule"][$i],0,1)=="*") {
384             $cond[]=$rule["rule"][$i];
385             $i++;
386         }
387         break;
388     }
389     // On a cond, on le parse :)
390     if (count($cond)) {
391         $s.="<small>";
392     }
393     for($i=0;$i<count($cond);$i++) {
394         if ($i) $s.=" et ";
395         if (ereg("^\\* \\^Subject\\.\\*(.*)$",$cond[$i],$t)) {
396             $s.=_("procmail_crit_0")."&nbsp;&nbsp;<code>".str_replace("\\","",$t[1])."</code>";
397         }
398         if (ereg("^\\* \\^From\\.\\*(.*)$",$cond[$i],$t)) {
399             $s.=_("procmail_crit_1")."&nbsp;&nbsp;<code>".str_replace("\\","",$t[1])."</code>";
400         }
401         if (ereg("^\\* \\^TO_(.*)$",$cond[$i],$t)) {
402             $s.=_("procmail_crit_2")."&nbsp;&nbsp;<code>".str_replace("\\","",$t[1])."</code>";
403         }
404         if (ereg("^\\* \\^List-Post: (.*)$",$cond[$i],$t)) {
405             $s.=_("procmail_crit_3")."&nbsp;&nbsp;<code>".str_replace("\\","",$t[1])."</code>";
406         }
407         if (ereg("^\\* \\^List-Id: (.*)$",$cond[$i],$t)) {
408             $s.=_("procmail_crit_4")."&nbsp;&nbsp;<code>".str_replace("\\","",$t[1])."</code>";
409         }
410         if (ereg("^\\* \\^X-Spam-Status: Yes$",$cond[$i])) {
411             $s.=_("procmail_crit_5");
412         }
413         if (ereg("^\\* \\^Delivered-To:\\.\\*(.*)$",$cond[$i],$t)) {
414             $s.=_("procmail_crit_6")."&nbsp;&nbsp;<code>".str_replace("\\","",$t[1])."</code>";
415         }
416         $s.="<br>\n";
417     }
418     if (count($cond)) {
419         $s.="</small>";
420     }
421     $s.="--&gt; ";
422     // Action :
423     switch ($rule["type"]) {
424     case 1:
425         $t=$rule["rule"][count($rule["rule"])-2];
426         $s.=_("Move the message to this folder")." &nbsp; <code>INBOX".substr($t,0,strlen($t)-1)."</code>";
427         break;
428     case 2:
429         $s.=_("Filter the message through SpamAssassin");
430         break;
431     case 3:
432         $s.=_("Discard the message (for good !)");
433         break;
434     case 4:
435         $t=$rule["rule"][count($rule["rule"])-2];
436         $s.=_("Forward the mail to")." &nbsp; <code>".substr($t,15)."</code>";   
437         break;
438     case 5:
439         $s.=_("Auto-reply");
440         break;
441     }
442     return $s;
443 }
444
445
446 } // CLASS
447
448 /*
449
450 Procmail sample rules :
451
452 # PROCMAILRC HEADING
453 VERBOSE=no
454 MAILDIR=$HOME/Maildir/
455 DEFAULT=$HOME/Maildir/
456
457 # RULETYPE 1 Filtrage sur l'expéditeur du mail
458 :0
459 * ^From.*www-data@sinerj.org
460 .Globenet.No-Log/
461
462 # RULETYPE 2 Filtrage sur le destinataire du mail
463 :0
464 * ^TO_frnog@frnog.org
465 .Listes.frnog/
466
467 # RULETYPE 3 Filtrage sur un List-Id
468 :0
469 * List-Id: <interne_lafil.org@lafil.org>
470 .Listes.interne_lafil/