Репозиторий ALT Linux backports/2.4
Последнее обновление: 9 июля 2008 | Пакетов: 497 | Посещений: 1584901
 поиск   регистрация   авторизация 
 
Группа :: Система/Серверы
Пакет: dbmail

 Главная   Изменения   Спек   Патчи   Загрузить   Bugs and FR 

Патч: dbmail-2.0.5_0.6-folders.patch


diff -urN dbmail-2.0.5/README.folders dbmail-2.0.5-folders/README.folders
--- dbmail-2.0.5/README.folders	1969-12-31 19:00:00.000000000 -0500
+++ dbmail-2.0.5-folders/README.folders	2005-08-16 15:47:51.000000000 -0400
@@ -0,0 +1,126 @@
+DBMail user+folder@domain.name Patch
+Patch Name: dbmail-2.0.5_0.6-folders.patch
+
+Author: <niblettda at gru dot com>
+Patch version: v0.6
+
+This patch allows the use of the common form: user+folder@domain.name.
+
+I wrote this patch because I wanted to sort Email out from Amavis such
+that it will be sent to a users Spam folder based on their Amavis/
+SpamAssassin settings.
+
+Currently this patch version only permits dbmail-lmtpd to sort based on
+the folder.
+
+There is a config option line CREATE_FOLDERS that takes the form of:
+
+	CREATE_FOLDERS=:FOLDER:FOLDER:FOLDER:
+
+These are folders that are allowed to be created if they don't exist.
+If a supplied folder to the LMTP Daemon doesn't exist is not in the
+CREATE_FOLDERS list, the email will delivered to the users INBOX.
+
+There is no need to include INBOX in the folder list, as the server
+should always be able to create that folder.
+
+
+
+* A NOTE ABOUT CASE *
+
+Without a doubt the biggest problem I've encountered has been surrounding
+case sensitivity.  For example, if Amavis is supposed to deliver the
+message to user+SPAM, and the user has a mailbox for spam, but it's called
+"Spam", then many things could happen.
+
+  - Deliver to the "Spam" box (this is what I do).
+  - Create a new box called "Spam", and deliver to it.
+  - Say that Spam isn't in the CREATE_FOLDERS list and dump it to INBOX.
+
+Each have their positives and negatives.  My approach has been based on
+what I expect my "general population" of users to expect.  I believe that
+most people are not going to make "Spam", "SPAM", "SpAm", etc. mailboxes.
+If your experience is different, then by all means, please feel free to
+alter my patch to suit your needs.
+
+
+
+* TO DO *
+- Currently there is a minor bug with delivery to multiple recipients
+  via aliases.  For example, if you have user1@domain and user2@domain,
+  then an alias alias@domain with a deliver_to BOTH user1@domain AND
+  user2@domain.  If either user has say mailbox XYZ, and a message is
+  delivered to alias+XYZ@domain, even if XYZ is not in the auto create
+  list, because one of the two users has the mailbox, the other user
+  will get one created as well.
+
+  The only way to fix the above problem would be a major change to the
+  dsnuser structure in DBMail and that is beyond the scope of this patch.
+  So for the time being this is one bug that will have to exist.
+
+
+
+* CHANGE LOG *
+
+dbmail-2.0.5_0.6-folder:
+- Renamed the patch to 2.0.5 since it is now based on the 2.0.5 code.
+
+- Removed code from sort/sort.c, now we will create the folder in the
+  db.c (db_find_create_mailbox) function per request from Paul.
+
+- Moved valid_folder checking in lmtp.c to after verification that the
+  username is valid before bothering to check if the folder is valid.
+
+- Changed valid_folder to recieve a userids list so that I can check
+  by user_idnr rather than the address to deliver.  This is important
+  to fix an issue where delivery to an alias, as the alias wouldn't
+  have any folders to deliver to.
+
+- Modified db_find_create_mailbox function to also IMAP subscribe the
+  mailbox to the user if it has to be created.
+
+- I no longer only check for subscribed mailboxes for delivery, so be
+  aware that if a user unscribes, but still has the box, that it may
+  be able to continue to grow in size.
+
+
+dbmail-2.0.4_0.5-folders:
+- Updated the README, which was forgotten in v0.4
+
+
+dbmail-2.0.4_0.4-folders:
+- Fixed a problem with creating the mailbox if it didn't exist.  This would
+  cause LMTPD to crash.  Mainly just changed order of events.
+
+- Found and fixed error with determining if the folder could be created.
+  Was appending to string rather than overwriting.
+
+- Added the feature that if the mailbox is created for the user they are
+  also automatically subscribed to the mailbox.
+
+
+dbmail-2.0.4_0.3-folders:
+- Found problems with code should a folder not exist.  This patch version
+  was never released.
+
+
+dbmail-2.0.4_0.2-folders:
+- Removed case insensitivity DB search that was valid only for  PostgreSQL.
+  (Thanks to Paul J. Stevens <paul at nfg dot nl>)
+
+- Added bound limits to strncpy() in misc.c to prevent excessive folder
+  length from over writing memory.
+  (Thanks to Paul J. Stevens <paul at nfg dot nl>)
+
+- Changed misc.c, valid_folders() function to use db_findfolder_by_regex().
+  (Thanks to Wolfram)
+
+- Changed misc.c, valid_folders() function to use the folder name as stored
+  in the database, which prevents us from creating two folders with same
+  name but different case.  (See above above)
+
+
+dbmail-2.0.4-folders:
+- Changed my_free() function in lmtp.c to dm_free() since my_free() was
+  renamed in v2.0.4 of DBMail
+
diff -urN dbmail-2.0.5/db.c dbmail-2.0.5-folders/db.c
--- dbmail-2.0.5/db.c	2005-04-22 09:03:31.000000000 -0400
+++ dbmail-2.0.5-folders/db.c	2005-08-16 15:36:45.000000000 -0400
@@ -2952,10 +2952,17 @@
 			      "%s, %s: seriously could not create mailbox [%s]",
 			      __FILE__, __func__, name);
 			return -1;
