Setting up horde to allow users to login with their e-mail addresses
Horde is a great webmail program. It's easy to use, and, for somebody who has a lot of time to learn its configuration options and its PHP code inside out, it can be altered for many uses. However, it's poorly documented, and if you have a problem you'll probably search and find a dozen mailing list threads with half-articulated solutions.
By default, Horde allows you to login with your user name, but ISPConfig, which was being used to manage a server I was working on recently, adds somewhat hard to remember prefixes to user names. That avoids collisions in a multisite environment. But who wants to remember a prefix (which includes an arbitrary number in it). I needed Horde to convert the e-mail address a client typed to a user name that my IMAP daemon would understand.
I chose to solve this problems using 'hooks.'
Horde allows administrators to program hooks, or functions that are called by the main program at key moments to perform various actions. There were a number of promising hooks in config/hooks.php (_username_hook_tobackend(), _horde_hook_preauthenticate() etc...) and people on IRC told me to use them. But they didn't work. They perform other functions.
What I needed was to turn authentication from the main horde program to IMP, it's mail component. IMP has its own hook called _imp_hook_vinfo() which you can configure in imp/config/hooks.php.
Once I discovered that hook, I just needed to write/borrow some code.
Roundcube, another PHP webmail program allows you to configure it to use a virtusertable file to map e-mails to user names. Luckily, my ISPConfig setup provided this file here: /etc/postfix/virtusertable. So, I borrowed some code from Roundcube and turned it into the hook below (in imp/config/hooks.php).
NOTE: The last step of this process is to turn on the hook, which you can do either through Horde's IMP administration interface in your browser, or by editing imp/config/conf.php.
Here's the code!
Example Horde hook to map login email to system user name
if (!function_exists('_imp_hook_vinfo')) {
function _imp_hook_vinfo($type = 'username') {
$user = Util::getFormData('imapuser');
$pattern = "^$user";
if ($type=='username') {
$result = array();
$virtual = file("/etc/postfix/virtusertable");
if ($virtual==FALSE)
return $result;
// check each line for matches
foreach ($virtual as $line) {
$line = trim(str_replace("www.", "", $line));
if (empty($line) || $line{0}=='#')
continue;
if (eregi($pattern, $line))
$result[] = $line;
}
$r = $result;
for ($i=0; $i<count($r); $i++) {
$data = $r[$i];
$arr = preg_split('/\s+/', $data);
if (count($arr) > 0) {
$user = trim($arr[count($arr)-1]);
break;
}
}
return $user;
} elseif ($type=='vdomain') {
return null; // You may also want to use this hook in this situation.
} else {
return null;
}
}
}
