diff -Naur cyrus-imapd-2.2.2-BETA/README.autocreate cyrus-imapd-2.2.2-BETA.autocreate/README.autocreate
--- cyrus-imapd-2.2.2-BETA/README.autocreate	1970-01-01 02:00:00.000000000 +0200
+++ cyrus-imapd-2.2.2-BETA.autocreate/README.autocreate	2004-01-03 19:44:08.000000000 +0200
@@ -0,0 +1,134 @@
+Cyrus IMAP autocreate Inbox 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 
+
+The design of Cyrus IMAP server does not predict the automatic creation of users'
+INBOX folders. The creation of a user's INBOX is considered to be an external task,
+that has to be completed as part of the user e-mail account creation procedure. 
+Hence, to create a new e-mail account the site administrator has to 
+a) Include the new account in the user database for the authentication procedure
+   (e.g. sasldb, shadow, mysql, ldap).
+b) Create the corresponding INBOX folder. 
+
+Alternatively, the user, if succesfully authenticated, may create his own INBOX folder,
+as long as the configuration of the site allows it (see "autocreatequota" in imapd.conf).
+Unlike what uncareful readers may think, enabling the "autocreatequota" option, doesn't 
+lead to the automatic INBOX folder creation by Cyrus IMAP server.
+In fact, "autocreate" means that the IMAP clients are allowed to automatically create 
+the user INBOX. 
+
+This patch adds the functionality of automatic creation of the users' INBOX folders into
+the Cyrus IMAP server. It is implemented as two features, namely the  "create on login"
+and "create on post".
+ 
+
+
+Create on login
+===============
+This feauture provides automatic creation of a user's INBOX folder when all of the 
+following requirements are met:
+
+i)  The user has succesfully passed the authentication procedure.
+
+ii) The user's authorization ID (typically the same as the user's
+authentication ID)  doesn't belong to the imap_admins or admins
+accounts (see imapd.conf).
+
+iii) The "autocreatequota" option in the imap configuration file 
+has been set to a non zero value. 
+
+iv) The corresponding to the user's authorizationID INBOX folder
+does not exist.
+
+The user's first login is the most typical case when all four requirements are met. 
+Note that if the authenticatedID is allowed to proxy to another account for which 
+all of the above requirements are met, the corresponding INBOX folder for that account 
+will be created.
+
+
+
+Create on post
+==============
+This feauture provides automatic creation of a user's INBOX folder when all of the 
+following requirements are met. 
+
+i) An e-mail message addressed to the user has been received.  
+
+ii) The recipient is not any of the imap_admins or admins accounts. 
+Note that passing e-mails to admins or imap_admins accounts from 
+the MTA to LMTP should be avoided in any case.
+
+iii) The recipient's INBOX does not exist.
+
+iv) The "autocreatequota" option in the imap configuration file 
+has been set to a non zero value. 
+
+v) The "createonpost" option in the imap configuration file 
+has been switched on. 
+
+
+Besides the automatic creation of INBOX folder, additional functionalities are
+provided:
+
+A) Automatic creation of INBOX subfolders controlled by "autocreateinboxfolders"
+configuration option. e.g 
+
+autocreateinboxfolders: sent|drafts|spam|templates
+
+B) Automatic subscription of INBOX subfolders controlled by "autosubscribeinboxfolders"
+configuration option. e.g
+
+autosubscribeinboxfolders: sent|spam
+
+Obviously, only subscription to subfolders included in the "autocreateinboxfolder"
+list is meaningfull. 
+
+C) Automatic subscription to shared folders (bulletin boards). The user gets
+automatically subscribed to the shared folders declared in the "autosubscribesharedfolders"
+configuration option in imapd.conf.
+e.g autosubscribesharedfolders: public_folder | public_folder.subfolder
+
+In order the above action to succeed, the shared folder has to pre-exist the INBOX creation
+and the user must have the apropriate permissions in order to be able to subscribe to the
+shared folder.
+
+
+
+Issues to be considered 
+=======================
+
+I) In order to use the create on post feauture one should be absolutely sure that: 
+a) The MTA checks the validity of the e-mail recipient before sending the e-mail to
+LMTP. This is an RFC821 requirement. This usually expands to "the mta should be 
+able to use the account database as user mailbox database". 
+b) Only authorized accounts/services can talk to LMTP.
+
+II) Especially in the case of imap logins, the current patch implementation checks
+for the INBOX folder existence upon login, causing an extra mailbox lookup in most 
+of the cases. 
+A better approach would be to chase the "IMAP_MAILBOX_NONEXISTENT" error code and
+check if the error is associated with an INBOX folder. However, this would mess up
+Cyrus code. The way it was implemented may not have been the most performance
+optimized, but it produces a much cleaner and simple patch.
+
+
+
+Virtual Domains Support
+=======================
+
+Virtual domains are supported by all versions of the patch for cyrus-imapd-2.2.1-BETA and 
+later. However, it is not possible to declare different INBOX subfolders to be created or 
+shared folders to be subscribed to for every domain.
+
+
+
+Things to be done
+=================
+
+1. Support MURDER architecture. 
+
+
+For more information and updates please visit http://email.uoa.gr/autocreate
+
diff -Naur cyrus-imapd-2.2.2-BETA/imap/imapd.c cyrus-imapd-2.2.2-BETA.autocreate/imap/imapd.c
--- cyrus-imapd-2.2.2-BETA/imap/imapd.c	2003-10-24 21:24:05.000000000 +0300
+++ cyrus-imapd-2.2.2-BETA.autocreate/imap/imapd.c	2004-01-03 19:44:13.000000000 +0200
@@ -148,6 +148,8 @@
 void shut_down(int code);
 void fatal(const char *s, int code);
 
+void autocreate_inbox(void);
+
 void cmdloop(void);
 void cmd_login(char *tag, char *user);
 void cmd_authenticate(char *tag, char *authtype, char *resp);
@@ -1553,6 +1555,50 @@
     }
 }
 
+
+
+
+
+/*
+ * Autocreate Inbox and subfolders upon login
+ */
+void autocreate_inbox()
+{
+    char inboxname[MAX_MAILBOX_NAME+1];
+    int autocreatequota;
+    int r;
+
+    /*
+     * Exlude admin's accounts
+     */
+    if (imapd_userisadmin || imapd_userisproxyadmin)
+        return;
+
+    /*
+     * Exclude anonymous
+     */
+    if (!strcmp(imapd_userid, "anonymous"))
+        return;
+
+    
+    if ((autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA))) {
+        /* This is actyally not required
+           as long as the lenght of userid is ok */
+           r = (*imapd_namespace.mboxname_tointernal) (&imapd_namespace,
+                                      "INBOX", imapd_userid, inboxname);
+           if (!r)
+               r = mboxlist_lookup(inboxname, NULL, NULL, NULL);
+
+           if (r == IMAP_MAILBOX_NONEXISTENT)
+               mboxlist_autocreateinbox(&imapd_namespace, imapd_userid,
+                         imapd_authstate, inboxname, autocreatequota);
+     }
+}
+
+
+
+
+
 /*
  * Perform a LOGIN command
  */
@@ -1696,6 +1742,9 @@
 				strcspn(imapd_userid, "@") : 0);
 
     freebuf(&passwdbuf);
+
+    autocreate_inbox();
+
     return;
 }
 
@@ -1819,6 +1868,8 @@
 				config_virtdomains ?
 				strcspn(imapd_userid, "@") : 0);
 
+    autocreate_inbox();
+
     return;
 }
 
diff -Naur cyrus-imapd-2.2.2-BETA/imap/lmtpd.c cyrus-imapd-2.2.2-BETA.autocreate/imap/lmtpd.c
--- cyrus-imapd-2.2.2-BETA/imap/lmtpd.c	2003-10-24 21:24:06.000000000 +0300
+++ cyrus-imapd-2.2.2-BETA.autocreate/imap/lmtpd.c	2004-01-03 19:44:18.000000000 +0200
@@ -149,6 +149,9 @@
 struct lmtp_func mylmtp = { &deliver, &verify_user, &shut_down,
 			    &spoolfile, &removespool, 0, 1, 0 };
 
