I had some time again this past weekend to work on contiguous UIDs and
spent it on a patch (to the 2_2 branch; I’ve yet to test trunk) which
ensures that whenever dbmail does a lookup on the messages table using
message_idnr it also contrains the query by mailbox_idnr.

That is necessary to make (mailbox_idnr,message_idnr) the primary key.

I’m running with this patch now, and have had no problems with it.

I also did some testing with the schema change and IMAP at least worked
perfectly.  There was, however, a small problem with injection — once
the schema is changed querying currval('dbmail_message_idnr_seq') to
find the new messages’ uid won’t work.  Either messages still must have
a serial column or I have to come up with another way to find out what
uid the trigger assigned to the newly injected messages row.

Since only IMAP really needs the contiguous uids, I suspect the way
forward is to have both the current message_idnr column and an imap_uid
column, keep message_idnr as the primary key, add an unique constraint
on (mailbox_idnr, imap_uid) and have imapd use the imap_uid column
instead of the message_idnr column.

In any case, this patch adds the additional contraint to the queries
which didn’t already have it — some already did — but doesn’t otherwise
change the behavior as seen by users.

Also, I only use smtp and imapd, so only those are actually tested.

-JimC

diff --git a/check_dbmail_misc.c b/check_dbmail_misc.c
index 2682170..3e80b38 100644
--- a/check_dbmail_misc.c
+++ b/check_dbmail_misc.c
@@ -229,8 +229,8 @@ START_TEST(test_create_unique_id)
 {
 	char *a = g_new0(char, 64);
 	char *b = g_new0(char, 64);
-	create_unique_id(a,0);
-	create_unique_id(b,0);
+	create_unique_id(a,0,0);
+	create_unique_id(b,0,0);
 	fail_unless(strlen(a)==32, "create_unique_id produced incorrect string length [%s]", a);
 	fail_unless(strlen(b)==32, "create_unique_id produced incorrect string length [%s]", b);
 	fail_unless(!MATCH(a,b),"create_unique_id shouldn't produce identical output");
diff --git a/db.c b/db.c
index e32f629..786b356 100644
--- a/db.c
+++ b/db.c
@@ -325,7 +325,7 @@ int db_rollback_savepoint_transaction(const char* name)
 	return DM_SUCCESS;
 }
 
-int db_get_physmessage_id(u64_t message_idnr, u64_t * physmessage_id)
+int db_get_physmessage_id(u64_t mailbox_idnr, u64_t message_idnr, u64_t * physmessage_id)
 {
 	char query[DEF_QUERYSIZE]; 
 	memset(query,0,DEF_QUERYSIZE);
@@ -335,7 +335,7 @@ int db_get_physmessage_id(u64_t message_idnr, u64_t * physmessage_id)
 
 	snprintf(query, DEF_QUERYSIZE,
 		 "SELECT physmessage_id FROM %smessages "
-		 "WHERE message_idnr = %llu", DBPFX, message_idnr);
+		 "WHERE mailbox_idnr = %llu AND message_idnr = %llu", DBPFX, mailbox_idnr, message_idnr);
 
 	if (db_query(query) == -1) {
 		TRACE(TRACE_ERROR, "error getting physmessage_id");
@@ -1052,6 +1052,7 @@ int db_get_reply_body(u64_t user_idnr, char **reply_body)
 	return DM_SUCCESS;
 }
 
+/* Cannot really have this w/ per-mailbox uids.... */
 u64_t db_get_mailbox_from_message(u64_t message_idnr)
 {
 	u64_t mailbox_idnr;
@@ -1079,7 +1080,7 @@ u64_t db_get_mailbox_from_message(u64_t message_idnr)
 	return mailbox_idnr;
 }
 
-u64_t db_get_useridnr(u64_t message_idnr)
+u64_t db_get_useridnr(u64_t mailbox_idnr, u64_t message_idnr)
 {
 	const char *query_result;
 	u64_t user_idnr;
@@ -1090,8 +1091,9 @@ u64_t db_get_useridnr(u64_t message_idnr)
 	snprintf(query, DEF_QUERYSIZE,
 		 "SELECT %smailboxes.owner_idnr FROM %smailboxes, %smessages "
 		 "WHERE %smailboxes.mailbox_idnr = %smessages.mailbox_idnr "
+		 "AND %smessages.mailbox_idnr = %llu "
 		 "AND %smessages.message_idnr = %llu", DBPFX,DBPFX,DBPFX,
-		DBPFX,DBPFX,DBPFX,message_idnr);
+		 DBPFX,DBPFX,DBPFX,mailbox_idnr,DBPFX,message_idnr);
 	if (db_query(query) == -1) {
 		/* query failed */
 		TRACE(TRACE_ERROR, "query failed" );
@@ -1147,7 +1149,7 @@ int db_insert_physmessage(u64_t * physmessage_id)
 	return db_insert_physmessage_with_internal_date(NULL, physmessage_id);
 }
 
-int db_message_set_unique_id(u64_t message_idnr, const char *unique_id)
+int db_message_set_unique_id(u64_t mailbox_idnr, u64_t message_idnr, const char *unique_id)
 {
 	char query[DEF_QUERYSIZE]; 
 	memset(query,0,DEF_QUERYSIZE);
@@ -1156,11 +1158,11 @@ int db_message_set_unique_id(u64_t message_idnr, const char *unique_id)
 	
 	snprintf(query, DEF_QUERYSIZE,
 		 "UPDATE %smessages SET unique_id = '%s', status = %d "
-		 "WHERE message_idnr = %llu", DBPFX, unique_id, MESSAGE_STATUS_NEW,
-		 message_idnr);
+		 "WHERE mailbox_idnr = %llu AND message_idnr = %llu", DBPFX,
+		 unique_id, MESSAGE_STATUS_NEW, mailbox_idnr, message_idnr);
 	if (db_query(query) == DM_EQUERY) {
-		TRACE(TRACE_ERROR, "setting unique id for message [%llu] failed",
-		      message_idnr);
+		TRACE(TRACE_ERROR, "setting unique id for mailbox [%llu] message [%llu] failed",
+		      mailbox_idnr, message_idnr);
 		return DM_EQUERY;
 	}
 	return DM_SUCCESS;
@@ -1186,27 +1188,27 @@ int db_physmessage_set_sizes(u64_t physmessage_id, u64_t message_size,
 	return DM_SUCCESS;
 }
 
