--- 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) {