+define('SUCCESS', 1);
+define('ERROR_INACTIVE_REDIRECTION', 2);
+define('ERROR_INVALID_EMAIL', 3);
+define('ERROR_LOOP_EMAIL', 4);
+
+// Checks if an email update is required in MLs and aliases.
+// This occurs when the user don't have email permissions and her email has changed.
+function require_email_update(User $user, $new_email)
+{
+ Platal::assert(!is_null($user), 'User cannot be null.');
+
+ $is_new = !$user->checkPerms(User::PERM_MAIL) && $new_email != strtolower($user->email);
+ if ($new_email && $is_new) {
+ $already = XDB::fetchOneCell('SELECT hruid
+ FROM accounts
+ WHERE email = {?} AND uid != {?}',
+ $new_email, $user->id());
+ if ($already) {
+ Platal::page()->trigError("L'email ne peut pas être utilisé pour ce compte car il correspond déjà au compte : "
+ . $already . ". Si l'utilisateur courant et cette personne ne sont en fait qu'une "
+ . "seul et même personne, ou en cas de problème, contacter : contact@polytechnique.org");
+ return false;
+ }
+ }
+ return $is_new;
+}
+
+function format_email_alias($email)
+{
+ if ($user = User::getSilent($email)) {
+ return $user->forlifeEmail();
+ }
+ if (isvalid_email($email)) {
+ return $email;
+ }
+ return null;
+}
+
+function add_to_list_alias($email, $local_part, $domain, $type = 'alias')
+{
+ $email = format_email_alias($email);
+ if (is_null($email)) {
+ return false;
+ }
+
+ XDB::execute('INSERT IGNORE INTO email_virtual (email, domain, redirect, type)
+ SELECT {?}, id, {?}, {?}
+ FROM email_virtual_domains
+ WHERE name = {?}',
+ $local_part, $email, $type, $domain);
+ return true;
+}
+
+function delete_from_list_alias($email, $local_part, $domain, $type = 'alias')
+{
+ $email = format_email_alias($email);
+ if (is_null($email)) {
+ return false;
+ }
+
+ XDB::execute('DELETE v
+ FROM email_virtual AS v
+ INNER JOIN email_virtual_domains AS m ON (v.domain = m.id)
+ INNER JOIN email_virtual_domains AS d ON (d.aliasing = m.id)
+ WHERE v.email = {?} AND d.name = {?} AND v.redirect = {?} AND type = {?}',
+ $local_part, $domain, $email, $type);
+ return true;
+}
+
+function update_list_alias($email, $former_email, $local_part, $domain, $type = 'alias')
+{
+ $email = format_email_alias($email);
+ if (is_null($email)) {
+ return false;
+ }
+
+ XDB::execute('UPDATE email_virtual AS v
+ INNER JOIN email_virtual_domains AS d ON (v.domain = d.id)
+ SET v.redirect = {?}
+ WHERE v.redirect = {?} AND d.name = {?} AND v.email = {?} AND v.type = {?}',
+ $email, $former_email, $domain, $local_part, $type);
+ return true;
+}
+
+// Updates an email in all aliases (groups and events).
+function update_alias_user($former_email, $new_email)
+{
+ XDB::execute('UPDATE email_virtual
+ SET redirect = {?}
+ WHERE redirect = {?} AND (type = \'alias\' OR type = \'event\')',
+ $new_email, $former_email);
+}
+
+function list_alias_members($local_part, $domain)
+{
+ $emails = XDB::fetchColumn('SELECT DISTINCT(redirect)
+ FROM email_virtual AS v
+ INNER JOIN email_virtual_domains AS m ON (v.domain = m.id)
+ INNER JOIN email_virtual_domains AS d ON (d.aliasing = m.id)
+ WHERE v.email = {?} AND d.name = {?} AND type = \'alias\'',
+ $local_part, $domain);
+
+ $users = array();
+ $nonusers = array();
+ foreach ($emails as $email) {
+ if ($user = User::getSilent($email)) {
+ $users[] = $user;
+ } else {
+ $nonusers[] = $email;
+ }
+ }
+
+ return array(
+ 'users' => $users,
+ 'nonusers' => $nonusers
+ );
+}
+
+function delete_list_alias($local_part, $domain)
+{
+ XDB::execute('DELETE v
+ FROM email_virtual AS v
+ INNER JOIN email_virtual_domains AS m ON (v.domain = m.id)
+ INNER JOIN email_virtual_domains AS d ON (d.aliasing = m.id)
+ WHERE v.email = {?} AND d.name = {?} AND type = \'alias\'',
+ $local_part, $domain);
+}
+
+function iterate_list_alias($domain)
+{
+ return XDB::fetchColumn('SELECT CONCAT(v.email, \'@\', m.name)
+ FROM email_virtual AS v
+ INNER JOIN email_virtual_domains AS m ON (v.domain = m.id)
+ WHERE m.name = {?} AND v.type = \'alias\'
+ GROUP BY v.email',
+ $domain);
+}
+
+function create_list($local_part, $domain)
+{
+ global $globals;
+
+ $redirect = $domain . '_' . $local_part . '+';
+ foreach(array('post', 'owner', 'admin', 'bounces', 'unsubscribe') as $suffix) {
+ XDB::execute('INSERT IGNORE INTO email_virtual (email, domain, redirect, type)
+ SELECT {?}, id, {?}, \'list\'
+ FROM email_virtual_domains
+ WHERE name = {?}',
+ ($suffix == 'post') ? $local_part : $local_part . '-' . $suffix,
+ $redirect . $suffix . '@' . $globals->lists->redirect_domain, $domain);
+ }
+}
+
+function delete_list($local_part, $domain)
+{
+ global $globals;
+
+ $redirect = $domain . '_' . $local_part . '+';
+ foreach(array('post', 'owner', 'admin', 'bounces', 'unsubscribe') as $suffix) {
+ XDB::execute('DELETE FROM email_virtual
+ WHERE redirect = {?} AND type = \'list\'',
+ $redirect . $suffix . '@' . $globals->lists->redirect_domain);
+ }
+}
+
+function list_exist($local_part, $domain)
+{
+ return XDB::fetchOneCell('SELECT COUNT(*)
+ FROM email_virtual AS v
+ INNER JOIN email_virtual_domains AS m ON (v.domain = m.id)
+ INNER JOIN email_virtual_domains AS d ON (m.id = d.aliasing)
+ WHERE v.email = {?} AND d.name = {?}',
+ $local_part, $domain);
+}
+
+// function mark_broken_email() {{{1
+function mark_broken_email($email, $admin = false)
+{
+ $email = valide_email($email);
+ if (empty($email) || $email == '@') {
+ return;
+ }
+
+ $user = XDB::fetchOneAssoc('SELECT r1.uid, a.hruid, a.full_name, r1.broken_level != 0 AS broken, COUNT(r2.uid) AS nb_mails,
+ s.email AS alias, DATE_ADD(r1.last, INTERVAL 14 DAY) < CURDATE() as notify
+ FROM email_redirect_account AS r1
+ INNER JOIN accounts AS a ON (a.uid = r1.uid)
+ INNER JOIN email_source_account AS s ON (a.uid = s.uid AND s.flags = \'bestalias\')
+ LEFT JOIN email_redirect_account AS r2 ON (a.uid = r2.uid AND r1.redirect != r2.redirect AND
+ r2.broken_level = 0 AND r2.flags = \'active\' AND
+ (r2.type = \'smtp\' OR r2.type = \'googleapps\'))
+ WHERE r1.redirect = {?}
+ GROUP BY r1.uid', $email);
+
+ if ($user) {
+ // Mark address as broken.
+ if (!$user['broken']) {
+ XDB::execute('UPDATE email_redirect_account
+ SET broken_date = NOW(), last = NOW(), broken_level = 1
+ WHERE redirect = {?}', $email);
+ } elseif ($admin) {
+ XDB::execute('UPDATE email_redirect_account
+ SET last = CURDATE(), broken_level = broken_level + 1
+ WHERE redirect = {?} AND DATE_ADD(last, INTERVAL 14 DAY) < CURDATE()',
+ $email);
+ } else {
+ XDB::execute('UPDATE email_redirect_account
+ SET broken_level = 1
+ WHERE redirect = {?} AND broken_level = 0', $email);
+ }
+ }
+
+ return $user;
+}