aboutsummaryrefslogtreecommitdiffstats
path: root/antispam-storage-1.0.c
diff options
context:
space:
mode:
Diffstat (limited to 'antispam-storage-1.0.c')
-rw-r--r--antispam-storage-1.0.c144
1 files changed, 137 insertions, 7 deletions
diff --git a/antispam-storage-1.0.c b/antispam-storage-1.0.c
index e1b00fa..1949454 100644
--- a/antispam-storage-1.0.c
+++ b/antispam-storage-1.0.c
@@ -12,6 +12,7 @@
#include "array.h"
#include "istream.h"
#include "mail-search.h"
+#include "mail-index.h"
#include "mail-storage-private.h"
#include "antispam-plugin.h"
@@ -53,6 +54,10 @@ struct antispam_mailbox {
unsigned int save_hack:1;
};
+struct antispam_mail {
+ struct mail_vfuncs super;
+};
+
static unsigned int antispam_storage_module_id = 0;
static bool antispam_storage_module_id_set = FALSE;
@@ -257,6 +262,98 @@ antispam_transaction_commit(struct mailbox_transaction_context *ctx,
return ret;
}
+static int
+antispam_mail_update_keywords(struct mail *mail,
+ enum modify_type modify_type,
+ struct mail_keywords *keywords)
+{
+ struct mail_private *pmail = (struct mail_private *)mail;
+ struct antispam_mail *amail = ANTISPAM_CONTEXT(pmail);
+ int ret;
+ unsigned int i, numkwds;
+ const array_t *idxkwd = mail_index_get_keywords(keywords->index);
+ const char *const *keyword_names = array_get(idxkwd, &numkwds);
+ const char *const *orig_keywords;
+ bool previous_spam_keyword, now_spam_keyword;
+
+ switch (modify_type) {
+ case MODIFY_ADD:
+ debug("adding keyword(s)\n");
+ break;
+ case MODIFY_REMOVE:
+ debug("removing keyword(s)\n");
+ break;
+ case MODIFY_REPLACE:
+ debug("replacing keyword(s)\n");
+ break;
+ default:
+ i_assert(0);
+ }
+
+ orig_keywords = pmail->v.get_keywords(mail);
+ if (orig_keywords) {
+ debug("original keyword list:\n");
+ while (*orig_keywords) {
+ debug(" * %s\n", *orig_keywords);
+ if (keyword_is_spam(*orig_keywords))
+ previous_spam_keyword = TRUE;
+ orig_keywords++;
+ }
+ }
+
+ debug("keyword list:\n");
+
+ for (i = 0; i < keywords->count; i++) {
+ unsigned int idx = keywords->idx[i];
+
+ i_assert(idx < numkwds);
+
+ debug(" * %s\n", keyword_names[idx]);
+
+ switch (modify_type) {
+ case MODIFY_ADD:
+ case MODIFY_REPLACE:
+ if (keyword_is_spam(keyword_names[idx]))
+ now_spam_keyword = TRUE;
+ break;
+ case MODIFY_REMOVE:
+ if (keyword_is_spam(keyword_names[idx]))
+ now_spam_keyword = FALSE;
+ break;
+ default:
+ i_assert(0);
+ }
+ }
+
+ ret = amail->super.update_keywords(mail, modify_type, keywords);
+
+ debug("ret = %d\n", ret);
+
+ debug("previous-spam, now-spam: %d, %d\n",
+ previous_spam_keyword, now_spam_keyword);
+
+ if (previous_spam_keyword != now_spam_keyword) {
+ /*
+ * Call backend here.
+ *
+ * TODO: It is not clear how to roll back the
+ * keyword change if the backend fails.
+ */
+ }
+
+ return ret;
+}
+
+static void
+antispam_mail_free(struct mail *mail)
+{
+ struct mail_private *pmail = (struct mail_private *)mail;
+ struct antispam_mail *amail = ANTISPAM_CONTEXT(pmail);
+
+ amail->super.free(mail);
+ i_free(amail);
+}
+
static struct mailbox_transaction_context *
antispam_mailbox_transaction_begin(struct mailbox *box,
enum mailbox_transaction_flags flags)
@@ -296,6 +393,33 @@ antispam_mailbox_transaction_rollback(struct mailbox_transaction_context *ctx)
asbox->super.transaction_rollback(ctx);
}
+static struct mail *
+antispam_mailbox_mail_alloc(struct mailbox_transaction_context *ctx,
+ enum mail_fetch_field wanted_fields,
+ struct mailbox_header_lookup_ctx *wanted_headers)
+{
+ struct antispam_mailbox *asbox = ANTISPAM_CONTEXT(ctx->box);
+ struct antispam_mail *amail = i_new(struct antispam_mail, 1);
+ struct mail_private *pmail;
+
+ /* XXX: is this cast the right thing to do? */
+ pmail = (struct mail_private *) asbox->super.mail_alloc(
+ ctx,
+ wanted_fields,
+ wanted_headers);
+
+ amail->super = pmail->v;
+
+ array_idx_set(&pmail->module_contexts,
+ antispam_storage_module_id,
+ &amail);
+
+ pmail->v.update_keywords = antispam_mail_update_keywords;
+ pmail->v.free = antispam_mail_free;
+
+ return (struct mail *)pmail;
+}
+
static struct mailbox *antispam_mailbox_open(struct mail_storage *storage,
const char *name,
struct istream *input,
@@ -314,13 +438,19 @@ static struct mailbox *antispam_mailbox_open(struct mail_storage *storage,
asbox->save_hack = FALSE;
asbox->movetype = MMT_APPEND;
- /* override save_init to override want_mail, we need that */
- box->v.save_init = antispam_save_init;
- box->v.save_finish = antispam_save_finish;
- box->v.transaction_begin = antispam_mailbox_transaction_begin;
- box->v.transaction_commit = antispam_mailbox_transaction_commit;
- box->v.transaction_rollback = antispam_mailbox_transaction_rollback;
- box->v.copy = antispam_copy;
+ if (need_folder_hook) {
+ /* override save_init to override want_mail, we need that */
+ box->v.save_init = antispam_save_init;
+ box->v.save_finish = antispam_save_finish;
+ box->v.transaction_begin = antispam_mailbox_transaction_begin;
+ box->v.transaction_commit = antispam_mailbox_transaction_commit;
+ box->v.transaction_rollback = antispam_mailbox_transaction_rollback;
+ box->v.copy = antispam_copy;
+ }
+
+ if (need_keyword_hook)
+ box->v.mail_alloc = antispam_mailbox_mail_alloc;
+
array_idx_set(&box->module_contexts, antispam_storage_module_id,
&asbox);
return box;