diff --git a/modules/webmessage/lib/webmessage_dblayer.py b/modules/webmessage/lib/webmessage_dblayer.py
index cd8702768..8466b79f6 100644
--- a/modules/webmessage/lib/webmessage_dblayer.py
+++ b/modules/webmessage/lib/webmessage_dblayer.py
@@ -1,596 +1,625 @@
 # -*- coding: utf-8 -*-
 ##
 ## $Id$
 ##
 ## This file is part of CDS Invenio.
 ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 CERN.
 ##
 ## CDS Invenio is free software; you can redistribute it and/or
 ## modify it under the terms of the GNU General Public License as
 ## published by the Free Software Foundation; either version 2 of the
 ## License, or (at your option) any later version.
 ##
 ## CDS Invenio is distributed in the hope that it will be useful, but
 ## WITHOUT ANY WARRANTY; without even the implied warranty of
 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 ## General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with CDS Invenio; if not, write to the Free Software Foundation, Inc.,
 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 
 """Every db-related function of module webmessage"""
 
 __revision__ = "$Id$"
 
 from time import localtime, mktime
 
 
 from invenio.config import \
      CFG_WEBMESSAGE_MAX_NB_OF_MESSAGES, \
      CFG_WEBMESSAGE_DAYS_BEFORE_DELETE_ORPHANS
 from invenio.dbquery import run_sql
 from invenio.webmessage_config import CFG_WEBMESSAGE_STATUS_CODE, \
                                       CFG_WEBMESSAGE_ROLES_WITHOUT_QUOTA
 from invenio.dateutils import datetext_default, \
                               convert_datestruct_to_datetext
 from invenio.webuser import list_users_in_roles
 from invenio.webbasket_dblayer import get_groups_user_member_of
 from invenio.websession_config import CFG_WEBSESSION_USERGROUP_STATUS
 
 def check_user_owns_message(uid, msgid):
     """
     Checks whether a user owns a message
     @param uid:   user id
     @param msgid: message id
     @return 1 if the user owns the message, else 0
     """
     query  = """SELECT count(*)
                 FROM   user_msgMESSAGE
                 WHERE id_user_to=%s AND
                       id_msgMESSAGE=%s"""
     params = (uid, msgid)
     res = run_sql(query, params)
     return int(res[0][0])
 
 def get_message(uid, msgid):
     """
     get a message with its status
     @param uid: user id
     @param msgid: message id
     @return a (message_id,
                id_user_from,
                nickname_user_from,
                sent_to_user_nicks,
                sent_to_group_names,
                subject,
                body,
                sent_date,
                received_date,
                status)
      formed tuple or 0 (ZERO) if none found
     """
     query = """SELECT m.id,
                       m.id_user_from,
                       u.nickname,
                       m.sent_to_user_nicks,
                       m.sent_to_group_names,
                       m.subject,
                       m.body,
                       DATE_FORMAT(m.sent_date, '%%Y-%%m-%%d %%H:%%i:%%s'),
                       DATE_FORMAT(m.received_date, '%%Y-%%m-%%d %%H:%%i:%%s'),
                       um.status
                FROM   msgMESSAGE m,
                       user_msgMESSAGE um,
                       user u
                WHERE  m.id=%s AND
                       um.id_msgMESSAGE=%s AND
                       um.id_user_to=%s AND
                       u.id=m.id_user_from"""
     params = (msgid, msgid, uid)
     res = run_sql(query, params)
     if res:
         return res[0]
     else:
         return 0
 
 def set_message_status(uid, msgid, new_status):
     """
     Change the status of a message (e.g. from "new" to "read").
     the status is a single character string, specified in constant
     CFG_WEBMESSAGE_STATUS_CODE in file webmessage_config.py
     examples:
         N: New message
         R: alreay Read message
         M: reminder
     @param uid:        user ID
     @param msgid:      Message ID
     @param new_status: new status. Should be a single character
     @return 1 if succes, 0 if not
     """
 
     return int(run_sql("""UPDATE user_msgMESSAGE
                              SET    status=%s
                            WHERE  id_user_to=%s AND
                                   id_msgMESSAGE=%s""",
                        (new_status, uid, msgid)))
 
 def get_nb_new_messages_for_user(uid):
     """ Get number of new mails for a given user
     @param uid: user id (int)
     @return number of new mails as int.
     """
     update_user_inbox_for_reminders(uid)
     new_status = CFG_WEBMESSAGE_STATUS_CODE['NEW']
     res = run_sql("""SELECT count(id_msgMESSAGE)
                        FROM user_msgMESSAGE
                       WHERE id_user_to=%s AND
                        BINARY status=%s""",
                   (uid, new_status))
     if res:
         return res[0][0]
     return 0
 
 def get_nb_readable_messages_for_user(uid):
     """ Get number of mails of a fiven user. Reminders are not counted
     @param uid: user id (int)
     @return number of messages (int)
     """
     reminder_status = CFG_WEBMESSAGE_STATUS_CODE['REMINDER']
     query = """SELECT count(id_msgMESSAGE)
                FROM user_msgMESSAGE
                WHERE id_user_to=%s AND
                      BINARY status!=%s"""
     params = (uid, reminder_status)
     res = run_sql(query, params)
     if res:
         return res[0][0]
     return 0
 
 
 def get_all_messages_for_user(uid):
     """
     Get all messages for a user's inbox, without the eventual
     non-expired reminders.
 
     @param uid: user id
     @return [(message_id,
               id_user_from,
               nickname_user_from,
               message_subject,
               message_sent_date,
               message_status)]
     """
     update_user_inbox_for_reminders(uid)
     reminder_status = CFG_WEBMESSAGE_STATUS_CODE['REMINDER']
     return run_sql("""SELECT  m.id,
                        m.id_user_from,
                        u.nickname,
                        m.subject,
                        DATE_FORMAT(m.sent_date, '%%Y-%%m-%%d %%H:%%i:%%s'),
                        um.status
                 FROM   user_msgMESSAGE um,
                        msgMESSAGE m,
                        user u
                 WHERE  um.id_user_to = %s AND
                        !(BINARY um.status=%s) AND
                        um.id_msgMESSAGE=m.id AND
                        u.id=m.id_user_from
                 ORDER BY m.sent_date DESC
                 """, (uid, reminder_status))
 
 def count_nb_messages(uid):
     """
     @param uid: user id
     @return integer of number of messages a user has, 0 if none
     """
     uid = int(uid)
     query = """SELECT count(id_user_to)
                FROM   user_msgMESSAGE
                WHERE  id_user_to=%s
             """
     res = run_sql(query, (uid, ))
     if res:
         return int(res[0][0])
     else:
         return 0
 
 def delete_message_from_user_inbox(uid, msg_id):
     """
     Delete message from users inbox
     If this message was does not exist in any other user's inbox,
     delete it permanently from the database
     @param uid: user id
     @param msg_id: message id
     @return integer 1 if delete was successful, integer 0 else
     """
     query1 = """DELETE FROM user_msgMESSAGE
                 WHERE id_user_to=%s AND
                       id_msgMESSAGE=%s"""
     params1 = (uid, msg_id)
     res1 = run_sql(query1, params1)
     check_if_need_to_delete_message_permanently([msg_id])
     return int(res1)
 
 def check_if_need_to_delete_message_permanently(msg_ids):
     """
     Checks if a list of messages exist in anyone's inbox, if not,
     delete them permanently
     @param msg_id: sequence of message ids
     @return number of deleted messages
     """
     if not((type(msg_ids) is list) or (type(msg_ids) is tuple)):
         msg_ids = [msg_ids]
     query1 = """SELECT count(id_msgMESSAGE)
                 FROM user_msgMESSAGE
                 WHERE id_msgMESSAGE=%s"""
     messages_to_delete = []
     for msg_id in msg_ids:
         nb_users = int(run_sql(query1, (msg_id,))[0][0])
         if nb_users == 0:
             messages_to_delete.append(int(msg_id))
 
     if len(messages_to_delete) > 0:
         query2 = """DELETE FROM msgMESSAGE
                     WHERE"""
         params2 = []
         for msg_id in messages_to_delete[0:-1]:
             query2 += " id=%s OR"
             params2.append(msg_id)
         query2 += " id=%s"
         params2.append(messages_to_delete[-1])
 
         run_sql(query2, tuple(params2))
     return len(messages_to_delete)
 
 def delete_all_messages(uid):
     """
     Delete all messages of a user (except reminders)
     @param uid: user id
     @return the number of messages deleted
     """
     reminder_status = CFG_WEBMESSAGE_STATUS_CODE['REMINDER']
     query1 = """SELECT id_msgMESSAGE
                FROM user_msgMESSAGE
                WHERE id_user_to=%s AND
                      NOT(BINARY status like %s)"""
     params = (uid, reminder_status)
     msg_ids = map(get_element, run_sql(query1, params))
 
     query2 = """DELETE FROM user_msgMESSAGE
                 WHERE id_user_to=%s AND
                 NOT(BINARY status like %s)"""
     nb_messages = int(run_sql(query2, params))
     check_if_need_to_delete_message_permanently(msg_ids)
     return nb_messages
 
 def get_uids_from_nicks(nicks):
     """
     Get the association uid/nickname of given nicknames
     @param nicks: list or sequence of strings, each string being a nickname
     @return a dictionary {nickname: uid}
     """
     # FIXME: test case
     if not((type(nicks) is list) or (type(nicks) is tuple)):
         nicks = [nicks]
     users = {}
     query = "SELECT nickname, id FROM user WHERE BINARY nickname IN ("
     query_params = ()
     if len(nicks)> 0:
         for nick in nicks:
             users[nick] = None
         users_keys = users.keys()
         for nick in users_keys[0:-1]:
             query += "%s,"
             query_params += (nick,)
         query += "%s)"
         query_params += (users_keys[-1],)
         res = run_sql(query, query_params)
         def enter_dict(couple):
             """ takes a a tuple and enters it into dict users """
             users[couple[0]] = int(couple[1])
         map(enter_dict, res)
     return users
 
 def get_nicks_from_uids(uids):
     """
     Get the association uid/nickname of given uids
     @param uids: list or sequence of uids
     @return a dictionary {uid: nickname} where empty value is possible
     """
     if not((type(uids) is list) or (type(uids) is tuple)):
         uids = [uids]
     users = {}
     query = "SELECT id, nickname FROM user WHERE id in("
     query_params = []
     if len(uids) > 0:
         for uid in uids:
             users[uid] = None
         for uid in users.keys()[0:-1]:
             query += "%s,"
             query_params.append(uid)
         query += "%s)"
         query_params.append(users.keys()[-1])
         res = run_sql(query, tuple(query_params))
         for (user_id, nickname) in res:
             users[int(user_id)] = nickname
     return users
 