+
+static int autocreate_inbox(char *rcpt_userid);
+
 static void usage();
 static void setup_sieve();
 
@@ -1287,6 +1290,56 @@
     exit(code);
 }
 
+
+
+
+
+
+/*
+ * Autocreate Inbox and subfolders upon login
+ */
+int autocreate_inbox(char *rcpt_userid)
+{
+    struct auth_state *authstate;
+    char inboxname[MAX_MAILBOX_NAME+1];
+    int rcptisadmin ;
+    int autocreatequota;
+    int r;
+
+    /*
+     * Exclude anonymous
+     */
+    if (!strcmp(rcpt_userid, "anonymous"))
+        return IMAP_MAILBOX_NONEXISTENT;
+
+    /*
+     * Check for autocreatequota and createonpost
+     */
+    if (!(autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA)) ||
+        !(config_getswitch(IMAPOPT_CREATEONPOST)))
+        return IMAP_MAILBOX_NONEXISTENT;
+
+    /*
+     * Exclude admin's accounts
+     */
+     authstate = auth_newstate(rcpt_userid);
+     rcptisadmin = global_authisa(authstate, IMAPOPT_ADMINS);
+     if (rcptisadmin)
+          return IMAP_MAILBOX_NONEXISTENT;
+
+     r = (*lmtpd_namespace.mboxname_tointernal) (&lmtpd_namespace,
+                                "INBOX", rcpt_userid, inboxname);
+     if (!r)
+     r = mboxlist_autocreateinbox(&lmtpd_namespace, rcpt_userid,
+                         authstate, inboxname, autocreatequota);
+     return r;
+}
+
+
+
+
+
+
 static int verify_user(const char *user, long quotacheck,
 		       struct auth_state *authstate)
 {
@@ -1338,6 +1391,12 @@
 	       - don't care about message size (1 msg over quota allowed) */
 	    r = append_check(buf, MAILBOX_FORMAT_NORMAL, authstate,
 			     0, quotacheck > 0 ? 0 : quotacheck);
+            if (r == IMAP_MAILBOX_NONEXISTENT) {
+                r = autocreate_inbox(user);
+		if (!r)
+	           r = append_check(buf, MAILBOX_FORMAT_NORMAL, authstate,
+					0, quotacheck > 0 ? 0 : quotacheck);
+	    }
 	}
     }
 
diff -Naur cyrus-imapd-2.2.2-BETA/imap/mboxlist.c cyrus-imapd-2.2.2-BETA.autocreate/imap/mboxlist.c
--- cyrus-imapd-2.2.2-BETA/imap/mboxlist.c	2003-10-24 21:24:06.000000000 +0300
+++ cyrus-imapd-2.2.2-BETA.autocreate/imap/mboxlist.c	2004-01-03 19:44:18.000000000 +0200
@@ -98,6 +98,10 @@
 static int mboxlist_changequota(const char *name, int matchlen, int maycreate,
 				void *rock);
 
