;;; crm114.el --- A CRM114 plugin for GNUS ;; Copyright (C) 2008 Daniel Franke ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as ;; published by the Free Software Foundation; either version 2, or (at ;; your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; The following documentation assumes basic knowledge of GNU Emacs ;; and the workings of GNUS spam filtering. If you are not already ;; familiar with it, read the section of the GNUS manual entitled "The ;; Spam Package". ;; This is a plugin to support spam filtering using CRM114 in GNUS. ;; It integrates with the standard spam filtering framework defined by ;; gnus/spam.el. ;; To take advantage of CRM114's caching features, it is recommended ;; that you filter incoming mail through mailreaver somewhere beneath ;; emacs in your mail stack, such as through procmail, so that the ;; needed X-CRM114-CacheID header will be inserted. If you do not do ;; this, then the plugin will still work. However, it is then ;; strongly recommended that you set `spam-log-to-registry' to true in ;; order to prevent double training, although this is a good idea ;; regardless. You should also customize the variable ;; `spam-crm114-remove-headers'. If you do use caching, then this ;; variable will have no effect on training since CRM114 will always ;; use its cached copy of the message rather than the version that you ;; send it. ;;; Installation: ;; To use this plugin, simply insert the line ;; ;; (require 'crm114) ;; ;; into your ~/.emacs. (spam-initialize) will be called ;; automatically. The variable `spam-use-crm114', which enables spam ;; filtering using this plugin, is set to true by default, since it is ;; assumed that if you are installing and loading this plugin, then ;; you probably want to use it. ;; To enable training, add (spam spam-use-crm114) and/or (ham spam-use-crm114) ;; to the `spam-process' group parameter. ;;; Customization: ;; The customization group for this plugin is named `crm114'. You will ;; probably need to customize the variable `spam-crm114-home'; all other ;; settings have sensible defaults. ;;; Notes: ;; This plugin is accompanied by a patch against gnus.el. Application ;; of this patch is completely optional; it adds CRM114 to certain ;; options in the GNUS customization group for spam filtering. Most ;; users will use group parameters in lieu of these customizations, ;; and they can always be set by hand rather than from customize. (require 'spam) (load-library "cl-extra") (defgroup crm114 nil "CRM114 configuration." :version "22.1" :group 'spam) (defcustom spam-crm114-formail (executable-find "formail") "Name of the formail program" :type '(file :tag "Location of formail") :group 'crm114) (defcustom spam-crm114-program (executable-find "crm") "Name of the crm114 program" :type '(file :tag "Location of crm1114") :group 'crm114) (defcustom spam-crm114-mailreaver-name "mailreaver.crm" "Name of the mailreaver script" :type 'file :group 'crm114) (defcustom spam-crm114-home (expand-file-name "~/.crm114") "Directory containing mailfilter.cf and training files" :type 'directory :group 'crm114) (defcustom spam-crm114-remove-headers '("X-CRM114-Version" "X-CRM114-Status" "X-CRM114-Notice" "X-Spam-Flag" "X-Spam-Status" "X-Spam-Level" "X-Spam-Checker-Version") "List of headers to remove before training" :type '(repeat string) :group 'crm114) (defvar spam-use-crm114 t "true if CRM114 should be used.") (defvar gnus-group-spam-exit-processor-crm114 "crm114-spam" "The CRM114 summary exit spam processor. Only applicable to spam groups.") (defvar gnus-group-ham-exit-processor-crm114 "crm114-ham" "The CRM114 summary exit ham processor. Only applicable to non-spam (unclassified and ham) groups.") ;; We need to filter incoming mail through CRM114 even if its ;; headers indicate that we have already done so. Otherwise, ;; spammers could forge the headers. (defun spam-check-crm114 () "Run CRM114 on an article to determine whether it's spam." (let ((article-buffer-name (buffer-name)) (spam-split-group (if spam-split-symbolic-return 'spam spam-split-group))) (with-temp-buffer (let ((temp-buffer-name (buffer-name))) (save-excursion (set-buffer article-buffer-name) (apply 'call-process-region (point-min) (point-max) spam-crm114-formail nil temp-buffer-name nil (mapcan (lambda (header) (list "-I" header)) spam-crm114-remove-headers)) (set-buffer temp-buffer-name) (call-process-region (point-min) (point-max) spam-crm114-program t t nil "--dontstore" "-u" spam-crm114-home spam-crm114-mailreaver-name) (goto-char (point-min)) (when (re-search-forward "^X-CRM114-Status: SPAM" nil t) spam-split-group)))))) (defun spam-crm114-register-with-crm114 (articles spam &optional unregister) (dolist (article articles) (let ((article-string (spam-get-article-as-string article)) (db spam-crm114-home)) (when (stringp article-string) (with-temp-buffer (let ((first-buffer (buffer-name))) (with-temp-buffer (let ((second-buffer (buffer-name))) (set-buffer first-buffer) (insert article-string) (apply 'call-process-region (point-min) (point-max) spam-crm114-formail nil second-buffer nil (mapcan (lambda (header) (list "-I" header)) spam-crm114-remove-headers)) (set-buffer second-buffer) (apply 'call-process-region (point-min) (point-max) spam-crm114-program nil nil nil "-u" spam-crm114-home spam-crm114-mailreaver-name (if spam "--spam" "--good") (if unregister '("undo") nil)))))))))) (defun spam-crm114-register-spam-routine (articles &optional unregister) (message "In spam routine, %d articles." (length articles)) (spam-crm114-register-with-crm114 articles t unregister)) (defun spam-crm114-unregister-spam-routine (articles) (spam-crm114-register-with-crm114 articles t t)) (defun spam-crm114-register-ham-routine (articles &optional unregister) (message "In ham routine, %d articles." (length articles)) (spam-crm114-register-with-crm114 articles nil unregister)) (defun spam-crm114-unregister-ham-routine (articles) (spam-crm114-register-with-crm114 articles nil t)) (spam-initialize) (add-to-list 'spam-list-of-checks '(spam-use-crm114 . spam-check-crm114)) (add-to-list 'spam-list-of-statistical-checks 'spam-use-crm114) (add-to-list 'spam-list-of-processors '(gnus-group-ham-exit-processor-crm114 ham spam-use-crm114)) (add-to-list 'spam-list-of-processors '(gnus-group-spam-exit-processor-crm114 spam spam-use-crm114)) (add-to-list 'spam-registration-functions '(spam-use-crm114 spam-crm114-register-ham-routine spam-crm114-register-spam-routine spam-crm114-unregister-ham-routine spam-crm114-unregister-spam-routine)) (provide 'crm114)