Ajout : dovecot-antispam + amavis + crm114.
[lhc/ateliers.git] / etc / dovecot / dovecot-antispam-call-backend-with-imap-keywords.patch
diff --git a/etc/dovecot/dovecot-antispam-call-backend-with-imap-keywords.patch b/etc/dovecot/dovecot-antispam-call-backend-with-imap-keywords.patch
new file mode 100644 (file)
index 0000000..11a7bce
--- /dev/null
@@ -0,0 +1,215 @@
+diff -ru a/dovecot-antispam-2.0+20120225/antispam-plugin.c b/dovecot-antispam-2.0+20120225/antispam-plugin.c
+--- a/dovecot-antispam-2.0+20120225/antispam-plugin.c  2012-02-24 20:22:48.000000000 +0100
++++ b/dovecot-antispam-2.0+20120225/antispam-plugin.c  2013-07-29 07:14:51.962245023 +0200
+@@ -246,6 +246,21 @@
+       return FALSE;
+ }
++bool keyword_is_ham(const struct antispam_config *cfg, const char *keyword)
++{
++      char **k = cfg->ham_keywords;
++
++      if (!cfg->ham_keywords)
++              return FALSE;
++
++      while (*k) {
++              if (strcmp(*k, keyword) == 0)
++                      return TRUE;
++              k++;
++      }
++
++      return FALSE;
++}
+ static int parse_folder_setting(const struct antispam_config *cfg,
+                               const char *setting, char ***strings,
+@@ -335,6 +350,17 @@
+                       iter++;
+               }
+       }
++      tmp = getenv("HAM_KEYWORDS", getenv_data);
++      if (tmp)
++              cfg->ham_keywords = p_strsplit(cfg->mem_pool, tmp, ";");
++
++      if (cfg->ham_keywords) {
++              iter = cfg->ham_keywords;
++              while (*iter) {
++                      debug(&cfg->dbgcfg, "\"%s\" is ham keyword\n", *iter);
++                      iter++;
++              }
++      }
+       tmp = getenv("BACKEND", getenv_data);
+       if (tmp) {
+diff -ru a/dovecot-antispam-2.0+20120225/antispam-plugin.h b/dovecot-antispam-2.0+20120225/antispam-plugin.h
+--- a/dovecot-antispam-2.0+20120225/antispam-plugin.h  2013-07-31 12:45:33.000000000 +0200
++++ b/dovecot-antispam-2.0+20120225/antispam-plugin.h  2013-07-30 05:22:21.248730740 +0200
+@@ -27,6 +27,7 @@
+ struct antispam_transaction_context;
+ enum classification {
++      CLASS_UNSURE,
+       CLASS_NOTSPAM,
+       CLASS_SPAM,
+ };
+@@ -72,6 +73,7 @@
+       char **unsure_folders[3]; // = { NULL,          NULL, NULL };
+       char **spam_keywords;
++      char **ham_keywords;
+       const char *signature_hdr;
+@@ -178,6 +180,7 @@
+ bool mailbox_is_trash(const struct antispam_config *cfg, struct mailbox *box);
+ bool mailbox_is_unsure(const struct antispam_config *cfg, struct mailbox *box);
+ bool keyword_is_spam(const struct antispam_config *cfg, const char *keyword);
++bool keyword_is_ham(const struct antispam_config *cfg, const char *keyword);
+ struct antispam_config *
+ antispam_setup_config(const char *(getenv)(const char *env, void *data),
+diff -ru a/dovecot-antispam-2.0+20120225/antispam-storage-2.0.c b/dovecot-antispam-2.0+20120225/antispam-storage-2.0.c
+--- a/dovecot-antispam-2.0+20120225/antispam-storage-2.0.c     2012-02-24 20:22:48.000000000 +0100
++++ b/dovecot-antispam-2.0+20120225/antispam-storage-2.0.c     2013-07-31 14:52:43.277922438 +0200
+@@ -310,21 +310,9 @@
+       const ARRAY_TYPE(keywords) *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(&amail->cfg->dbgcfg, "adding keyword(s)\n");
+-              break;
+-      case MODIFY_REMOVE:
+-              debug(&amail->cfg->dbgcfg, "removing keyword(s)\n");
+-              break;
+-      case MODIFY_REPLACE:
+-              debug(&amail->cfg->dbgcfg, "replacing keyword(s)\n");
+-              break;
+-      default:
+-              i_assert(0);
+-      }
++      bool previous_spam_keyword = FALSE, previous_ham_keyword = FALSE;
++      enum classification spam_class = CLASS_UNSURE;
++      struct antispam_transaction_context *ast;
+       orig_keywords = pmail->v.get_keywords(mail);
+       if (orig_keywords) {
+@@ -333,6 +321,8 @@
+                       debug(&amail->cfg->dbgcfg, " * %s\n", *orig_keywords);
+                       if (keyword_is_spam(amail->cfg, *orig_keywords))
+                               previous_spam_keyword = TRUE;
++                      if (keyword_is_ham(amail->cfg, *orig_keywords))
++                              previous_ham_keyword = TRUE;
+                       orig_keywords++;
+               }
+       }
+@@ -350,29 +340,47 @@
+               case MODIFY_ADD:
+               case MODIFY_REPLACE:
+                       if (keyword_is_spam(amail->cfg, keyword_names[idx]))
+-                              now_spam_keyword = TRUE;
++                              spam_class = CLASS_SPAM;
++                      if (keyword_is_ham(amail->cfg, keyword_names[idx]))
++                              spam_class = CLASS_NOTSPAM;
+                       break;
+               case MODIFY_REMOVE:
+                       if (keyword_is_spam(amail->cfg, keyword_names[idx]))
+-                              now_spam_keyword = FALSE;
++                              spam_class = CLASS_NOTSPAM;
++                      if (keyword_is_ham(amail->cfg, keyword_names[idx]))
++                              spam_class = CLASS_SPAM;
+                       break;
+               default:
+                       i_assert(0);
+               }
+       }
+-
++      
++      debug(&amail->cfg->dbgcfg, "spam_class=%d previous_spam_keyword=%d previous_ham_keyword=%d\n",
++       spam_class, previous_spam_keyword, previous_ham_keyword);
++      
+       amail->module_ctx.super.update_keywords(mail, modify_type, keywords);
+-
+-      debug(&amail->cfg->dbgcfg, "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.
++      
++      if (previous_spam_keyword && previous_ham_keyword) {
++              /* NOTE: avoid to call the backend two times for the same change
++               * once when adding one spam or ham keyword
++               * and once when removing the other.
++               */
++              debug(&amail->cfg->dbgcfg, "does not run backend a second time\n");
++              return;
++       }
++      
++      if (spam_class != CLASS_UNSURE) {
++              /* NOTE: on error, backend uses mail_storage_set_error()
++               * which is checked in commit() where a rollback() can be done.
+                */
++              debug(&amail->cfg->dbgcfg, "call backend->start()\n");
++              ast = amail->cfg->backend->start(amail->cfg, mail->transaction->box);
++              i_assert(ast != NULL);
++              debug(&amail->cfg->dbgcfg, "call backend->handle_mail()\n");
++              if (!amail->cfg->backend->handle_mail(amail->cfg, mail->transaction, ast, mail, spam_class)) {
++                      debug(&amail->cfg->dbgcfg, "call backend->commit()\n");
++                      amail->cfg->backend->commit(amail->cfg, mail->transaction, ast);
++               }
+       }
+ }
+@@ -401,7 +409,9 @@
+       struct antispam_mailbox *asbox = ANTISPAM_CONTEXT(ctx->box);
+       struct antispam_internal_context *ast = ANTISPAM_CONTEXT(ctx);
+-      if (antispam_transaction_commit(asbox->cfg, ctx, &ast->backendctx) < 0) {
++      if ((ctx->box->storage->error != MAIL_ERROR_NONE)
++         || antispam_transaction_commit(asbox->cfg, ctx, &ast->backendctx) < 0) {
++              debug(&asbox->cfg->dbgcfg, "transaction rollback\n");
+               if (ast->mail)
+                       mail_free(&ast->mail);
+diff -ru a/dovecot-antispam-2.0+20120225/crm114-exec.c b/dovecot-antispam-2.0+20120225/crm114-exec.c
+--- a/dovecot-antispam-2.0+20120225/crm114-exec.c      2012-02-24 20:22:48.000000000 +0100
++++ b/dovecot-antispam-2.0+20120225/crm114-exec.c      2013-07-30 06:00:16.266596502 +0200
+@@ -43,6 +43,8 @@
+       case CLASS_SPAM:
+               class_arg = "--spam";
+               break;
++      default:
++              i_assert(0);
+       }
+       /*
+diff -ru a/dovecot-antispam-2.0+20120225/dspam-exec.c b/dovecot-antispam-2.0+20120225/dspam-exec.c
+--- a/dovecot-antispam-2.0+20120225/dspam-exec.c       2012-02-24 20:22:48.000000000 +0100
++++ b/dovecot-antispam-2.0+20120225/dspam-exec.c       2013-07-31 13:28:39.217464532 +0200
+@@ -45,6 +45,8 @@
+       case CLASS_SPAM:
+               class_arg = t_strconcat("--class=", "spam", NULL);
+               break;
++      default:
++              i_assert(0);
+       }
+       /*
+diff -ru a/dovecot-antispam-2.0+20120225/pipe.c b/dovecot-antispam-2.0+20120225/pipe.c
+--- a/dovecot-antispam-2.0+20120225/pipe.c     2012-02-24 20:22:48.000000000 +0100
++++ b/dovecot-antispam-2.0+20120225/pipe.c     2013-07-31 14:16:12.164255967 +0200
+@@ -48,6 +48,8 @@
+               dest = cfg->pipe.ham_args;
+               dest_num = cfg->pipe.spam_args_num;
+               break;
++      default:
++              i_assert(0);
+       }
+       if (!dest)