; Maximum number of mails an instance of the moderation cron accepts to deliver.
max_mail_per_min = 400
+; $globals->lists->redirect_domain
+; Domain where mailing list emails are redirected.
+redirect_domain = ""
+
; The mail section contains parameters used to interacts with email routing
[Mail]
define('ERROR_INVALID_EMAIL', 3);
define('ERROR_LOOP_EMAIL', 4);
+function add_to_list_alias(User $user, $local_part, $domain)
+{
+ Platal::assert($user !== null);
+
+ XDB::execute('INSERT IGNORE INTO email_virtual (email, domain, redirect, type)
+ SELECT {?}, id, {?}, {?}
+ FROM email_virtual_domains
+ WHERE name = {?}',
+ $local_part, $user->forlifeEmail(), $type, $domain);
+}
+
+function delete_from_list_alias(User $user, $local_part, $domain)
+{
+ Platal::assert($user !== null);
+
+ 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, $user->forlifeEmail(), $type);
+}
+
+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 = \'user\'',
+ $local_part, $domain);
+
+ $members = array();
+ foreach ($emails as $email) {
+ $members[] = User::getSilent($email);
+ }
+
+ return $members;
+}
+
+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 = \'user\'',
+ $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 = \'user\'
+ 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 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)
{
// {{{ constructor
public function __construct(User $_user, $_asso, $_liste, $_domain, $_desc, $_advertise,
- $_modlevel, $_inslevel, $_owners, $_members, $_stamp=0)
+ $_modlevel, $_inslevel, $_owners, $_members, $_stamp = 0)
{
parent::__construct($_user, false, 'liste', $_stamp);
public function commit()
{
- global $globals;
+ require_once 'emails.inc.php';
- if ($this->asso == "alias") {
- $new = $this->liste . '@' . $this->domain;
- XDB::query('INSERT INTO virtual (alias, type) VALUES({?}, "user")', $new);
+ if ($this->asso == 'alias') {
foreach ($this->members as $member) {
$user = User::get($member);
- if ($user != null) {
- XDB::query(
- "INSERT INTO virtual_redirect (vid, redirect)
- SELECT vid, {?}
- FROM virtual
- WHERE alias = {?}", $user->forlifeEmail(), $new);
- }
+ add_to_list_alias($user, $this->liste, $this->domain);
}
- return 1;
- }
-
- $list = new MMList(S::user(), $this->domain);
- $ret = $list->create_list($this->liste, utf8_decode($this->desc), $this->advertise,
- $this->modlevel, $this->inslevel,
- $this->owners, $this->members);
- $liste = strtolower($this->liste);
- if ($ret && !$this->asso) {
- foreach(Array($liste, $liste . "-owner", $liste . "-admin", $liste . "-bounces", $liste . "-unsubscribe") as $l) {
- XDB::execute("INSERT INTO aliases (alias, type) VALUES({?}, 'liste')", $l);
- }
- } elseif ($ret) {
- foreach (Array('', 'owner', 'admin', 'bounces', 'unsubscribe') as $app) {
- $mdir = $app == '' ? '+post' : '+' . $app;
- if (!empty($app)) {
- $app = '-' . $app;
- }
- $red = $this->domain . '_' . $liste;
- XDB::execute('INSERT INTO virtual (alias, type)
- VALUES({?}, {?})', $liste . $app . '@' . $this->domain, 'list');
- XDB::execute('INSERT INTO virtual_redirect (vid, redirect)
- VALUES ({?}, {?})', XDB::insertId(),
- $red . $mdir . '@listes.polytechnique.org');
+ } else {
+ $list = new MMList(S::user(), $this->domain);
+ $success = $list->create_list($this->liste, utf8_decode($this->desc), $this->advertise,
+ $this->modlevel, $this->inslevel,
+ $this->owners, $this->members);
+ if ($success) {
+ create_list($this->liste, $this->domain);
}
+ return $success;
}
- return $ret;
}
// }}}
S::assert_xsrf_token();
}
- $asso = Post::v('asso');
- $liste = Post::v('liste');
+ $asso = Post::t('asso');
+ $list = strtolower(Post::t('liste'));
- if (empty($liste)) {
+ if (empty($list)) {
$page->trigError('Le champ « adresse souhaitée » est vide.');
}
- if (!preg_match("/^[a-zA-Z0-9\-]*$/", $liste)) {
+ if (!preg_match("/^[a-zA-Z0-9\-]*$/", $list)) {
$page->trigError('Le nom de la liste ne doit contenir que des lettres non accentuées, chiffres et tirets.');
}
- if (($asso == "binet") || ($asso == "alias")) {
+ if (($asso == 'binet') || ($asso == 'alias')) {
$promo = Post::i('promo');
$domain = $promo . '.' . $globals->mail->domain;
$page->trigError('La promotion est mal renseignée, elle doit être du type : 2004.');
}
- $new = $liste . '@' . $domain;
- $res = XDB::query('SELECT COUNT(*) FROM virtual WHERE alias={?}', $new);
-
- } else {
- if ($asso == "groupex") {
- $groupex_name = Post::v('groupex_name');
-
- $res_groupe = XDB::query('SELECT mail_domain FROM groups WHERE nom={?}', $groupex_name);
- $domain = $res_groupe->fetchOneCell();
+ } elseif ($asso == 'groupex') {
+ $domain = XDB::fetchOneCell('SELECT mail_domain
+ FROM groups
+ WHERE nom = {?}',
+ Post::t('groupex_name'));
if (!$domain) {
$page->trigError('Il n\'y a aucun groupe de ce nom sur Polytechnique.net.');
}
-
- $new = $liste . '@' . $domain;
- $res = XDB::query('SELECT COUNT(*) FROM virtual WHERE alias={?}', $new);
- } else {
- $res = XDB::query("SELECT COUNT(*) FROM aliases WHERE alias={?}", $liste);
- $domain = $globals->mail->domain;
- }
+ } else {
+ $domain = $globals->mail->domain;
}
- $n = $res->fetchOneCell();
-
- if ($n) {
+ require_once 'emails.inc.php';
+ if (list_exist($list, $domain)) {
$page->trigError("L'« adresse souhaitée » est déjà prise.");
}
- if (!Post::v('desc')) {
+ if (!Post::t('desc')) {
$page->trigError('Le sujet est vide.');
}
$page->trigError('Il n\'y a pas de gestionnaire.');
}
- if (count($members)<4) {
+ if (count($members) < 4) {
$page->trigError('Il n\'y a pas assez de membres.');
}
if (!$page->nb_errs()) {
$page->trigSuccess('Demande de création envoyée !');
$page->assign('created', true);
- $req = new ListeReq(S::user(), $asso, $liste, $domain,
- Post::v('desc'), Post::i('advertise'),
+ $req = new ListeReq(S::user(), $asso, $list, $domain,
+ Post::t('desc'), Post::i('advertise'),
Post::i('modlevel'), Post::i('inslevel'),
$owners, $members);
$req->submit();
}
$domain = $this->prepare_client($page);
- if ($domain == $globals->mail->domain || $domain == $globals->mail->domain2) {
- $domain = '';
- $table = 'aliases';
- $type = 'liste';
- } else {
- $domain = '@' . $domain;
- $table = 'virtual';
- $type = 'list';
- }
-
$page->changeTpl('lists/delete.tpl');
if (Post::v('valid') == 'OUI') {
S::assert_xsrf_token();
if ($this->client->delete_list($liste, Post::b('del_archive'))) {
- foreach (array('', '-owner', '-admin', '-bounces', '-unsubscribe') as $app) {
- XDB::execute("DELETE FROM $table
- WHERE type={?} AND alias={?}",
- $type, $liste.$app.$domain);
- }
+ require_once 'emails.inc.php';
+
+ delete_list($liste, $domain);
$page->assign('deleted', true);
$page->trigSuccess('La liste a été détruite !');
} else {
function handler_lists($page)
{
global $globals;
+ require_once 'emails.inc.php';
if (!$globals->asso('mail_domain')) {
return PL_NOT_FOUND;
if (Post::has('del_alias') && may_update()) {
S::assert_xsrf_token();
- $alias = Post::v('del_alias');
- // prevent group admin from erasing aliases from other groups
- $alias = substr($alias, 0, strpos($alias, '@')).'@'.$globals->asso('mail_domain');
- XDB::query(
- 'DELETE FROM r, v
- USING virtual AS v
- LEFT JOIN virtual_redirect AS r USING(vid)
- WHERE v.alias={?}', $alias);
- $page->trigSuccess(Post::v('del_alias')." supprimé !");
+ $alias = Post::t('del_alias');
+ list($local_part, ) = explode('@', $alias);
+ delete_list_alias($local_part, $globals->asso('mail_domain'));
+ $page->trigSuccess($alias . ' supprimé !');
}
$listes = $this->client->get_lists();
$page->assign('listes', $listes);
-
- $alias = XDB::iterator(
- 'SELECT alias,type
- FROM virtual
- WHERE alias
- LIKE {?} AND type="user"
- ORDER BY alias', '%@'.$globals->asso('mail_domain'));
- $page->assign('alias', $alias);
-
+ $page->assign('aliases', iterate_list_alias($globals->asso('mail_domain')));
$page->assign('may_update', may_update());
if (count($listes) > 0 && !$globals->asso('has_ml')) {
S::assert_xsrf_token();
}
- if (!Post::has('liste') || !Post::v('liste')) {
+ if (!Post::has('liste') || !Post::t('liste')) {
$page->trigError('Le champs « adresse souhaitée » est vide.');
return;
}
- $liste = strtolower(Post::v('liste'));
-
- if (!preg_match("/^[a-zA-Z0-9\-]*$/", $liste)) {
+ $list = strtolower(Post::t('liste'));
+ if (!preg_match("/^[a-zA-Z0-9\-]*$/", $list)) {
$page->trigError('le nom de la liste ne doit contenir que des lettres non accentuées, chiffres et tirets');
return;
}
- $new = $liste.'@'.$globals->asso('mail_domain');
- $res = XDB::query('SELECT alias FROM virtual WHERE alias={?}', $new);
-
- if ($res->numRows()) {
- $page->trigError('cet alias est déjà pris');
+ require_once 'emails.inc.php';
+ if (list_exist($list, $globals->asso('mail_domain'))) {
+ $page->trigError('Cet alias est déjà pris.');
return;
}
- if (!Post::v('desc')) {
- $page->trigError('le sujet est vide');
+ if (!Post::t('desc')) {
+ $page->trigError('Le sujet est vide.');
return;
}
- $ret = $this->client->create_list(
- $liste, utf8_decode(Post::v('desc')), Post::v('advertise'),
- Post::v('modlevel'), Post::v('inslevel'),
- array(S::user()->forlifeEmail()), array(S::user()->forlifeEmail()));
-
- $dom = strtolower($globals->asso("mail_domain"));
- $red = $dom.'_'.$liste;
+ $success = $this->client->create_list($list, utf8_decode(Post::t('desc')), Post::t('advertise'),
+ Post::t('modlevel'), Post::t('inslevel'),
+ array(S::user()->forlifeEmail()), array(S::user()->forlifeEmail()));
- if (!$ret) {
+ if (!$success) {
$page->kill("Un problème est survenu, contacter "
."<a href='mailto:support@m4x.org'>support@m4x.org</a>");
return;
}
- foreach (array('', 'owner', 'admin', 'bounces', 'unsubscribe') as $app) {
- $mdir = $app == '' ? '+post' : '+' . $app;
- if (!empty($app)) {
- $app = '-' . $app;
- }
- XDB::execute('INSERT INTO virtual (alias,type)
- VALUES({?},{?})', $liste. $app . '@'.$dom, 'list');
- XDB::execute('INSERT INTO virtual_redirect (vid,redirect)
- VALUES ({?}, {?})', XDB::insertId(),
- $red . $mdir . '@listes.polytechnique.org');
- }
+ create_list($list, $globals->asso('mail_domain'));
XDB::execute("UPDATE groups
SET flags = CONCAT_WS(',', IF(flags = '', NULL, flags), 'has_ml')
WHERE id = {?}",
$globals->asso('id'));
- pl_redirect('lists/admin/'.$liste);
+ pl_redirect('lists/admin/' . $list);
}
function handler_sync($page, $liste = null)
}
$page->changeTpl('xnetlists/alias-admin.tpl');
+ require_once 'emails.inc.php';
+ list($local_part, $domain) = explode('@', $lfull);
if (Env::has('add_member')) {
S::assert_xsrf_token();
- $add = Env::t('add_member');
- $user = User::getSilent($add);
+ $email = Env::t('add_member');
+ $user = User::getSilent($email);
if ($user) {
- $add = $user->forlifeEmail();
- } else if (!User::isForeignEmailAddress($add)) {
- $add = null;
- }
- if (!empty($add)) {
- XDB::execute('INSERT INTO virtual_redirect (vid, redirect)
- SELECT vid, {?}
- FROM virtual
- WHERE alias = {?}', strtolower($add), $lfull);
- $page->trigSuccess($add . ' ajouté.');
+ add_to_list_alias($user, $local_part, $domain);
+ $page->trigSuccess($email . ' ajouté.');
} else {
- $page->trigError($add . " n'existe pas.");
+ $page->trigError($email . " n'existe pas.");
}
}
if (Env::has('del_member')) {
S::assert_xsrf_token();
- XDB::query(
- "DELETE FROM virtual_redirect
- USING virtual_redirect
- INNER JOIN virtual USING(vid)
- WHERE redirect={?} AND alias={?}", Env::v('del_member'), $lfull);
- pl_redirect('alias/admin/'.$lfull);
- }
- global $globals;
- $emails = XDB::fetchColumn('SELECT redirect
- FROM virtual_redirect AS vr
- INNER JOIN virtual AS v USING(vid)
- WHERE v.alias = {?}
- ORDER BY redirect', $lfull);
- $mem = array();
- foreach ($emails as $email) {
- $user = User::getSilent($email);
- if ($user) {
- $mem[] = array('user' => $user, 'email' => $email);
- } else {
- $mem[] = array('email' => $email);
- }
+ $user = User::getSilent(Env::t('del_member'));
+ delete_from_list_alias($user, $local_part, $domain);
+ $page->trigSuccess($user->fullName() . ' supprimé.');
}
- $page->assign('mem', $mem);
+
+ $page->assign('members', list_alias_members($local_part, $domain));
}
function handler_acreate($page)
$page->trigError('Le champs « adresse souhaitée » est vide.');
return;
}
- $liste = Post::v('liste');
- if (!preg_match("/^[a-zA-Z0-9\-\.]*$/", $liste)) {
- $page->trigError('le nom de l\'alias ne doit contenir que des lettres,'
- .' chiffres, tirets et points');
+ $list = Post::v('liste');
+ if (!preg_match("/^[a-zA-Z0-9\-\.]*$/", $list)) {
+ $page->trigError('Le nom de l\'alias ne doit contenir que des lettres,'
+ .' chiffres, tirets et points.');
return;
}
- $new = $liste.'@'.$globals->asso('mail_domain');
- $res = XDB::query('SELECT COUNT(*) FROM virtual WHERE alias = {?}', $new);
- $n = $res->fetchOneCell();
- if ($n) {
- $page->trigError('cet alias est déjà pris');
+ require_once 'emails.inc.php';
+ if (list_exist($list, $globals->asso('mail_domain'))) {
+ $page->trigError('Cet alias est déjà pris.');
return;
}
- XDB::query('INSERT INTO virtual (alias,type) VALUES({?}, "user")', $new);
-
- pl_redirect("alias/admin/$new");
+ add_to_list_alias(S::user(), $list, $globals->asso('mail_domain'));
+ pl_redirect('alias/admin/' . $list . '@' . $globals->asso('mail_domain'));
}
function handler_profile($page, $user = null)
<p>[<a href='{$platal->ns}lists'>retour à la page des listes</a>]</p>
<h1>Membres de {$platal->argv[1]}</h1>
-
<table class='tinybicol'>
- {if $mem|@count}
- {foreach from=$mem item=m}
+ {if $members|@count}
+ {foreach from=$members item=member}
<tr>
<td>
- {if $m.user}
- {if $m.admin}<strong>{/if}
- <a href="https://www.polytechnique.org/profile/{$m.user->login()}" class="popup2">{$m.user->fullName()}</a>
- {if $m.admin}</strong>{/if}
- {else}
- {$m.email}
- {/if}
- </td>
- <td class="right">
- {if $m.user}
- {if $m.admin}<strong>{/if}
- {$m.user->promo()}
- {if $m.admin}</strong>{/if}
- {/if}
+ <a href="https://www.polytechnique.org/profile/{$member->profile()->hrpid}" class="popup2">{$member->fullName()}</a>
</td>
+ <td class="right">{$member->promo()}</td>
<td class="center">
- <a href='{$platal->ns}alias/admin/{$platal->argv[1]}?del_member={$m.email|urlencode}&token={xsrf_token}'>
+ <a href='{$platal->ns}alias/admin/{$platal->argv[1]}?del_member={$member->id()}&token={xsrf_token}'>
{icon name=delete title='retirer membre'}
</a>
</td>
{else}
<tr>
<td colspan="3">
- <em>aucun membre…<em>
+ <em>aucun membre…</em>
</td>
</tr>
{/if}
<tr>
<th{if $may_update} colspan='3'{/if}>Alias</th>
</tr>
- {if $alias->total()}
- {iterate from=$alias item=a}
+ {if $aliases|@count}
+ {foreach from=$aliases item=alias}
<tr>
{if $may_update}
- <td class="center"><a href='mailto:{$a.alias}'>{icon name=email title="email"}</a></td>
- <td><a href="{$platal->ns}alias/admin/{$a.alias}">{$a.alias}</a></td>
- <td class="center"><a href="{$platal->ns}lists?del_alias={$a.alias}">{icon name=delete title='supprimer'}</a></td>
+ <td class="center"><a href='mailto:{$alias}'>{icon name=email title="email"}</a></td>
+ <td><a href="{$platal->ns}alias/admin/{$alias}">{$alias}</a></td>
+ <td class="center"><a href="{$platal->ns}lists?del_alias={$alias}">{icon name=delete title='supprimer'}</a></td>
{else}
- <td><a href='mailto:{$a.alias}'>{icon name=email title="email"} {$a.alias}</a></td>
+ <td><a href='mailto:{$alias}'>{icon name=email title="email"} {$alias}</a></td>
{/if}
</tr>
- {/iterate}
+ {/foreach}
{else}
<tr>
<td{if $may_update} colspan='3'{/if}>Aucun alias pour ce groupe</td>