diff -ruN dbmail-20031108-omit-frame-pointer/mysql/dbauthmysql.c dbmail-20031108-usermap/mysql/dbauthmysql.c
--- dbmail-20031108-omit-frame-pointer/mysql/dbauthmysql.c	2003-07-25 14:24:10.000000000 -0600
+++ dbmail-20031108-usermap/mysql/dbauthmysql.c	2003-11-08 10:32:59.000000000 -0700
@@ -120,21 +120,33 @@
 char __auth_encryption_desc_string[_DESCSTRLEN];
 
 
-u64_t auth_user_exists(const char *username)
+u64_t auth_user_exists(const char *user)
 {
   u64_t uid;
+  char *escuser;
 
-  if (!username)
+  if (!user)
     {
-      trace(TRACE_ERROR,"auth_user_exists(): got NULL as username\n");
+      trace(TRACE_ERROR,"auth_user_exists(): got NULL as username");
       return 0;
     }
 
-  snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr FROM users WHERE userid='%s'",username);
+  if (! (escuser = (char*)malloc(strlen(user)*2 +1)) )
+    {
+      trace(TRACE_ERROR, "auth_validate(): out of memory allocating for escaped username");
+      return -1;
+    }
+
+  mysql_real_escape_string(&__auth_conn, escuser, user, strlen(user));
+
+  snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr FROM users WHERE userid='%s'",escuser);
+
+  free(escuser);
+  escuser = NULL;
 
   if (__auth_query(__auth_query_data)==-1)
     {
-      trace(TRACE_ERROR, "auth_user_exists(): could not execute query\n");
+      trace(TRACE_ERROR, "auth_user_exists(): could not execute query");
       return -1;
     }
 
@@ -159,7 +171,7 @@
 {
   if (!users)
     {
-      trace(TRACE_ERROR,"auth_get_known_users(): got a NULL pointer as argument\n");
+      trace(TRACE_ERROR,"auth_get_known_users(): got a NULL pointer as argument");
       return -2;
     }
 
@@ -170,7 +182,7 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_get_known_users(): could not retrieve user list\n");
+      trace(TRACE_ERROR,"auth_get_known_users(): could not retrieve user list");
       return -1;
     }
 
@@ -202,13 +214,13 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_getclientid(): could not retrieve client id for user [%llu]\n",useridnr);
+      trace(TRACE_ERROR,"auth_getclientid(): could not retrieve client id for user [%llu]",useridnr);
       return -1;
     }
 
   if ((__auth_res = mysql_store_result(&__auth_conn)) == NULL)
     {
-      trace(TRACE_ERROR,"auth_getclientid(): could not store query result: [%s]\n",mysql_error(&__auth_conn));
+      trace(TRACE_ERROR,"auth_getclientid(): could not store query result: [%s]",mysql_error(&__auth_conn));
       return -1;
     }
 
@@ -228,13 +240,13 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_getmaxmailsize(): could not retrieve client id for user [%llu]\n",useridnr);
+      trace(TRACE_ERROR,"auth_getmaxmailsize(): could not retrieve client id for user [%llu]",useridnr);
       return -1;
     }
 
   if ((__auth_res = mysql_store_result(&__auth_conn)) == NULL)
     {
-      trace(TRACE_ERROR,"auth_getmaxmailsize(): could not store query result: [%s]\n",
+      trace(TRACE_ERROR,"auth_getmaxmailsize(): could not store query result: [%s]",
 	    mysql_error(&__auth_conn));
       return -1;
     }
@@ -275,14 +287,14 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_getencryption(): could not retrieve encryption type for user [%llu]\n",
+      trace(TRACE_ERROR,"auth_getencryption(): could not retrieve encryption type for user [%llu]",
 	    useridnr);
       return __auth_encryption_desc_string; /* return empty */
     }
 
   if ((__auth_res = mysql_store_result(&__auth_conn)) == NULL)
     {
-      trace(TRACE_ERROR,"auth_getencryption(): could not store query result: [%s]\n",
+      trace(TRACE_ERROR,"auth_getencryption(): could not store query result: [%s]",
 	    mysql_error(&__auth_conn));
       return __auth_encryption_desc_string; /* return empty */
     }
@@ -477,7 +489,7 @@
   if (__auth_query(__auth_query_data) == -1)
     {
       /* query failed */
-      trace (TRACE_ERROR, "auth_adduser(): query failed\n");
+      trace (TRACE_ERROR, "auth_adduser(): query failed");
       return -1;
     }
 
@@ -490,7 +502,7 @@
   if (mysql_num_rows(__auth_res) > 0)
     {
       /* this username already exists */
-      trace(TRACE_ERROR,"auth_adduser(): user already exists\n");
+      trace(TRACE_ERROR,"auth_adduser(): user already exists");
       return -1;
     }
 
@@ -537,7 +549,7 @@
   trace (TRACE_DEBUG,"auth_adduser(): executing query for mailbox");
 
 	
-  if (__auth_query(__auth_query_data))
+  if (__auth_query(__auth_query_data) == -1)
     {
       trace (TRACE_ERROR,"auth_adduser(): query failed for adding mailbox");
       return -1;
@@ -569,7 +581,7 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_change_username(): could not change name for user [%llu]\n",useridnr);
+      trace(TRACE_ERROR,"auth_change_username(): could not change name for user [%llu]",useridnr);
       return -1;
     }
 
@@ -585,7 +597,7 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_change_password(): could not change passwd for user [%llu]\n",useridnr);
+      trace(TRACE_ERROR,"auth_change_password(): could not change passwd for user [%llu]",useridnr);
       return -1;
     }
 
