X-Git-Url: http://git.polytechnique.org/?a=blobdiff_plain;f=modules%2Femail.php;h=8c363a80e804ad36c234822684eacb5914866d8b;hb=ee71865181e96e7b0754ef9e7da4b3cb26f4c1d7;hp=ccf08bf9cd532d782bf9118b7e3055c6fde80d6b;hpb=805f3d1679a53bb04fff34619c171a1381068612;p=platal.git diff --git a/modules/email.php b/modules/email.php index ccf08bf..8c363a8 100644 --- a/modules/email.php +++ b/modules/email.php @@ -1,6 +1,6 @@ $this->make_hook('emails', AUTH_COOKIE), - 'emails/alias' => $this->make_hook('alias', AUTH_MDP), - 'emails/antispam' => $this->make_hook('antispam', AUTH_MDP), - 'emails/broken' => $this->make_hook('broken', AUTH_COOKIE), - 'emails/redirect' => $this->make_hook('redirect', AUTH_MDP), - 'emails/send' => $this->make_hook('send', AUTH_MDP), - 'emails/antispam/submit' => $this->make_hook('submit', AUTH_COOKIE), - 'emails/test' => $this->make_hook('test', AUTH_COOKIE, 'user', NO_AUTH), - - 'emails/imap/in' => $this->make_hook('imap_in', AUTH_PUBLIC), - - 'admin/emails/duplicated' => $this->make_hook('duplicated', AUTH_MDP, 'admin'), - 'admin/emails/watch' => $this->make_hook('duplicated', AUTH_MDP, 'admin'), - 'admin/emails/lost' => $this->make_hook('lost', AUTH_MDP, 'admin'), + 'emails' => $this->make_hook('emails', AUTH_COOKIE), + 'emails/alias' => $this->make_hook('alias', AUTH_MDP), + 'emails/antispam' => $this->make_hook('antispam', AUTH_MDP), + 'emails/broken' => $this->make_hook('broken', AUTH_COOKIE), + 'emails/redirect' => $this->make_hook('redirect', AUTH_MDP), + 'emails/send' => $this->make_hook('send', AUTH_MDP), + 'emails/antispam/submit' => $this->make_hook('submit', AUTH_COOKIE), + 'emails/test' => $this->make_hook('test', AUTH_COOKIE, 'user', NO_AUTH), + + 'emails/rewrite/in' => $this->make_hook('rewrite_in', AUTH_PUBLIC), + 'emails/rewrite/out' => $this->make_hook('rewrite_out', AUTH_PUBLIC), + + 'emails/imap/in' => $this->make_hook('imap_in', AUTH_PUBLIC), + + 'admin/emails/duplicated' => $this->make_hook('duplicated', AUTH_MDP, 'admin'), + 'admin/emails/watch' => $this->make_hook('duplicated', AUTH_MDP, 'admin'), + 'admin/emails/lost' => $this->make_hook('lost', AUTH_MDP, 'admin'), + 'admin/emails/broken' => $this->make_hook('broken_addr', AUTH_MDP, 'admin'), ); } @@ -232,9 +236,9 @@ class EmailModule extends PLModule $email = str_replace(' ', '+', $email); // Apply email redirection change requests. + $result = SUCCESS; if ($action == 'remove' && $email) { - $retour = $redirect->delete_email($email); - $page->assign('retour', $retour); + $result = $redirect->delete_email($email); } if ($action == 'active' && $email) { @@ -256,15 +260,37 @@ class EmailModule extends PLModule $actifs = Env::v('emails_actifs', Array()); print_r(Env::v('emails_rewrite')); if (Env::v('emailop') == "ajouter" && Env::has('email')) { - $page->assign('retour', $redirect->add_email(Env::v('email'))); + $new_email = Env::v('email'); + if ($new_email == "new@example.org") { + $new_email = Env::v('email_new'); + } + $result = $redirect->add_email($new_email); + if ($result == ERROR_INVALID_EMAIL) { + $page->assign('email', $new_email); + } + $page->assign('retour', $result); } elseif (empty($actifs)) { - $page->assign('retour', ERROR_INACTIVE_REDIRECTION); + $result = ERROR_INACTIVE_REDIRECTION; } elseif (is_array($actifs)) { - $page->assign('retour', $redirect->modify_email($actifs, - Env::v('emails_rewrite',Array()))); + $result = $redirect->modify_email($actifs, Env::v('emails_rewrite', Array())); } } + switch ($result) { + case ERROR_INACTIVE_REDIRECTION: + $page->trigError('Tu ne peux pas avoir aucune adresse de redirection active, sinon ton adresse ' + . $user->forlifeEmail() . ' ne fonctionnerait plus.'); + break; + case ERROR_INVALID_EMAIL: + $page->trigError('Erreur: l\'email n\'est pas valide.'); + break; + case ERROR_LOOP_EMAIL: + $page->trigError('Erreur : ' . $user->forlifeEmail() + . ' ne doit pas être renvoyé vers lui-même, ni vers son équivalent en ' + . $globals->mail->domain2 . ' ni vers polytechnique.edu.'); + break; + } + // Fetch the @alias_dom email alias, if any. $res = XDB::query( "SELECT alias @@ -294,6 +320,9 @@ class EmailModule extends PLModule // Display GoogleApps acount information. require_once 'googleapps.inc.php'; $page->assign('googleapps', GoogleAppsAccount::account_status($user->id())); + + require_once 'emails.combobox.inc.php'; + fill_email_combobox($page); } function handler_antispam(&$page, $statut_filtre = null) @@ -400,14 +429,26 @@ class EmailModule extends PLModule $to2 = getEmails(Env::v('to_contacts')); $cc2 = getEmails(Env::v('cc_contacts')); $txt = str_replace('^M', '', Env::v('contenu')); - $to = Env::v('to'); - $subj = Env::v('sujet'); - $from = Env::v('from'); - $cc = trim(Env::v('cc')); - $bcc = trim(Env::v('bcc')); - + $to = str_replace(';', ',', Env::t('to')); + $subj = Env::t('sujet'); + $from = Env::t('from'); + $cc = str_replace(';', ',', Env::t('cc')); + $bcc = str_replace(';', ',', Env::t('bcc')); + + $email_regex = '/^[a-z0-9.\-+_\$]+@([\-.+_]?[a-z0-9])+$/i'; + foreach (explode(',', $to . ',' . $cc . ',' . $bcc) as $email) { + $email = trim($email); + if ($email != '' && !preg_match($email_regex, $email)) { + $page->trigError("L'adresse email " . $email . ' est erronée.'); + $error = true; + } + } if (empty($to) && empty($cc) && empty($to2) && empty($bcc) && empty($cc2)) { $page->trigError("Indique au moins un destinataire."); + $error = true; + } + + if ($error) { $page->assign('uploaded_f', PlUpload::listFilenames(S::user()->login(), 'emails.send')); } else { $mymail = new PlMailer(); @@ -471,7 +512,7 @@ class EmailModule extends PLModule } // Retrieves the User object for the test email recipient. - if (S::has_perms() && $hruid) { + if (S::admin() && $hruid) { $user = User::getSilent($hruid); } else { $user = S::user(); @@ -492,6 +533,75 @@ class EmailModule extends PLModule exit; } + function handler_rewrite_in(&$page, $mail, $hash) + { + $page->changeTpl('emails/rewrite.tpl'); + $page->assign('option', 'in'); + if (empty($mail) || empty($hash)) { + return PL_NOT_FOUND; + } + $pos = strrpos($mail, '_'); + if ($pos === false) { + return PL_NOT_FOUND; + } + $mail{$pos} = '@'; + $res = XDB::query("SELECT COUNT(*) + FROM emails + WHERE email = {?} AND hash = {?}", + $mail, $hash); + $count = intval($res->fetchOneCell()); + if ($count > 0) { + XDB::query("UPDATE emails + SET allow_rewrite = true, hash = NULL + WHERE email = {?} AND hash = {?}", + $mail, $hash); + $page->trigSuccess("Réécriture activée pour l'adresse " . $mail); + return; + } + return PL_NOT_FOUND; + } + + function handler_rewrite_out(&$page, $mail, $hash) + { + $page->changeTpl('emails/rewrite.tpl'); + $page->assign('option', 'out'); + if (empty($mail) || empty($hash)) { + return PL_NOT_FOUND; + } + $pos = strrpos($mail, '_'); + if ($pos === false) { + return PL_NOT_FOUND; + } + $mail{$pos} = '@'; + $res = XDB::query("SELECT COUNT(*) + FROM emails + WHERE email = {?} AND hash = {?}", + $mail, $hash); + $count = intval($res->fetchOneCell()); + if ($count > 0) { + global $globals; + $res = XDB::query("SELECT e.email, e.rewrite, a.alias + FROM emails AS e + INNER JOIN aliases AS a ON (a.id = e.uid AND a.type = 'a_vie') + WHERE e.email = {?} AND e.hash = {?}", + $mail, $hash); + XDB::query("UPDATE emails + SET allow_rewrite = false, hash = NULL + WHERE email = {?} AND hash = {?}", + $mail, $hash); + list($mail, $rewrite, $forlife) = $res->fetchOneRow(); + $mail = new PlMailer(); + $mail->setFrom("webmaster@" . $globals->mail->domain); + $mail->addTo("support@" . $globals->mail->domain); + $mail->setSubject("Tentative de détournement de correspondance via le rewrite"); + $mail->setTxtBody("$forlife a tenté un rewrite de $mail vers $rewrite. Cette demande a été rejetée via le web"); + $mail->send(); + $page->trigWarning("Un mail d'alerte a été envoyé à l'équipe de " . $globals->core->sitename); + return; + } + return PL_NOT_FOUND; + } + function handler_imap_in(&$page, $hash = null, $login = null) { $page->changeTpl('emails/imap_register.tpl'); @@ -568,7 +678,7 @@ L'équipe d'administration mail->domain . '>'; $mail->setSubject("Une de tes adresse de redirection Polytechnique.org ne marche plus !!"); $mail->setTxtBody($message); $mail->send(); - $page->trigSuccess("Email envoyé !"); + $page->trigSuccess('Email envoyé !'); } } elseif (Post::has('email')) { S::assert_xsrf_token(); @@ -704,6 +814,7 @@ L'équipe d'administration mail->domain . '>'; $page->assign('doublon', $props); } } + function handler_lost(&$page, $action = 'list', $email = null) { $page->changeTpl('emails/lost.tpl'); @@ -716,6 +827,144 @@ L'équipe d'administration mail->domain . '>'; u.deces = 0 AND u.perms IN ('user', 'admin', 'disabled') ORDER BY u.promo DESC, u.nom, u.prenom")); } + + function handler_broken_addr(&$page) + { + require_once 'emails.inc.php'; + $page->changeTpl('emails/broken_addr.tpl'); + + if (Env::has('sort_broken')) { + S::assert_xsrf_token(); + + $list = trim(Env::v('list')); + if ($list == '') { + $page->trigError('La liste est vide.'); + } else { + $valid_emails = array(); + $invalid_emails = array(); + $broken_list = explode("\n", $list); + sort($broken_list); + foreach ($broken_list as $orig_email) { + $email = valide_email(trim($orig_email)); + if (empty($email) || $email == '@') { + $invalid_emails[] = trim($orig_email) . ': invalid email'; + } elseif (!in_array($email, $valid_emails)) { + $res = XDB::query('SELECT COUNT(*) + FROM emails + WHERE email = {?}', $email); + if ($res->fetchOneCell() > 0) { + $valid_emails[] = $email; + } else { + $invalid_emails[] = "$orig_email: no such redirection"; + } + } + } + + $page->assign('valid_emails', $valid_emails); + $page->assign('invalid_emails', $invalid_emails); + } + } + + if (Env::has('process_broken')) { + S::assert_xsrf_token(); + + $list = trim(Env::v('list')); + if ($list == '') { + $page->trigError('La liste est vide.'); + } else { + global $platal; + + $broken_user_list = array(); + $broken_list = explode("\n", $list); + sort($broken_list); + foreach ($broken_list as $orig_email) { + $email = valide_email(trim($orig_email)); + if (empty($email) || $email == '@') { + continue; + } + + $sel = XDB::query( + "SELECT e1.uid, e1.panne != 0 AS panne, count(e2.uid) AS nb_mails, + u.nom, u.prenom, u.promo, a.alias + FROM emails AS e1 + LEFT JOIN emails AS e2 ON (e1.uid = e2.uid AND FIND_IN_SET('active', e2.flags) + AND e1.email != e2.email) + INNER JOIN auth_user_md5 AS u ON (e1.uid = u.user_id) + INNER JOIN aliases AS a ON (u.user_id = a.id AND FIND_IN_SET('bestalias', a.flags)) + WHERE e1.email = {?} + GROUP BY e1.uid", $email); + + if ($x = $sel->fetchOneAssoc()) { + if (!$x['panne']) { + XDB::execute('UPDATE emails + SET panne=NOW(), last=NOW(), panne_level = 1 + WHERE email = {?}', + $email); + } else { + XDB::execute('UPDATE emails + SET last = CURDATE(), panne_level = panne_level + 1 + WHERE email = {?} + AND DATE_ADD(last, INTERVAL 14 DAY) < CURDATE()', + $email); + } + + if (!empty($x['nb_mails'])) { + $mail = new PlMailer('emails/broken.mail.tpl'); + $mail->addTo("\"{$x['prenom']} {$x['nom']}\" <{$x['alias']}@" + . $globals->mail->domain . '>'); + $mail->assign('x', $x); + $mail->assign('email', $email); + $mail->send(); + } + + if (!isset($broken_user_list[$x['alias']])) { + $broken_user_list[$x['alias']] = array($email); + } else { + $broken_user_list[$x['alias']][] = $email; + } + } + } + + XDB::execute("UPDATE emails + SET panne_level = panne_level - 1 + WHERE flags = 'active' AND panne_level > 1 + AND DATE_ADD(last, INTERVAL 1 MONTH) < CURDATE()"); + XDB::execute("UPDATE emails + SET panne_level = 0 + WHERE flags = 'active' AND panne_level = 1 + AND DATE_ADD(last, INTERVAL 1 YEAR) < CURDATE()"); + + // Output the list of users with recently broken addresses, + // along with the count of valid redirections. + require_once 'include/notifs.inc.php'; + pl_content_headers("text/x-csv"); + + $csv = fopen('php://output', 'w'); + fputcsv($csv, array('nom', 'prenom', 'promo', 'alias', 'bounce', 'nbmails', 'url'), ';'); + foreach ($broken_user_list as $alias => $mails) { + $sel = Xdb::query( + "SELECT u.user_id, count(e.email) AS nb_mails, u.nom, u.prenom, u.promo + FROM aliases AS a + INNER JOIN auth_user_md5 AS u ON a.id = u.user_id + LEFT JOIN emails AS e ON (e.uid = u.user_id + AND FIND_IN_SET('active', e.flags) AND e.panne = 0) + WHERE a.alias = {?} + GROUP BY u.user_id", $alias); + + if ($x = $sel->fetchOneAssoc()) { + if ($x['nb_mails'] == 0) { + register_profile_update($x['user_id'], 'broken'); + } + fputcsv($csv, array($x['nom'], $x['prenom'], $x['promo'], $alias, + join(',', $mails), $x['nb_mails'], + 'https://www.polytechnique.org/marketing/broken/' . $alias), ';'); + } + } + fclose($csv); + exit; + } + } + } } // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: