9d65fa6
diff -Naur cyrus-imapd-2.3.16/README.autosievefolder cyrus-imapd-2.3.16-autosieve.uncompiled/README.autosievefolder
9d65fa6
--- cyrus-imapd-2.3.16/README.autosievefolder	1970-01-01 02:00:00.000000000 +0200
9d65fa6
+++ cyrus-imapd-2.3.16-autosieve.uncompiled/README.autosievefolder	2009-12-23 01:08:09.000000000 +0200
38f2261
@@ -0,0 +1,42 @@
38f2261
+Cyrus IMAP autosievefolder patch
38f2261
+----------------------------------
38f2261
+
38f2261
+NOTE : This patch has been created at the University of Athens. For more info, as well 
38f2261
+as more patches on Cyrus IMAPD server, please visit http://email.uoa.gr 
38f2261
+
38f2261
+
38f2261
+  When the lmtpd daemon receives an email message prior to delivering it to the 
38f2261
+INBOX folder of the user, checks if the user has specified sieve filters. If the
38f2261
+user has specified sieve filters the filters are evaluated. If the message matches
38f2261
+any of the filters the action that is specified in the filter is executed. If the action 
38f2261
+is FileInto it is stored in the subfolder specified in the filter. If the 
38f2261
+subfolder doesn't exist then the message is sent to the INBOX folder of the user.
38f2261
+
38f2261
+  With this patch if the folder doesn't exist AND the name of the subfolder is 
38f2261
+specified in the autosievefolders option, OR the anysievefolder is set to 
38f2261
+yes in the cyrus-imap configuration file then the subfolder is created and the mail 
38f2261
+is stored there.
38f2261
+
38f2261
+
38f2261
+Check the following options of the imapd.conf file
38f2261
+==================================================
38f2261
+
38f2261
+* anysievefolder : It must be "yes" in order to permit the autocreation of any 
38f2261
+INBOX subfolder requested by a sieve filter, through the "fileinto" action. (default = no)
38f2261
+* autosievefolders : It is a "|" separated list of subfolders of INBOX that will be 
38f2261
+automatically created, if requested by a sieve filter, through the "fileinto" 
38f2261
+action. (default = null)
38f2261
+	i.e. autosievefolders: Junk | Spam
38f2261
+
38f2261
+WARNING: anysievefolder, takes precedence over autosievefolders . Which means that if 
38f2261
+anysievefolder is set to "yes", cyrus will create any INBOX subfolder requested, no-matter what the value of autosievefolders is.
38f2261
+
38f2261
+
38f2261
+Things to be done
38f2261
+=================
38f2261
+
38f2261
+1. Support cyrus wildcards in the autosievefolders option. 
38f2261
+
38f2261
+
38f2261
+For more information and updates please visit http://email.uoa.gr/projects/cyrus/autosievefolder
38f2261
+
9d65fa6
diff -Naur cyrus-imapd-2.3.16/imap/lmtp_sieve.c cyrus-imapd-2.3.16-autosieve.uncompiled/imap/lmtp_sieve.c
9d65fa6
--- cyrus-imapd-2.3.16/imap/lmtp_sieve.c	2009-03-31 07:11:18.000000000 +0300
9d65fa6
+++ cyrus-imapd-2.3.16-autosieve.uncompiled/imap/lmtp_sieve.c	2009-12-23 01:08:09.000000000 +0200
Tomas Janousek 7515ec7
@@ -88,6 +88,9 @@
9e566a4
     struct auth_state *authstate;
9e566a4
 } script_data_t;
38f2261
 
38f2261
+static int autosieve_subfolder(char *userid, struct auth_state *auth_state,
38f2261
+                               char *subfolder, struct namespace *namespace);
38f2261
+
38f2261
 static char *make_sieve_db(const char *user)
38f2261
 {
38f2261
     static char buf[MAX_MAILBOX_PATH+1];
Tomas Janousek 7515ec7
@@ -484,7 +487,20 @@
38f2261
 			      sd->username, mdata->notifyheader,
38f2261
 			      namebuf, quotaoverride, 0);
38f2261
     }
38f2261
-
9e566a4
+    
38f2261
+    if (ret == IMAP_MAILBOX_NONEXISTENT) {
38f2261
+        /* if "plus" folder under INBOX, then try to create it */
38f2261
+        ret = autosieve_subfolder((char *) sd->username, sd->authstate, namebuf, mdata->namespace);
38f2261
+
9e566a4
+	/* Try to deliver the mail again. */
38f2261
+        if (!ret)
9e566a4
+            ret = deliver_mailbox(md->f, mdata->content, mdata->stage, md->size,
38f2261
+                                  fc->imapflags->flag, fc->imapflags->nflags,
38f2261
+                                  (char *) sd->username, sd->authstate, md->id,
38f2261
+                                  sd->username, mdata->notifyheader,
38f2261
+                                  namebuf, quotaoverride, 0);
38f2261
+    }
9e566a4
+    
38f2261
     if (!ret) {
38f2261
 	snmp_increment(SIEVE_FILEINTO, 1);
38f2261
 	return SIEVE_OK;
Tomas Janousek d4ef9ed
@@ -935,3 +951,80 @@
9e566a4
        we'll do normal delivery */
38f2261
     return r;
38f2261
 }
