Hi all,

i have installed the current version cyrus-imapd on Fedora 15 Beta.

Sad to say, but it doesn't offer the same functionality anymore, a delivery of mail to subfolder
in fails (e.g. in a howto at http://www.bsdforen.de/showthread.php?p=144338)

This is the way i operated my old cyrus installation for 7 years, so i'd like to claim that
it is a recommended feature.

I attached the description here
http://bugzilla.cyrusimap.org/show_bug.cgi?id=3163


Actually when i tried to fix this, i found another bug (you even cannot deliver with the correct
user id in the current release).

But for review i also post the patch here, and hope that it is integrated in one or another form
into the next release.

Regards
Baldur (which of course is not my name, but my spam protection)


--- BUILD/cyrus-imapd-2.4.8/imap/lmtpd.c        2011-04-13 16:35:22.000000000 
+0200
+++ cyrus-imapd-2.4.8.modified/imap/lmtpd.c     2011-04-24 22:24:39.548528963 
+0200
@@ -477,6 +477,61 @@
     return r;
 }
 
+/* helper function which notifies the user
+ *
+ */
+void notify_user(const char *user, char*notifyheader, const char* mailboxname)
+{
+  if (!user) {
+    return; 
+  }
+
+  const char *notifier = config_getstring(IMAPOPT_MAILNOTIFIER);
+  if (!notifier) {
+    return;
+  }
+
+  const char *notify_mailbox = mailboxname;
+  char inbox[MAX_MAILBOX_BUFFER];
+  int r;
+
+  /* translate user.foo to INBOX */
+  r = (*lmtpd_namespace.mboxname_tointernal)(&lmtpd_namespace, 
+       "INBOX", user, inbox);
+ 
+  if ( r != 0 ) {
+    size_t inboxlen = strlen(inbox);
+    if (strlen(mailboxname) >= inboxlen &&
+               !strncmp(mailboxname, inbox, inboxlen) &&
+               (!mailboxname[inboxlen] || mailboxname[inboxlen] == '.')) {
+
+               strlcpy(inbox, "INBOX", sizeof(inbox)); 
+               strlcat(inbox, mailboxname+inboxlen, sizeof(inbox));
+               notify_mailbox = inbox;
+           }
+  }
+  
+  char namebuf[MAX_MAILBOX_BUFFER];
+
+  /* translate mailboxname */
+  r = (*lmtpd_namespace.mboxname_toexternal)(&lmtpd_namespace,
+                                                   notify_mailbox,
+                                                   user, namebuf);
+  if (r != 0 ) 
+       return;
+
+  char userbuf[MAX_MAILBOX_BUFFER];
+  strlcpy(userbuf, user, sizeof(userbuf));
+  /* translate any separators in user */
+  mboxname_hiersep_toexternal(&lmtpd_namespace, userbuf,
+                             config_virtdomains ?
+                             strcspn(userbuf, "@") : 0);
+
+  notify(notifier, "MAIL", NULL, userbuf, namebuf, 0, NULL,
+                  notifyheader ? notifyheader : "");
+ 
+  return;
+}
 /* places msg in mailbox mailboxname.  
  * if you wish to use single instance store, pass stage as non-NULL
  * if you want to deliver message regardless of duplicates, pass id as NULL
@@ -503,84 +558,61 @@
     struct appendstate as;
     unsigned long uid;
     const char *notifier;
+    
+    syslog(LOG_DEBUG, "deliver_mailbox: 
user=%s,mailboxname=%s,quotaoverride=%i,acloverride=%i", user, 
mailboxname,quotaoverride,acloverride);
+
+    r = append_setup(&as, mailboxname, authuser, authstate, 
+                       acloverride   ?         0 : ACL_POST, 
+                       quotaoverride ? (long) -1 : 
config_getswitch(IMAPOPT_LMTP_STRICT_QUOTA) ?  (long) size : 0);
 
-    r = append_setup(&as, mailboxname,
-                    authuser, authstate, acloverride ? 0 : ACL_POST, 
-                    quotaoverride ? (long) -1 :
-                    config_getswitch(IMAPOPT_LMTP_STRICT_QUOTA) ?
-                    (long) size : 0);
+    if ( r != 0 ) {
+      return r;
+    }
 
     /* check for duplicate message */
