Originally posted on August 8, 2006 9:57 PM
This little tutorial will show you how to create custom SquirrelMail login pages for many virtual hosts, or in plain English, you have one copy of SquirrelMail and host many web sites on a single server. The purpose is to provide a unique login page for each web site domain without installing multiple copies of SquirrelMail. This is very useful if you are running a webhosting business or you host your friend’s web sites (like I do) and you don’t want SquirrelMail branded with your name but theirs. If that isn’t a good enough reason then how about the fact that the default SquirrelMail login page is boring and you should jazz it up with a custom web site theme.
The following screenshots are examples of some webmail login pages on my server. They all use the same copy of SquirrelMail (version 1.4.6) but with my tweaks each domain has a custom login page.
This walkthrough makes the assumption that you have HTML, PHP, and some graphic design skills. To edit the SquirrelMail files you should know how to copy and paste and understand PHP, but to create your own custom templates you’ll need to know HTML, PHP, and graphics. You should also have root access to your server or have the ability to upload the modified SquirrelMail files to your server. The other obvious assumption is that you have SquirrelMail 1.4.6 installed and configured on your server (using another version of SquirrelMail may work, but I don’t know how much their code changed between revisions). If you don’t have SquirrelMail installed then you can check out my SquirrelMail 1.4.6 tutorial on XenoCafe. With that said, let’s get started.
1. You should already know where SquirrelMail is installed on your server and have it configured for each domain that accesses it. For this howto I’ll use the example directory location of /www/webmail/html/ and the Apache virtual host file for webmail has a ServerAlias directive set for each domain (webmail.domain1.com, webmail.domain2.com, etc…). See my Apache Web Server tutorial for more information on setting up virtual hosts.
2. The way I accomplished custom webmail login pages was to create a directory in /www/webmail/html/ called hosts. This directory is where all your templates are stored for each custom webmail login page and their associated images. Start by creating a host directory in your webmail root directory (for clarification, this is the same top level directory where the SquirrelMail "src" directory exists).
cd /www/webmail/html/
mkdir hosts
3. There are three SquirrelMail PHP files that we’ll need to edit. The primary one is called global.php that resides in the functions directory. We’ll insert our custom function called show_login_page that makes custom logins possible. Let’s take a look at this login page function we’re creating.
function show_login_page( $errTitle="", $errString="" ) {
$httphost = strtolower( $_SERVER["HTTP_HOST"] );
switch ($httphost) {
case "webmail.domain1.com":
require( SM_PATH . "hosts/domain1/domain1.php" );
break;
case "domain2.com":
case "www.domain2.com":
case "webmail.domain2.com":
include( SM_PATH . "hosts/domain2/domain2.php" );
break;
default:
require( SM_PATH . "hosts/default/default.php" );
break;
}
}
This function accepts two arguments ($errTitle and $errString). You’ll learn about these later when we modify one of the other SquirrelMail files. $httphost contains the server name of which web site the user is visiting. This is acquired from the global $_SERVER["HTTP_HOST"] PHP variable. We use a switch/case structure to evaluate the HTTP HOST name. Depending on which host is visited the custom template for that host is shown for the login page. The host names are set up through Apache virtual hosts and DNS, in the case of the webmail subdomain. For www.domain.com and domain.com, it is assumed access to the site is coming from a /webmail directory. That can be established via symbolic links like so.
ln -s /www/webmail/html/ /www/domain/html/webmail
So webmail can be accessed from http://webmail.domain.com or from http://www.domain.com/webmail since both paths map to the same physical space. You’ll see the PHP include function being used once a host is matched. The include function inserts your custom login page’s code as part of the HTML output to the web browser. The path to the PHP page is within the hosts directory we created earlier. For each host you want to serve custom logins you’ll create a subdirectory within hosts (I use the domain name without the ending .com, .net, etc). You’ll store your custom login page and image files within that domain directory. The last part of the switch/case is the default login page. This is shown when there are no HTTP HOST matches and thus displays the default SquirrelMail login page.
Open up the functions/global.php file in a text editor and add the show_login_page function to the end of the file right above the ending ?> PHP tag. Customize the hosts for your server and save the file when you’re done.
4. Next we’ll edit the src/login.php page. We’re basically gonna strip out parts of the exsiting SquirrelMail code and replace it with a call to our show_login_page function. Make a backup copy of login.php and open the original in a text editor. Delete everything in the file and insert this code.
<?php
/**
* login.php -- simple login screen
*
* Copyright (c) 1999-2006 The SquirrelMail Project Team
* Licensed under the GNU GPL. For full terms see the file COPYING.
*
* This a simple login screen. Some housekeeping is done to clean
* cookies and find language.
*
* @version $Id: login.php,v 1.98.2.11 2006/02/03 22:27:55 jervfors Exp $
* @package squirrelmail
*/
/**
* Path for SquirrelMail required files.
* @ignore
*/
define("SM_PATH","../");
/* SquirrelMail required files. */
require_once(SM_PATH . "functions/strings.php");
require_once(SM_PATH . "config/config.php");
require_once(SM_PATH . "functions/i18n.php");
require_once(SM_PATH . "functions/plugin.php");
require_once(SM_PATH . "functions/constants.php");
require_once(SM_PATH . "functions/page_header.php");
require_once(SM_PATH . "functions/html.php");
require_once(SM_PATH . "functions/global.php");
require_once(SM_PATH . "functions/forms.php");
/**
* $squirrelmail_language is set by a cookie when the user selects
* language and logs out
*/
set_up_language($squirrelmail_language, TRUE, TRUE);
/**
* Find out the base URI to set cookies.
*/
if (!function_exists("sqm_baseuri")){
require_once(SM_PATH . "functions/display_messages.php");
}
$base_uri = sqm_baseuri();
/*
* In case the last session was not terminated properly, make sure
* we get a new one.
*/
sqsession_destroy();
header("Pragma: no-cache");
do_hook("login_cookie");
$loginname_value = (sqGetGlobalVar("loginname", $loginname) ? htmlspecialchars($loginname) : "");
if(sqgetGlobalVar("mailto", $mailto)) {
$rcptaddress = "<input type=\"hidden\" name=\"mailto\" value=\"$mailto\" />\n";
} else {
$rcptaddress = "";
}
show_login_page();
?>
Save your changes when you’re done and then we’ll move on to the last file.
5. The last file we edit is functions/display_messages.php. This file contains functions to display any messages (error or otherwise) on the screen, such as login failures, IMAP failures, etc. We need to change the logout_error function so when a login failure occurs that our custom page is shown instead of the default SquirrelMail version. Replace the logout_error function with this code.
function logout_error( $errString, $errTitle = "" ) {
list($junk, $errString, $errTitle) = do_hook("logout_error", $errString, $errTitle);
if ( $errTitle == "" ) {
$errTitle = $errString;
}
show_login_page($errTitle, $errString);
}
If you were wondering about those arguments to our show_login_page function, now you can see what they’re for. SquirrelMail uses a hook to capture error messages on events. All we are doing is passing those error values to our login page function. When you intially go to the page, no errors are shown. If you login in and provide invalid information, our same login page will be shown again, but this time it’ll have the error messages within it. It’s similar to a postback but the URL is different. When we defined our login page function, we initialized those arguments with default null string values so no errors would show. When logout_error is called we pass the errors so they will be shown.
6. SquirrelMail’s PHP files are done so what’s left is to go over the steps of creating a custom login theme. I’ll now go over the parts you need to include when creating a template. Here is an example of the default template.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta name="robots" content="noindex,nofollow">
<link rel="stylesheet" type="text/css" href="../themes/css/verdana-10.css" />
<title>Domain - Login<?php echo (($errTitle != "" ) ? " - ".$errTitle : ""); ?></title><script language="JavaScript" type="text/javascript">
<!--
function squirrelmail_loginpage_onload() {
document.forms[0].js_autodetect_results.value = "<?php echo SMPREF_JS_ON; ?>";
var textElements = 0;
for (i = 0; i < document.forms[0].elements.length; i++) {
if (document.forms[0].elements[i].type == "text" || document.forms[0].elements[i].type == "password" ) {
textElements++;
if (textElements == <?php echo (isset($loginname) ? 2 : 1); ?>) {
document.forms[0].elements[i].focus();
break;
}
}
}
}
// -->
</script>
<style type="text/css">
<!--
/* avoid stupid IE6 bug with frames and scrollbars */
body {
voice-family: "\"}\"";
voice-family: inherit;
width: expression(document.documentElement.clientWidth - 30);
}
-->
</style>
</head>
<body text="#000000" bgcolor="#ffffff" link="#0000cc" vlink="#0000cc" alink="#0000cc" onLoad="squirrelmail_loginpage_onload();">
<form action="redirect.php" method="post">
<table bgcolor="#ffffff" border="0" cellspacing="0" cellpadding="0" width="100%"><tr><td align="center"><center><img src="http://webmail.domain.com/images/domain_logo.gif" alt="Domain Logo" width="180" height="50" /><br />
<small>SquirrelMail version 1.4.6<br />
By the SquirrelMail Project Team<br /></small>
<table bgcolor="#ffffff" border="0" width="350"><tr><td bgcolor="#dcdcdc" align="center"><b>Domain Login</b>
</td>
</tr>
<tr><td bgcolor="#ffffff" align="left">
<table bgcolor="#ffffff" align="center" border="0" width="100%"><tr><td align="right" width="30%">Name:</td>
<td align="left" width="*"><input type="text" name="login_username" value="<?php echo $loginname_value; ?>" />
</td>
</tr>
<tr><td align="right" width="30%">Password:</td>
<td align="left" width="*"><input type="password" name="secretkey" />
<input type="hidden" name="js_autodetect_results" value="<?php echo SMPREF_JS_OFF; ?>" />
<?php echo $rcptaddress; ?>
<input type="hidden" name="just_logged_in" value="1" />
</td>
</tr>
</table>
</td>
</tr>
<tr><td align="left"><center><input type="submit" value="Login" />
</center></td>
</tr>
</table>
</center>
<br><?php if ($errString != "" ) { echo "<center><font size=\"2\" face=\"Arial, Helvetica, sans-serif\" color=\"#ff0000\"><strong>$errString</strong></font></center>"; } ?>
</td>
</tr>
</table>
</form>
</body></html>
The code pieces in bold should be included in your template. I won’t go in depth over the code, that’s why I said you should know HTML and PHP.
I’ve included a zip file containing the altered PHP files and a couple templates to give you examples to follow when creating your own custom login pages. Be sure to read the README file included in the zip.
Source Files: sqmail-custom-logins.zip