@@ -600,7 +612,7 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_change_password(): could not change client id for user [%llu]\n",useridnr);
+      trace(TRACE_ERROR,"auth_change_password(): could not change client id for user [%llu]",useridnr);
       return -1;
     }
 
@@ -614,7 +626,7 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_change_password(): could not change maxmailsize for user [%llu]\n",
+      trace(TRACE_ERROR,"auth_change_password(): could not change maxmailsize for user [%llu]",
 	    useridnr);
       return -1;
     }
@@ -623,6 +635,8 @@
 }
 
 
+int use_usermap = 0;  /* global var for existence of usermap test */
+
 /* 
  * auth_validate()
  *
@@ -633,6 +647,7 @@
 u64_t auth_validate (char *user, char *password)
 {
   u64_t id;
+  u64_t tmpid;
   int is_validated = 0;
   char timestr[30];
   time_t td;
@@ -645,19 +660,42 @@
   tm = *localtime(&td);   /* get components */
   strftime(timestr, sizeof(timestr), "%G-%m-%d %H:%M:%S", &tm);
 
+  /* test existence of usermap table */
+  if (use_usermap == 0)
+    {
+      snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr FROM usermap "
+	"WHERE 1 = 2");
+
+      if (__auth_query(__auth_query_data)==-1)
+        {
+          trace(TRACE_DEBUG, "auth_validate(): disabling usermap table lookups");
+	  use_usermap = -1;
+        }
+      else
+        {
+          trace(TRACE_DEBUG, "auth_validate(): usermap table found: enabling usermap lookups");
+	  use_usermap = 1;
+        }
+
+      if ((__auth_res = mysql_use_result(&__auth_conn)) == NULL)
+        {
+          trace (TRACE_ERROR,"auth_validate(): mysql_use_result failed: %s",mysql_error(&__auth_conn));
+          return -1;
+        }
+      mysql_free_result(__auth_res);
+    }
+
   if (! (escuser = (char*)malloc(strlen(user)*2 +1)) )
     {
       trace(TRACE_ERROR, "auth_validate(): out of memory allocating for escaped userid");
       return -1;
     }
 
-  mysql_real_escape_string(&__auth_conn, escuser, user, strlen(user)); 
+  mysql_real_escape_string(&__auth_conn, escuser, user, strlen(user));
 
+  // try to get the userid from users table (normal dbmail behavior)
   snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr, passwd, encryption_type FROM users WHERE userid = '%s'", escuser);
 