-int db_update_message(u64_t message_idnr, const char *unique_id,
+int db_update_message(u64_t mailbox_idnr, u64_t message_idnr, const char *unique_id,
 		      u64_t message_size, u64_t rfc_size)
 {
 	assert(unique_id);
 	u64_t physmessage_id = 0;
 
-	if (db_message_set_unique_id(message_idnr, unique_id))
+	if (db_message_set_unique_id(mailbox_idnr, message_idnr, unique_id))
 		return DM_EQUERY;
 
 	/* update the fields in the physmessage table */
-	if (db_get_physmessage_id(message_idnr, &physmessage_id)) 
+	if (db_get_physmessage_id(mailbox_idnr, message_idnr, &physmessage_id)) 
 		return DM_EQUERY;
 
 	if (db_physmessage_set_sizes(physmessage_id, message_size, rfc_size)) 
 		return DM_EQUERY;
 
-	if (user_quotum_inc(db_get_useridnr(message_idnr), message_size)) {
+	if (user_quotum_inc(db_get_useridnr(mailbox_idnr, message_idnr), message_size)) {
 		TRACE(TRACE_ERROR, "error calculating quotum "
 		      "used for user [%llu]. Database might be "
 		      "inconsistent. Run dbmail-util.",
-		      db_get_useridnr(message_idnr));
+		      db_get_useridnr(mailbox_idnr, message_idnr));
 		return DM_EQUERY;
 	}
 	return DM_SUCCESS;
@@ -1263,7 +1265,7 @@ int db_insert_message_block_physmessage(const char *block,
 }
 
 int db_insert_message_block(const char *block, u64_t block_size,
-			    u64_t message_idnr, u64_t * messageblk_idnr, unsigned is_header)
+			    u64_t mailbox_idnr, u64_t message_idnr, u64_t * messageblk_idnr, unsigned is_header)
 {
 	u64_t physmessage_id;
 
@@ -1274,7 +1276,7 @@ int db_insert_message_block(const char *block, u64_t block_size,
 		return DM_EQUERY;
 	}
 
-	if (db_get_physmessage_id(message_idnr, &physmessage_id) == DM_EQUERY) {
+	if (db_get_physmessage_id(mailbox_idnr, message_idnr, &physmessage_id) == DM_EQUERY) {
 		TRACE(TRACE_ERROR, "error getting physmessage_id");
 		return DM_EQUERY;
 	}
@@ -1565,7 +1567,7 @@ int db_icheck_physmessages(gboolean cleanup)
 
 int db_icheck_messages(struct dm_list *lost_list)
 {
-	u64_t message_idnr;
+	static box_uid_t box_uid = { .mailbox = 0, .uid = 0 };
 	int i, n;
 	char query[DEF_QUERYSIZE]; 
 	memset(query,0,DEF_QUERYSIZE);
@@ -1574,7 +1576,7 @@ int db_icheck_messages(struct dm_list *lost_list)
 	dm_list_init(lost_list);
 
 	snprintf(query, DEF_QUERYSIZE,
-		 "SELECT msg.message_idnr FROM %smessages msg "
+		 "SELECT msg.mailbox_idnr, msg.message_idnr FROM %smessages msg "
 		 "LEFT JOIN %smailboxes mbx ON "
 		 "msg.mailbox_idnr=mbx.mailbox_idnr "
 		 "WHERE mbx.mailbox_idnr IS NULL",DBPFX,DBPFX);
@@ -1592,11 +1594,14 @@ int db_icheck_messages(struct dm_list *lost_list)
 	}
 
 	for (i = 0; i < n; i++) {
-		if (!(message_idnr = db_get_result_u64(i, 0)))
+		if (!(box_uid.mailbox = db_get_result_u64(i, 0)))
 			continue;
 
-		TRACE(TRACE_INFO, "found lost message id [%llu]", message_idnr);
-		if (!dm_list_nodeadd(lost_list, &message_idnr, sizeof(u64_t))) {
+		if (!(box_uid.uid = db_get_result_u64(i, 1)))
+			continue;
+
+		TRACE(TRACE_INFO, "found lost message id [%llu/%llu]", box_uid.mailbox, box_uid.uid);
+		if (!dm_list_nodeadd(lost_list, &box_uid, sizeof(box_uid_t))) {
 			TRACE(TRACE_ERROR, "could not add message to list");
 			dm_list_free(&lost_list->start);
 			db_free_result();
@@ -1699,7 +1704,7 @@ int db_icheck_null_physmessages(struct dm_list *lost_list)
 
 int db_icheck_null_messages(struct dm_list *lost_list)
 {
-	u64_t message_idnr;
+	static box_uid_t box_uid = { .mailbox = 0, .uid = 0 };
 	int i, n;
 	char query[DEF_QUERYSIZE]; 
 	memset(query,0,DEF_QUERYSIZE);
@@ -1708,7 +1713,7 @@ int db_icheck_null_messages(struct dm_list *lost_list)
 	dm_list_init(lost_list);
 
 	snprintf(query, DEF_QUERYSIZE,
-		 "SELECT msg.message_idnr FROM %smessages msg "
+		 "SELECT msg.mailbox_idnr, msg.message_idnr FROM %smessages msg "
 		 "LEFT JOIN %sphysmessage pm ON "
 		 "msg.physmessage_id = pm.id WHERE pm.id is NULL",DBPFX,DBPFX);
 
@@ -1725,11 +1730,14 @@ int db_icheck_null_messages(struct dm_list *lost_list)
 	}
 
 	for (i = 0; i < n; i++) {
-		if (!(message_idnr = db_get_result_u64(i, 0)))
+		if (!(box_uid.mailbox = db_get_result_u64(i, 0)))
+			continue;
+
+		if (!(box_uid.uid = db_get_result_u64(i, 1)))
 			continue;
 
-		TRACE(TRACE_INFO, "found empty message id [%llu]", message_idnr);
-		if (!dm_list_nodeadd(lost_list, &message_idnr, sizeof(u64_t))) {
+		TRACE(TRACE_INFO, "found empty mailbox id [ %llu] message id [%llu]", box_uid.mailbox, box_uid.uid);
+		if (!dm_list_nodeadd(lost_list, &box_uid, sizeof(box_uid_t))) {
 			TRACE(TRACE_ERROR, "could not add message to list");
 			dm_list_free(&lost_list->start);
 			db_free_result();
@@ -2011,13 +2019,13 @@ int db_icheck_envelope(GList **lost)
 }
 
 
-int db_set_message_status(u64_t message_idnr, MessageStatus_t status)
+int db_set_message_status(u64_t mailbox_idnr, u64_t message_idnr, MessageStatus_t status)
 {
 	char query[DEF_QUERYSIZE]; 
 	memset(query,0,DEF_QUERYSIZE);
 
-	snprintf(query, DEF_QUERYSIZE, "UPDATE %smessages SET status = %d WHERE message_idnr = %llu",
-		DBPFX, status, message_idnr);
+	snprintf(query, DEF_QUERYSIZE, "UPDATE %smessages SET status = %d WHERE mailbox_idnr = %llu AND message_idnr = %llu",
+		DBPFX, status, mailbox_idnr, message_idnr);
 	return db_query(query);
 }
 
@@ -2057,7 +2065,7 @@ int db_delete_physmessage(u64_t physmessage_id)
 	return DM_EGENERAL;
 }
 
-int db_delete_message(u64_t message_idnr)
+int db_delete_message(u64_t mailbox_idnr, u64_t message_idnr)
 {
 	u64_t physmessage_id;
 	int rows;
@@ -2065,25 +2073,25 @@ int db_delete_message(u64_t message_idnr)
 	memset(query,0,DEF_QUERYSIZE);
 
 
-	if (db_get_physmessage_id(message_idnr, &physmessage_id) == DM_EQUERY)
+	if (db_get_physmessage_id(mailbox_idnr, message_idnr, &physmessage_id) == DM_EQUERY)
 		return DM_EQUERY;
 
 	/* now delete the message from the message table */
 	snprintf(query, DEF_QUERYSIZE, "DELETE FROM %smessages "
-			"WHERE message_idnr = %llu",
-			DBPFX, message_idnr);
+			"WHERE mailbox_idnr = %llu AND message_idnr = %llu",
+			DBPFX, mailbox_idnr, message_idnr);
 	
 	if (db_query(query) == DM_EQUERY) {
-		TRACE(TRACE_ERROR,"error deleting message [%llu]", message_idnr);
+		TRACE(TRACE_ERROR,"error deleting mailbox [%llu] message [%llu]", mailbox_idnr, message_idnr);
 		return DM_EQUERY;
 	}
 
 	/* find other messages pointing to the same physmessage entry */
-	snprintf(query, DEF_QUERYSIZE, "SELECT message_idnr FROM %smessages "
+	snprintf(query, DEF_QUERYSIZE, "SELECT mailbox_idnr, message_idnr FROM %smessages "
 			"WHERE physmessage_id = %llu",DBPFX, physmessage_id);
 	
 	if (db_query(query) == -1) {
-		TRACE(TRACE_ERROR, "error finding physmessage for message [%llu]", message_idnr);
+		TRACE(TRACE_ERROR, "error finding physmessage for mailbox [%llu] message [%llu]", mailbox_idnr, message_idnr);
 		return DM_EQUERY;
 	}
 	
@@ -2148,7 +2156,7 @@ static int mailbox_empty(u64_t mailbox_idnr)
 	db_free_result();
 	/* delete every message in the mailbox */
 	for (i = 0; i < n; i++) {
-		if (db_delete_message(message_idnrs[i]) == -1) {
+		if (db_delete_message(mailbox_idnr, message_idnrs[i]) == -1) {
 			g_free(message_idnrs);
 			return DM_EQUERY;
 		}
@@ -2208,7 +2216,7 @@ int db_delete_mailbox(u64_t mailbox_idnr, int only_empty,
 	return DM_SUCCESS;
 }
 
-int db_send_message_lines(void *fstream, u64_t message_idnr, long lines, int no_end_dot)
+int db_send_message_lines(void *fstream, u64_t mailbox_idnr, u64_t message_idnr, long lines, int no_end_dot)
 {
 	struct DbmailMessage *msg;
 	
@@ -2221,7 +2229,7 @@ int db_send_message_lines(void *fstream, u64_t message_idnr, long lines, int no_
 	TRACE(TRACE_DEBUG, "request for [%ld] lines", lines);
 
 	/* first find the physmessage_id */
-	if (db_get_physmessage_id(message_idnr, &physmessage_id) != DM_SUCCESS)
+	if (db_get_physmessage_id(mailbox_idnr, message_idnr, &physmessage_id) != DM_SUCCESS)
 		return DM_EGENERAL;
 
 	TRACE(TRACE_DEBUG, "sending [%ld] lines from message [%llu]",
@@ -2285,6 +2293,8 @@ int db_createsession(u64_t user_idnr, PopSession_t * session_ptr)
 
 	g_return_val_if_fail(mailbox_idnr > 0, DM_EQUERY);
 
+	session_ptr->mailbox_idnr = mailbox_idnr;
+
 	/* query is < MESSAGE_STATUS_DELETE  because we don't want deleted 
 	 * messages
 	 */
@@ -2385,14 +2395,19 @@ int db_update_pop(PopSession_t * session_ptr)
 				user_idnr =
 				    db_get_useridnr(((struct message *)
 						     tmpelement->data)->
+						    mailbox,
+						    ((struct message *)
+						     tmpelement->data)->
 						    realmessageid);
 
 			/* yes they need an update, do the query */
 			snprintf(query, DEF_QUERYSIZE,
 				 "UPDATE %smessages set status=%d WHERE "
-				 "message_idnr=%llu AND status < %d",DBPFX,
+				 "mailbox_idnr=%llu AND message_idnr=%llu AND status < %d",DBPFX,
 				 ((struct message *)
 				  tmpelement->data)->virtual_messagestatus,
+				 ((struct message *)
+				  tmpelement->data)->mailbox,
 				 ((struct message *) tmpelement->data)->
 				 realmessageid, MESSAGE_STATUS_DELETE);
 
@@ -2462,6 +2477,7 @@ int db_deleted_purge(u64_t * affected_rows)
 	char query[DEF_QUERYSIZE]; 
 	memset(query,0,DEF_QUERYSIZE);
 
+	u64_t *mailbox_idnrs;
 	u64_t *message_idnrs;
 
 	assert(affected_rows != NULL);
@@ -2469,12 +2485,12 @@ int db_deleted_purge(u64_t * affected_rows)
 
 	/* first we're deleting all the messageblks */
 	snprintf(query, DEF_QUERYSIZE,
-		 "SELECT message_idnr FROM %smessages WHERE status=%d",DBPFX,
+		 "SELECT mailbox_idnr, message_idnr FROM %smessages WHERE status=%d",DBPFX,
 		 MESSAGE_STATUS_PURGE);
 	TRACE(TRACE_DEBUG, "executing query [%s]", query);
 
 	if (db_query(query) == -1) {
-		TRACE(TRACE_ERROR, "Cound not fetch message ID numbers");
+		TRACE(TRACE_ERROR, "Cound not fetch mailbox/message ID number tuples");
 		return DM_EQUERY;
 	}
 
@@ -2485,21 +2501,26 @@ int db_deleted_purge(u64_t * affected_rows)
 		return DM_SUCCESS;
 	}
 
+	mailbox_idnrs = g_new0(u64_t, *affected_rows);
 	message_idnrs = g_new0(u64_t, *affected_rows);
 	
 	/* delete each message */
-	for (i = 0; i < *affected_rows; i++)
-		message_idnrs[i] = db_get_result_u64(i, 0);
-	
+	for (i = 0; i < *affected_rows; i++) {
+		mailbox_idnrs[i] = db_get_result_u64(i, 0);
+		message_idnrs[i] = db_get_result_u64(i, 1);
+	}
+
 	db_free_result();
 	for (i = 0; i < *affected_rows; i++) {
-		if (db_delete_message(message_idnrs[i]) == -1) {
-			TRACE(TRACE_ERROR, "error deleting message");
+	    if (db_delete_message(mailbox_idnrs[i], message_idnrs[i]) == -1) {
+			TRACE(TRACE_ERROR, "error deleting mailbox [%llu] message [%llu]",
+				mailbox_idnrs[i], message_idnrs[i]);
 			g_free(message_idnrs);
 			return DM_EQUERY;
 		}
 	}
 	g_free(message_idnrs);
+	g_free(mailbox_idnrs);
 	
 	return DM_EGENERAL;
 }
@@ -2558,8 +2579,8 @@ int db_imap_append_msg(const char *msgdata, u64_t datalen UNUSED,
 	}
 
         dbmail_message_store(message);
-	result = db_copymsg(message->id, mailbox_idnr, user_idnr, msg_idnr);
-	db_delete_message(message->id);
+	result = db_copymsg(message->mailbox, message->id, mailbox_idnr, user_idnr, msg_idnr);
+	db_delete_message(mailbox_idnr, message->id);
         dbmail_message_free(message);
 	
         switch (result) {
@@ -2580,7 +2601,7 @@ int db_imap_append_msg(const char *msgdata, u64_t datalen UNUSED,
 	
         TRACE(TRACE_MESSAGE, "message id=%llu is inserted", *msg_idnr);
         
-        return db_set_message_status(*msg_idnr, MESSAGE_STATUS_SEEN);
+        return db_set_message_status(mailbox_idnr, *msg_idnr, MESSAGE_STATUS_SEEN);
 }
 
 int db_findmailbox(const char *fq_name, u64_t owner_idnr, u64_t * mailbox_idnr)
@@ -3767,7 +3788,7 @@ int db_mailbox_has_message_id(u64_t mailbox_idnr, const char *messageid)
 }
 
 
-static u64_t message_get_size(u64_t message_idnr)
+static u64_t message_get_size(u64_t mailbox_idnr, u64_t message_idnr)
 {
 	u64_t size = 0;
 	char query[DEF_QUERYSIZE]; 
@@ -3777,7 +3798,7 @@ static u64_t message_get_size(u64_t message_idnr)
 	snprintf(query, DEF_QUERYSIZE,
 		 "SELECT pm.messagesize FROM %sphysmessage pm, %smessages msg "
 		 "WHERE pm.id = msg.physmessage_id "
-		 "AND message_idnr = %llu",DBPFX,DBPFX, message_idnr);
+		 "AND mailbox_idnr = %llu AND message_idnr = %llu",DBPFX,DBPFX, mailbox_idnr, message_idnr);
 
 	if (db_query(query))
 		return size; /* err */
@@ -3789,8 +3810,8 @@ static u64_t message_get_size(u64_t message_idnr)
 	return size;
 }
 
-int db_copymsg(u64_t msg_idnr, u64_t mailbox_to, u64_t user_idnr,
-	       u64_t * newmsg_idnr)
+int db_copymsg(u64_t mailbox_from, u64_t msg_idnr, u64_t mailbox_to,
+	       u64_t user_idnr, u64_t * newmsg_idnr)
 {
 	u64_t msgsize;
 	char unique_id[UID_SIZE];
@@ -3799,9 +3820,9 @@ int db_copymsg(u64_t msg_idnr, u64_t mailbox_to, u64_t user_idnr,
 
 
 	/* Get the size of the message to be copied. */
-	if (! (msgsize = message_get_size(msg_idnr))) {
+	if (! (msgsize = message_get_size(mailbox_from, msg_idnr))) {
 		TRACE(TRACE_ERROR, "error getting message size for "
-		      "message [%llu]", msg_idnr);
+		      "mailbox [%llu] message [%llu]", mailbox_from, msg_idnr);
 		return DM_EQUERY;
 	}
 
@@ -3816,7 +3837,7 @@ int db_copymsg(u64_t msg_idnr, u64_t mailbox_to, u64_t user_idnr,
 		return -2;
 	}
 
-	create_unique_id(unique_id, msg_idnr);
+	create_unique_id(unique_id, mailbox_to, msg_idnr);
 
 	/* Copy the message table entry of the message. */
 	snprintf(query, DEF_QUERYSIZE,
@@ -3826,8 +3847,8 @@ int db_copymsg(u64_t msg_idnr, u64_t mailbox_to, u64_t user_idnr,
 		 "SELECT %llu, "
 		 "physmessage_id, seen_flag, answered_flag, deleted_flag, "
 		 "flagged_flag, recent_flag, draft_flag, '%s', status "
-		 "FROM %smessages WHERE message_idnr = %llu",DBPFX,
-		 mailbox_to, unique_id,DBPFX, msg_idnr);
+		 "FROM %smessages WHERE mailbox_idnr = %llu AND message_idnr = %llu",
+		 DBPFX, mailbox_to, unique_id, DBPFX, mailbox_from, msg_idnr);
 
 	if (db_query(query) == -1) {
 		TRACE(TRACE_ERROR, "error copying message");
diff --git a/db.h b/db.h
index b5fdd6d..ea31c49 100644
--- a/db.h
+++ b/db.h
@@ -302,18 +302,19 @@ int db_rollback_savepoint_transaction(const char*);
 
 /* shared implementattion from hereon */
 /**
- * \brief get the physmessage_id from a message_idnr
+ * \brief get the physmessage_id from a mailbox_idnr, message_idnr tuple
+ * \param mailbox_idnr
  * \param message_idnr
  * \param physmessage_id will hold physmessage_id on return. Must hold a valid
  * pointer on call.
  * \return 
  *     - -1 on error
  *     -  0 if a physmessage_id was found
- *     -  1 if no message with this message_idnr found
+ *     -  1 if no message with this mailbox_idnr, message_idnr tuple was found
  * \attention function will fail and halt program if physmessage_id is
  * NULL on call.
  */
-int db_get_physmessage_id(u64_t message_idnr, /[EMAIL PROTECTED]@*/ u64_t * physmessage_id);
+int db_get_physmessage_id(u64_t mailbox_idnr, u64_t message_idnr, /[EMAIL PROTECTED]@*/ u64_t * physmessage_id);
 
 /**
  * \brief return number of bytes used by user identified by userid
@@ -502,13 +503,14 @@ int db_get_reply_body(u64_t user_idnr, char **body);
 
 /**
  * \brief get user idnr of a message. 
+ * \param mailbox_idnr idnr of message
  * \param message_idnr idnr of message
  * \return 
  *              - -1 on failure
  * 		- 0 if message is located in a shared mailbox.
  * 		- user_idnr otherwise
  */
-u64_t db_get_useridnr(u64_t message_idnr);
+u64_t db_get_useridnr(u64_t mailbox_idnr, u64_t message_idnr);
 
 /**
  * \brief insert a new physmessage. This inserts only an new record in the
@@ -536,6 +538,7 @@ int db_insert_physmessage_with_internal_date(timestring_t internal_date,
 /**
  * \brief update unique_id, message_size and rfc_size of
  *        a message identified by message_idnr
+ * \param mailbox_idnr
  * \param message_idnr
  * \param unique_id unique id of message
  * \param message_size size of message
@@ -544,17 +547,18 @@ int db_insert_physmessage_with_internal_date(timestring_t internal_date,
  *      - -1 on database error
  *      - 0 on success
  */
-int db_update_message(u64_t message_idnr, const char *unique_id,
+int db_update_message(u64_t mailbox_idnr, u64_t message_idnr, const char *unique_id,
 		      u64_t message_size, u64_t rfc_size);
 /**
  * \brief set unique id of a message 
+ * \param mailbox_idnr
  * \param message_idnr
  * \param unique_id unique id of message
  * \return 
  *     - -1 on database error
  *     -  0 on success
  */
-int db_message_set_unique_id(u64_t message_idnr, const char *unique_id);
+int db_message_set_unique_id(u64_t mailbox_idnr, u64_t message_idnr, const char *unique_id);
 
 /**
  * \brief set messagesize and rfcsize of a message
@@ -588,6 +592,7 @@ int db_insert_message_block_physmessage(const char *block,
 * \brief insert a message block into the message block table
 * \param block the message block (which is a string)
 * \param block_size length of the block
+* \param mailbox_idnr mailbox of the message the block belongs to
 * \param message_idnr id of the message the block belongs to
 * \param messageblock_idnr will hold id of messageblock after call. Should
 * be a valid pointer on call.
@@ -596,6 +601,7 @@ int db_insert_message_block_physmessage(const char *block,
 *        - 0 otherwise
 */
 int db_insert_message_block(const char *block, u64_t block_size,
+			    u64_t mailbox_idnr, 
 			    u64_t message_idnr, 
 			    /[EMAIL PROTECTED]@*/ u64_t * messageblock_idnr,
 			    unsigned is_header);
@@ -751,11 +757,12 @@ int db_icheck_envelope(GList **lost);
 int db_set_envelope(GList *lost);
 /**
  * \brief set status of a message
+ * \param mailbox_idnr
  * \param message_idnr
  * \param status new status of message
  * \return result of db_query()
  */
-int db_set_message_status(u64_t message_idnr, MessageStatus_t status);
+int db_set_message_status(u64_t mailbox_idnr, u64_t message_idnr, MessageStatus_t status);
 
 /**
 * \brief delete a message block
@@ -774,12 +781,13 @@ int db_delete_physmessage(u64_t physmessage_id);
 
 /**
  * \brief delete a message 
+ * \param mailbox_idnr
  * \param message_idnr
  * \return 
  *     - -1 on error
  *     -  1 on success
  */
-int db_delete_message(u64_t message_idnr);
+int db_delete_message(u64_t mailbox_idnr, u64_t message_idnr);
 
 /**
  * \brief delete a mailbox. 
@@ -799,6 +807,7 @@ int db_delete_mailbox(u64_t mailbox_idnr, int only_empty,
 /**
  * \brief write lines of message to fstream. Always write full headers.
  * \param fstream the stream to write to
+ * \param mailbox_idnr mailbox of message to write
  * \param message_idnr idrn of message to write
  * \param lines number of lines to write. If <PRE>lines == -2</PRE>, then
  *              the whole message (excluding the header) is written.
@@ -810,7 +819,7 @@ int db_delete_mailbox(u64_t mailbox_idnr, int only_empty,
  * 		- 0 on failure
  * 		- 1 on success
  */
-int db_send_message_lines(void *fstream, u64_t message_idnr,
+int db_send_message_lines(void *fstream, u64_t mailbox_idnr, u64_t message_idnr,
 			  long lines, int no_end_dot);
 /**
  * \brief create a new POP3 session. (was createsession() in dbmysql.c)
@@ -1093,6 +1102,7 @@ int db_removemsg(u64_t user_idnr, u64_t mailbox_idnr);
 int db_movemsg(u64_t mailbox_to, u64_t mailbox_from);
 /**
  * \brief copy a message to a mailbox
+ * \param mailbox_from mailbox to copy from
  * \param msg_idnr
  * \param mailbox_to mailbox to copy to
  * \param user_idnr user to copy the messages for.
@@ -1101,7 +1111,7 @@ int db_movemsg(u64_t mailbox_to, u64_t mailbox_from);
  * 		- -1 on failure
  * 		- 0 on success
  */
-int db_copymsg(u64_t msg_idnr, u64_t mailbox_to,
+int db_copymsg(u64_t mailbox_from, u64_t msg_idnr, u64_t mailbox_to,
 	       u64_t user_idnr, u64_t * newmsg_idnr);
 
 /**
diff --git a/dbmail-imapsession.c b/dbmail-imapsession.c
index 3051336..6eb6943 100644
--- a/dbmail-imapsession.c
+++ b/dbmail-imapsession.c
@@ -362,7 +362,7 @@ static u64_t _imap_cache_update(struct ImapSession *self, message_filter_t filte
 			cached_msg.dmsg = NULL;
 		}
 
-		cached_msg.dmsg = db_init_fetch(self->msg_idnr, DBMAIL_MESSAGE_FILTER_FULL);
+		cached_msg.dmsg = db_init_fetch(self->mailbox->id, self->msg_idnr, DBMAIL_MESSAGE_FILTER_FULL);
 		buf = dbmail_message_to_string(cached_msg.dmsg);
 	
 		outcnt = _imap_cache_set_dump(buf,IMAP_CACHE_MEMDUMP);
@@ -2076,12 +2076,15 @@ int dbmail_imap_session_mailbox_close(struct ImapSession *self)
 	return 0;
 }
 
-static int imap_session_update_recent(GList *recent) 
+static int imap_session_update_recent(struct DbmailMailbox *mailbox, GList *recent) 
 {
 	GList *slices, *topslices;
 	char query[DEF_QUERYSIZE];
 	memset(query,0,DEF_QUERYSIZE);
 
+	if (mailbox == NULL)
+		return 0;
+
 	if (recent == NULL)
 		return 0;
 
@@ -2091,8 +2094,8 @@ static int imap_session_update_recent(GList *recent)
 	db_begin_transaction();
 	while (slices) {
 		snprintf(query, DEF_QUERYSIZE, "UPDATE %smessages SET recent_flag = 0 "
-				"WHERE message_idnr IN (%s) AND recent_flag = 1", 
-				DBPFX, (gchar *)slices->data);
+				"WHERE mailbox_idnr = %llu AND message_idnr IN (%s) AND recent_flag = 1", 
+			 DBPFX, mailbox->id, (gchar *)slices->data);
 		if (db_query(query) == -1) {
 			db_rollback_transaction();
 			return (-1);
@@ -2109,7 +2112,7 @@ static int imap_session_update_recent(GList *recent)
 
 int dbmail_imap_session_mailbox_update_recent(struct ImapSession *self) 
 {
-	imap_session_update_recent(self->recent);
+	imap_session_update_recent(self->mailbox, self->recent);
 	g_list_destroy(self->recent);
 	self->recent = NULL;
 
diff --git a/dbmail-mailbox.c b/dbmail-mailbox.c
index b22f96f..ab03456 100644
--- a/dbmail-mailbox.c
+++ b/dbmail-mailbox.c
@@ -320,10 +320,10 @@ int dbmail_mailbox_dump(struct DbmailMailbox *self, FILE *file)
 		g_string_printf(q,"SELECT is_header,messageblk,%s FROM %smessageblks b "
 				"JOIN %sphysmessage p ON b.physmessage_id = p.id "
 				"JOIN %smessages m USING (physmessage_id) "
-				"WHERE message_idnr IN (%s) "
+				"WHERE mailbox_idnr = %llu AND message_idnr IN (%s) "
 				"ORDER BY messageblk_idnr ",
 				date2char,
-				DBPFX, DBPFX, DBPFX,
+				DBPFX, DBPFX, DBPFX, self->id,
 				(char *)slice->data);
 		
 		if (db_query(q->str) == -1) {
diff --git a/dbmail-message.c b/dbmail-message.c
index f55a71b..d967a2a 100644
--- a/dbmail-message.c
+++ b/dbmail-message.c
@@ -788,7 +788,7 @@ int dbmail_message_store(struct DbmailMessage *self)
 		break;
 	}
 
-	create_unique_id(unique_id, user_idnr);
+	create_unique_id(unique_id, user_idnr, user_idnr);
 	/* create a message record */
 	if(_message_insert(self, user_idnr, DBMAIL_TEMPMBOX, unique_id) < 0)
 		return -1;
@@ -806,7 +806,7 @@ int dbmail_message_store(struct DbmailMessage *self)
 
 	hdrs = dbmail_message_hdrs_to_string(self);
 	hdrs_size = (u64_t)dbmail_message_get_hdrs_size(self, FALSE);
-	if(db_insert_message_block(hdrs, hdrs_size, self->id, &messageblk_idnr,1) < 0) {
+	if(db_insert_message_block(hdrs, hdrs_size, self->mailbox, self->id, &messageblk_idnr,1) < 0) {
 		g_free(hdrs);
 		return -1;
 	}
@@ -815,14 +815,14 @@ int dbmail_message_store(struct DbmailMessage *self)
 	/* store body in several blocks (if needed */
 	body = dbmail_message_body_to_string(self);
 	body_size = (u64_t)dbmail_message_get_body_size(self, FALSE);
-	if (store_message_in_blocks(body, body_size, self->id) < 0) {
+	if (store_message_in_blocks(body, body_size, self->mailbox, self->id) < 0) {
 		g_free(body);
 		return -1;
 	}
 	g_free(body);
 
 	rfcsize = (u64_t)dbmail_message_get_rfcsize(self);
-	if (db_update_message(self->id, unique_id, (hdrs_size + body_size), rfcsize) < 0)
+	if (db_update_message(self->mailbox, self->id, unique_id, (hdrs_size + body_size), rfcsize) < 0)
 		return -1;
 
 	/* store message headers */
@@ -885,6 +885,7 @@ int _message_insert(struct DbmailMessage *self,
 		return -1;
 	}
 
+	self->mailbox = mailboxid;
 	self->id = db_insert_result("message_idnr");
 	return 1;
 }
@@ -1360,13 +1361,13 @@ struct DbmailMessage * dbmail_message_construct(struct DbmailMessage *self,
 
 /* old stuff moved here from dbmsgbuf.c */
 
-struct DbmailMessage * db_init_fetch(u64_t msg_idnr, int filter)
+struct DbmailMessage * db_init_fetch(u64_t mailbox_idnr, u64_t msg_idnr, int filter)
 {
 	struct DbmailMessage *msg;
 
 	int result;
 	u64_t physid = 0;
-	if ((result = db_get_physmessage_id(msg_idnr, &physid)) != DM_SUCCESS)
+	if ((result = db_get_physmessage_id(mailbox_idnr, msg_idnr, &physid)) != DM_SUCCESS)
 		return NULL;
 	msg = dbmail_message_new();
 	if (! (msg = dbmail_message_retrieve(msg, physid, filter)))
diff --git a/dbmail-message.h b/dbmail-message.h
index 979c105..7240ad5 100644
--- a/dbmail-message.h
+++ b/dbmail-message.h
@@ -61,6 +61,7 @@ typedef enum DBMAIL_STREAM_TYPE {
 } dbmail_stream_t;
 
 struct DbmailMessage {
+	u64_t mailbox;
 	u64_t id;
 	u64_t physid;
 	time_t internal_date;
@@ -172,7 +173,7 @@ char * g_mime_object_get_body(const GMimeObject *object);
  *     -  1 on success
  */
 
-struct DbmailMessage * db_init_fetch(u64_t msg_idnr, int filter);
+struct DbmailMessage * db_init_fetch(u64_t mailbox_idnr, u64_t msg_idnr, int filter);
 
 #define db_init_fetch_headers(x) db_init_fetch(x,DBMAIL_MESSAGE_FILTER_HEAD)
 #define db_init_fetch_message(x) db_init_fetch(x,DBMAIL_MESSAGE_FILTER_FULL)
diff --git a/dbmailtypes.h b/dbmailtypes.h
index d26265b..9b64d97 100644
--- a/dbmailtypes.h
+++ b/dbmailtypes.h
@@ -138,6 +138,7 @@ typedef struct {
 /** all virtual_ definitions are session specific
  *  when a RSET occurs all will be set to the real values */
 struct message {
+	u64_t mailbox;	  /**< mailbox idnr */
 	u64_t msize;	  /**< message size */
 	u64_t messageid;  /**< messageid (from database) */
 	u64_t realmessageid;
@@ -183,8 +184,9 @@ typedef struct {
 	char *apop_stamp; /**< timestamp for APOP */
 
 	u64_t useridnr;	/**< Used by timsieved */
+	u64_t mailbox_idnr;
 
-	u64_t totalsize;/**< total size of messages */
+	u64_t totalsize; /**< total size of messages */
 	u64_t virtual_totalsize;
 	u64_t totalmessages; /**< number of messages */
 	u64_t virtual_totalmessages;
@@ -515,5 +517,9 @@ typedef enum {
 	IMAP_FLAG_RECENT
 } imap_flag_t;
 
+typedef struct box_uid {
+    u64_t mailbox;
+    u64_t uid;
+} box_uid_t;
 
 #endif
diff --git a/export.c b/export.c
index b81e454..e01942f 100644
--- a/export.c
+++ b/export.c
@@ -141,7 +141,7 @@ static int mailbox_dump(u64_t mailbox_idnr, const char *dumpfile,
 			// Set deleted status on each message
 			// Following this, dbmail-util -p sets purge status
 			if (delete_after_dump & 2) {
-				if (db_set_message_status(*(u64_t *)ids->data, MESSAGE_STATUS_DELETE)) {
+				if (db_set_message_status(mailbox_idnr, *(u64_t *)ids->data, MESSAGE_STATUS_DELETE)) {
 					qerrorf("Error setting status for message [%llu]\n", *(u64_t *)ids->data);
 					result = -1;
 				}
diff --git a/imapcommands.c b/imapcommands.c
index de05907..79e5cba 100644
--- a/imapcommands.c
+++ b/imapcommands.c
@@ -1692,7 +1692,7 @@ static gboolean _do_copy(u64_t *id, gpointer UNUSED value, struct ImapSession *s
 	u64_t newid;
 	int result;
 
-	result = db_copymsg(*id, cmd->mailbox_id, ud->userid, &newid);
+	result = db_copymsg(self->mailbox->id, *id, cmd->mailbox_id, ud->userid, &newid);
 	if (result == -1) {
 		dbmail_imap_session_printf(self, "* BYE internal dbase error\r\n");
 		db_rollback_transaction();
diff --git a/maintenance.c b/maintenance.c
index c3459e3..68027b6 100644
--- a/maintenance.c
+++ b/maintenance.c
@@ -461,12 +461,14 @@ int do_dangling_aliases(void)
 	return result;
 }
 
+/* FIXME: lostlist needs to be of pairs of ints rather than of ints */
+/*        figure out how to recover the individual pairs            */
 int do_null_messages(void)
 {
 	time_t start, stop;
 	struct dm_list lostlist;
 	struct element *el;
-	u64_t id;
+	u64_t mailbox, id;
 
 	if (no_to_all) {
 		qprintf("\nChecking DBMAIL for NULL messages...\n");
@@ -494,11 +496,12 @@ int do_null_messages(void)
 		if (lostlist.total_nodes > 0) {
 			el = lostlist.start;
 			while (el) {
-				id = *((u64_t *) el->data);
-				if (db_set_message_status(id, MESSAGE_STATUS_ERROR) < 0)
-					qerrorf("Warning: could not set status on message [%llu]. Check log.\n", id);
+				mailbox = ((box_uid_t *) el->data)->mailbox;
+				id      = ((box_uid_t *) el->data)->uid;
+				if (db_set_message_status(mailbox, id, MESSAGE_STATUS_ERROR) < 0)
+					qerrorf("Warning: could not set status on mailbox [%llu] message [%llu]. Check log.\n", mailbox, id);
 				else
-					qverbosef("[%llu] set to MESSAGE_STATUS_ERROR)\n", id);
+					qverbosef("[%llu/%llu] set to MESSAGE_STATUS_ERROR)\n", mailbox, id);
         
 				el = el->nextnode;
 			}
@@ -551,7 +554,7 @@ int do_check_integrity(void)
 	struct element *el;
 	const char *action;
 	int count = 0;
-	u64_t id;
+	u64_t mailbox, id;
 
 	if (yes_to_all)
 		action = "Repairing";
@@ -664,12 +667,13 @@ int do_check_integrity(void)
 		if (lostlist.total_nodes > 0) {
 			el = lostlist.start;
 			while (el) {
-				id = *((u64_t *) el->data);
+				mailbox = ((box_uid_t *) el->data)->mailbox;
+				id      = ((box_uid_t *) el->data)->uid;
         
 				if (no_to_all) {
 					qerrorf("%llu ", id);
 				} else if (yes_to_all) {
-					if (db_delete_message(id) < 0)
+					if (db_delete_message(mailbox,id) < 0)
 						qerrorf
 						    ("Warning: could not delete message #%llu. Check log.\n",
 						     id);
diff --git a/misc.c b/misc.c
index efc3bcc..0ec5282 100644
--- a/misc.c
+++ b/misc.c
@@ -95,17 +95,18 @@ int drop_privileges(char *newuser, char *newgroup)
 	return 0;
 }
 
-void create_unique_id(char *target, u64_t message_idnr)
+void create_unique_id(char *target, u64_t mailbox_idnr, u64_t message_idnr)
 {
-	char *a_message_idnr, *a_rand;
+	char *a_mailbox_idnr, *a_message_idnr, *a_rand;
 	char *md5_str;
 
+	a_mailbox_idnr = g_strdup_printf("%llu",mailbox_idnr);
 	a_message_idnr = g_strdup_printf("%llu",message_idnr);
 	a_rand = g_strdup_printf("%d",g_random_int());
 
 	if (message_idnr != 0)
-		snprintf(target, UID_SIZE, "%s:%s",
-			 a_message_idnr, a_rand);
+		snprintf(target, UID_SIZE, "%s:%s:%s",
+			 a_mailbox_idnr, a_message_idnr, a_rand);
 	else
 		snprintf(target, UID_SIZE, "%s", a_rand);
 	md5_str = dm_md5((unsigned char *)target);
diff --git a/misc.h b/misc.h
index 5993a6f..51827d6 100644
--- a/misc.h
+++ b/misc.h
@@ -40,9 +40,10 @@ int drop_privileges(char *newuser, char *newgroup);
 /**
  * \brief create a unique id for a message (used for pop, stored per message)
  * \param target target string. Length should be UID_SIZE 
+ * \param message_idnr mailbox_idnr of message
  * \param message_idnr message_idnr of message
  */
-void create_unique_id(/[EMAIL PROTECTED]@*/ char *target, u64_t message_idnr);
+void create_unique_id(/[EMAIL PROTECTED]@*/ char *target, u64_t mailbox_idnr, u64_t message_idnr);
 
 /**
  * \brief create a timestring with the current time.
diff --git a/pipe.c b/pipe.c
index 63b4a23..8e9ffe2 100644
--- a/pipe.c
+++ b/pipe.c
@@ -157,7 +157,7 @@ static int send_mail(struct DbmailMessage *message,
 		if (preoutput)
 			fprintf(mailpipe, "%s\n", preoutput);
 		// This function will dot-stuff the message.
-		db_send_message_lines(mailpipe, message->id, -2, 1);
+		db_send_message_lines(mailpipe, message->mailbox, message->id, -2, 1);
 		break;
 	case SENDMESSAGE:
 		message_string = dbmail_message_to_string(message);
@@ -462,7 +462,7 @@ static int execute_auto_ran(struct DbmailMessage *message, u64_t useridnr)
 
 
 int store_message_in_blocks(const char *message, u64_t message_size,
-			    u64_t msgidnr) 
+			    u64_t mailbox, u64_t msgidnr) 
 {
 	u64_t tmp_messageblk_idnr;
 	u64_t rest_size = message_size;
@@ -478,7 +478,7 @@ int store_message_in_blocks(const char *message, u64_t message_size,
 			     0 : rest_size - READ_BLOCK_SIZE);
 		TRACE(TRACE_DEBUG, "inserting message [%s]", &message[offset]);
 		if (db_insert_message_block(&message[offset],
-					    block_size, msgidnr,
+					    block_size, mailbox, msgidnr,
 					    &tmp_messageblk_idnr,0) < 0) {
 			TRACE(TRACE_ERROR, "db_insert_message_block() failed");
 			return -1;
@@ -528,7 +528,7 @@ int insert_messages(struct DbmailMessage *message,
 		struct dm_list *dsnusers)
 {
 	u64_t bodysize, rfcsize;
-	u64_t tmpid;
+	u64_t tmpbox, tmpid;
 	struct element *element;
 	u64_t msgsize;
 
@@ -553,7 +553,9 @@ int insert_messages(struct DbmailMessage *message,
 	if (db_commit_transaction() < 0) 
 		return -1;
 
-	tmpid = message->id; // for later removal
+	/* for later removal */
+	tmpbox = message->mailbox;
+	tmpid  = message->id;
 
 	bodysize = (u64_t)dbmail_message_get_body_size(message, FALSE);
 	rfcsize = (u64_t)dbmail_message_get_rfcsize(message);
@@ -662,7 +664,7 @@ int insert_messages(struct DbmailMessage *message,
 	/* Always delete the temporary message, even if the delivery failed.
 	 * It is the MTA's job to requeue or bounce the message,
 	 * and our job to keep a tidy database ;-) */
-	if (db_delete_message(tmpid) < 0) 
+	if (db_delete_message(tmpbox, tmpid) < 0) 
 		TRACE(TRACE_ERROR, "failed to delete temporary message [%llu]", message->id);
 	TRACE(TRACE_DEBUG, "temporary message deleted from database. Done.");
 
@@ -715,7 +717,8 @@ int send_alert(u64_t user_idnr, char *subject, char *body)
 
 	// Pre-insert the message and get a new_message->id
 	dbmail_message_store(new_message);
-	u64_t tmpid = new_message->id;
+	u64_t tmpbox = new_message->mailbox;
+	u64_t tmpid  = new_message->id;
 
 	if (sort_deliver_to_mailbox(new_message, user_idnr,
 			"INBOX", BOX_BRUTEFORCE, msgflags) != DSN_CLASS_OK) {
@@ -723,7 +726,7 @@ int send_alert(u64_t user_idnr, char *subject, char *body)
 	}
 
 	g_free(to);
-	db_delete_message(tmpid);
+	db_delete_message(tmpbox, tmpid);
 	dbmail_message_free(new_message);
 
 	return 0;
diff --git a/pipe.h b/pipe.h
index f433f88..e1cb9b7 100644
--- a/pipe.h
+++ b/pipe.h
@@ -41,6 +41,7 @@ int insert_messages(struct DbmailMessage *message, struct dm_list *dsnusers);
  */
 int store_message_in_blocks(const char* message,
 				   u64_t message_size,
+				   u64_t mailbox,
 				   u64_t msgidnr);
 
 int send_vacation(struct DbmailMessage *message,
diff --git a/pop3.c b/pop3.c
index 1b94adf..27b4483 100644
--- a/pop3.c
+++ b/pop3.c
@@ -92,7 +92,7 @@ int pop3_handle_connection(clientinfo_t * ci)
 	
 	/* create an unique timestamp + processid for APOP authentication */
 	session.apop_stamp = g_new0(char,APOP_STAMP_SIZE);
-	create_unique_id(unique_id, 0);
+	create_unique_id(unique_id, 0, 0);
 	snprintf(session.apop_stamp, APOP_STAMP_SIZE, "<[EMAIL PROTECTED]>", unique_id, myhostname);
 
 	if (ci->tx) {
@@ -509,7 +509,7 @@ int pop3(clientinfo_t *ci, char *buffer, PopSession_t * session)
 			if (msg->messageid == strtoull(value, NULL, 10) && msg->virtual_messagestatus < MESSAGE_STATUS_DELETE) {	/* message is not deleted */
 				msg->virtual_messagestatus = MESSAGE_STATUS_SEEN;
 				ci_write((FILE *) stream, "+OK %llu octets\r\n", msg->msize);
-				return db_send_message_lines((void *) stream, msg->realmessageid, -2, 0);
+				return db_send_message_lines((void *) stream, session->mailbox_idnr, msg->realmessageid, -2, 0);
 			}
 			tmpelement = tmpelement->nextnode;
 		}
@@ -769,7 +769,7 @@ int pop3(clientinfo_t *ci, char *buffer, PopSession_t * session)
 			msg = (struct message *) tmpelement->data;
 			if (msg->messageid == top_messageid && msg->virtual_messagestatus < MESSAGE_STATUS_DELETE) {	/* message is not deleted */
 				ci_write((FILE *) stream, "+OK %llu lines of message %llu\r\n", top_lines, top_messageid);
-				return db_send_message_lines(stream, msg->realmessageid, top_lines, 0);
+				return db_send_message_lines(stream, session->mailbox_idnr, msg->realmessageid, top_lines, 0);
 			}
 			tmpelement = tmpelement->nextnode;
 		}
diff --git a/sort.c b/sort.c
index 8359e9e..e954bac 100644
--- a/sort.c
+++ b/sort.c
@@ -182,7 +182,7 @@ dsn_class_t sort_deliver_to_mailbox(struct DbmailMessage *message,
 	}
 
 	// Ok, we have the ACL right, time to deliver the message.
-	switch (db_copymsg(message->id, mboxidnr, useridnr, &newmsgidnr)) {
+	switch (db_copymsg(message->mailbox, message->id, mboxidnr, useridnr, &newmsgidnr)) {
 	case -2:
 		TRACE(TRACE_DEBUG, "error copying message to user [%llu],"
 				"maxmail exceeded", useridnr);
@@ -192,14 +192,15 @@ dsn_class_t sort_deliver_to_mailbox(struct DbmailMessage *message,
 				useridnr);
 		return DSN_CLASS_TEMP;
 	default:
-		TRACE(TRACE_MESSAGE, "message id=%llu, size=%zd is inserted", 
-				newmsgidnr, msgsize);
+		TRACE(TRACE_MESSAGE, "message id=%llu, size=%zd is inserted to mailbox id=%llu", 
+				newmsgidnr, msgsize, mboxidnr);
 		if (msgflags) {
-			TRACE(TRACE_MESSAGE, "message id=%llu, setting imap flags", 
-				newmsgidnr);
+			TRACE(TRACE_MESSAGE, "mbox id=%llu, message id=%llu, setting imap flags", 
+				mboxidnr, newmsgidnr);
 			db_set_msgflag(newmsgidnr, mboxidnr, msgflags, IMAPFA_ADD);
 		}
 		message->id = newmsgidnr;
+		message->mailbox = mboxidnr;
 		return DSN_CLASS_OK;
 	}
 }
-- 
James Cloos <[EMAIL PROTECTED]>         OpenPGP: 1024D/ED7DAEA6
_______________________________________________
Dbmail-dev mailing list
Dbmail-dev@dbmail.org
http://twister.fastxs.net/mailman/listinfo/dbmail-dev

Reply via email to