+static int mboxlist_autosubscribe_sharedfolders(struct namespace *namespace,
+                        char *userid,
+                        struct auth_state *auth_state);
+
 #define FNAME_SUBSSUFFIX ".sub"
 
 /*
@@ -3065,3 +3069,208 @@
 
     return DB->abort(mbdb, tid);
 }
+
+
+#define SEP '|'
+
+/*
+ * Automatically subscribe user to a shared folder.
+ * Subscription is done successfully, if the shared
+ * folder exists and the user has the necessary 
+ * permissions.
+ */
+static int mboxlist_autosubscribe_sharedfolders(struct namespace *namespace,
+                        char *userid,
+                        struct auth_state *auth_state) {
+        
+    const char *sub ;
+    char *p, *q, *next_sub;
+    char folder [MAX_MAILBOX_NAME+1], name[MAX_MAILBOX_NAME+1], mailboxname[MAX_MAILBOX_NAME+1];
+    int len;
+    int r = 0;
+
+    if ((sub=config_getstring(IMAPOPT_AUTOSUBSCRIBESHAREDFOLDERS)) == NULL)
+	return r;
+
+    next_sub = (char *) sub;
+    while (*next_sub) {
+        for (p = next_sub ; isspace((int) *p) || *p == SEP ; p++);
+        for (next_sub = p ; *next_sub && *next_sub != SEP ; next_sub++);
+        for (q = next_sub ; q > p && (isspace((int) *q) || *q == SEP || !*q) ; q--);
+        if (!*p ) continue;
+
+        len = q - p + 1;
+        /* Check for folder length */
+        if (len  > sizeof(folder)-1)
+                continue;
+
+        if (!r) {
+                strncpy(folder, p, len);
+                folder[len] = NULL;
+
+		strlcpy(name, namespace->prefix[NAMESPACE_SHARED], sizeof(name));
+		len = strlcat(name, folder, sizeof(name));
+
+		r = (namespace->mboxname_tointernal) (namespace, name, userid,
+		                                                   mailboxname);
+	}
+								   
+        if (!r)
+		r = mboxlist_changesub(mailboxname, userid, auth_state, 1, 0);
+
+        if (!r) {
+                syslog(LOG_DEBUG,"autosubscribe: User %s to %s succeeded", 
+			userid, folder);
+        } else {
+                syslog(LOG_ERR, "autosubscribe: User %s to %s failed: %s", 
+			userid, folder, error_message(r));
+                r = 0;
+        }
+    }
+
+    return r;
+}
+
+
+int mboxlist_autocreateinbox(struct namespace *namespace,
+                        char *userid,
+                        struct auth_state *auth_state,
+                        char *mailboxname, int autocreatequota) {
+    char name [MAX_MAILBOX_NAME+1];
+    char folder [MAX_MAILBOX_NAME+1];
+    char *partition = NULL;
+    const char *crt;
+    const char *sub;
+    char *p, *q, *next_crt, *next_sub;
+    int len;
+    int r = 0;
+    int numcrt = 0;
+    int numsub = 0;
+
+#if 0
+        /*
+         * Get Partition info or return.
+         * (Here you should propably use
+         * you own "get_partition(char *userid)"
+         * function. Otherwise all new INBOXes will be
+         * created into whatever partition has been declared
+         * as default in your imapd.conf)
+         */
+
+        partition = get_partition(userid);
+
+        if (partition == NULL) {
+            /*
+             * Couldn't get partition info
+             */
+            syslog(LOG_WARNING,
+                   "Could not get imapPartition info for user %s", userid);
+            return IMAP_PARTITION_UNKNOWN;
+        }
+#endif
+
+
+    r = mboxlist_createmailbox(mailboxname, MAILBOX_FORMAT_NORMAL, NULL,
+                                      1, userid, auth_state, 0, 0, 0);
+
+    if (!r && autocreatequota > 0)
+        r = mboxlist_setquota(mailboxname, autocreatequota, 0);
+
+    if (!r)
+        r = mboxlist_changesub(mailboxname, userid,
+                              auth_state, 1, 1);
+
+    if (!r)
+    	syslog(LOG_NOTICE, "autocreateinbox: User %s, INBOX was successfully created in partition %s", 
+		userid, partition == NULL ? "default" : partition);
+    else {
+    	syslog(LOG_ERR, "autocreateinbox: User %s, INBOX failed. %s", 
+		userid, error_message(r));
+    	return r;
+    }
+
+    /* INBOX's subfolders */
+    if ((crt=config_getstring(IMAPOPT_AUTOCREATEINBOXFOLDERS)))
+        sub=config_getstring(IMAPOPT_AUTOSUBSCRIBEINBOXFOLDERS);
+
+    /* Roll through crt */
+    next_crt = (char *) crt;
+    while (next_crt!=NULL && *next_crt) {
+          for (p = next_crt ; isspace((int) *p) || *p == SEP ; p++);
+          for (next_crt = p ; *next_crt && *next_crt != SEP ; next_crt++);
+          for (q = next_crt ; q > p && (isspace((int) *q) || *q == SEP || !*q); q--);
+
+          if (!*p) continue;
+
+          len = q - p + 1;
+
+          /* First time we check for length */
+          if (len > sizeof(folder) - 5)
+              r = IMAP_MAILBOX_BADNAME;
+
+          if (!r) {
+                  strncpy(folder, p, len);
+                  folder[len] = '\0';
+
+                  strlcpy(name, namespace->prefix[NAMESPACE_INBOX], sizeof(name));
+                  len = strlcat(name, folder, sizeof(name));
+          }
+
+          if (!r)
+            r = (namespace->mboxname_tointernal) (namespace, name, userid,
+                                                 mailboxname);
+          if (!r)
+             r = mboxlist_createmailbox(mailboxname, MAILBOX_FORMAT_NORMAL, NULL,
+                                            1, userid, auth_state, 0, 0, 0);
+
+
+          if (!r) {
+	     numcrt++;
+	     syslog(LOG_DEBUG, "autocreateinbox: User %s, subfolder %s creation succeeded.", 
+	     	userid, name);
+	  } else {
+             syslog(LOG_ERR, "autocreateinbox: User %s, subfolder %s creation failed. %s", 
+	     	userid, name, error_message(r));
+             r=0;
+             continue;
+          }
+
+          /* Roll through sub */
+          next_sub = (char *) sub;
+          while (next_sub!=NULL && *next_sub) {
+                for (p = next_sub ; isspace((int) *p) || *p == SEP ; p++);
+                for (next_sub = p ; *next_sub && *next_sub != SEP ; next_sub++);
+                for (q = next_sub ; q > p && (isspace((int) *q) || *q == SEP || !*q) ; q--);
+                if (!*p ) continue;
+
+                len = q - p + 1;
+
+                if (len != strlen(folder) || strncmp(folder, p, len))
+                    continue;
+
+                r = mboxlist_changesub(mailboxname, userid, auth_state, 1, 1);
+
+		if (!r) {
+  		    numsub++;
+  		    syslog(LOG_DEBUG,"autocreateinbox: User %s, subscription to %s succeeded",
+		    	userid, name);
+           	} else
+                    syslog(LOG_ERR, "autocreateinbox: User %s, subscription to  %s failed. %s",
+		    	userid, name, error_message(r));
+
+                break;
+         }
+    }
+
+    if (*crt)
+    	syslog(LOG_INFO, "User %s, Inbox subfolders, created %d, subscribed %d", 
+		userid, numcrt, numsub);
+
+    /*
+     * Check if shared folders are available for subscription.
+     */
+    mboxlist_autosubscribe_sharedfolders(namespace, userid, auth_state);
+
+    return r;
+}
+
diff -Naur cyrus-imapd-2.2.2-BETA/imap/mboxlist.h cyrus-imapd-2.2.2-BETA.autocreate/imap/mboxlist.h
--- cyrus-imapd-2.2.2-BETA/imap/mboxlist.h	2003-10-22 21:50:08.000000000 +0300
+++ cyrus-imapd-2.2.2-BETA.autocreate/imap/mboxlist.h	2004-01-03 19:44:20.000000000 +0200
@@ -197,4 +197,9 @@
 int mboxlist_commit(struct txn *tid);
 int mboxlist_abort(struct txn *tid);
 
