source: bureau/class/m_mail.php @ 619

Revision 619, 19.9 KB checked in by anarcat, 7 years ago (diff)

[project @ alternc: changeset 2005-04-26 20:42:52 by anarcat]
inscrire l'addresse email complète dans le message d'erreur lorsque
l'alias existe déjà

Original author: anarcat
Date: 2005-04-26 20:42:52

Line 
1<?php
2/*
3 $Id: m_mail.php,v 1.29 2005/04/26 20:42:52 anarcat Exp $
4 ----------------------------------------------------------------------
5 LICENSE
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License (GPL)
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 To read the license please visit http://www.gnu.org/copyleft/gpl.html
18 ----------------------------------------------------------------------
19 Original Author of file: Benjamin Sonntag, Franck Missoum
20 Purpose of file: Manage Email accounts and aliases.
21 ----------------------------------------------------------------------
22*/
23/**
24* Classe de gestion des comptes mails de l'hébergé.
25*
26* Cette classe permet de gérer les comptes pop, alias
27* mail des domaines d'un membre hébergé.<br />
28* Copyleft {@link http://alternc.net/ AlternC Team}
29*
30* @copyright    AlternC-Team 2002-11-01 http://alternc.net/
31*
32*/
33class m_mail {
34
35  /** Liste des domaines
36   * @access private
37   */
38  var $domains;
39
40
41  /* ----------------------------------------------------------------- */
42  /**
43   * Constructeur
44   */
45  function m_mail() {
46  }
47
48  /* ----------------------------------------------------------------- */
49  /**
50   * Liste des quotas
51   */
52  function alternc_quota_names() {
53    return "mail";
54  }
55
56  /* ----------------------------------------------------------------- */
57  /** Retourne la liste des domaines hébergés en mails sur le compte.
58   * @return array Tableau indexé des domaines hébergés en mail.
59   */
60  function enum_domains() {
61    global $db,$err,$cuid;
62    $err->log("mail","enum_domains");
63    if (!is_array($this->domains)) {
64      $db->query("select * from domaines where compte='$cuid' AND gesmx=1;");
65      $this->domains=array();
66      if ($db->num_rows()>0) {
67        while ($db->next_record()) {
68          $this->domains[]=$db->f("domaine");
69        }
70      }
71    }
72    return $this->domains;
73  }
74
75  /* ----------------------------------------------------------------- */
76  /** Retourne la liste des mails du domaine $dom
77   * Retourne un tableau indexé de tableaux associatifs sous la forme :
78   * $a["mail"]=Adresse email
79   * $a["pop"]=1 ou 0 selon s'il s'agit d'un compte pop ou pas
80   * $a["size"]=taille en octets de la boite s'il s'agit d'un compte pop.
81   * @param string $dom Domaine dont on veut les mails
82   * @param integer $sort Champs de tri (0 pour non trié (default), 1 pour email, 2 pour type)
83   * @return array Tableau de mails comme indiqué ci-dessus ou FALSE si une erreur
84   *  s'est produite
85   */
86  function enum_doms_mails($dom,$sort=0) {
87    global $err,$cuid,$db;
88    $err->log("mail","enum_doms_mails",$dom);
89    $db->query("SELECT mail,pop FROM mail_domain WHERE mail LIKE '%@$dom' AND uid='$cuid' AND type=0;");
90    $res=array(); $i=0;
91    while ($db->next_record()) {
92        if ($db->f("pop")) { 
93        /*
94        $size=exec("/usr/lib/alternc/du.pl /var/alternc/mail/".substr($info[$i]["mail"][0],0,1)."/".str_replace("@","_",$info[$i]["mail"][0]));
95        $size=$size*1024;
96        */
97        $size=0;
98        } else $size=0;
99        $res[]=array("mail" => $db->f("mail"),  "pop" => $db->f("pop"),"size"=>$size);
100        $i++;
101    }
102    if ($sort==1) {
103        usort($res,array("m_mail","_cmp_mail"));
104    }
105    if ($sort==2) {
106        usort($res,array("m_mail","_cmp_type"));
107    }
108    $res["count"]=$i;
109    return $res;
110  }
111
112 function _cmp_mail($a, $b)
113    {
114        $al = strtolower($a["mail"]);
115        $bl = strtolower($b["mail"]);
116        if ($al == $bl) return 0;
117        return ($al > $bl) ? +1 : -1;
118    }
119 function _cmp_type($a, $b)
120    {
121        $al = strtolower($a["pop"]);
122        $bl = strtolower($b["pop"]);
123        if ($al == $bl) {
124          $al = strtolower($a["mail"]);
125          $bl = strtolower($b["mail"]);
126          if ($al == $bl) return 0;
127        }
128        return ($al > $bl) ? +1 : -1;
129    }
130
131  /* ----------------------------------------------------------------- */
132  /** Retourne les détails d'un mail
133   * Le mail $mail est retourné sous la forme d'un tableaau associatif comme suit :
134   * $a["mail"]= Adresse email
135   * $a["login"]= Login pop
136   * $a["password"]= Mot de passe pop (crypté)
137   * $a["alias"]= Alias destination, 1 par ligne
138   * $a["pop"]= 1 ou 0 s'il s'agit d'un compte pop
139   * @param string $mail Mail dont on veut retourner le détail
140   * @return array Tableau associatif comme ci-dessus.
141   */
142  function get_mail_details($mail) {
143    global $err,$db,$cuid;
144    $err->log("mail","get_mail_details",$mail);
145    $db->query("SELECT mail,pop,alias FROM mail_domain WHERE mail='$mail' AND uid='$cuid';");
146    if (!$db->next_record()) { 
147      $err->raise("mail",3,$mail);
148      return false;
149    }
150    $pop=$db->f("pop"); 
151    if ($pop) {
152      $login=str_replace("@","_",$db->f("mail"));
153      $account=str_replace($login,"",$db->f("alias")); 
154    } else {
155      $account=$db->f("alias");
156    }
157    return array("mail" => $mail, "login" => $login, "alias" => $account, "pop" => $pop);
158  }
159
160  /*****************************************************************************/
161  /** Tell if a mail is available or not */
162  function available($mail) {
163    global $err,$db,$cuid;
164    $err->log("mail","available",$mail);
165    $db->query("SELECT mail FROM mail_domain WHERE mail='$mail';");
166    if ($db->next_record()) {
167        return false;
168    } else {
169        return true;
170    }
171  }
172
173  /* ----------------------------------------------------------------- */
174  /** Crée un mail 'executeur' (wrapper) pour $login@$domain
175   * @param string $login partie gauche du @ pour le mail concerné
176   * @param string $domain partie droite du @ pour le mail concerné
177   * @param string $command Commande à exécuter, sans le | ni les "" (commande brute)
178   * @param string $type ignoré désormais (plus de ldap...) TODO : remplacer cela par une appropriation de wrapper par une classe (donc mettre dans ce champ le nom de la classe appelante ? )
179   * @return boolean TRUE si le wrapper a été créé, FALSE si une erreur s'est produite.
180   */
181  function add_wrapper($login,$domain,$command,$type="") {
182    global $err,$cuid,$db;
183    if (!$this->available($login."@".$domain)) {
184      $err->raise("mail",7,$login."@".$domain);
185      return false;
186    }
187    $db->query("INSERT INTO mail_domain (mail,alias,uid,pop,type) VALUES ('".$login."@".$domain."','".$login."_".$domain."','$cuid',0,1);");
188    $db->query("INSERT INTO mail_alias (mail,alias) VALUES ('".$login."_".$domain."','\"| $command\"');");
189    return true;
190  }
191
192  /* ----------------------------------------------------------------- */
193  /** Efface un mail 'executeur' (wrapper) pour $login@$domain
194   * @param string $login partie gauche du @ pour le mail concerné
195   * @param string $domain partie droite du @ pour le mail concerné
196   * @return boolean TRUE si le wrapper a été effacé, FALSE si une erreur s'est produite.
197   */
198  function del_wrapper($login,$domain) {
199    global $err,$cuid,$db;
200    $db->query("DELETE FROM mail_domain WHERE mail='".$login."@".$domain."' AND uid='$cuid' AND type=1;");
201    $db->query("DELETE FROM mail_alias WHERE mail='".$login."_".$domain."';");
202    return true;
203  }
204
205
206  /* ----------------------------------------------------------------- */
207  /** Change le mot de passe du compte pop $mail
208   * @param string $mail Compte mail concerné
209   * @param string $pass Nouveau mot de passe
210   * @return boolean TRUE si le mot de passe a été changé, FALSE si une erreur s'est produite.
211   */
212  function change_password($mail,$pass) {
213    global $err,$db,$cuid;
214    $err->log("mail","change_password",$mail);
215    $t=explode("@",$mail);
216    $email=$t[0];
217    $dom=$t[1];
218    $db->query("SELECT mail,alias,pop FROM mail_domain WHERE mail='$mail' AND uid='$cuid';");
219    if (!$db->next_record()) {
220      $err->raise("mail",3,$mail);
221      return false;
222    }
223    if (!$db->f("pop")) {
224      $err->raise("mail",15);
225      return false;
226    }
227    if (!$this->_updatepop($email,$dom,$pass)) {
228      return false;
229    }
230    return true;
231  }
232
233  /* ----------------------------------------------------------------- */
234  /** Modifie les paramètres d'un compte email
235   * Tout peut être modifié dans l'email (sauf l'adresse elle-même)
236   * @param string $mail Adresse à modifier. Le domaine doit appartenir au membre
237   * @param integer $pop Doit-il etre un compte pop (1) ou juste un alias (0)
238   * @param string $pass Nouveau mot de passe pop, si pop=1
239   * @param string $alias Liste des destinataires auxiliaires, un par ligne.
240   * @return boolean TRUE si l'email a bien été modifié, FALSE si une erreur s'est produite.
241   */
242  function put_mail_details($mail,$pop,$pass,$alias) {
243    global $err,$cuid,$db;
244    $err->log("mail","put_mail_details",$mail);
245    $mail=strtolower($mail);
246    $t=explode("@",$mail);
247    $email=$t[0];
248    $dom=$t[1];
249
250    $account=array();
251
252    if ($pop) $pop="1"; else $pop="0";
253    //vérifie si les champs obligatoires sont renseignés
254    if ($pop=="0" && $alias=="") {
255      $err->raise("mail",4);
256      return false;
257    }
258    if ($pop=="1"){
259      $account[]=$email."_".$dom;
260    }
261    //vérifie la validité des alias :
262    if ($alias){
263      $a=explode("\n",$alias);
264      if (count($a)>0) {
265        reset($a);
266        for ($i=0;$i<count($a);$i++){
267          $a[$i]=trim($a[$i]);
268          if ($a[$i]){
269            if(checkmail($a[$i])>1){
270              $err->raise("mail",14);
271              return false;
272            }
273          }
274        $account[]=$a[$i];
275        }
276      }
277    }
278
279    $db->query("SELECT mail,alias,pop FROM mail_domain WHERE mail='$mail' AND uid='$cuid' AND type=0;");
280    if (!$db->next_record()) {
281      $err->raise("mail",3,$mail);
282      return false;
283    }
284    $oldpop= $db->f("pop");
285    // When we CREATE a pop account, we MUST give a password
286    if ($pop=="1" && $oldpop!=1) {
287      if (!$pass) {
288        $err->raise("mail",4);
289        return false;
290      }
291    }
292
293    $db->query("UPDATE mail_domain SET alias='".implode("\n",$account)."', pop='$pop' WHERE mail='$mail';");
294
295    if ($pop=="1" && $oldpop!=1) { /* Creation du compte pop */
296      if (!$this->_createpop($email,$dom,$pass)) {
297        return false;
298      }
299    }
300    if ($pop!="1" && $oldpop==1) { /* Destruction du compte pop */
301      if (!$this->_deletepop($email,$dom)) {
302        return false;
303      }
304    }
305    if ($pop=="1" && $oldpop==1 && $pass!="") { /* Modification du compte pop */
306      if (!$this->_updatepop($email,$dom,$pass)) {
307        return false;
308      }
309    }
310    return true;
311  }
312
313  /* ----------------------------------------------------------------- */
314  /** Crée un compte email $mail sur le domaine $dom
315   * @param string $dom Domaine concerné, il doit appartenir au membre
316   * @param string $mail Email à créer, il ne doit pas exister ni en mail, ni en liste.
317   * @param integer $pop vaut 1 pour créer un compte pop, 0 pour un alias
318   * @param string $alias Liste des alias, un par ligne
319   * @return boolean TRUE si le compte a bien été créé, FALSE si une erreur s'est produite.
320   */
321  function add_mail($dom,$mail,$pop,$pass,$alias) {
322    global $quota,$err,$cuid,$db;
323    $err->log("mail","add_mail",$dom."/".$mail);
324    $account=array();
325    $mail=strtolower($mail);
326    if ($pop) $pop="1"; else $pop="0";
327    if ($mail) {
328      //vérifie la validité du login mail
329      if (!checkloginmail($mail)) {
330        $err->raise("mail",13);
331        return false;
332      }
333    }
334    //vérifie si les champs obligatoires sont renseignés
335    if (($pop=="1" && $pass=="")||($pop!="1" && $alias=="")){
336      $err->raise("mail",4);
337      return false;
338    }
339    if ($pop=="1"){
340      $account[]=$mail."_".$dom;
341    }
342    //vérifie la validité des alias :
343    if ($alias){
344      $a=explode("\n",$alias);
345      if (count($a)>0) {
346        reset($a);
347        for ($i=0;$i<count($a);$i++){
348          $a[$i]=trim($a[$i]);
349          if ($a[$i]){
350            if(checkmail($a[$i])>1){
351              $err->raise("mail",14);
352              return false;
353            }
354          }
355        $account[]=$a[$i];
356        }
357      }
358    }
359
360    // check that the domains is a user's one ...
361    $db->query("SELECT domaine FROM domaines WHERE compte='$cuid' AND domaine='$dom';");
362    if (!$db->next_record()) {
363      $err->raise("mail",6,$dom);
364      return false;
365    }   
366    $db->query("SELECT mail FROM mail_domain WHERE mail='".$mail."@".$dom."' AND uid='$cuid';");
367    if ($db->next_record()) {
368      $err->raise("mail",7,$mail."@".$dom);
369      return false;
370    }   
371
372    /* QuotaCheck */
373    if (!$quota->cancreate("mail")) {
374      $err->raise("mail",8);
375      return false;
376    }
377    $db->query("INSERT INTO mail_domain (mail,alias,uid,pop,type) VALUES ('".$mail."@".$dom."','".implode("\n",$account)."','$cuid','$pop',0);");
378
379    // Ajout du compte pop dans ldap-users
380    if ($pop=="1") {
381      if (!$this->_createpop($mail,$dom,$pass))
382        return false;
383    }
384    return true;
385  }
386
387  /* ----------------------------------------------------------------- */
388  /** Efface le compte mail $mail
389   * @param string $mail Email à effacer
390   * @return boolean TRUE si le compte mail a bien été détruit, FALSE si une erreur s'est produite.
391   */
392  function del_mail($mail) {
393    global $err,$cuid,$db;
394    $err->log("mail","del_mail",$mail);
395    $mail=strtolower($mail);
396
397    $db->query("SELECT pop,mail FROM mail_domain WHERE mail='$mail' AND uid='$cuid' AND type=0;");
398    if (!$db->next_record()) {
399      $err->raise("mail",3,$dom);
400      return false;
401    }   
402    /* Ok, le mail existe, on le detruit donc... */
403    $t=explode("@",$mail);
404    $mdom=$t[0]; $dom=$t[1];
405    $pop=$db->f("pop");
406   
407    $db->query("DELETE FROM mail_domain WHERE mail='$mail' AND uid='$cuid';");
408
409    if ($pop=="1") {
410      if (!$this->_deletepop($mdom,$dom)) {
411        return false;
412      }
413    }
414    return true;
415  }
416
417  /* ----------------------------------------------------------------- */
418  /** Crée le compte pop $mail@$dom, avec pour mot de passe $pass
419   * @param string $mail Compte email à créer en pop
420   * @param string $dom Domaine sur lequel on crée le compte email
421   * @param string $pass Mot de passe du compte email.
422   * @return boolean TRUE si le compte pop a bien été créé, FALSE si une erreur est survenur
423   * @access private
424   */
425  function _createpop($mail,$dom,$pass) {
426    global $err,$cuid,$db;
427    $err->log("mail","_createpop",$mail."@".$dom);
428    $m=substr($mail,0,1);
429    $gecos=$mail;
430    if (!$mail) {
431      // Cas du CATCH-ALL
432      $gecos="Catch-All";
433      $m="_";
434    }
435    $db->query("INSERT INTO mail_users (uid,alias,path,password,sasl) VALUES ('$cuid','".$mail."_".$dom."','/var/alternc/mail/".$m."/".$mail."_".$dom."','"._md5cr($pass)."','$pass');");
436    $db->query("INSERT INTO mail_users (uid,alias,path,password,sasl) VALUES ('$cuid','".$mail."@".$dom."','/var/alternc/mail/".$m."/".$mail."_".$dom."','"._md5cr($pass)."','$pass');");
437    $db->query("INSERT INTO mail_alias (mail,alias) VALUES ('".$mail."_".$dom."','/var/alternc/mail/".$m."/".$mail."_".$dom."/Maildir/');");
438
439    $f=fopen("/var/lib/squirrelmail/data/".$mail."_".$dom.".pref","wb");
440    fputs($f,"email_address=$mail@$dom\nchosen_theme=default_theme.php\n");
441    fclose($f);
442    $f=fopen("/var/lib/squirrelmail/data/".$mail."@".$dom.".pref","wb");
443    fputs($f,"email_address=$mail@$dom\nchosen_theme=default_theme.php\n");
444    fclose($f);
445    exec("/usr/lib/alternc/mail_add ".$mail."_".$dom." ".$cuid);
446    exec("/bin/echo ".escapeshellarg($pass)." | /usr/sbin/saslpasswd -u postfix -c -p ".$mail."@".$dom);
447    exec("/bin/echo ".escapeshellarg($pass)." | /usr/sbin/saslpasswd -u postfix -c -p ".$mail."_".$dom);
448    return true;
449  }
450
451  /* ----------------------------------------------------------------- */
452  /** Met à jour un compte pop existant
453   * @param string $mail mail à modifier
454   * @param string $dom Domaine dont on modifie le compte pop
455   * @param string $pass Nouveau mot de passe.
456   * @return boolean TRUE si le compte pop a bien été modifié, FALSE si une erreur s'est produite.
457   * @access private
458   */
459  function _updatepop($mail,$dom,$pass) {
460    global $err,$cuid,$db;
461    $err->log("mail","_updatepop",$mail."@".$dom);
462    $m=substr($mail,0,1);
463    $gecos=$mail;
464    $db->query("UPDATE mail_users SET sasl='$pass', password='"._md5cr($pass)."' WHERE ( alias='". $mail."_".$dom."' OR alias='". $mail."@".$dom."' ) AND uid='$cuid';");
465    exec("/bin/echo ".escapeshellarg($pass)." | /usr/sbin/saslpasswd -u postfix -p ".$mail."@".$dom);
466    exec("/bin/echo ".escapeshellarg($pass)." | /usr/sbin/saslpasswd -u postfix -p ".$mail."_".$dom);
467    return true;
468  }
469
470  /* ----------------------------------------------------------------- */
471  /** Détruit le compte pop $mail@$dom.
472   * @param string $mail Email dont on souhaite détruire le compte pop
473   * @param string $dom Domaine dont on souhaite détuire le compte pop.
474   * @return boolean TRUE si le compte pop a bien été détruit, FALSE si une erreur s'est produite.
475   * @access private
476   */
477  function _deletepop($mail,$dom) {
478    global $err,$cuid,$db;
479    $err->log("mail","_deletepop",$mail."@".$dom);
480    $db->query("DELETE FROM mail_users WHERE uid='$cuid' AND (  alias='". $mail."_".$dom."' OR alias='". $mail."@".$dom."' ) ;");
481    $db->query("DELETE FROM mail_alias WHERE mail='".$mail."_".$dom."';");
482    @unlink("/var/lib/squirrelmail/data/".$mail."_".$dom.".pref");
483    @unlink("/var/lib/squirrelmail/data/".$mail."_".$dom.".abook");
484    @unlink("/var/lib/squirrelmail/data/".$mail."@".$dom.".pref");
485    @unlink("/var/lib/squirrelmail/data/".$mail."@".$dom.".abook");
486    exec("/usr/lib/alternc/mail_del ".$mail."_".$dom);
487    exec("/usr/sbin/saslpasswd -u postfix -d ".$mail."@".$dom);
488    exec("/usr/sbin/saslpasswd -u postfix -d ".$mail."_".$dom);
489    return true;
490  }
491
492  /* ----------------------------------------------------------------- */
493  /** Fonction appellée par domaines lorsqu'un domaine est effacé.
494   * Cette fonction efface tous les comptes mails du domaine concerné.
495   * @param string $dom Domaine à effacer
496   * @return boolean TRUE si le domaine a bien été effacé, FALSE si une erreur s'est produite.
497   * @access private
498   */
499  function alternc_del_mx_domain($dom) {
500    global $err,$db,$cuid;
501    $err->error=0;
502    $err->log("mail","alternc_del_mx_domain",$dom);
503
504/*
505    $db->query("SELECT domaine FROM domaines WHERE compte='$cuid' AND domaine='$dom';");
506    if (!$db->next_record()) {
507      $err->raise("mail",6,$dom);
508      return false;
509    }   
510*/
511
512    /* Effacement de tous les mails de ce domaine : */
513    $a=$this->enum_doms_mails($dom);
514    if (is_array($a)) {
515      reset($a);
516      for($i=0;$i<$a["count"];$i++) {
517        $val=$a[$i];
518        if (!$this->del_mail($val["mail"])) {
519          $err->raise("mail",5);
520        }
521      }
522    }
523    /* Effacement du domaine himself */
524    $db->query("DELETE FROM mail_domain WHERE mail LIKE '%@$dom';");     
525    $db->query("DELETE FROM mail_users WHERE alias LIKE '%@$dom' OR alias LIKE '%\\_$dom';");     
526    $db->query("DELETE FROM mail_alias WHERE mail LIKE '%\\_$dom';");     
527    $db->query("DELETE FROM mail_domain WHERE mail='$dom';");
528    return true;
529  }
530
531  /* ----------------------------------------------------------------- */
532  /** Fonction appellée par domaines lorsqu'un domaine est créé.
533   * Cette fonction crée les comptes par défaut du domaine concerné.
534   * @param string $dom Domaine à créer
535   * @return boolean TRUE si le domaine a bien été créé, FALSE si une erreur s'est produite.
536   * @access private
537   */
538  function alternc_add_mx_domain($dom) {
539    global $err,$cuid,$db,$mem;
540    $err->log("mail","alternc_add_mx_domain",$dom);
541    $db->query("INSERT INTO mail_domain (mail,alias) VALUES ('$dom','$dom');");
542        // Create the postmaster email for this new domain :
543    $this->add_mail($dom,"postmaster",0,"",$mem->user["mail"]);
544    return true;
545  }
546
547  /* ----------------------------------------------------------------- */
548  /**
549   * Returns the used quota for the $name service for the current user.
550   * @param $name string name of the quota
551   * @return integer the number of service used or false if an error occured
552   * @access private
553   */
554  function alternc_get_quota($name) {
555    global $db,$err,$cuid;
556    if ($name=="mail") {
557      $err->log("mail","getquota");
558      $db->query("SELECT COUNT(*) AS cnt FROM mail_domain WHERE type=0 AND uid='$cuid'");
559      $db->next_record();
560      return $db->f("cnt");
561    }
562  }
563
564
565} /* Class m_mail */
566
567?>
Note: See TracBrowser for help on using the repository browser.