--- imap/index.h.orig 2012-12-01 23:57:54.000000000 +0400 +++ imap/index.h 2015-02-21 22:31:42.000000000 +0300 @@ -208,7 +208,8 @@ int usinguid, char *name, char **copyuidp, - int nolink); + int nolink, + char hs); extern int find_thread_algorithm(char *arg); extern int index_open(const char *name, struct index_init *init, --- imap/index.c.orig 2015-02-21 11:59:36.000000000 +0300 +++ imap/index.c 2015-02-21 22:43:20.000000000 +0300 @@ -1460,6 +1460,71 @@ int index_thread(struct index_state *sta return nmsg; } +#define UPREFIX "!user." +#define UPREFIX_LEN 6 +#define UINBOX "INBOX" + +void +antispam_log(char hs, char *srcname, char*srcpath, char *dstname, + char *dstpath, unsigned first, unsigned last) +{ + static char *sep = NULL; + static char uprefix[UPREFIX_LEN+1] = UPREFIX; + char *src, *dst, *tmp; + + uprefix[UPREFIX_LEN-1] = hs; + if (sep == NULL) { + sep = getenv("IMAPLOGFS"); + if (sep == NULL) + sep = "\t"; + } + + /* srcpath and srcname may be NULL (APPEND command) */ + if (srcpath == NULL) + srcpath = ""; + if (srcname == NULL) + srcname = srcpath; + + /* convert pathname to basename */ + src = strrchr(srcpath, '/'); + if (src == NULL) + src = srcpath; + else + src++; + + dst = strrchr(dstpath, '/'); + if (dst == NULL) + dst = dstpath; + else + dst++; + + /* replace "username" with "INBOX" in case of default mailbox */ + if ((tmp = strstr(srcname, uprefix))) { + tmp += UPREFIX_LEN; + if (strcmp(src, tmp)) { + src = tmp; + if ((tmp = strchr(src, hs))) + src = tmp + 1; + } else + src = UINBOX; + } + if ((tmp = strstr(dstname, uprefix))) { + tmp += UPREFIX_LEN; + if (strcmp(dst, tmp)) { + dst = tmp; + if ((tmp = strchr(dst, hs))) + dst = tmp + 1; + } else + dst = UINBOX; + } + + syslog(LOG_INFO, "antispam: %u%s%u%s%s%s%s%s%s", + first, sep, last, sep, dstpath, sep, dst, sep, src); +} +#undef UINBOX +#undef UPREFIX_LEN +#undef UPREFIX + /* * Performs a COPY command */ @@ -1469,7 +1534,8 @@ index_copy(struct index_state *state, int usinguid, char *name, char **copyuidp, - int nolink) + int nolink, + char hs) { static struct copyargs copyargs; int i; @@ -1548,9 +1614,15 @@ index_copy(struct index_state *state, } if (!r) { + char *dp = strdup(mailbox_datapath(destmailbox)); /* we log the first name to get GUID-copy magic */ mailbox_close(&destmailbox); sync_log_mailbox_double(mailbox->name, name); + if (dp) { + antispam_log(hs, mailbox->name, mailbox_datapath(mailbox), + name, dp, baseuid, baseuid + appendstate.nummsg - 1); + free(dp); + } } return r; --- imap/imapd.c.orig 2012-12-01 23:57:54.000000000 +0400 +++ imap/imapd.c 2015-02-21 22:38:39.000000000 +0300 @@ -3201,6 +3201,10 @@ static int append_catenate(FILE *f, cons return r; } +extern void +antispam_log(char hs, char *srcname, char *srcpath, char *dstname, + char *dstpath, unsigned first, unsigned last); + /* If an APPEND is proxied from another server, * 'cur_name' is the name of the currently selected mailbox (if any) * in case we have to resolve relative URLs @@ -3226,6 +3230,7 @@ void cmd_append(char *tag, char *name, c char *newserver; unsigned numalloc = 5; struct appendstage *curstage; + char *dp = NULL; /* See if we can append */ r = (*imapd_namespace.mboxname_tointernal)(&imapd_namespace, name, @@ -3431,6 +3436,7 @@ void cmd_append(char *tag, char *name, c if (!r) { struct body *body; + dp = strdup(mailbox_datapath(appendstate.mailbox)); doappenduid = (appendstate.myrights & ACL_READ); for (i = 0; !r && i < numstage; i++) { @@ -3501,6 +3507,11 @@ void cmd_append(char *tag, char *name, c prot_printf(imapd_out, "%s OK %s\r\n", tag, error_message(IMAP_OK_COMPLETED)); } + if (dp) { + antispam_log(imapd_namespace.hier_sep, NULL, NULL, + mailboxname, dp, firstuid, firstuid + num - 1); + free(dp); + } } /* @@ -4914,7 +4925,8 @@ void cmd_copy(char *tag, char *sequence, /* local mailbox -> local mailbox */ if (!r) { r = index_copy(imapd_index, sequence, usinguid, mailboxname, - ©uid, !config_getswitch(IMAPOPT_SINGLEINSTANCESTORE)); + ©uid, !config_getswitch(IMAPOPT_SINGLEINSTANCESTORE), + imapd_namespace.hier_sep); } imapd_check(NULL, usinguid);