-  free(escuser);
-  escuser = NULL;
-
   if (__auth_query(__auth_query_data)==-1)
     {
       trace(TRACE_ERROR, "auth_validate(): could not select user information");
@@ -666,7 +704,7 @@
 	
   if ((__auth_res = mysql_store_result(&__auth_conn)) == NULL)
     {
-      trace (TRACE_ERROR,"auth_validate(): mysql_store_result failed: %s\n",mysql_error(&__auth_conn));
+      trace (TRACE_ERROR,"auth_validate(): mysql_store_result failed: %s",mysql_error(&__auth_conn));
       return -1;
     }
 
@@ -674,9 +712,79 @@
   
   if (!__auth_row)
     {
-      trace (TRACE_DEBUG,"auth_validate(): userid '%s' not found", user);
       mysql_free_result(__auth_res);
-      return 0;
+
+      if (use_usermap < 0)  /* no usermap table */
+        {
+          trace (TRACE_DEBUG,"auth_validate(): userid '%s' not found in users table", user);
+	  return 0;
+	}
+      else  /* usermap table exists */
+        trace (TRACE_DEBUG,"auth_validate(): userid '%s' not found in users table, checking usermap", user);
+	
+      // user_idnr not found, so try to get it from the usermap
+      snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr FROM usermap "
+	"WHERE userid = '%s'", escuser);
+
+      free(escuser);
+      escuser = NULL;
+
+      if (__auth_query(__auth_query_data)==-1)
+        {
+          trace(TRACE_ERROR, "auth_validate(): could not select usermap");
+          return -1;
+        }
+	
+      if ((__auth_res = mysql_store_result(&__auth_conn)) == NULL)
+        {
+          trace (TRACE_ERROR,"auth_validate(): mysql_store_result failed: %s",mysql_error(&__auth_conn));
+          return -1;
+        }
+
+      __auth_row = mysql_fetch_row(__auth_res);
+  
+      if (!__auth_row)
+        {
+          /* user does not exist */
+          trace (TRACE_DEBUG,"auth_validate(): userid '%s' not found in usermap", user);
+          mysql_free_result(__auth_res);
+          return 0;
+        }
+
+      trace (TRACE_DEBUG,"auth_validate(): userid '%s' found in usermap", user);
+
+      tmpid = (__auth_row[0]) ? strtoull(__auth_row[0], NULL, 10) : 0;
+      mysql_free_result(__auth_res);
+
+      // now do the lookup using the user_idnr rather than userid
+      snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr, passwd, encryption_type FROM users "
+	"WHERE user_idnr = %llu", tmpid);
+
+    if (__auth_query(__auth_query_data)==-1)
+      {
+        trace(TRACE_ERROR, "auth_validate(): could not select user information");
+        return -1;
+      }
+	
+    if ((__auth_res = mysql_store_result(&__auth_conn)) == NULL)
+      {
+        trace (TRACE_ERROR,"auth_validate(): mysql_store_result failed: %s",mysql_error(&__auth_conn));
+        return -1;
+      }
+
+    __auth_row = mysql_fetch_row(__auth_res);
+  
+    if (!__auth_row)
+      {
+        trace (TRACE_DEBUG,"auth_validate(): user_idnr '%llu' not found in users table", tmpid);
+        mysql_free_result(__auth_res);
+        return 0;
+      }
+    }
+  else
+    {
+      free(escuser);
+      escuser = NULL;
     }
 
   if (!__auth_row[2] || strcasecmp(__auth_row[2], "") == 0)
@@ -736,44 +844,149 @@
   return id;
 }
 
-u64_t auth_md5_validate (char *username,unsigned char *md5_apop_he, char *apop_stamp)
+/* returns useridnr on OK, 0 on validation failed, -1 on error */
+u64_t auth_md5_validate (char *user,unsigned char *md5_apop_he, char *apop_stamp)
 {
-  /* returns useridnr on OK, 0 on validation failed, -1 on error */
-  
   char *checkstring;
   unsigned char *md5_apop_we;
   u64_t useridnr;	
+  u64_t tmpid;	
   char timestr[30];
   time_t td;
   struct tm tm;
+  char *escuser;
 
   time(&td);              /* get time */
   tm = *localtime(&td);   /* get components */
   strftime(timestr, sizeof(timestr), "%G-%m-%d %H:%M:%S", &tm);
   
-  snprintf (__auth_query_data, AUTH_QUERY_SIZE, "SELECT passwd,user_idnr FROM users WHERE userid=\"%s\"",username);
-	
+  /* test existence of usermap table */
+  if (use_usermap == 0)
+    {
+      snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr FROM usermap "
+	"WHERE 1 = 2");
+
+      if (__auth_query(__auth_query_data)==-1)
+        {
+          trace(TRACE_DEBUG, "auth_md5_validate(): disabling usermap table lookups");
+	  use_usermap = -1;
+        }
+      else
+        {
+          trace(TRACE_DEBUG, "auth_md5_validate(): usermap table found: enabling usermap lookups");
+	  use_usermap = 1;
+        }
+
+      if ((__auth_res = mysql_use_result(&__auth_conn)) == NULL)
+        {
+          trace (TRACE_ERROR,"auth_md5_validate(): mysql_use_result failed: %s",mysql_error(&__auth_conn));
+          return -1;
+        }
+      mysql_free_result(__auth_res);
+    }
+
+  if (! (escuser = (char*)malloc(strlen(user)*2 +1)) )
+    {
+      trace(TRACE_ERROR, "auth_md5_validate(): out of memory allocating for escaped userid");
+      return -1;
+    }
+
+  mysql_real_escape_string(&__auth_conn, escuser, user, strlen(user));
+
+  // try to get the user_idnr from users table (normal dbmail behavior)
+  snprintf (__auth_query_data, AUTH_QUERY_SIZE, "SELECT passwd,user_idnr FROM users WHERE userid=\"%s\"",escuser);
+
   if (__auth_query(__auth_query_data)==-1)
     {
-      trace(TRACE_ERROR, "auth_md5_validate(): query failed: %s",mysql_error(&__auth_conn));
+      trace(TRACE_ERROR, "auth_md5_validate(): could not select user information: %s",mysql_error(&__auth_conn));
       return -1;
     }
 	
   if ((__auth_res = mysql_store_result(&__auth_conn)) == NULL)
     {
-      trace (TRACE_ERROR,"auth_md5_validate(): mysql_store_result failed:  %s",mysql_error(&__auth_conn));
-      
+      trace (TRACE_ERROR,"auth_md5_validate(): mysql_store_result failed: %s",mysql_error(&__auth_conn));
+
       return -1;
     }
 