+		} else {
+			/* Since we had to create the mailbox, subscribe to it too. */
+			trace(TRACE_DEBUG,
+			      "%s, %s: mailbox [%s] created on the fly", __FILE__,
+			      __func__, name);
+
+			/* No reason to output an error since db_subscribe does it. */
+			/* Also, as long as the box was created, even if we have a */
+			/* problem subscribing we assume message delivery will work. */
+			db_subscribe(mboxidnr, owner_idnr);
 		}
-		trace(TRACE_DEBUG,
-		      "%s, %s: mailbox [%s] created on the fly", __FILE__,
-		      __func__, name);
 	}
 	trace(TRACE_DEBUG, "%s, %s: mailbox [%s] found",
 	      __FILE__, __func__, name);
diff -urN dbmail-2.0.5/dbmail.conf dbmail-2.0.5-folders/dbmail.conf
--- dbmail-2.0.5/dbmail.conf	2005-04-22 09:03:31.000000000 -0400
+++ dbmail-2.0.5-folders/dbmail.conf	2005-08-16 15:34:47.000000000 -0400
@@ -19,6 +19,7 @@
 pass=                   # password for user to database
 db=                     # name of database
 POSTMASTER=		# postmaster's email address.
+CREATE_FOLDER=:INBOX:SPAM:
 # trace level for dbmail-util	
 TRACE_LEVEL=2      
 
