diff -Naur cyrus-imapd-2.2.3/imap/lmtpd.c cyrus-imapd-2.2.3-autosievefolder.uncompiled/imap/lmtpd.c --- cyrus-imapd-2.2.3/imap/lmtpd.c 2003-12-16 22:36:55.000000000 +0200 +++ cyrus-imapd-2.2.3-autosievefolder.uncompiled/imap/lmtpd.c 2004-01-22 15:05:40.292081000 +0200 @@ -166,6 +166,8 @@ static int sieve_usehomedir = 0; static const char *sieve_dir = NULL; #endif +static int autosieve_subfolder(char *userid, struct auth_state *auth_state, + char *subfolder); /* per-user/session state */ static struct protstream *deliver_out, *deliver_in; @@ -628,6 +630,20 @@ sd->username, mdata->notifyheader, fc->mailbox, quotaoverride, 0); + if (ret == IMAP_MAILBOX_NONEXISTENT) { + /* if "plus" folder under INBOX, then try to create it */ +// syslog(LOG_DEBUG, "calling autosieve folder for : %s", fc->mailbox); + ret = autosieve_subfolder(sd->username, sd->authstate, fc->mailbox); + + if (!ret) + ret = deliver_mailbox(md->data, mdata->stage, md->size, + fc->imapflags->flag, fc->imapflags->nflags, + sd->username, sd->authstate, md->id, + sd->username, mdata->notifyheader, + fc->mailbox, quotaoverride, 0); + } + + if (ret == 0) { snmp_increment(SIEVE_FILEINTO, 1); @@ -1475,3 +1491,126 @@ append_removestage(stage); } + +#define SEP '|' + +static int autosieve_subfolder(char *userid, struct auth_state *auth_state, + char *subfolder) +{ + char foldername[MAX_MAILBOX_NAME+1]; + char f[MAX_MAILBOX_NAME+1]; + char nam[MAX_MAILBOX_NAME+1]; + const char *subf ; + char *checkfoldername, *user; + char *p, *q, *next_subf, *mbox; + int len, r = 0; + int createsievefolder = 0; + + + /* Check if subfolder is NULL */ + if(subfolder == NULL) + return IMAP_MAILBOX_NONEXISTENT; + + + + r = (*lmtpd_namespace.mboxname_tointernal)(&lmtpd_namespace, subfolder, + userid, foldername); + + if(r) return r; // We have an error .. we return it above. + + + if(config_virtdomains) { + if((p = strrchr(userid,'@'))) { + user = xmalloc(strlen(userid)*sizeof(char)); + strncpy(user,userid,( p ? (strlen(userid) - strlen(p)) : strlen(userid))); + } + else + user = userid; + } + else + user = userid; + + + + strlcpy(nam,"user.",6); + strlcat(nam,user,MAX_MAILBOX_NAME); + strlcat(nam,".",MAX_MAILBOX_NAME); + + + if(!(checkfoldername = strchr(foldername,(int)'!'))) + checkfoldername = foldername; + else + checkfoldername++; + + if(strncasecmp(checkfoldername,nam,strlen(nam))) { + return IMAP_MAILBOX_BADNAME; + } + + if(strchr((checkfoldername + strlen(nam) +1),'.')) { //we are in internal namespace + return IMAP_MAILBOX_BADNAME; + } + + if(user != userid) + free(user); + + + if (config_getswitch(IMAPOPT_ANYSIEVEFOLDER)) + createsievefolder = 1; + else if ((subf = config_getstring(IMAPOPT_AUTOSIEVEFOLDERS)) != NULL) { + /* + * mbox contains only the subfolder to be created name + */ + if((mbox = strrchr(foldername, (int) '.'))) // We are in internal namespace. Megalh efeyresh to internal namespace :)) + mbox++; + else + return IMAP_MAILBOX_BADNAME; //Probably we have a BAD combination of sieve filter and imap.conf + + + /* 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; + /* + * This is a preliminary length check based on the assumption + * that the *final* internal format will be something + * like user.userid.subfolder(s). + */ + len = q - p + 1; + + if (len > sizeof(f) - strlen(userid) - 5) + r = IMAP_MAILBOX_BADNAME; + + if (!r) { + strncpy(f, p, len); + f[len] = '\0'; + + if (!strcmp(f, mbox)) { + createsievefolder = 1; + break; + } + } + } + } + + if (createsievefolder) { + +// Folder is already in internal namespace format + r = mboxlist_createmailbox(foldername, MAILBOX_FORMAT_NORMAL, NULL, + 1, userid, auth_state, 0, 0, 0); + if (!r) { + mboxlist_changesub(foldername, userid, auth_state, 1, 1); + syslog(LOG_DEBUG, "Ondemand subfolder: User %s, subfolder %s creation succeeded.", + userid, foldername); + return 0; + } else { + syslog(LOG_ERR, "Requested subfolder: User %s, subfolder %s creation failed. %s", + userid, foldername,error_message(r)); + return r; + } + } else + return IMAP_MAILBOX_NONEXISTENT; +} diff -Naur cyrus-imapd-2.2.3/lib/imapoptions cyrus-imapd-2.2.3-autosievefolder.uncompiled/lib/imapoptions --- cyrus-imapd-2.2.3/lib/imapoptions 2004-01-07 22:17:17.000000000 +0200 +++ cyrus-imapd-2.2.3-autosievefolder.uncompiled/lib/imapoptions 2004-01-22 19:05:14.809510000 +0200 @@ -575,6 +575,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, lmtpd and nntpd attempt to only write one copy of a message per partition and create hard links, resulting in a potentially large