+int mboxlist_autocreateinbox(struct namespace *namespace,
+                        char *userid,
+                        struct auth_state *auth_state,
+                        char *mailboxname, int autocreatequota);
+
 #endif
diff -Naur cyrus-imapd-2.2.2-BETA/imap/pop3d.c cyrus-imapd-2.2.2-BETA.autocreate/imap/pop3d.c
--- cyrus-imapd-2.2.2-BETA/imap/pop3d.c	2003-10-24 21:24:07.000000000 +0300
+++ cyrus-imapd-2.2.2-BETA.autocreate/imap/pop3d.c	2004-01-03 19:44:21.000000000 +0200
@@ -151,6 +151,8 @@
 static char popd_apop_chal[45 + MAXHOSTNAMELEN + 1]; /* <rand.time@hostname> */
 static void cmd_apop(char *response);
 
+static int autocreate_inbox(char *inboxname);
+
 static void cmd_auth(char *arg);
 static void cmd_capa(void);
 static void cmd_pass(char *pass);
@@ -1299,6 +1301,49 @@
     }
 }
 
+
+
+
+/*
+ * Autocreate Inbox and subfolders upon login
+ */
+int autocreate_inbox(char *inboxname)
+{
+    struct auth_state *authstate;
+    int userisadmin ;
+    int autocreatequota;
+    int r;
+
+    /*
+     * Exclude anonymous
+     */
+    if (!strcmp(popd_userid, "anonymous"))
+        return IMAP_MAILBOX_NONEXISTENT;
+
+    /*
+     * Check for autocreatequota
+     */
+    if (!(autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA)))
+        return IMAP_MAILBOX_NONEXISTENT;
+
+    /*
+     * Exclude admin's accounts
+     */
+
+     authstate = auth_newstate(popd_userid);
+     userisadmin = global_authisa(authstate, IMAPOPT_ADMINS);
+     if (userisadmin)
+          return IMAP_MAILBOX_NONEXISTENT;
+
+     r = mboxlist_autocreateinbox(&popd_namespace, popd_userid,
+                         authstate, inboxname, autocreatequota);
+     return r;
+}
+
+
+
+
+
 /*
  * Complete the login process by opening and locking the user's inbox
  */