-  if (mysql_num_rows(__auth_res)<1)
+  __auth_row = mysql_fetch_row(__auth_res);
+  
+  if (!__auth_row)
     {
-      /* no such user found */
-      
-      return 0;
-    }
+      mysql_free_result(__auth_res);
+
+      if (use_usermap < 0)  /* no usermap table */
+        {
+          trace (TRACE_DEBUG,"auth_md5_validate(): userid '%s' not found in users table", user);
+	  return 0;
+	}
+      else  /* usermap table exists */
+        trace (TRACE_DEBUG,"auth_md5_validate(): userid '%s' not found in users table, checking usermap", user);
 	
-  __auth_row = mysql_fetch_row(__auth_res);
+      // user_idnr not found, so try to get it from the usermap
+      snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr FROM usermap "
+	"WHERE userid = '%s'", escuser);
+
+      free(escuser);
+      escuser = NULL;
+
+      if (__auth_query(__auth_query_data)==-1)
+        {
+          trace(TRACE_ERROR, "auth_md5_validate(): could not select usermap");
+          return -1;
+        }
+	
+      if ((__auth_res = mysql_store_result(&__auth_conn)) == NULL)
+        {
+          trace (TRACE_ERROR,"auth_md5_validate(): mysql_store_result failed: %s",mysql_error(&__auth_conn));
+          return -1;
+        }
+
+      __auth_row = mysql_fetch_row(__auth_res);
+  
+      if (!__auth_row)
+        {
+          /* user does not exist */
+          trace (TRACE_DEBUG,"auth_md5_validate(): userid '%s' not found in usermap", user);
+          mysql_free_result(__auth_res);
+          return 0;
+        }
+
+      trace (TRACE_DEBUG,"auth_md5_validate(): userid '%s' found in usermap", user);
+
+      tmpid = (__auth_row[0]) ? strtoull(__auth_row[0], NULL, 10) : 0;
+      mysql_free_result(__auth_res);
+
+      // now do the lookup using the user_idnr rather than userid
+      snprintf (__auth_query_data, AUTH_QUERY_SIZE, "SELECT passwd,user_idnr FROM users "
+	"WHERE user_idnr = %llu", tmpid);
+
+    if (__auth_query(__auth_query_data)==-1)
+      {
+        trace(TRACE_ERROR, "auth_md5_validate(): could not select user information");
+        return -1;
+      }
+	
+    if ((__auth_res = mysql_store_result(&__auth_conn)) == NULL)
+      {
+        trace (TRACE_ERROR,"auth_md5_validate(): mysql_store_result failed: %s",mysql_error(&__auth_conn));
+        return -1;
+      }
+
+    __auth_row = mysql_fetch_row(__auth_res);
+  
+    if (!__auth_row)
+      {
+        trace (TRACE_DEBUG,"auth_md5_validate(): user_idnr '%llu' not found in users table", tmpid);
+        mysql_free_result(__auth_res);
+        return 0;
+      }
+    }
+  else
+    {
+      free(escuser);
+      escuser = NULL;
+    }
 	
 	/* now authenticate using MD5 hash comparison 
 	 * __auth_row[0] contains the password */
@@ -792,7 +1005,7 @@
 
   if (strcmp(md5_apop_he,makemd5(checkstring))==0)
     {
-      trace(TRACE_MESSAGE,"auth_md5_validate(): user [%s] is validated using APOP",username);
+      trace(TRACE_MESSAGE,"auth_md5_validate(): user [%s] is validated using APOP",user);
 		
       useridnr = (__auth_row && __auth_row[1]) ? strtoull(__auth_row[1], NULL, 10) : 0;
       mysql_free_result(__auth_res);
@@ -803,12 +1016,12 @@
 	       "WHERE user_idnr = %llu", timestr, useridnr);
       
       if (__auth_query(__auth_query_data)==-1)
-	trace(TRACE_ERROR, "auth_validate(): could not update user login time");
+	trace(TRACE_ERROR, "auth_md5_validate(): could not update user login time");
 
       return useridnr;
     }
 	
-  trace(TRACE_MESSAGE,"auth_md5_validate(): user [%s] could not be validated",username);
+  trace(TRACE_MESSAGE,"auth_md5_validate(): user [%s] could not be validated",user);
 
   if (__auth_res!=NULL)
     mysql_free_result(__auth_res);
