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