@@ -1321,6 +1366,11 @@
 					      userid, inboxname);
 
     if (!r) r = mboxlist_detail(inboxname, &type, NULL, &server, NULL, NULL);
+
+    /* Try once again after autocreate_inbox */
+    if (r == IMAP_MAILBOX_NONEXISTENT && !(r = autocreate_inbox(inboxname)))
+    	 r = mboxlist_detail(inboxname, &type, NULL, &server, NULL, NULL);
+     
     if (r) {
 	sleep(3);
 	prot_printf(popd_out, "-ERR [SYS/PERM] Unable to locate maildrop\r\n");
@@ -1359,6 +1409,7 @@
 	popd_login_time = time(0);
 
 	r = mailbox_open_header(inboxname, 0, &mboxstruct);
+
 	if (r) {
 	    sleep(3);
 	    prot_printf(popd_out, "-ERR [SYS/PERM] Unable to open maildrop\r\n");
diff -Naur cyrus-imapd-2.2.2-BETA/lib/imapoptions cyrus-imapd-2.2.2-BETA.autocreate/lib/imapoptions
--- cyrus-imapd-2.2.2-BETA/lib/imapoptions	2003-10-22 23:05:15.000000000 +0300
+++ cyrus-imapd-2.2.2-BETA.autocreate/lib/imapoptions	2004-01-03 19:44:22.000000000 +0200
@@ -139,6 +139,30 @@
    creating the mailbox INBOX.  The user's quota is set to the value
    if it is positive, otherwise the user has unlimited quota. */
 
+
+{ "createonpost", 0, SWITCH }
+/* If yes, when lmtpd receives an incoming mail for an INBOX that does not exist,
+   then the INBOX is automatically created by lmtpd. */
+
+{ "autocreateinboxfolders", NULL, STRING }
+/* If a user does not have an INBOX created then the INBOX as well as some INBOX subfolders are
+   created under two conditions.
+     1. The user logins via the IMAP or the POP3 protocol. (autocreatequota option must have a nonzero value)
+     2. A message arrives for the user through the LMTPD protocol.(createonpost option must yes)
+   autocreateinboxfolders is a list of INBOX's subfolders separated by a "|", that are automatically created by the server
+   under the previous two situations. */
+
+{ "autosubscribeinboxfolders", NULL, STRING } 
+/* A list of folder names, separated by "|" that the users get automatically subscribed to, when their INBOX
+  is created.
+  These folder names must have been included in the autocreateinboxfolders option of the imapd.conf. */
+
+{ "autosubscribesharedfolders", NULL, STRING }
+/* A list of shared folders (bulletin boards), separated by "|" that the users get 
+   automatically subscribed to, after their INBOX
+   is created. The shared folder must have been created and the user must have the 
+   required permissions to get subscribed to the it. Otherwise the subscription fails. */
+
 { "configdirectory", NULL, STRING }
 /* The pathname of the IMAP configuration directory.  This field is
    required. */