diff -ruN dbmail-20031108-omit-frame-pointer/pgsql/dbauthpgsql.c dbmail-20031108-usermap/pgsql/dbauthpgsql.c
--- dbmail-20031108-omit-frame-pointer/pgsql/dbauthpgsql.c	2003-07-25 14:35:02.000000000 -0600
+++ dbmail-20031108-usermap/pgsql/dbauthpgsql.c	2003-11-08 10:31:41.000000000 -0700
@@ -183,22 +183,34 @@
 #define _DESCSTRLEN 50
 char __auth_encryption_desc_string[_DESCSTRLEN];
 
-u64_t auth_user_exists(const char *username)
+u64_t auth_user_exists(const char *user)
 {
   u64_t uid;
   char *row;
+  char *escuser;
 
-  if (!username)
+  if (!user)
     {
-      trace(TRACE_ERROR,"auth_user_exists(): got NULL as username\n");
+      trace(TRACE_ERROR,"auth_user_exists(): got NULL as username");
       return 0;
     }
 
-  snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr FROM users WHERE userid='%s'",username);
+  if (! (escuser = (char*)malloc(strlen(user)*2 +1)) )
+    {
+      trace(TRACE_ERROR, "auth_validate(): out of memory allocating for escaped username");
+      return -1;
+    }
+
+  PQescapeString(escuser, user, strlen(user));
+
+  snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr FROM users WHERE userid='%s'",escuser);
+
+  free(escuser);
+  escuser = NULL;
 
   if (__auth_query(__auth_query_data)==-1)
     {
-      trace(TRACE_ERROR, "auth_user_exists(): could not execute query\n");
+      trace(TRACE_ERROR, "auth_user_exists(): could not execute query");
       return -1;
     }
 
@@ -226,7 +238,7 @@
 
   if (!users)
     {
-      trace(TRACE_ERROR,"auth_get_known_users(): got a NULL pointer as argument\n");
+      trace(TRACE_ERROR,"auth_get_known_users(): got a NULL pointer as argument");
       return -2;
     }
 
@@ -237,7 +249,7 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_get_known_users(): could not retrieve user list\n");
+      trace(TRACE_ERROR,"auth_get_known_users(): could not retrieve user list");
       return -1;
     }
 
@@ -268,7 +280,7 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_getclientid(): could not retrieve client id for user [%llu]\n",useridnr);
+      trace(TRACE_ERROR,"auth_getclientid(): could not retrieve client id for user [%llu]",useridnr);
       return -1;
     }
 
@@ -295,7 +307,7 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_getmaxmailsize(): could not retrieve client id for user [%llu::bigint]\n",useridnr);
+      trace(TRACE_ERROR,"auth_getmaxmailsize(): could not retrieve client id for user [%llu::bigint]",useridnr);
       return -1;
     }
 
@@ -343,7 +355,7 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_getencryption(): could not retrieve encryption type for user [%llu::bigint]\n",
+      trace(TRACE_ERROR,"auth_getencryption(): could not retrieve encryption type for user [%llu::bigint]",
 	    useridnr);
       return __auth_encryption_desc_string; /* return empty */
     }
@@ -556,14 +568,14 @@
   if (__auth_query(__auth_query_data) == -1)
     {
       /* query failed */
-      trace (TRACE_ERROR, "auth_adduser(): query failed\n");
+      trace (TRACE_ERROR, "auth_adduser(): query failed");
       return -1;
     }
 
   if (PQntuples(__auth_res) > 0)
     {
       /* this username already exists */
-      trace(TRACE_ERROR,"auth_adduser(): user already exists\n");
+      trace(TRACE_ERROR,"auth_adduser(): user already exists");
       return -1;
     }
 
@@ -610,7 +622,7 @@
   trace (TRACE_DEBUG,"auth_adduser(): executing query for mailbox");
 
 	
-  if (__auth_query(__auth_query_data))
+  if (__auth_query(__auth_query_data) == -1)
     {
       trace (TRACE_ERROR,"auth_adduser(): query failed for adding mailbox");
       return -1;
@@ -642,7 +654,7 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_change_username(): could not change name for user [%llu::bigint]\n",useridnr);
+      trace(TRACE_ERROR,"auth_change_username(): could not change name for user [%llu::bigint]",useridnr);
       return -1;
     }
 
@@ -658,7 +670,7 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_change_password(): could not change passwd for user [%llu::bigint]\n",useridnr);
+      trace(TRACE_ERROR,"auth_change_password(): could not change passwd for user [%llu::bigint]",useridnr);
       return -1;
     }
 
@@ -673,7 +685,7 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_change_password(): could not change client id for user [%llu::bigint]\n",useridnr);
+      trace(TRACE_ERROR,"auth_change_password(): could not change client id for user [%llu::bigint]",useridnr);
       return -1;
     }
 
@@ -687,7 +699,7 @@
 
   if (__auth_query(__auth_query_data) == -1)
     {
-      trace(TRACE_ERROR,"auth_change_password(): could not change maxmailsize for user [%llu::bigint]\n",
+      trace(TRACE_ERROR,"auth_change_password(): could not change maxmailsize for user [%llu::bigint]",
 	    useridnr);
       return -1;
     }
@@ -696,6 +708,8 @@
 }
 
 
