You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

301 lines
11 KiB
PHP

<?php
/**
* postfixAdmin managed user identities
*
* This plugin requires that a postfixAdmin database is configured.
*
* @author alphanoob1337
* @license MIT
*/
class postfixadmin_user_identities extends rcube_plugin
{
public $task = 'login';
private $rc;
private $db;
function init()
{
$this->rc = rcmail::get_instance();
$this->add_hook('user_create', array($this, 'fetch_identities'));
$this->add_hook('login_after', array($this, 'recheck_identities'));
}
function fetch_identities($args)
{
$this->load_config('config.inc.php.dist');
$this->load_config('config.inc.php');
// Connect to database
$this->db = rcube_db::factory($this->rc->config->get('postfixadmin_user_identities_db_dsnr'), '', false);
$this->db->db_connect('w');
// Get full name and main identity
$t_mbox = $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_table_mbox'));
$c_mbox_uid = $t_mbox . '.' . $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_col_uname'));
$c_mbox_fname = $t_mbox . '.' . $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_col_fullname'));
$c_mbox_email = $t_mbox . '.' . $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_col_email'));
$c_mbox_dom = $t_mbox . '.' . $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_col_mbox_domain'));
$qrystr = "SELECT " .
$c_mbox_fname . ", " .
$c_mbox_email . ", " .
$c_mbox_dom .
" FROM " . $t_mbox .
" WHERE " . $c_mbox_uid . " = '" . $this->db->escape($args['user']) . "'";
$qh = $this->db->query($qrystr);
$result = $this->db->fetch_array($qh);
$email_list = array();
$hidden_domains = $this->rc->config->get('postfixadmin_user_identities_hide_domains');
while ($result !== FALSE)
{
$args['user_name'] = $result[0];
$email_list[] = array($result[1], $result[2]);
$result = $this->db->fetch_array($qh);
}
if (count($email_list) > 0)
{
// Fetch alias domains
$t_adom = $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_table_aliasdomain'));
$c_adom_source = $t_adom . '.' . $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_col_aliasdomain'));
$c_adom_destin = $t_adom . '.' . $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_col_gotodomain'));
$c_adom_active = $t_adom . '.' . $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_col_aliasdomain_active'));
$t_dom = $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_table_domain'));
$c_dom_dom = $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_col_domain'));
$c_dom_active = $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_col_domain_active'));
$sdom = $this->db->quote_identifier('srcdom');
$ddom = $this->db->quote_identifier('dstdom');
$qrystr = "SELECT " .
$c_adom_source . ", " .
$c_adom_destin .
" FROM " . $t_adom .
" LEFT OUTER JOIN " . $t_dom . " AS " . $sdom . " ON " . $c_adom_source . " = " . $sdom . "." . $c_dom_dom .
" LEFT OUTER JOIN " . $t_dom . " AS " . $ddom . " ON " . $c_adom_destin . " = " . $ddom . "." . $c_dom_dom .
" WHERE " . $c_adom_active . " = 1 AND" .
" " . $sdom . "." . $c_dom_active . " = 1 AND" .
" " . $ddom . "." . $c_dom_active . " = 1";
$adom_map = array();
$qh = $this->db->query($qrystr);
$result = $this->db->fetch_array($qh);
while ($result !== FALSE)
{
$adom_map[] = array($result[1], $result[0]);
$result = $this->db->fetch_array($qh);
}
// Apply alias domains for the first time
$maxrecursion = count($adom_map);
foreach ($email_list AS $list_item)
{
$email = $list_item[0];
$domain = $list_item[1];
$adom_map2 = $adom_map;
for ($i = 0; $i < $maxrecursion; $i++)
{
foreach ($adom_map2 AS $k => $alias)
{
if ($domain == $alias[0])
{
$newdomain = $alias[1];
$newemail = substr($email, 0, -1*strlen($domain)) . $newdomain;
if (!in_array(array($newemail, $newdomain), $email_list))
$email_list[] = array($newemail, $newdomain);
unset($adom_map2[$k]);
break;
}
}
}
}
// Fetch address aliases
$t_a = $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_table_alias'));
$c_a_source = $t_a . '.' . $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_col_address'));
$c_a_destin = $t_a . '.' . $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_col_goto'));
$c_a_active = $t_a . '.' . $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_col_alias_active'));
$c_a_dom = $t_a . '.' . $this->db->quote_identifier($this->rc->config->get('postfixadmin_user_identities_col_alias_domain'));
$qrystr = "SELECT " .
$c_a_source . ", " .
$c_a_destin .
" FROM " . $t_a .
" LEFT OUTER JOIN " . $t_dom . " ON " . $c_a_dom . " = " . $t_dom . "." . $c_dom_dom .
" WHERE " . $c_a_active . " = 1 AND" .
" " . $t_dom . "." . $c_dom_active . " = 1";
$alias_map = array();
$qh = $this->db->query($qrystr);
$result = $this->db->fetch_array($qh);
while ($result !== FALSE)
{
foreach(explode(',', $result[1]) AS $dest)
$alias_map[] = array($dest, $result[0]);
$result = $this->db->fetch_array($qh);
}
// Apply aliases
$maxrecursion = count($alias_map);
foreach ($email_list AS $list_item)
{
$email = $list_item[0];
$domain = $list_item[1];
$alias_map2 = $alias_map;
for ($i = 0; $i < $maxrecursion; $i++)
{
foreach ($alias_map2 AS $k => $alias)
{
if ($email == $alias[0])
{
$newemail = $alias[1];
$newdomain = strrev(explode('@', strrev($newemail), 2)[0]);
if (!in_array(array($newemail, $newdomain), $email_list))
$email_list[] = array($newemail, $newdomain);
unset($alias_map2[$k]);
break;
}
}
}
}
// Apply alias domains again
$maxrecursion = count($adom_map);
foreach ($email_list AS $list_item)
{
$email = $list_item[0];
$domain = $list_item[1];
$adom_map2 = $adom_map;
for ($i = 0; $i < $maxrecursion; $i++)
{
foreach ($adom_map2 AS $k => $alias)
{
if ($domain == $alias[0])
{
$newdomain = $alias[1];
$newemail = substr($email, 0, -1*strlen($domain)) . $newdomain;
if (!in_array(array($newemail, $newdomain), $email_list))
$email_list[] = array($newemail, $newdomain);
unset($adom_map2[$k]);
break;
}
}
}
}
// Filter results
$f_email_list = array();
foreach ($email_list AS $list_item)
{
$email = $list_item[0];
$domain = $list_item[1];
if (!in_array($domain, $hidden_domains))
{
$f_email_list[] = $email;
}
}
$email_list = $f_email_list;
if (count($email_list) == 1)
$args['user_email'] = $email_list[0];
if (count($email_list) >= 1)
$args['email_list'] = $email_list;
}
$this->db->closeConnection();
return $args;
}
function recheck_identities($args)
{
$this->load_config('config.inc.php.dist');
$this->load_config('config.inc.php');
// Fetch the existing e-mail addresses of the user
$old_identities = $this->rc->user->list_identities();
// Fetch the database
$db_data = $this->fetch_identities(
array(
'user' => $this->rc->user->data['username'],
'host' => $this->rc->user->data['mail_host'],
));
// Add new identities
foreach ($db_data['email_list'] as $email)
{
$already_existing = FALSE;
foreach ($old_identities as $identity)
{
if ($identity['email'] == $email) {
$already_existing = TRUE;
break;
}
}
if (!$already_existing)
{
$plugin = $this->rc->plugins->exec_hook('identity_create',
array(
'login' => true,
'record' => array(
'user_id' => $this->rc->user->ID,
'standard' => 0,
'email' => $email,
'name' => $db_data['user_name']
)
));
if (!$plugin['abort'] && $plugin['record']['email']) {
$this->rc->user->insert_identity($plugin['record']);
}
}
}
// Remove missing identities
foreach ($old_identities as $identity)
{
$missing = TRUE;
foreach ($db_data['email_list'] as $email)
{
if ($identity['email'] == $email) {
$missing = FALSE;
break;
}
}
if ($missing)
{
$plugin = $this->rc->plugins->exec_hook('identity_delete',
array(
'id' => $identity['identity_id']
));
if (!$plugin['abort']) {
$this->rc->user->delete_identity($plugin['id']);
}
}
}
return $args;
}
}