+def get_uids_from_emails(emails):
+    """
+    Get the association uid/nickname of given nicknames
+    @param nicks: list or sequence of strings, each string being a nickname
+    @return a dictionary {nickname: uid}
+    """
+    # FIXME: test case
+    if not((type(emails) is list) or (type(emails) is tuple)):
+        emails = [emails]
+    users = {}
+    query = "SELECT email, id FROM user WHERE BINARY email IN ("
+    query_params = ()
+    if len(emails)> 0:
+        for mail in emails:
+            users[mail] = None
+        users_keys = users.keys()
+        for mail in users_keys[0:-1]:
+            query += "%s,"
+            query_params += (mail,)
+        query += "%s)"
+        query_params += (users_keys[-1],)
+        res = run_sql(query, query_params)
+        def enter_dict(couple):
+            """ takes a a tuple and enters it into dict users """
+            users[couple[0]] = int(couple[1])
+        map(enter_dict, res)
+    return users
+
+
 def get_gids_from_groupnames(groupnames):
     """
     Get the gids of given groupnames
     @param groupnames: list or sequence of strings, each string being a groupname
     @return a dictionary {groupname: gid}
     """
     # FIXME: test case
     if not((type(groupnames) is list) or (type(groupnames) is tuple)):
         groupnames = [groupnames]
     groups = {}
     query = "SELECT name, id FROM usergroup WHERE BINARY name IN ("
     query_params = ()
     if len(groupnames) > 0:
         for groupname in groupnames:
             groups[groupname] = None
             groups_keys = groups.keys()
         for groupname in groups_keys[0:-1]:
             query += "%s,"
             query_params += (groupname,)
         query += "%s)"
         query_params += (groups_keys[-1],)
         res = run_sql(query, query_params)
         def enter_dict(couple):
             """ enter a tuple into dictionary groups """
             groups[couple[0]] = int(couple[1])
         map(enter_dict, res)
     return groups
 
 def get_uids_members_of_groups(gids):
     """
     Get the distinct ids of users members of given groups.
     @param groupnames: list or sequence of group ids
     @return a list of uids.
     """
     if not((type(gids) is list) or (type(gids) is tuple)):
         gids = [gids]
     query = """SELECT DISTINCT id_user
                FROM user_usergroup
                WHERE user_status!=%s AND (
             """
     query_params = [CFG_WEBSESSION_USERGROUP_STATUS['PENDING']]
     if len(gids) > 0:
         for gid in gids[0:-1]:
             query += " id_usergroup=%s OR"
             query_params.append(gid)
         query += " id_usergroup=%s)"
         query_params.append(gids[-1])
         return map(get_element, run_sql(query, tuple(query_params)))
     return []
 
 def user_exists(uid):
     """ checks if a user exists in the system, given his uid. return 0 or 1"""
     query = "SELECT count(id) FROM user WHERE id=%s GROUP BY id"
     res = run_sql(query, (uid, ))
     if res:
         return int(res[0][0])
     return 0
 
 def create_message(uid_from,
                    users_to_str="",
                    groups_to_str="",
                    msg_subject="",
                    msg_body="",
                    msg_send_on_date=datetext_default):
     """
     Creates a message in the msgMESSAGE table. Does NOT send the message.
     This function is like a datagramPacket...
     @param uid_from: uid of the sender (int)
     @param users_to_str: a string, with nicknames separated by semicolons (';')
     @param groups_to_str: a string with groupnames separated by semicolons
     @param msg_subject: string containing the subject of the message
     @param msg_body: string containing the body of the message
     @param msg_send_on_date: date on which message must be sent. Has to be a
                              datetex format (i.e. YYYY-mm-dd HH:MM:SS)
     @return id of the created message
     """
     now = convert_datestruct_to_datetext(localtime())
     msg_id = run_sql("""INSERT INTO msgMESSAGE(id_user_from,
                                       sent_to_user_nicks,
                                       sent_to_group_names,
                                       subject,
                                       body,
                                       sent_date,
                                       received_date)
              VALUES (%s,%s,%s,%s,%s,%s,%s)""",
                      (uid_from,
                       users_to_str,
                       groups_to_str,
                       msg_subject,
                       msg_body,
                       now,
                       msg_send_on_date))
     return int(msg_id)
 
 def send_message(uids_to, msgid, status=CFG_WEBMESSAGE_STATUS_CODE['NEW']):
     """
     Send message to uids
     @param uids: sequence of user ids
     @param msg_id: id of message
     @param status: status of the message. (single char, see webmessage_config.py).
     @return a list of users having their mailbox full
     """
     if not((type(uids_to) is list) or (type(uids_to) is tuple)):
         uids_to = [uids_to]
     user_problem = []
     if len(uids_to) > 0:
         users_quotas = check_quota(CFG_WEBMESSAGE_MAX_NB_OF_MESSAGES - 1)
         query = """INSERT INTO user_msgMESSAGE (id_user_to, id_msgMESSAGE,
                     status) VALUES """
         fixed_value = ",%s,%s)"
         query_params = []
         def not_users_quotas_has_key(key):
             """ not(is key in users over  quota?)"""
             return not(users_quotas.has_key(key))
         user_ids_to = filter(not_users_quotas_has_key, uids_to)
         user_problem = filter(users_quotas.has_key, uids_to)
         if len(user_ids_to) > 0:
             for uid_to in user_ids_to[0:-1]:
                 query += "(%%s%s," % fixed_value
                 query_params += [uid_to, msgid, status]
             query += "(%%s%s" % fixed_value
             query_params += [user_ids_to[-1], msgid, status]
             run_sql(query, tuple(query_params))
     return user_problem
 
 
 def check_quota(nb_messages):
     """
     @param nb_messages: max number of messages a user can have
     @return a dictionary of users over-quota
     """
     where = ''
     no_quota_users = list_users_in_roles(CFG_WEBMESSAGE_ROLES_WITHOUT_QUOTA)
     query_params = []
     if len(no_quota_users) > 0:
         where = """WHERE """
         for uid in no_quota_users[:-1]:
             where += "id_user_to!=%s AND "
             query_params.append(uid)
         where += "id_user_to!=%s"
         query_params.append(no_quota_users[-1])
     query = """SELECT id_user_to,
                       count(id_user_to)
                FROM user_msgMESSAGE
                %s
                GROUP BY id_user_to
                HAVING count(id_user_to)>%%s"""
     query_params.append(nb_messages)
     res = run_sql(query % where, tuple(query_params))
     user_over_quota = {}
     def enter_dict(couple):
         """ enter a tuple in user_over_quota dict """
         user_over_quota[int(couple[0])] = int(couple[1])
     map(enter_dict, res)
     return user_over_quota
 
 def update_user_inbox_for_reminders(uid):
     """
     Updates user's inbox with any reminders that should have arrived
     @param uid: user id
     @return integer number of new expired reminders
     """
     now =  convert_datestruct_to_datetext(localtime())
     reminder_status = CFG_WEBMESSAGE_STATUS_CODE['REMINDER']
     new_status = CFG_WEBMESSAGE_STATUS_CODE['NEW']
     query1 = """SELECT m.id
                 FROM   msgMESSAGE m,
                        user_msgMESSAGE um
                 WHERE  um.id_user_to=%s AND
                        um.id_msgMESSAGE=m.id AND
                        m.received_date<=%s AND
                        um.status like binary %s
                 """
     params1 = (uid, now, reminder_status)
     res_ids = run_sql(query1, params1)
     out = len(res_ids)
     if (out>0):
         query2 = """UPDATE user_msgMESSAGE
                     SET    status=%s
                     WHERE  id_user_to=%s AND ("""
         query_params = [new_status, uid]
         for msg_id in res_ids[0:-1]:
             query2 += "id_msgMESSAGE=%s OR "
             query_params.append(msg_id[0])
         query2 += "id_msgMESSAGE=%s)"
         query_params.append(res_ids[-1][0])
         run_sql(query2, tuple(query_params))
     return out
 
 def get_nicknames_like(pattern):
     """get nicknames like pattern"""
     if pattern:
         res = run_sql("SELECT nickname FROM user WHERE nickname RLIKE %s", (pattern,))
         return res
     return ()
 
 def get_groupnames_like(uid, pattern):
     """Get groupnames like pattern. Will return only groups that user is allowed to see
     """
     groups = {}
     if pattern:
         # For this use case external groups are like invisible one
         query1 = "SELECT id, name FROM usergroup WHERE name RLIKE %s AND join_policy like 'V%%' AND join_policy<>'VE'"
         res = run_sql(query1, (pattern,))
         # The line belows inserts into groups dictionary every tuple the database returned,
         # assuming field0=key and field1=value
         map(lambda x: groups.setdefault(x[0], x[1]), res)
         query2 = """SELECT g.id, g.name
                     FROM usergroup g, user_usergroup ug
                     WHERE g.id=ug.id_usergroup AND ug.id_user=%s AND g.name RLIKE %s"""
         res = run_sql(query2, (uid, pattern))
         map(lambda x: groups.setdefault(x[0], x[1]), res)
     return groups
 
 def get_element(sql_res):
     """convert mySQL output
     @param x: a tuple like this: (6789L,)
     @return integer conversion of the number in tuple
     """
     return int(sql_res[0])
 
 def clean_messages():
     """ Cleans msgMESSAGE table"""
     current_time = localtime()
     seconds = mktime(current_time)
     seconds -= CFG_WEBMESSAGE_DAYS_BEFORE_DELETE_ORPHANS * 86400
     sql_date = convert_datestruct_to_datetext(localtime(seconds))
     deleted_items = 0
     #find id and email from every user who has got an email
     query1 = """SELECT distinct(umsg.id_user_to),
                        user.email
                 FROM user_msgMESSAGE umsg
                 LEFT JOIN user ON
                      umsg.id_user_to=user.id"""
     res1 = run_sql(query1)
     # if there is no email, user has disappeared
     users_deleted = map(lambda u: int(u[0]), filter(lambda x: x[1] is None, res1))
     # find ids from messages in user's inbox
     query2 = """SELECT distinct(umsg.id_msgMESSAGE),
                        msg.id
                 FROM user_msgMESSAGE umsg
                 LEFT JOIN msgMESSAGE msg ON
                      umsg.id_msgMESSAGE=msg.id"""
     res2 = run_sql(query2)
     # if there is no id, message was deleted from table msgMESSAGE...
     messages_deleted = map(lambda u: int(u[0]), filter(lambda x: x[1] is None, res2))
     def tuplize(el1, el2):
         return str(el1) + ',' + str(el2)
     if len(users_deleted) or len(messages_deleted):
         # Suppress every referential error from user_msgMESSAGE
         query3 = "DELETE FROM user_msgMESSAGE WHERE "
         query_params = []
         if len(users_deleted):
             query3 += "id_user_to IN (%s)"
             query_params.append(reduce(tuplize, users_deleted))
             if len(messages_deleted):
                 query3 += ' OR '
         if len(messages_deleted):
             query3 += "id_msgMESSAGE IN (%s)"
             query_params.append(reduce(tuplize, messages_deleted))
         deleted_items = int(run_sql(query3, tuple(query_params)))
     # find every message that is nobody's inbox
     query4 = """SELECT msg.id
                 FROM msgMESSAGE msg
                      LEFT JOIN user_msgMESSAGE umsg
                                ON msg.id=umsg.id_msgMESSAGE
                 WHERE msg.sent_date<%s
                 GROUP BY umsg.id_msgMESSAGE
                 HAVING count(umsg.id_msgMESSAGE)=0
                 """
     res4 = map(lambda x: x[0], run_sql(query4, (sql_date, )))
     if len(res4):
         # delete these messages
         query5 = "DELETE FROM msgMESSAGE WHERE "
         query5 += "id IN (%s)"
         deleted_items += int(run_sql(query5, (reduce(tuplize, res4), )))
     return deleted_items