54 var
$forbiddenchars = array(
'"',
"'",
'\\',
'/',
'?',
'!',
'*',
'$',
'|',
'#',
'+');
75 $this->srv_postfix = variable_get(
'fqdn_postfix', $L_FQDN,
'FQDN name for humans for smtp services. If you change it, launch reload-certs', array(
'desc' =>
'Name',
'type' =>
'string'));
76 $this->srv_dovecot = variable_get(
'fqdn_dovecot', $L_FQDN,
'FQDN name for humans for pop/imap services. If you change it, launch reload-certs', array(
'desc' =>
'Name',
'type' =>
'string'));
85 'title' => _(
"Email Addresses"),
92 $obj[
'links'][] = array(
93 'txt' => htmlentities($d[
"domaine"]) .
' ' . htmlentities(
"(" . $d[
"nb_mail"] .
")"),
94 'url' =>
"mail_list.php?domain_id=" . urlencode($d[
'id']),
104 if (empty($this->cache_domain_mail_size)) {
105 $db->query(
"SELECT SUBSTRING_INDEX(user,'@', -1) as domain, SUM(quota_dovecot) AS sum FROM dovecot_quota group by domain ;");
106 while ($db->next_record()) {
107 $dd = $db->f(
'domain');
108 $this->cache_domain_mail_size[$dd] = $db->f(
'sum');
111 if (isset($this->cache_domain_mail_size[$domain])) {
112 return $this->cache_domain_mail_size[$domain];
125 'domain' => $dom->get_domain_byid($domain_id),
130 $db->query(
"select r.recipients as dst, a.id mail_id from address a, recipient r where a.domain_id = ? and r.address_id = a.id and a.address='';", array($domain_id));
131 if ($db->next_record()) {
132 $rr[
'target'] = $db->f(
'dst');
133 $rr[
'mail_id'] = $db->f(
'mail_id');
137 if (empty($rr[
'target'])) {
138 $rr[
'type'] =
'none';
139 } elseif (substr($rr[
'target'], 0, 1) ==
'@') {
140 $rr[
'type'] =
'domain';
142 $rr[
'type'] =
'mail';
154 if (empty($catch[
'mail_id'])) {
157 return $this->
delete($catch[
'mail_id']);
167 $target = rtrim($target);
168 if (strlen($target) > 0 && substr_count($target,
'@') == 0) {
169 $target =
'@' . $target;
172 if (substr($target, 0, 1) ==
'@') {
175 if (!filter_var($target, FILTER_VALIDATE_EMAIL)) {
176 $msg->raise(
"ERROR",
"mail", _(
"The email you entered is syntaxically incorrect"));
181 return $this->
create_alias($domain_id,
'', $target,
"catchall",
true);
193 global $db, $msg, $cuid, $quota;
194 $msg->debug(
"mail",
"getquota");
195 $q = Array(
"name" =>
"mail",
"description" => _(
"Email addresses"),
"used" => 0);
196 $db->query(
"SELECT COUNT(*) AS cnt FROM address a, domaines d WHERE a.domain_id=d.id AND d.compte= ? AND a.type='';", array($cuid));
197 if ($db->next_record()) {
198 $q[
'used'] = $db->f(
"cnt");
199 $q[
'sizeondisk'] = $quota->get_size_mail_sum_user($cuid)/1024;
210 return array(
"pop" => _(
"Email account password"));
219 global $db, $msg, $cuid;
220 $msg->debug(
"mail",
"enum_domains");
228 IFNULL( COUNT(a.id), 0) as nb_mail
230 domaines d LEFT JOIN address a ON (d.id=a.domain_id AND a.type='')
241 while ($db->next_record()) {
255 global $db, $msg, $dom;
256 $msg->log(
"mail",
"available");
257 list($login, $domain) = explode(
"@", $mail, 2);
259 if (!($dom_id = $dom->get_domain_byname($domain))) {
263 if (!filter_var($mail, FILTER_VALIDATE_EMAIL)) {
264 $msg->raise(
"ERROR",
"mail", _(
"The email you entered is syntaxically incorrect"));
268 $db->query(
"SELECT a.id FROM address a WHERE a.domain_id= ? AND a.address= ?;", array($dom_id, $login));
269 if ($db->next_record()) {
285 function enum_domain_mails($dom_id =
null, $search =
"", $offset = 0, $count = 30, $show_systemmails =
false) {
286 global $db, $msg, $hooks;
287 $msg->debug(
"mail",
"enum_domains_mail");
289 $query_args = array($dom_id);
290 $search = trim($search);
291 $where =
" a.domain_id = ? ";
294 $where .=
" AND (a.address LIKE ? OR r.recipients LIKE ? )";
295 array_push($query_args,
"%" . $search .
"%",
"%" . $search .
"%");
297 if (!$show_systemmails) {
298 $where .=
" AND type='' ";
300 $db->query(
"SELECT count(a.id) AS total FROM address a LEFT JOIN recipient r ON r.address_id=a.id WHERE " . $where .
";", $query_args);
302 $this->total = $db->f(
"total");
304 $offset = intval($offset);
305 $count = intval($count);
306 $limit =
" LIMIT $offset, $count ";
310 $db->query(
"SELECT a.id, a.address, a.password, a.`enabled`, a.mail_action, d.domaine AS domain, m.quota, m.quota*1024*1024 AS quotabytes, q.quota_dovecot as used, NOT ISNULL(m.id) AS islocal, a.type, r.recipients, m.lastlogin, a.domain_id
311 FROM ((domaines d, address a LEFT JOIN mailbox m ON m.address_id=a.id) LEFT JOIN dovecot_quota q ON CONCAT(a.address,'@',d.domaine) = q.user) LEFT JOIN recipient r ON r.address_id=a.id
312 WHERE " . $where .
" AND d.id=a.domain_id ORDER BY a.address ASC " . $limit .
" ;", $query_args);
313 if (!$db->next_record()) {
314 $msg->raise(
"ERROR",
"mail", _(
"No email found for this query"));
319 $details = $db->Record;
321 if ($details[
"type"]) {
322 $result = $hooks->invoke(
"hook_mail_get_details", array($details));
323 $details[
"typedata"] = implode(
"<br />", $result);
326 }
while ($db->next_record());
331 if ($detail[
'type'] ==
'catchall') {
332 return _(sprintf(
"Special mail address for catch-all. <a href='mail_manage_catchall.php?domain_id=%s'>Click here to manage it.</a>", $detail[
'domain_id']));
350 function create($dom_id, $mail, $type =
"", $dontcheck =
false) {
351 global $msg, $db, $quota, $dom, $hooks;
352 $msg->log(
"mail",
"create", $mail);
355 if (!($domain = $dom->get_domain_byid($dom_id))) {
360 $m = $mail .
"@" . $domain;
361 if (!filter_var($m, FILTER_VALIDATE_EMAIL) && !$dontcheck) {
362 $msg->raise(
"ERROR",
"mail", _(
"The email you entered is syntaxically incorrect"));
367 $cancreate = $hooks->invoke(
"hook_mail_cancreate", array($dom_id, $mail));
368 if (in_array(
false, $cancreate,
true)) {
373 if (($type==
"")&&!$quota->cancreate(
"mail")) {
374 $msg->raise(
"ALERT",
"mail", _(
"You cannot create email addresses: your quota is over"));
378 $db->query(
"SELECT * FROM address WHERE domain_id= ? AND address= ? ;", array($dom_id, $mail));
379 if ($db->next_record()) {
380 if ($db->f(
"type") ==
"mailman")
381 $msg->raise(
"ERROR",
"mail", _(
"This email address already exists in mailman"));
383 $msg->raise(
"ERROR",
"mail", _(
"This email address already exists"));
388 $db->query(
"INSERT INTO address (domain_id, address,type) VALUES (?, ?, ?);", array($dom_id, $mail, $type));
389 if (!($id = $db->lastid())) {
390 $msg->raise(
"ERROR",
"mail", _(
"An unexpected error occured when creating the email"));
403 global $db, $msg, $hooks;
404 $msg->debug(
"mail",
"get_details");
406 $mail_id = intval($mail_id);
413 $db->query(
"SELECT a.id, a.address, a.password, a.enabled, d.domaine AS domain, m.path, m.quota, m.quota*1024*1024 AS quotabytes, q.quota_dovecot AS used, NOT ISNULL(m.id) AS islocal, a.type, r.recipients, m.lastlogin, a.mail_action, m.mail_action AS mailbox_action FROM ((domaines d, address a LEFT JOIN mailbox m ON m.address_id=a.id) LEFT JOIN dovecot_quota q ON CONCAT(a.address,'@',d.domaine) = q.user) LEFT JOIN recipient r ON r.address_id=a.id WHERE a.id= ? AND d.id=a.domain_id;", array($mail_id));
414 if (!$db->next_record()) {
417 $details = $db->Record;
419 if ($details[
"type"]) {
420 $result = $hooks->invoke(
"hook_mail_get_details", array($mail_id));
421 $details[
"typedata"] = implode(
"<br />", $result);
437 global $msg, $db, $cuid;
438 $mail_id = intval($mail_id);
440 if (isset($this->isitmy_cache[$mail_id])) {
441 return $this->isitmy_cache[$mail_id];
443 $db->query(
"SELECT concat(a.address,'@',d.domaine) AS email FROM address a, domaines d WHERE d.id=a.domain_id AND a.id= ? AND d.compte= ?;", array($mail_id, $cuid));
444 if ($db->next_record()) {
445 return $this->isitmy_cache[$mail_id] = $db->f(
"email");
447 $msg->raise(
"ERROR",
"mail", _(
"This email is not yours, you can't change anything on it"));
448 return $this->isitmy_cache[$mail_id] =
false;
463 if (is_array($list)) {
464 foreach ($list as $one) {
465 $this->
delete($one[
"id"]);
468 $db->query(
"SELECT domaine FROM domaines WHERE id= ? ;", array($dom_id));
469 if (!$db->next_record()) {
472 $domain=$db->Record[
"domaine"];
473 $db->query(
"UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND (type='defmx' OR type='defmx2');", array($domain));
480 $db->query(
"UPDATE domaines SET dns_action='UPDATE' WHERE id= ? ;", array($dom_id));
490 $db->query(
"select compte as uid from domaines d, address a where a.domain_id = d.id and a.id = ? ;", array($mail_id));
491 if (!$db->next_record()) {
494 return $db->f(
'uid');
506 function delete($mail_id) {
507 global $msg, $db, $hooks;
508 $msg->log(
"mail",
"delete");
510 $mail_id = intval($mail_id);
513 $msg->raise(
"ERROR",
"mail", _(
"The email you entered is syntaxically incorrect"));
522 $hooks->invoke(
'hook_mail_delete', array($mail_id, $mailinfos[
'address'] .
'@' . $mailinfos[
'domain']));
525 $db->query(
"SELECT a.id, a.type, a.mail_action, m.mail_action AS mailbox_action, NOT ISNULL(m.id) AS islocal FROM address a LEFT JOIN mailbox m ON m.address_id=a.id WHERE a.id= ? ;", array($mail_id));
526 if (!$db->next_record()) {
527 $msg->raise(
"ERROR",
"mail", _(
"The email %s does not exist, it can't be deleted"), $mail);
530 if ($db->f(
"mail_action") !=
"OK" || ($db->f(
"islocal") && $db->f(
"mailbox_action") !=
"OK")) {
531 $msg->raise(
"ERROR",
"mail", _(
"The email %s is already marked for deletion, it can't be deleted"), $mail);
534 $mail_id = $db->f(
"id");
536 if ($db->f(
"islocal")) {
538 $db->query(
"UPDATE address SET mail_action='DELETE', enabled=0 WHERE id= ?;", array($mail_id));
539 $db->query(
"UPDATE mailbox SET mail_action='DELETE' WHERE address_id= ?;", array($mail_id));
542 $db->query(
"DELETE FROM address WHERE id= ? ;", array($mail_id));
543 $db->query(
"DELETE FROM mailbox WHERE address_id= ? ;", array($mail_id));
544 $db->query(
"DELETE FROM recipient WHERE address_id= ? ;", array($mail_id));
560 $msg->log(
"mail",
"undelete");
562 $mail_id = intval($mail_id);
565 $msg->raise(
"ERROR",
"mail", _(
"The email you entered does not exist"));
574 $db->query(
"SELECT a.id, a.type, a.mail_action, m.mail_action AS mailbox_action, NOT ISNULL(m.id) AS islocal FROM address a LEFT JOIN mailbox m ON m.address_id=a.id WHERE a.id= ? ;", array($mail_id));
575 if (!$db->next_record()) {
576 $msg->raise(
"ERROR",
"mail", _(
"The email %s does not exist, it can't be undeleted"), $mail);
579 if ($db->f(
"type") !=
"") {
580 $msg->raise(
"ERROR",
"mail", _(
"The email %s is special, it can't be undeleted"), $mail);
583 if ($db->f(
"mailbox_action") !=
"DELETE" || $db->f(
"mail_action") !=
"DELETE") {
584 $msg->raise(
"ALERT",
"mail", _(
"Sorry, deletion of email %s is already in progress, or not marked for deletion, it can't be undeleted"), $mail);
587 $mail_id = $db->f(
"id");
589 if ($db->f(
"islocal")) {
591 $db->query(
"UPDATE address SET mail_action='OK', `enabled`=1 WHERE id= ?;", array($mail_id));
592 $db->query(
"UPDATE mailbox SET mail_action='OK' WHERE address_id= ? ;", array($mail_id));
595 $msg->raise(
"ERROR",
"mail", _(
"-- Program Error -- The email %s can't be undeleted"), $mail);
608 global $db, $msg, $admin;
609 $msg->log(
"mail",
"setpasswd");
614 if (!$admin->checkPolicy(
"pop", $email, $pass, $canbeempty)) {
617 if ($canbeempty && empty($pass)) {
618 return $db->query(
"UPDATE address SET password= ? where id = ? ;",
619 array(
null, $mail_id ));
620 }
else if (!$db->query(
"UPDATE address SET password= ? where id = ? ;",
621 array(_dovecot_hash($pass), $mail_id ))) {
635 $msg->log(
"mail",
"enable");
639 if (!$db->query(
"UPDATE address SET `enabled`=1 where id= ? ;", array($mail_id))) {
653 $msg->log(
"mail",
"disable");
657 if (!$db->query(
"UPDATE address SET `enabled`=0 where id= ? ;", array($mail_id))) {
675 function set_details($mail_id, $islocal, $quotamb, $recipients, $delivery =
"dovecot", $dontcheck =
false) {
677 $msg->log(
"mail",
"set_details");
681 if ($me[
"islocal"] && !$islocal) {
683 $db->query(
"UPDATE mailbox SET mail_action='DELETE' WHERE address_id= ? ;", array($mail_id));
685 if (!$me[
"islocal"] && $islocal) {
688 if ($delivery ==
"dovecot") {
689 $path = ALTERNC_MAIL .
"/" . substr($me[
"address"] .
"_", 0, 1) .
"/" . $me[
"address"] .
"_" . $me[
"domain"];
691 foreach ($this->forbiddenchars as $str) {
692 if (strpos($me[
"address"], $str) !==
false) {
693 $msg->raise(
"ERROR",
"mail", _(
"There is forbidden characters in your email address. You can't make it a POP/IMAP account, you can only use it as redirection to other emails"));
697 foreach ($this->specialchars as $str) {
698 if (strpos($me[
"address"], $str) !==
false) {
699 $path = ALTERNC_MAIL .
"/_/" . $me[
"id"] .
"_" . $me[
"domain"];
703 $db->query(
"INSERT INTO mailbox SET address_id= ? , delivery= ?, path= ? ;", array($mail_id, $delivery, $path));
705 if ($me[
"islocal"] && $islocal && $me[
"mailbox_action"] ==
"DELETE") {
706 $db->query(
"UPDATE mailbox SET mail_action='OK' WHERE mail_action='DELETE' AND address_id= ? ;", array($mail_id));
710 if ($quotamb != 0 && $quotamb < (intval($me[
"used"] / 1024 / 1024) + 1)) {
711 $quotamb = intval($me[
"used"] / 1024 / 1024) + 1;
712 $msg->raise(
"ALERT",
"mail", _(
"You set a quota smaller than the current mailbox size. Since it's not allowed, we set the quota to the current mailbox size"));
714 $db->query(
"UPDATE mailbox SET quota= ? WHERE address_id= ? ;", array($quotamb, $mail_id));
717 $recipients = preg_replace(
'/[\r\t\s]/',
"\n", $recipients);
718 $r = explode(
"\n", $recipients);
722 if ($m && ( filter_var($m, FILTER_VALIDATE_EMAIL) || $dontcheck)
723 && $m != ($me[
"address"] .
"@" . $me[
"domain"])) {
727 $db->query(
"DELETE FROM recipient WHERE address_id= ? ;", array($mail_id));
728 if (isset($red) && $red) {
729 $db->query(
"INSERT INTO recipient SET address_id= ?, recipients= ? ;", array($mail_id, $red));
731 if (!$islocal && !$red) {
732 $msg->raise(
"ALERT",
"mail", _(
"Warning: you created an email which is not an alias, and not a POP/IMAP mailbox. This is certainly NOT what you want to do. To fix this, edit the email address and check 'Yes' in POP/IMAP account, or set some recipients in the redirection field."));
746 $msg->log(
"mail",
"add_wrapper",
"creating $delivery $m address");
748 $mail_id = $mail->create($dom_id, $m, $delivery);
764 function create_alias($dom_id, $m, $alias, $type =
"", $dontcheck =
false) {
766 $msg->log(
"mail",
"create_alias",
"creating $m alias for $alias type $type");
768 $mail_id = $mail->create($dom_id, $m, $type, $dontcheck);
772 $this->
set_details($mail_id, 0, 0, $alias,
"dovecot", $dontcheck);
784 $msg->log(
"mail",
"del_wrapper");
785 $this->
delete($mail_id);
796 $msg->log(
"mail",
"export");
799 foreach ($domain as $d) {
800 $str.=
" <domain>\n <name>" . xml_entities($d[
"domain"]) .
"</name>\n";
803 while (list($key, $val) = each($s)) {
804 $str.=
" <address>\n";
805 $str.=
" <name>" . xml_entities($val[
"address"]) .
"</name>\n";
806 $str.=
" <enabled>" . xml_entities($val[
"enabled"]) .
"</enabled>\n";
807 if (is_array($val[
"islocal"])) {
808 $str.=
" <islocal>1</islocal>\n";
809 $str.=
" <quota>" . $val[
"quota"] .
"</quota>\n";
810 $str.=
" <path>" . $val[
"path"] .
"</path>\n";
812 $str.=
" <islocal>0</islocal>\n";
814 if (!empty($val[
"recipients"])) {
815 $r = explode(
"\n", $val[
"recipients"]);
816 foreach ($r as $recip) {
817 $str.=
" <recipients>" . $recip .
"<recipients>\n";
820 $str.=
" </address>\n";
823 $str.=
" </domain>\n";
836 $db->query(
"SELECT login,pass FROM mxaccount;");
838 while ($db->next_record()) {
839 $res[] = $db->Record;
856 $db->query(
"SELECT * FROM mxaccount WHERE login= ? AND pass= ?;", array($login, $pass));
857 if ($db->next_record()) {
869 $db->query(
"SELECT domaine FROM domaines WHERE gesmx=1 ORDER BY domaine");
872 while ($db->next_record()) {
873 $lst[] = $db->f(
"domaine");
874 $tt.=$db->f(
"domaine");
878 $obj = array(
'integrity' => md5($tt),
'items' => $lst);
882 return json_encode($obj);
884 foreach ($lst as $l) {
900 $db->query(
"SELECT * FROM mxaccount WHERE login= ? ;", array($login));
901 if ($db->next_record()) {
902 $msg->raise(
"ERROR",
"mail", _(
"The slave MX account was not found"));
905 $db->query(
"INSERT INTO mxaccount (login,pass) VALUES (?, ?);", array($login, $pass));
916 $db->query(
"DELETE FROM mxaccount WHERE login= ? ;", array($login));
932 $msg->log(
"mail",
"hook_dom_add_slave_domain", $domain_id);
948 global $msg, $mem, $db, $L_FQDN;
949 $msg->log(
"mail",
"hook_dom_add_mx_domain", $domain_id);
951 $db->query(
"SELECT value FROM variable where name='mailname_bounce';");
952 if (!$db->next_record()) {
953 $msg->raise(
"ERROR",
"mail", _(
"Problem: can't create default bounce mail"));
956 $mailname = $db->f(
"value");
958 $db->query(
"SELECT domaine,compte FROM domaines WHERE id= ?;", array($domain_id));
959 if ($db->next_record()) {
960 $domaine=$db->Record[
"domaine"];
961 $compte=$db->Record[
"compte"];
963 if ($spf = variable_get(
"default_spf_value")) {
966 if ($dmarc = variable_get(
"default_dmarc_value")) {
970 return $this->
create_alias($domain_id,
'postmaster', $mem->user[
'login'] .
'@' . $mailname);
981 $msg->log(
"mail",
"hook_variable_set($name,$old,$new)");
983 if ($name ==
"default_spf_value") {
986 $db->query(
"SELECT domaine,login,compte FROM domaines, membres WHERE gesdns=1 AND gesmx=1 and membres.uid=domaines.compte;");
988 while ($db->next_record())
$res[]=$db->Record;
989 foreach (
$res as $record) {
990 $this->
set_dns_spf($record[
"domaine"], $new, $old, $record[
"compte"], $record[
"login"]);
994 if ($name ==
"default_dmarc_value") {
997 $db->query(
"SELECT domaine,login,compte FROM domaines, membres WHERE gesdns=1 AND gesmx=1 and membres.uid=domaines.compte;");
999 while ($db->next_record())
$res[]=$db->Record;
1000 foreach (
$res as $record) {
1001 $this->
set_dns_dmarc($record[
"domaine"], $new, $old, $record[
"compte"], $record[
"login"]);
1012 global $db, $L_FQDN, $cuid;
1014 if ($uid==-1) $uid=$cuid;
1016 $db->query(
"SELECT domaine,sub,type,valeur FROM sub_domaines WHERE domaine=? AND sub='autodiscover' AND type='autodiscover';",array($domain));
1017 if (!$db->next_record()) {
1018 $db->query(
"INSERT INTO sub_domaines SET domaine=?, compte=?, sub='autodiscover', type='autodiscover', valeur='';",array($domain,$uid));
1021 $db->query(
"SELECT domaine,sub,type,valeur FROM sub_domaines WHERE domaine=? AND sub='autoconfig' AND type='autodiscover';",array($domain));
1022 if (!$db->next_record()) {
1023 $db->query(
"INSERT INTO sub_domaines SET domaine=?, compte=?, sub='autoconfig', type='autodiscover', valeur='';",array($domain,$uid));
1027 $db->query(
"UPDATE domaines SET dns_action='UPDATE' WHERE domaine= ?;", array($domain));
1038 global $db, $L_FQDN, $cuid;
1039 $db->query(
"UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='autodiscover' AND sub='autoconfig';", array($domain));
1040 $db->query(
"UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='autodiscover' AND sub='autodiscover';", array($domain));
1050 function set_dns_spf($domain, $spf, $previous = -1, $uid = -1, $login = -1) {
1051 global $db, $cuid, $mem, $msg;
1052 $msg->debug(
"mail",
"set_dns_spf($domain, $spf, $previous, $uid, $login)");
1055 $uid = intval($cuid);
1057 $uid = intval($uid);
1059 if ($login === -1) {
1060 $login = $mem->user[
"login"];
1063 $db->query(
"SELECT * FROM sub_domaines WHERE compte= ? AND domaine= ? AND sub='' AND type='txt' AND valeur LIKE 'v=spf1 %' AND web_action!='DELETE';", array($uid, $domain));
1064 if ($db->next_record()) {
1065 if ($previous !== -1 && $db->Record[
"valeur"] ==
"v=spf1 " . $spf) {
1068 $db->query(
"UPDATE sub_domaines SET web_action='DELETE' WHERE id= ? ;",array($db->Record[
"id"]));
1070 $db->query(
"INSERT INTO sub_domaines SET compte= ?, domaine= ?, sub='', type='txt', valeur= ? , web_action='UPDATE';", array($uid, $domain,
"v=spf1 " . $spf));
1071 $db->query(
"UPDATE domaines SET dns_action='UPDATE' WHERE domaine= ?;", array($domain));
1081 $db->query(
"UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='txt' AND sub='' AND valeur LIKE 'v=spf1 %';", array($domain));
1092 function set_dns_dmarc($domain, $dmarc, $previous = -1, $uid = -1, $login = -1) {
1093 global $db, $cuid, $mem, $L_FQDN, $msg;
1094 $msg->debug(
"mail",
"set_dns_dmarc($domain, $dmarc, $previous, $uid, $login)");
1097 $uid = intval($cuid);
1099 $uid = intval($uid);
1101 if ($login === -1) {
1102 $login = $mem->user[
"login"];
1104 $dmarc = str_replace(
"%%ADMINMAIL%%",
"admin@" . $L_FQDN, $dmarc);
1105 $dmarc = str_replace(
"%%USERMAIL%%", $login .
"@" . $L_FQDN, $dmarc);
1108 $db->query(
"SELECT * FROM sub_domaines WHERE compte= ? AND domaine= ? AND sub='_dmarc' AND type='txt' AND valeur LIKE lower('v=DMARC1;%') AND web_action!='DELETE';", array($uid, $domain));
1109 if ($db->next_record()) {
1110 if ($previous !== -1 && $db->Record[
"valeur"] ==
"v=DMARC1;" . $dmarc) {
1113 $db->query(
"UPDATE sub_domaines SET web_action='DELETE' WHERE id= ?;", array($db->Record[
"id"]));
1115 $db->query(
"INSERT INTO sub_domaines SET compte= ?, domaine= ?, sub='_dmarc', type='txt', valeur= ?, web_action='UPDATE';", array($uid, $domain,
"v=DMARC1;" . $dmarc));
1116 $db->query(
"UPDATE domaines SET dns_action='UPDATE' WHERE domaine= ?;", array($domain));
1127 $db->query(
"UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='txt' AND sub='_dmarc' AND valeur LIKE lower('v=DMARC1;%');", array($domain));
1142 $this->shouldreloaddkim=
false;
1143 $db->query(
"SELECT domaine,compte,gesdns,gesmx,dns_action FROM domaines WHERE dns_action!='OK';");
1146 while ($db->next_record()) {
1147 if ($db->Record[
"gesdns"]==0 || $db->Record[
"gesmx"]==0 || $db->Record[
'dns_action'] ==
'DELETE') {
1153 foreach($add as $domain) {
1154 $this->
dkim_add($domain[
"domaine"],$domain[
"compte"]);
1156 foreach($del as $domain) {
1157 $this->
dkim_del($domain[
"domaine"]);
1167 if ($this->shouldreloaddkim) {
1168 exec(
"service opendkim reload");
1169 $this->shouldreloaddkim=
false;
1180 $target_dir =
"/etc/opendkim/keys/$domain";
1182 if (!file_exists($target_dir.
'/alternc.txt')) {
1183 $this->shouldreloaddkim=
true;
1184 if (! is_dir($target_dir)) mkdir($target_dir);
1190 exec(
'opendkim-genkey -b 2048 -r -d '.escapeshellarg($domain).
' -s "alternc" ');
1193 chown(
"$target_dir/alternc.private",
'opendkim');
1194 chgrp(
"$target_dir/alternc.private",
'opendkim');
1196 add_line_to_file(
"/etc/opendkim/KeyTable",
"alternc._domainkey.".$domain.
" ".$domain.
":alternc:/etc/opendkim/keys/".$domain.
"/alternc.private");
1197 add_line_to_file(
"/etc/opendkim/SigningTable",$domain.
" alternc._domainkey.".$domain);
1201 $db->query(
"SELECT id FROM sub_domaines WHERE domaine=? AND sub='alternc._domainkey';",array($domain));
1202 if (!$db->next_record()) {
1205 $db->query(
"INSERT INTO sub_domaines SET domaine=?, compte=?, sub='alternc._domainkey', type='dkim', valeur=?;",array($domain,$uid,$dkim_key));
1217 $target_dir =
"/etc/opendkim/keys/$domain";
1218 if (file_exists($target_dir)) {
1219 $this->shouldreloaddkim=
true;
1220 @unlink(
"$target_dir/alternc.private");
1221 @unlink(
"$target_dir/alternc.txt");
1222 @rmdir($target_dir);
1223 del_line_from_file(
"/etc/opendkim/KeyTable",
"alternc._domainkey.".$domain.
" ".$domain.
":alternc:/etc/opendkim/keys/".$domain.
"/alternc.private");
1224 del_line_from_file(
"/etc/opendkim/SigningTable",$domain.
" alternc._domainkey.".$domain);
1226 $db->query(
"DELETE FROM sub_domaines WHERE domaine=? AND sub='alternc._domainkey';",array($domain));
1240 $key=file_get_contents(
"/etc/opendkim/keys/".$domain.
"/alternc.txt");
1242 if (preg_match(
'#alternc._domainkey IN TXT "(.*)"#',$key,$mat)) {
1246 $inkey=
false; $result=
"";
1247 $lines=explode(
"\n",$key);
1248 foreach($lines as $line) {
1249 if (preg_match(
'#alternc._domainkey\s+IN\s+TXT\s+\( "(.*)"#',$line,$mat)) {
1250 $result.=$mat[1]; $inkey=
true;
continue;
1252 if ($inkey && preg_match(
'#^\s*"(.*)"\s*\)#',$line,$mat)) {
1253 $result.=$mat[1]; $inkey=
false;
break;
1255 if ($inkey && preg_match(
'#^\s*"(.*)"\s*$#',$line,$mat)) {
1256 $result.=$mat[1]; $inkey=
true;
continue;
1262 $msg->debug(
"mail",
"dkim_get_entry($domain) failed");
This class handle emails (pop and/or aliases and even wrapper for internal classes) of hosted users.
catchall_getinfos($domain_id)
del_dns_dmarc($domain)
delete the DMARC entries in the sub_domaine table for a domain called by del_domain or del_mx_domain ...
set_passwd($mail_id, $pass, $canbeempty=false)
set the password of an email address.
echo_domain_list($format=null)
Out (echo) the complete hosted domain list :
get_details($mail_id)
function used to get every information we can on a mail
create_alias($dom_id, $m, $alias, $type="", $dontcheck=false)
A function used to create an alias for a specific address @ param : $dom_id , the domain sql identifi...
dkim_del($domain)
Delete a domain from OpenDKIM configuration.
hook_quota_get()
get_quota (hook for quota class), returns the number of used service for a quota-bound service
get_account_by_mail_id($mail_id)
return the alternc account's ID of the mail_id
catchall_set($domain_id, $target)
alternc_export_conf()
Export the mail information of an account.
hook_dom_add_mx_domain($domain_id)
hook function called by AlternC when a domain is created for the current user account This function c...
set_dns_spf($domain, $spf, $previous=-1, $uid=-1, $login=-1)
Set or UPDATE the DNS record for the domain $dom(str) to be $spf account's login is current and if no...
disable($mail_id)
Disables an email address.
set_dns_dmarc($domain, $dmarc, $previous=-1, $uid=-1, $login=-1)
Set or UPDATE the DNS record for the domain $dom(str) to be $dmarc account's login is current and if ...
hook_dom_add_slave_domain($domain_id, $target_domain)
hook function called by AlternC when a domain is created for the current user account using the SLAVE...
dkim_add($domain, $uid)
Add a domain into OpenDKIM configuration.
del_dns_spf($domain)
delete the SPF entries in the sub_domaine table for a domain called by del_domain or del_mx_domain by...
$forbiddenchars
If an email has those chars, we will ONLY allow RECIPIENTS, NOT POP/IMAP for DOVECOT !...
alternc_password_policy()
Password policy kind used in this class (hook for admin class)
$total
Number of results for a pager display @access public.
del_slave_account($login)
Remove a slave account.
hook_mail_get_details($detail)
hook_updatedomains_dns_pre()
Hook launched before doing anything dns-related.
enum_slave_account()
Return the list of allowed slave accounts (secondary-mx)
hook_updatedomains_dns_post()
Hook launched after doing anything dns-related.
undelete($mail_id)
Function used to undelete a pending deletion mail from the db should be used by the web interface,...
$specialchars
If an email has those chars, 'not nice in shell env' ;) we don't store the email in $mail/u/{user}_do...
hook_dom_del_mx_domain($dom_id)
Hook called when the DOMAIN class will delete a domain.
add_slave_account($login, $pass)
Add a slave account that will be allowed to access the mxdomain list.
check_slave_account($login, $pass)
Check for a slave account (secondary mx)
enable($mail_id)
Enables an email address.
create($dom_id, $mail, $type="", $dontcheck=false)
Function used to insert a new mail into the db should be used by the web interface,...
enum_domain_mails($dom_id=null, $search="", $offset=0, $count=30, $show_systemmails=false)
function used to list every mail address hosted on a domain.
set_details($mail_id, $islocal, $quotamb, $recipients, $delivery="dovecot", $dontcheck=false)
Function used to update an email settings should be used by the web interface, not by third-party pro...
$shouldreloaddkim
Manage DKIM when adding / removing a domain MX management.
dkim_get_entry($domain)
return the content of the TXT information to be added into the DB for DKIM subdomains
del_dns_autoconf($domain)
delete the autoconf / autodiscover vhosts when removing a domain as MX
hook_variable_set($name, $old, $new)
hook function called by variables when a variable is changed @access private
get_total_size_for_domain($domain)
$domains
domain list for this account @access private
add_wrapper($dom_id, $m, $delivery)
A wrapper used by mailman class to create it's needed addresses @ param : $dom_id ,...
set_dns_autoconf($domain, $uid=-1)
Add dns entries for autodiscover / autoconf on the domain.
is_it_my_mail($mail_id)
Check if an email is mine ...
enum_domains($uid=-1)
Returns the list of mail-hosting domains for a user.
available($mail)
available: tells if an email address can be installed in the server check the domain part (is it mine...
del_wrapper($mail_id)
A wrapper used by mailman class to create it's needed addresses @ param : $mail_id ,...
hook_menu()
Hook called by menu class to add the email menu to the left pane.