diff -urN dbmail-2.0.5/lmtp.c dbmail-2.0.5-folders/lmtp.c
--- dbmail-2.0.5/lmtp.c	2005-04-22 09:03:31.000000000 -0400
+++ dbmail-2.0.5-folders/lmtp.c	2005-08-16 13:07:31.000000000 -0400
@@ -525,10 +525,14 @@
 			} else {
 				size_t tmplen = 0, tmppos = 0;
 				char *tmpaddr = NULL;
+				char *tmpfolder = NULL;
 
 				find_bounded(value, '<', '>', &tmpaddr,
 					     &tmplen, &tmppos);
 
+				/* Remove the folder if there is one. */
+				remove_folder(&tmpaddr, &tmplen);
+
 				if (tmplen < 1) {
 					ci_write((FILE *) stream,
 						"500 No address found.\r\n");
@@ -556,6 +560,16 @@
 					/* Class 2 means the address was deliverable in some way. */
 					switch (dsnuser.dsn.class) {
 					case DSN_CLASS_OK:
+						/* Determine if there is a folder involved for this address. */
+						if (! find_bounded(value, '+', '@', &tmpfolder, &tmplen, &tmppos)) {
+							/* Is it a valid mailbox for this address? */
+							if (valid_folder(dsnuser.userids, tmpfolder)) {
+								dsnuser.mailbox = tmpfolder;
+							} else {
+								/* Free the memory from find_bounded */
+								dm_free(tmpfolder);
+							}
+						}
 						ci_write((FILE *) stream,
 							"250 Recipient <%s> OK\r\n",
 							dsnuser.address);
diff -urN dbmail-2.0.5/misc.c dbmail-2.0.5-folders/misc.c
--- dbmail-2.0.5/misc.c	2005-04-22 09:03:31.000000000 -0400
+++ dbmail-2.0.5-folders/misc.c	2005-08-16 15:38:28.000000000 -0400
@@ -491,3 +491,138 @@
 		return 0;
 	}
 }
+
+/* Finds the folder if included in an address between a '+' and '@'.
+ * Does not allocate memory since that should already be done prior to
+ * calling this function.  The string must be shorter if anything.
+ * retchar will have the new string or the original value if there is
+ * no folder to remove.
+ *
+ * Return values are:
+ *   0 on success (found)
+ *   -1 on failure (not found)
+ *
+ * */
+int remove_folder(char **retchar, size_t * retsize)
+{
+	char *value;
+	char *tmpleft;
+	char *tmpright;
+	size_t tmplen;
+
+	char left = '+';
+	char right = '@';
+
+	value = *retchar;
+	tmpleft = value;
+	tmpright = value + strlen(value);
+
+	while (tmpleft[0] != left && tmpleft < tmpright)
+		tmpleft++;
+	while (tmpright[0] != right && tmpright > tmpleft)
+		tmpright--;
+
+	if (tmpleft[0] != left || tmpright[0] != right) {
+		trace(TRACE_INFO,
+		      "%s, %s: No folder found.",
+		      __FILE__, __func__);
+		*retsize = strlen(*retchar);
+		return -1;
+	} else {
+		tmplen = strlen(value) - (strlen(tmpleft) - strlen(tmpright));
+		strncpy(*retchar, value, (strlen(value) - strlen(tmpleft)));
+		(*retchar)[(strlen(value) - strlen(tmpleft))] = '\0';
+		strncat(*retchar, tmpright, strlen(tmpright));
+		(*retchar)[tmplen] = '\0';
+		*retsize = tmplen;
+		trace(TRACE_INFO,
+		      "%s, %s: Found [%s] of length [%zd] around '%c' and '%c'.",
+		      __FILE__, __func__, *retchar, *retsize, left,
+		      right);
+		return 0;
+	}
+}
+
+/* Function to determine if the requested mailbox exists or is valid to
+ * be created for the specified userid
+ *
+ * Return values are:
+ *   1 on success (existing or allowed to be created)
+ *   0 on failure (does not exist not allowed to be created)
+ *
+ * */
+
+int valid_folder(struct list *userids, char *folder)
+{
+	int result;
+	field_t val;
+	char tmp[IMAP_MAX_MAILBOX_NAMELEN+2] = "";
+	u64_t *children = NULL;
+	unsigned nchildren;
+	struct element *element;
+
+	/* Create the pattern to search on the folder list. */
+	tmp[0] = '^';
+	strncat(&tmp[1], folder, IMAP_MAX_MAILBOX_NAMELEN-3);
+	strcat(tmp, "$");
+
+	/* We need to check all the user_idnr's */
+	for (element = list_getstart(userids); element != NULL;
+	     element = element->nextnode) {
+		/* Save the current useridnr in something more useful. */
+		u64_t useridnr = *(u64_t *) element->data;
+
+		/* Search folders for delivery. */
+		result = db_findmailbox_by_regex(useridnr, tmp, &children, &nchildren, 1);
+
+		/* Invalid response, deal with it. */
+		if (result != 0) {
+			trace(TRACE_INFO, "%s, %s: Folder [%s] regex failure for id [%llu].",
+					   __FILE__, __func__, folder, useridnr);
+			return 0;
+		}
+
+		/* If we got some children back we are home free. */
+		if (nchildren > 0) {
+
+			u64_t mailboxidnr = children[0];	/* Save the mailboxid for later. */
+			dm_free(children);			/* Done with the children. */
+
+			/* Set the folder name to what is in the database, this is */
+			/* to avoid mixed case differences.  See README.folders. */
+			result = db_getmailboxname(mailboxidnr, useridnr, folder);
+
+			/* No success, then bail out and assume INBOX */
+			if (result == -1) {
+				trace(TRACE_INFO, "%s, %s: Folder [%s] lookup failure for id [%llu].",
+						   __FILE__, __func__, folder, useridnr);
+				return 0;
+			}
+
+			/* Otherwise we now have the foldername as appears in the DB. */
+			trace(TRACE_INFO, "%s, %s: mailbox [%s] exists for id [%llu].",
+					   __FILE__, __func__, folder, useridnr);
+			return 1;
+		}
+
+		/* No existing folder, are we allowed to create it? */
+		GetConfigValue("CREATE_FOLDERS", "DBMAIL", val);
+
+		/* Reset the tmp string and get our search item. */
+		/* we can cheat and just modify our initial search string some */
+		tmp[0] = ':';
+		tmp[strlen(tmp)-1] = ':';
+
+		if (strcasestr(val, tmp) != NULL) {
+			trace(TRACE_INFO, "%s,%s: folder [%s] is in create list [%s]",
+					   __FILE__, __func__, tmp, val);
+			return 1;
+		}
+
+		trace(TRACE_INFO, "%s,%s: failed to find or create folder [%s] for id [%llu], using INBOX",
+				   __FILE__, __func__, folder, useridnr);
+	}
+
+	/* Either user doesn't exist, or not allowed to create. */
+	return 0;
+}
diff -urN dbmail-2.0.5/misc.h dbmail-2.0.5-folders/misc.h
--- dbmail-2.0.5/misc.h	2005-04-22 09:03:31.000000000 -0400
+++ dbmail-2.0.5-folders/misc.h	2005-08-16 13:04:17.000000000 -0400
@@ -105,6 +105,8 @@
 int read_from_stream(FILE * instream, char **m_buf, size_t maxlen);
 int find_bounded(char *value, char left, char right, char **retchar,
 		 size_t * retsize, size_t * retlast);
+int remove_folder(char **retchar, size_t * retsize);
+int valid_folder(struct list *userids, char *folder);
 int base64_grow_ret(char ***inchar, size_t ** inint, size_t newcount,
 		    size_t newchar);
 
 
design & coding: Vladimir Lettiev aka crux © 2004-2005