Michael Monnerie wrote:
> On Montag, 18. Juni 2007 Paul J Stevens wrote:
>> This is a todo for 2.3.0, together with what we've started calling
>> single-instance-storage. With SiS, mime-parts such as attachments
>> will never be stored more than once.
> 
> And while doing this, would it be possible to do the "cyrus way" of 
> checking for duplicate message id's? This would be nice also, and 
> saving some space. We've had the problem with an Apple mail client, 
> where the user copied some mailbox 5 times into the same folder, having 
> 5 duplicates of each e-mail. It would be nice if the server just 
> dropped a duplicate message right on the floor.

Does cyrus do this by default? I have a patch to avoid duplicate message-ids
which I can apply to the 2.2 branch right away. I'll attach it for good measure.

Or is it necessary to add a config/compile-time option?


-- 
  ________________________________________________________________
  Paul Stevens                                      paul at nfg.nl
  NET FACILITIES GROUP                     GPG/PGP: 1024D/11F8CD31
  The Netherlands________________________________http://www.nfg.nl
>From f294a5444771ff4c9f5962c92b7b55294ee36bce Mon Sep 17 00:00:00 2001
From: Paul J Stevens <[EMAIL PROTECTED]>
Date: Mon, 18 Jun 2007 13:40:36 +0200
Subject: avoid duplicate message-ids in a mailbox

---
 db.c   |   31 +++++++++++++++++++++++++++++++
 db.h   |   11 +++++++++++
 sort.c |    8 ++++++++
 3 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/db.c b/db.c
index af08d32..63f55a6 100644
--- a/db.c
+++ b/db.c
@@ -3636,6 +3636,37 @@ int db_movemsg(u64_t mailbox_to, u64_t mailbox_from)
 	return DM_SUCCESS;		/* success */
 }
 
+int db_mailbox_has_message_id(u64_t mailbox_idnr, const char *messageid)
+{
+	int rows;
+	char *safe_messageid;
+	char query[DEF_QUERYSIZE];
+	memset(query,0,DEF_QUERYSIZE);
+
+	g_return_val_if_fail(messageid!=NULL,0);
+
+	safe_messageid = dm_stresc(messageid);
+	snprintf(query, DEF_QUERYSIZE,
+		"SELECT message_idnr FROM %smessages m "
+		"JOIN %sphysmessage p ON m.physmessage_id=p.id "
+		"JOIN %sheadervalue v ON v.physmessage_id=p.id "
+		"JOIN %sheadername n ON v.headername_id=n.id "
+		"WHERE m.mailbox_idnr=%llu "
+		"AND n.headername='message-id' "
+		"AND v.headervalue='%s'", DBPFX, DBPFX, 
+		DBPFX, DBPFX, mailbox_idnr, safe_messageid);
+	g_free(safe_messageid);
+	
+	if (db_query(query) == DM_EQUERY)
+		return DM_EQUERY;
+
+	rows = db_num_rows();
+	db_free_result();
+	
+	return rows;
+}
+
+
 static u64_t message_get_size(u64_t message_idnr)
 {
 	u64_t size = 0;
diff --git a/db.h b/db.h
index b7563e3..649fe32 100644
--- a/db.h
+++ b/db.h
@@ -1102,6 +1102,15 @@ int db_movemsg(u64_t mailbox_to, u64_t mailbox_from);
  */
 int db_copymsg(u64_t msg_idnr, u64_t mailbox_to,
 	       u64_t user_idnr, u64_t * newmsg_idnr);
+
+/**
+ * \brief check if mailbox already holds message with message-id
+ * \param mailbox_idnr
+ * \param messageid Message-ID header to check for
+ * \return number of matching messages or -1 on failure
+ */
+int db_mailbox_has_message_id(u64_t mailbox_idnr, const char *messageid);
+
 /**
  * \brief get name of mailbox
  * \param mailbox_idnr
@@ -1112,6 +1121,8 @@ int db_copymsg(u64_t msg_idnr, u64_t mailbox_to,
  * \attention name should be large enough to hold the name 
  * (preferably of size IMAP_MAX_MAILBOX_NAMELEN + 1)
  */
+
+
 int db_getmailboxname(u64_t mailbox_idnr, u64_t user_idnr, char *name);
 /**
  * \brief set name of mailbox
diff --git a/sort.c b/sort.c
index 62a820c..6674b9e 100644
--- a/sort.c
+++ b/sort.c
@@ -131,6 +131,7 @@ dsn_class_t sort_deliver_to_mailbox(struct DbmailMessage *message,
 		int *msgflags)
 {
 	u64_t mboxidnr, newmsgidnr;
+	char *messageid;
 	size_t msgsize = (u64_t)dbmail_message_get_size(message, FALSE);
 
 	TRACE(TRACE_INFO,"useridnr [%llu] mailbox [%s]", useridnr, mailbox);
@@ -180,6 +181,13 @@ dsn_class_t sort_deliver_to_mailbox(struct DbmailMessage *message,
 		}
 	}
 
+	// if the mailbox already holds this message we're done
+	messageid = dbmail_message_get_header(message, "message-id");
+	if ( messageid && ((db_mailbox_has_message_id(mboxidnr, messageid)) > 0) ) {
+		TRACE(TRACE_DEBUG, "mailbox already contains this message.");
+		return DSN_CLASS_OK;
+	}
+
 	// Ok, we have the ACL right, time to deliver the message.
 	switch (db_copymsg(message->id, mboxidnr, useridnr, &newmsgidnr)) {
 	case -2:
-- 
1.5.1

_______________________________________________
DBmail mailing list
[email protected]
https://mailman.fastxs.nl/mailman/listinfo/dbmail

Reply via email to