+int use_usermap = 0;  /* global var for existence of usermap test */
+
 /* 
  * auth_validate()
  *
@@ -706,6 +720,7 @@
 u64_t auth_validate (char *user, char *password)
 {
   u64_t id;
+  u64_t tmpid;
   char *row;
   int is_validated = 0;
   char timestr[30];
@@ -719,6 +734,25 @@
   tm = *localtime(&td);   /* get components */
   strftime(timestr, sizeof(timestr), "%G-%m-%d %H:%M:%S", &tm);
 
+  /* test existence of usermap table */
+  if (use_usermap == 0)
+    {
+      snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr FROM usermap "
+        "WHERE 1 = 2");
+
+      if (__auth_query(__auth_query_data)==-1)
+        {
+          trace(TRACE_ERROR, "auth_validate(): disabling usermap table lookups");
+          use_usermap = -1;
+        }
+      else
+        {
+          trace(TRACE_ERROR, "auth_validate(): usermap table found: enabling usermap lookps");
+          PQclear(__auth_res);
+          use_usermap = 1;
+        }
+    }
+
   if (! (escuser = (char*)malloc(strlen(user)*2 +1)) )
     {
       trace(TRACE_ERROR, "auth_validate(): out of memory allocating for escaped userid");
@@ -727,6 +761,7 @@
 
   PQescapeString(escuser, user, strlen(user));
 
+  // try to get the userid from users table (normal dbmail behavior)
   snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr, passwd, encryption_type FROM users WHERE userid = '%s'", escuser);
 
   if (__auth_query(__auth_query_data)==-1)
@@ -737,8 +772,63 @@
 
   if (PQntuples(__auth_res) == 0 ) 
     {
-        PQclear (__auth_res);
-        return 0;
+      PQclear (__auth_res);
+
+      if (use_usermap < 0)  /* no usermap table */
+        {
+          trace (TRACE_DEBUG,"auth_validate(): userid '%s' not found in users table", user);
+          return 0;
+        }
+      else  /* usermap table exists */
+        trace (TRACE_DEBUG,"auth_validate(): userid '%s' not found in users table, checking usermap", user);
+
+      // user_idnr not found, so try to get it from the usermap
+      snprintf(__auth_query_data, AUTH_QUERY_SIZE, "select user_idnr from usermap "
+        "where userid = '%s'", escuser);
+
+      free(escuser);
+      escuser = NULL;
+
+      if (__auth_query(__auth_query_data)==-1)
+        {
+          trace(TRACE_ERROR, "auth_validate(): could not select user_idnr from usermap");
+          return -1;
+        }
+
+      if (PQntuples(__auth_res) == 0 ) 
+        {
+            trace (TRACE_DEBUG,"auth_validate(): userid '%s' not found in usermap", user);
+            PQclear (__auth_res);
+            return 0;
+        }
+
+      trace (TRACE_DEBUG,"auth_validate(): userid '%s' found in usermap", user);
+
+      row = PQgetvalue(__auth_res, 0, 0);
+      tmpid = (row) ? strtoull(row, NULL, 10) : 0;
+      PQclear(__auth_res);
+
+      // now proceed in a normal fashion, but use the user_idnr rather than userid
+      snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr, passwd, encryption_type FROM users "
+	"WHERE user_idnr = %llu::bigint", tmpid);
+
+      if (__auth_query(__auth_query_data)==-1)
+        {
+          trace(TRACE_ERROR, "auth_validate(): could not select user information");
+          return -1;
+        }
+
+      if (PQntuples(__auth_res) == 0 ) 
+        {
+            trace (TRACE_DEBUG,"auth_validate(): user_idnr '%llu' not found in users table", tmpid);
+            PQclear (__auth_res);
+            return 0;
+        }
+    }
+  else
+    {
+      free(escuser);
+      escuser = NULL;
     }
 
   row = PQgetvalue(__auth_res, 0, 2);
@@ -808,36 +898,123 @@
 }
 
 