38f2261
+
38f2261
+
38f2261
+#define SEP '|'
38f2261
+
38f2261
+static int autosieve_subfolder(char *userid, struct auth_state *auth_state,
38f2261
+                               char *subfolder, struct namespace *namespace)
38f2261
+{
38f2261
+     char option_name_external[MAX_MAILBOX_NAME + 1];
38f2261
+     char option_name_internal[MAX_MAILBOX_NAME + 1];
38f2261
+     const char *subf ;
38f2261
+     char *p, *q, *next_subf;
38f2261
+     int len, r = 0;
38f2261
+     int createsievefolder = 0;
38f2261
+
38f2261
+    /* Check if subfolder or userid are NULL */
9e566a4
+    if(userid == NULL || subfolder == NULL)
38f2261
+         return IMAP_MAILBOX_NONEXISTENT;
38f2261
+
9e566a4
+    syslog(LOG_DEBUG, "autosievefolder: autosieve_subfolder() was called for user %s, folder %s", 
9e566a4
+		    userid, subfolder);
9e566a4
+
9e566a4
+    if (config_getswitch(IMAPOPT_ANYSIEVEFOLDER)) {
38f2261
+         createsievefolder = 1;
9e566a4
+    } else if ((subf = config_getstring(IMAPOPT_AUTOSIEVEFOLDERS)) != NULL) {
38f2261
+         /* Roll through subf */
38f2261
+         next_subf = (char *) subf;
38f2261
+         while (*next_subf) {
38f2261
+              for (p = next_subf ; isspace((int) *p) || *p == SEP ; p++);
38f2261
+              for (next_subf = p ; *next_subf && *next_subf != SEP ; next_subf++);
38f2261
+              for (q = next_subf ; q > p && (isspace((int) *q) || *q == SEP || !*q); q--);
38f2261
+
38f2261
+              if (!*p) continue;
38f2261
+                    
38f2261
+              len = q - p + 1;
38f2261
+             /*
38f2261
+              * This is a preliminary length check based on the assumption
38f2261
+              * that the *final* internal format will be something
38f2261
+              * like user.userid.subfolder(s).
38f2261
+              */
38f2261
+              if (len > sizeof(option_name_external) - strlen(userid) - 5)
38f2261
+                   return IMAP_MAILBOX_BADNAME;
38f2261
+
38f2261
+              strlcpy(option_name_external, namespace->prefix[NAMESPACE_INBOX], sizeof(option_name_external));
38f2261
+	      strncat(option_name_external, p, len);
38f2261
+                    
38f2261
+              /* 
38f2261
+               * Transform the option folder name to internal namespace and compare it
38f2261
+	       * with what must be created.
38f2261
+               */
38f2261
+              r = namespace->mboxname_tointernal(namespace, option_name_external, userid, option_name_internal);
38f2261
+              if (r) continue;
38f2261
+
38f2261
+              if (!strcmp(option_name_internal, subfolder)) {
38f2261
+                  createsievefolder = 1;
38f2261
+                  break;
38f2261
+              }
38f2261
+         }
38f2261
+    }
38f2261
+
38f2261
+    if (createsievefolder) {
38f2261
+        /* Folder is already in internal namespace format */
38f2261
+        r = mboxlist_createmailbox(subfolder, MAILBOX_FORMAT_NORMAL, NULL,
38f2261
+                                           1, userid, auth_state, 0, 0, 0);
38f2261
+        if (!r) {
38f2261
+            mboxlist_changesub(subfolder, userid, auth_state, 1, 1);
9e566a4
+            syslog(LOG_DEBUG, "autosievefolder: User %s, folder %s creation succeeded",
38f2261
+                                                   userid, subfolder);
38f2261
+            return 0;
38f2261
+        } else {
38f2261
+            syslog(LOG_ERR, "autosievefolder: User %s, folder %s creation failed. %s",
38f2261
+                                                  userid, subfolder,error_message(r));
38f2261
+            return r;
38f2261
+        }
38f2261
+    } else
38f2261
+        return IMAP_MAILBOX_NONEXISTENT;
38f2261
+}
38f2261
+
9d65fa6
diff -Naur cyrus-imapd-2.3.16/lib/imapoptions cyrus-imapd-2.3.16-autosieve.uncompiled/lib/imapoptions
9d65fa6
--- cyrus-imapd-2.3.16/lib/imapoptions	2009-12-21 13:25:22.000000000 +0200
9d65fa6
+++ cyrus-imapd-2.3.16-autosieve.uncompiled/lib/imapoptions	2009-12-23 01:08:09.000000000 +0200
9d65fa6
@@ -1043,6 +1043,15 @@
38f2261
 /* If enabled, lmtpd will look for Sieve scripts in user's home
38f2261
    directories: ~user/.sieve. */
38f2261
 
38f2261
+{ "anysievefolder", 0, SWITCH }
38f2261
+/* It must be "yes" in order to permit the autocreation of any INBOX subfolder 
38f2261
+   requested by a sieve filter, through the "fileinto" action. (default = no) */
38f2261
+
38f2261
+{ "autosievefolders", NULL, STRING }
38f2261
+/* It is a "|" separated list of subfolders of INBOX that will be automatically created, 
38f2261
+   if requested by a sieve filter, through the "fileinto" action. (default = null)
38f2261
+   i.e. autosievefolders: Junk | Spam */
38f2261
+
38f2261
 { "singleinstancestore", 1, SWITCH }
9e566a4
 /* If enabled, imapd, lmtpd and nntpd attempt to only write one copy
9e566a4
    of a message per partition and create hard links, resulting in a