-    if (!r && id && dupelim && !(as.mailbox->i.options & OPT_IMAP_DUPDELIVER) 
&&
-       duplicate_check(id, strlen(id), mailboxname, strlen(mailboxname))) {
+    if ( id 
+       && dupelim 
+       && !(as.mailbox->i.options & OPT_IMAP_DUPDELIVER) 
+       && duplicate_check(id, strlen(id), mailboxname, strlen(mailboxname))) {
+
        duplicate_log(id, mailboxname, "delivery");
        append_abort(&as);
        return 0;
     }
 
-    if (!r && !content->body) {
+    if (!content->body) {
        /* parse the message body if we haven't already,
           and keep the file mmap'ed */
        r = message_parse_file(f, &content->base, &content->len, 
&content->body);
+       if (r != 0) {
+         return r;
+        }
     }
 
-    if (!r) {
-       r = append_fromstage(&as, &content->body, stage, 0,
+    r = append_fromstage(&as, &content->body, stage, 0,
                             (const char **) flag, nflags, !singleinstance);
-
-       if (r) {
-           append_abort(&as);
-       } else {
-           struct mailbox *mailbox = NULL;
-           /* hold the mailbox open until the duplicate mark is done */
-           r = append_commit(&as, quotaoverride ? -1 : 0, NULL, &uid,
-                             NULL, &mailbox);
-           if (!r) {
-               syslog(LOG_INFO, "Delivered: %s to mailbox: %s",
-                      id, mailboxname);
-               if (dupelim && id) {
-                   duplicate_mark(id, strlen(id), mailboxname, 
-                                  strlen(mailboxname), time(NULL), uid);
-               }
-               mailbox_close(&mailbox);
-           }
-       }
-    }
-
-    if (!r && user && (notifier = config_getstring(IMAPOPT_MAILNOTIFIER))) {
-       char inbox[MAX_MAILBOX_BUFFER];
-       char namebuf[MAX_MAILBOX_BUFFER];
-       char userbuf[MAX_MAILBOX_BUFFER];
-       const char *notify_mailbox = mailboxname;
-       int r2;
-
-       /* translate user.foo to INBOX */
-       if (!(*lmtpd_namespace.mboxname_tointernal)(&lmtpd_namespace,
-                                                   "INBOX", user, inbox)) {
-           size_t inboxlen = strlen(inbox);
-           if (strlen(mailboxname) >= inboxlen &&
-               !strncmp(mailboxname, inbox, inboxlen) &&
-               (!mailboxname[inboxlen] || mailboxname[inboxlen] == '.')) {
-               strlcpy(inbox, "INBOX", sizeof(inbox)); 
-               strlcat(inbox, mailboxname+inboxlen, sizeof(inbox));
-               notify_mailbox = inbox;
-           }
-       }
-
-       /* translate mailboxname */
-       r2 = (*lmtpd_namespace.mboxname_toexternal)(&lmtpd_namespace,
-                                                   notify_mailbox,
-                                                   user, namebuf);
-       if (!r2) {
-           strlcpy(userbuf, user, sizeof(userbuf));
-           /* translate any separators in user */
-           mboxname_hiersep_toexternal(&lmtpd_namespace, userbuf,
-                                       config_virtdomains ?
-                                       strcspn(userbuf, "@") : 0);
-           notify(notifier, "MAIL", NULL, userbuf, namebuf, 0, NULL,
-                  notifyheader ? notifyheader : "");
-       }
+    if (r !=0 ) {
+      append_abort(&as);
+      return r; 
+    } 
+
+    struct mailbox *mailbox = NULL;
+    /* hold the mailbox open until the duplicate mark is done */
+    r = append_commit(&as, quotaoverride ? -1 : 0, NULL, &uid,
+                     NULL, &mailbox);
+    if ( r !=0 ) {
+      return r;
+    }
+
+    syslog(LOG_INFO, "Delivered: %s to mailbox: %s", id, mailboxname);
+
+    if (dupelim && id) {
+      duplicate_mark(id, strlen(id), mailboxname, 
+      strlen(mailboxname), time(NULL), uid);
     }
+    mailbox_close(&mailbox);
+   
+    notify_user(user,notifyheader,mailboxname); 
 
     return r;
 }
@@ -671,6 +703,9 @@
     }
 }
 
+
+
+
 int deliver_local(deliver_data_t *mydata, char **flag, int nflags,
                  const char *username, const char *mailboxname)
 {
@@ -679,66 +714,91 @@
     int quotaoverride = msg_getrcpt_ignorequota(md, mydata->cur_rcpt);
     int ret;
 
+    syslog(LOG_DEBUG, "deliver_local : user=%s 
mailbox=%s",username,mailboxname);
+
     /* case 1: shared mailbox request */
-    if (!*username || username[0] == '@') {
-       if (*username) snprintf(namebuf, sizeof(namebuf), "%s!", username+1);
+    if (!*username || username[0] == '@') 
+    {
+       if (*username) 
+               snprintf(namebuf, sizeof(namebuf), "%s!", username+1);
        strlcat(namebuf, mailboxname, sizeof(namebuf));
 
-       return deliver_mailbox(md->f, mydata->content, mydata->stage,
+       ret = deliver_mailbox(md->f, mydata->content, mydata->stage,
                               md->size, flag, nflags,
                               mydata->authuser, mydata->authstate, md->id,
                               NULL, mydata->notifyheader,
                               namebuf, quotaoverride, 0);
+       if (ret == 0 )  {
+         syslog(LOG_DEBUG, "delivered into shared mailbox %s", namebuf);
+       } 
+       return ret;
     }
 
     /* case 2: ordinary user */
     ret = (*mydata->namespace->mboxname_tointernal)(mydata->namespace,
                                                    "INBOX",
                                                    username, namebuf);
+    if ( ret != 0 ) {
+      return ret;
+    }
+    
+    struct auth_state *authstate = auth_newstate(username);
+    tail = namebuf + strlen(namebuf);
 
-    if (!ret) {
-       int ret2 = 1;
+    if ( !mailboxname ) {
+       goto normaldelivery;
+    }
 
-       tail = namebuf + strlen(namebuf);
-       if (mailboxname) {
-           strlcat(namebuf, ".", sizeof(namebuf));
-           strlcat(namebuf, mailboxname, sizeof(namebuf));
-
-           ret2 = deliver_mailbox(md->f, mydata->content, mydata->stage,
-                                  md->size, flag, nflags,
-                                  mydata->authuser, mydata->authstate, md->id,
-                                  username, mydata->notifyheader,
-                                  namebuf, quotaoverride, 0);
-       }
-       if (ret2 == IMAP_MAILBOX_NONEXISTENT && mailboxname &&
-           config_getswitch(IMAPOPT_LMTP_FUZZY_MAILBOX_MATCH) &&
-           fuzzy_match(namebuf)) {
-           /* try delivery to a fuzzy matched mailbox */
-           ret2 = deliver_mailbox(md->f, mydata->content, mydata->stage,
-                                  md->size, flag, nflags,
-                                  mydata->authuser, mydata->authstate, md->id,
-                                  username, mydata->notifyheader,
-                                  namebuf, quotaoverride, 0);
-       }
-       if (ret2) {
-           /* normal delivery to INBOX */
-           struct auth_state *authstate = auth_newstate(username);
 
-           *tail = '\0';
+    /* if the prefix is already existing in the mailbox name, then do not 
attach him */
+    if ( strncmp(mailboxname,namebuf,strlen(namebuf)) == 0 ) {
+      strncpy(namebuf,mailboxname,strlen(mailboxname));
+    } else  {
+      strlcat(namebuf, ".", sizeof(namebuf));
+      strlcat(namebuf, mailboxname, sizeof(namebuf));
+    }
 
-           ret = deliver_mailbox(md->f, mydata->content, mydata->stage,
+    ret = deliver_mailbox(md->f, mydata->content, mydata->stage,
+                          md->size, flag, nflags,
+                          (char *) username, authstate, md->id,
+                          username, mydata->notifyheader,
+                          namebuf, quotaoverride, 0);  
+    if (ret == 0 )  {
+      syslog(LOG_DEBUG, "delivered into mailbox %s", namebuf);
+      return ret; 
+    }
+
+     /* try delivery to a fuzzy matched mailbox , if enabled*/
+    if ( ret == IMAP_MAILBOX_NONEXISTENT  
+        && config_getswitch(IMAPOPT_LMTP_FUZZY_MAILBOX_MATCH) 
+        && fuzzy_match(namebuf)) {
+       
+        ret = deliver_mailbox(md->f, mydata->content, mydata->stage,
+                               md->size, flag, nflags,
+                               (char *) username, authstate, md->id,
+                               username, mydata->notifyheader,
+                               namebuf, quotaoverride, 0);
+    }
+    if (ret == 0 ) {
+      syslog(LOG_DEBUG, "delivered with fuzzymatch into mailbox %s", namebuf);
+      return ret;
+    }
+
+normaldelivery:
+    /* normal delivery to INBOX */
+    *tail = '\0';
+    ret = deliver_mailbox(md->f, mydata->content, mydata->stage,
                                  md->size, flag, nflags,
                                  (char *) username, authstate, md->id,
                                  username, mydata->notifyheader,
                                  namebuf, quotaoverride, 1);
-
-           if (authstate) auth_freestate(authstate);
-       }
+    if (ret == 0 ) {
+      syslog(LOG_DEBUG, "delivered into default mailbox %s",namebuf);
     }
+    if (authstate) auth_freestate(authstate);
 
     return ret;
 }
-
 int deliver(message_data_t *msgdata, char *authuser,
            struct auth_state *authstate)
 {

Reply via email to