-u64_t auth_md5_validate (char *username,unsigned char *md5_apop_he, char *apop_stamp)
+/* returns useridnr on OK, 0 on validation failed, -1 on error */
+u64_t auth_md5_validate (char *user,unsigned char *md5_apop_he, char *apop_stamp)
 {
-  /* returns useridnr on OK, 0 on validation failed, -1 on error */
   
   char *checkstring;
   unsigned char *md5_apop_we;
   u64_t useridnr;	
+  u64_t tmpid;
   char *value;
   char timestr[30];
   time_t td;
   struct tm tm;
+  char *escuser;
 
   time(&td);              /* get time */
   tm = *localtime(&td);   /* get components */
   strftime(timestr, sizeof(timestr), "%G-%m-%d %H:%M:%S", &tm);
   
+  /* test existence of usermap table */
+  if (use_usermap == 0)
+    {
+      snprintf(__auth_query_data, AUTH_QUERY_SIZE, "SELECT user_idnr FROM usermap "
+        "WHERE 1 = 2");
+
+      if (__auth_query(__auth_query_data)==-1)
+        {
+          trace(TRACE_ERROR, "auth_md5_validate(): disabling usermap table lookups");
+          use_usermap = -1;
+        }
+      else
+        {
+          trace(TRACE_ERROR, "auth_md5_validate(): usermap table found: enabling usermap lookps");
+          PQclear(__auth_res);
+          use_usermap = 1;
+        }
+    }
+
+  if (! (escuser = (char*)malloc(strlen(user)*2 +1)) )
+    {
+      trace(TRACE_ERROR, "auth_md5_validate(): out of memory allocating for escaped userid");
+      return -1;
+    }
+
+  PQescapeString(escuser, user, strlen(user));
+
+  // try to get the userid from users table (normal dbmail behavior)
   snprintf (__auth_query_data, AUTH_QUERY_SIZE, "SELECT passwd,user_idnr FROM users WHERE "
-	    "userid=\'%s\'",username);
-	
+    "userid=\'%s\'",escuser);
+
   if (__auth_query(__auth_query_data)==-1)
+    {
+      trace(TRACE_ERROR, "auth_md5_validate(): could not select user information");
       return -1;
+    }
 
-  if (PQntuples(__auth_res)<1)
+  if (PQntuples(__auth_res) == 0 ) 
     {
-      PQclear(__auth_res);  
-      /* no such user found */
-      return 0;
+      PQclear (__auth_res);
+
+      if (use_usermap < 0)  /* no usermap table */
+        {
+          trace (TRACE_DEBUG,"auth_md5_validate(): userid '%s' not found in users table", user);
+          return 0;
+        }
+      else  /* usermap table exists */
+        trace (TRACE_DEBUG,"auth_md5_validate(): userid '%s' not found in users table, checking usermap", user);
+
+      // user_idnr not found, so try to get it from the usermap
+      snprintf(__auth_query_data, AUTH_QUERY_SIZE, "select user_idnr from usermap "
+        "where userid = '%s'", escuser);
+
+      free(escuser);
+      escuser = NULL;
+
+      if (__auth_query(__auth_query_data)==-1)
+        {
+          trace(TRACE_ERROR, "auth_md5_validate(): could not select user_idnr from usermap");
+          return -1;
+        }
+
+      if (PQntuples(__auth_res) == 0 ) 
+        {
+            trace (TRACE_DEBUG,"auth_md5_validate(): userid '%s' not found in usermap", user);
+            PQclear (__auth_res);
+            return 0;
+        }
+
+      trace (TRACE_DEBUG,"auth_md5_validate(): userid '%s' found in usermap", user);
+
+      value = PQgetvalue(__auth_res, 0, 0);
+      tmpid = (value) ? strtoull(value, NULL, 10) : 0;
+      PQclear(__auth_res);
+
+      // now proceed in a normal fashion, but use the user_idnr rather than userid
+      snprintf (__auth_query_data, AUTH_QUERY_SIZE, "SELECT passwd,user_idnr FROM users WHERE "
+	"user_idnr = %llu::bigint", tmpid);
+
+      if (__auth_query(__auth_query_data)==-1)
+        {
+          trace(TRACE_ERROR, "auth_md5_validate(): could not select user information");
+          return -1;
+        }
+
+      if (PQntuples(__auth_res) == 0 ) 
+        {
+            trace (TRACE_DEBUG,"auth_md5_validate(): user_idnr '%llu' not found in users table", tmpid);
+            PQclear (__auth_res);
+            return 0;
+        }
     }
-	
-	/* now authenticate using MD5 hash comparisation  */
+  else
+    {
+      free(escuser);
+      escuser = NULL;
+    }
+
+	/* now authenticate using MD5 hash comparison  */
   value = PQgetvalue (__auth_res, 0, 0);
 
   /* value holds the password */
@@ -857,7 +1034,7 @@
 
   if (strcmp(md5_apop_he,makemd5(checkstring))==0)
     {
-      trace(TRACE_MESSAGE,"auth_md5_validate(): user [%s] is validated using APOP",username);
+      trace(TRACE_MESSAGE,"auth_md5_validate(): user [%s] is validated using APOP",user);
 		
       value = PQgetvalue (__auth_res, 0, 1);     /* value contains useridnr */
       useridnr = (value) ? strtoull(value, NULL, 10) : 0;
@@ -869,17 +1046,16 @@
 	       "WHERE user_idnr = %llu::bigint", timestr, useridnr);
       
       if (__auth_query(__auth_query_data)==-1)
