Hi,

There are no suitable way for mail filtering with DBMail. Sieve support is not stable and excluded by default, procmail will slow perfomance by invoking another process ...

So, I write very simple filtering engine for DBMail. It's attached and based on this new table:

CREATE TABLE dbmail_filters (
        user_id bigint(21) not null default '0',
        filter_id bigint(21) not null default '0',
        filter_field varchar(128) NOT NULL default '',
        filter_value varchar(255) NOT NULL default '',  
        index user_id_index (user_id),
        index filter_id_index (filter_id),
        PRIMARY KEY (user_id, filter_id),
        FOREIGN KEY user_id_fk (user_id)
                REFERENCES dbmail_users (user_idnr) ON DELETE CASCADE ON UPDATE 
CASCADE
) TYPE=InnoDB;

If mail message field value contains value of filter_value database field it will be moved to folder referenced by mailbox database field.

My implementation is not optimal and is not hight perfomance. It's seems to work with MySQL, but it's make sense to test it more. It hasn't been tested with PostgreSQL.

Is my patch helpful for anybody? What can you say about including it in main source tree of DBMail?

--
Regards,
Eugene Prokopiev
--- ./pipe.c.orig	2005-08-19 18:30:42 +0400
+++ ./pipe.c	2005-09-20 13:04:08 +0400
@@ -574,8 +574,9 @@
 			trace(TRACE_DEBUG,
 			      "%s, %s: calling sort_and_deliver for useridnr [%llu]",
 			      __FILE__, __func__, useridnr);
-			
-			dsn_result = sort_and_deliver(tmpmsgidnr, msgsize, useridnr, delivery->mailbox);
+							 
+			dsn_result = sort_and_deliver(tmpmsgidnr, msgsize, useridnr, 
+				db_get_mailbox_from_filters(useridnr, headerfields, delivery->mailbox));
 			
 			switch (dsn_result) {
 			case DSN_CLASS_OK:
--- ./sql/mysql/create_tables.mysql.orig	2005-08-19 18:30:42 +0400
+++ ./sql/mysql/create_tables.mysql	2005-09-20 15:16:54 +0400
@@ -61,6 +61,20 @@
    UNIQUE INDEX owner_idnr_name_index (owner_idnr, name)
  );
 
+DROP TABLE IF EXISTS dbmail_filters;
+CREATE TABLE dbmail_filters (
+	user_id bigint(21) not null default '0',
+	filter_id bigint(21) not null default '0',
+	filter_field varchar(128) NOT NULL default '',
+	filter_value varchar(255) NOT NULL default '',	
+	mailbox varchar(100) NOT NULL default '',	
+	index user_id_index (user_id),
+	index filter_id_index (filter_id),
+	PRIMARY KEY (user_id, filter_id),
+	FOREIGN KEY user_id_fk (user_id) 
+		REFERENCES dbmail_users (user_idnr) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
 DROP TABLE IF EXISTS dbmail_subscription;
 CREATE TABLE dbmail_subscription (
 	user_id bigint(21) NOT NULL,
--- ./sql/mysql/create_tables_innoDB.mysql.orig	2005-09-05 18:52:57 +0400
+++ ./sql/mysql/create_tables_innoDB.mysql	2005-09-20 15:17:16 +0400
@@ -73,6 +73,20 @@
 		REFERENCES dbmail_users (user_idnr) ON DELETE CASCADE ON UPDATE CASCADE
 ) TYPE=InnoDB;
 
+DROP TABLE IF EXISTS dbmail_filters;
+CREATE TABLE dbmail_filters (
+	user_id bigint(21) not null default '0',
+	filter_id bigint(21) not null default '0',
+	filter_field varchar(128) NOT NULL default '',
+	filter_value varchar(255) NOT NULL default '',	
+	mailbox varchar(100) NOT NULL default '',	
+	index user_id_index (user_id),
+	index filter_id_index (filter_id),
+	PRIMARY KEY (user_id, filter_id),
+	FOREIGN KEY user_id_fk (user_id) 
+		REFERENCES dbmail_users (user_idnr) ON DELETE CASCADE ON UPDATE CASCADE
+) TYPE=InnoDB;
+
 DROP TABLE IF EXISTS dbmail_subscription;
 CREATE TABLE dbmail_subscription (
 	user_id bigint(21) not null default '0',
--- ./db.c.orig	2005-08-19 18:30:42 +0400
+++ ./db.c	2005-09-20 14:51:26 +0400
@@ -524,6 +524,58 @@
 	return 1;
 }
 
+char *db_get_mailbox_from_filters(u64_t useridnr, struct list *headerfields, const char *mailbox)
+{
+	trace(TRACE_MESSAGE, "%s, %s: default mailbox [%s]", __FILE__, __func__, mailbox);
+	
+	if (mailbox == NULL)
+	{
+		unsigned i = 0;	
+		unsigned num_filters = 0;
+		
+		snprintf(query, DEF_QUERYSIZE,
+			"SELECT filter_field, filter_value, mailbox FROM dbmail_filters WHERE user_id = '%llu' ORDER BY filter_id",
+			useridnr);
+		
+		if (db_query(query) == -1) {
+			trace(TRACE_ERROR, "%s,%s: error gettings filters for "
+				"user_id [%llu]", __FILE__, __func__,
+				useridnr);
+				return NULL;
+		}
+		
+		num_filters = db_num_rows();
+		for (i = 0; i < num_filters; i++) {
+			
+			struct element *el = list_getstart(headerfields);
+			char *filter_field = db_get_result(i, 0);
+			char *filter_value = db_get_result(i, 1);
+			char *mailbox = db_get_result(i, 2);
+			
+			trace(TRACE_MESSAGE,
+				"%s, %s: filter [%s : \"%s\" => %s]",
+				__FILE__, __func__, filter_field, filter_value, mailbox);
+			
+			while (el) {
+				struct mime_record *record = (struct mime_record *) el->data;
+				
+				if (!strcmp(record->field, filter_field) && strstr(record->value, filter_value))
+					return mailbox;
+				
+				el = el->nextnode;
+			}
+		}
+		
+		db_free_result();
+		
+		return NULL;
+	}
+	else
+	{
+		return NULL;
+	}
+}
+
 char *db_get_deliver_from_alias(const char *alias)
 {
 	char *escaped_alias;
--- ./db.h.orig	2005-08-19 18:30:42 +0400
+++ ./db.h	2005-09-20 13:23:02 +0400
@@ -349,6 +349,14 @@
  *         - deliver_to address otherwise
  * \attention caller needs to free the return value
  */
+/[EMAIL PROTECTED]@*/ char *db_get_mailbox_from_filters(u64_t useridnr, struct list *headerfields, const char *mailbox);
+/**
+ * \brief get a mailbox for a user's user_idnr, default mailbox and filter table
+ * \param user_idnr idnr of user
+ * \param headerfields header fields
+ * \param mailbox default mailbox name
+ * \return mailbox name
+ */
 /[EMAIL PROTECTED]@*/ char *db_get_deliver_from_alias(const char *alias);
 /**
  * \brief get a list of aliases associated with a user's user_idnr
@@ -360,7 +368,7 @@
  * 		- 0 on success
  * \attention aliases list needs to be empty. Method calls list_init()
  *            which sets list->start to NULL.
- */
+ */  
 int db_get_user_aliases(u64_t user_idnr, struct list *aliases);
 /**
  * \brief add an alias for a user

Reply via email to