-	trace(TRACE_ERROR, "auth_validate(): could not update user login time");
+	trace(TRACE_ERROR, "auth_md5_validate(): could not update user login time");
 
       return useridnr;
     }
 	
-  trace(TRACE_MESSAGE,"auth_md5_validate(): user [%s] could not be validated",username);
+  trace(TRACE_MESSAGE,"auth_md5_validate(): user [%s] could not be validated",user);
 
   if (__auth_res)
     PQclear(__auth_res);
   
-  
   my_free(checkstring);
   
   return 0;
diff -ruN dbmail-20031108-omit-frame-pointer/sql/mysql/add_usermap.mysql dbmail-20031108-usermap/sql/mysql/add_usermap.mysql
--- dbmail-20031108-omit-frame-pointer/sql/mysql/add_usermap.mysql	1969-12-31 17:00:00.000000000 -0700
+++ dbmail-20031108-usermap/sql/mysql/add_usermap.mysql	2003-11-08 08:42:30.000000000 -0700
@@ -0,0 +1,8 @@
+
+CREATE TABLE usermap(
+  user_idnr INT8 REFERENCES users
+      ON UPDATE CASCADE ON DELETE CASCADE,
+  userid VARCHAR(100)
+);
+CREATE INDEX ndx_usermap_userid ON usermap(userid);
+
diff -ruN dbmail-20031108-omit-frame-pointer/sql/mysql/create_tables.mysql dbmail-20031108-usermap/sql/mysql/create_tables.mysql
--- dbmail-20031108-omit-frame-pointer/sql/mysql/create_tables.mysql	2003-03-17 09:04:09.000000000 -0700
+++ dbmail-20031108-usermap/sql/mysql/create_tables.mysql	2003-11-08 08:42:30.000000000 -0700
@@ -128,3 +128,11 @@
        KEY msg_index (message_idnr),
        UNIQUE messageblk_idnr_2 (messageblk_idnr)
 ) TYPE=MyISAM;
+
+CREATE TABLE usermap(
+  user_idnr INT8 REFERENCES users
+    ON UPDATE CASCADE ON DELETE CASCADE,
+  userid VARCHAR(100)
+) TYPE=MyISAM;
+CREATE INDEX ndx_usermap_userid ON usermap(userid);
+
diff -ruN dbmail-20031108-omit-frame-pointer/sql/mysql/create_tables_innoDB.mysql dbmail-20031108-usermap/sql/mysql/create_tables_innoDB.mysql
--- dbmail-20031108-omit-frame-pointer/sql/mysql/create_tables_innoDB.mysql	2003-03-17 09:04:09.000000000 -0700
+++ dbmail-20031108-usermap/sql/mysql/create_tables_innoDB.mysql	2003-11-08 08:42:30.000000000 -0700
@@ -106,3 +106,11 @@
        KEY msg_index (message_idnr),
        UNIQUE messageblk_idnr_2 (messageblk_idnr)
 ) TYPE = InnoDB;
+
+CREATE TABLE usermap(
+  user_idnr INT8 REFERENCES users
+    ON UPDATE CASCADE ON DELETE CASCADE,
+  userid VARCHAR(100)
+) TYPE = InnoDB;
+CREATE INDEX ndx_usermap_userid ON usermap(userid);
+
diff -ruN dbmail-20031108-omit-frame-pointer/sql/postgresql/add_usermap.pgsql dbmail-20031108-usermap/sql/postgresql/add_usermap.pgsql
--- dbmail-20031108-omit-frame-pointer/sql/postgresql/add_usermap.pgsql	1969-12-31 17:00:00.000000000 -0700
+++ dbmail-20031108-usermap/sql/postgresql/add_usermap.pgsql	2003-11-08 08:42:30.000000000 -0700
@@ -0,0 +1,8 @@
+
+CREATE TABLE usermap(
+  user_idnr INT8 REFERENCES users
+      ON UPDATE CASCADE ON DELETE CASCADE,
+  userid VARCHAR(100)
+);
+CREATE INDEX ndx_usermap_userid ON usermap(userid);
+
diff -ruN dbmail-20031108-omit-frame-pointer/sql/postgresql/create_tables.pgsql dbmail-20031108-usermap/sql/postgresql/create_tables.pgsql
--- dbmail-20031108-omit-frame-pointer/sql/postgresql/create_tables.pgsql	2003-10-15 03:56:13.000000000 -0600
+++ dbmail-20031108-usermap/sql/postgresql/create_tables.pgsql	2003-11-08 08:42:30.000000000 -0700
@@ -113,3 +113,10 @@
 	value VARCHAR(255) NOT NULL
 );
 
+CREATE TABLE usermap(
+  user_idnr INT8 REFERENCES users
+      ON UPDATE CASCADE ON DELETE CASCADE,
+  userid VARCHAR(100)
+);
+CREATE INDEX ndx_usermap_userid ON usermap(userid);
+
