From 18d35108c4abd9aebc8eef0b94ebc519eb6e8683 Mon Sep 17 00:00:00 2001 From: yamaoka Date: Sun, 4 Jan 2004 05:51:55 +0000 Subject: [PATCH] Import Gnus v5.10.4. --- ChangeLog | 4 + GNUS-NEWS | 2 + lisp/ChangeLog | 121 +++++++++ lisp/gnus-art.el | 21 +- lisp/gnus-dired.el | 6 +- lisp/gnus-group.el | 434 +++++++++++++++--------------- lisp/gnus-logic.el | 1 + lisp/gnus-nocem.el | 3 +- lisp/gnus-score.el | 90 +++++-- lisp/gnus-start.el | 32 ++- lisp/gnus-sum.el | 33 +-- lisp/gnus-util.el | 1 + lisp/gnus.el | 24 +- lisp/message.el | 1 - lisp/mml-sec.el | 26 +- lisp/mml.el | 32 ++- lisp/mml2015.el | 16 +- lisp/nnml.el | 9 +- lisp/smime.el | 23 ++ lisp/spam.el | 24 +- texi/ChangeLog | 49 ++++ texi/gnus.texi | 762 ++++++++++++++++++++++++++++++++++++---------------- texi/message.texi | 4 +- 23 files changed, 1170 insertions(+), 548 deletions(-) diff --git a/ChangeLog b/ChangeLog index d0015f1..59104b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2004-01-02 Reiner Steib + + * GNUS-NEWS: Add `gnus-group-read-ephemeral-group'. + 2003-12-23 Reiner Steib * GNUS-NEWS: Mention change of `e' in draft groups. diff --git a/GNUS-NEWS b/GNUS-NEWS index 97aa520..eb74175 100644 --- a/GNUS-NEWS +++ b/GNUS-NEWS @@ -8,6 +8,8 @@ For older news, see Gnus info node "New Features". * Changes in Oort Gnus +** `gnus-group-read-ephemeral-group' can be called interactively, using `G M'. + ** In draft groups, `e' is now bound to `gnus-draft-edit-message'. Use `B w' for `gnus-summary-edit-article' instead. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 44d78ed..8c3c124 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,124 @@ +2004-01-03 Lars Magne Ingebrigtsen + + * gnus.el: Gnus v5.10.4 is released. + +2004-01-02 Reiner Steib + + * gnus.el (gnus-mode-line-buffer-identification): Show version in + help-echo. + (gnus-read-group): Allow most group names. Changed warning. + +2004-01-02 Lars Magne Ingebrigtsen + + * gnus-dired.el (gnus-dired-mode-map): Change keymaps. + +2004-01-02 Arne J,Ax(Brgensen + + * smime.el (smime-crl-check): Doc fix. + +2004-01-02 Edwin Steiner + + * gnus-nocem.el (gnus-nocem-enter-article): Use the real group + hashtb (tiny patch). + +2004-01-02 Kai Grossjohann + + * nnml.el (nnml-save-mail): Grok compressed articles. From + Michael Albinus . + +2004-01-02 Teodor Zlatanov + + * spam.el (spam-ham-copy-or-move-routine): use spam-list-articles + (spam-list-articles): rewritten to only check a mark once per + invocation + +2004-01-01 Simon Josefsson + + * mml-sec.el (mml-default-encrypt-method) + (mml-default-sign-method): Defcustom. + +2003-12-31 Lars Magne Ingebrigtsen + + * mml.el (mml-generate-mime-1): Remove extra ). + + * gnus-group.el (gnus-group-set-current-level): Signal errors on + topic lines. + (gnus-group-set-current-level): Fix fix. + +2003-12-31 Jeremy Maitin-Shepard + + * mml.el (mml-generate-mime-1): Use mml-compute-boundary (tiny + change). + +2003-12-30 Reiner Steib + + * gnus-group.el: Removed `(when t ...)' around `gnus-define-keys'. + (gnus-group-group-map): Added `gnus-group-read-ephemeral-group' + (already in previous commit inadvertently). + (gnus-group-make-menu-bar): Added `gnus-group-read-ephemeral-group'. + (gnus-group-read-ephemeral-group): Made interactive. + + * gnus-score.el (gnus-score-find-trace): Added comment on sync + with `gnus-score-edit-file-at-point'. + + * gnus-logic.el (gnus-score-advanced): Ditto. + + * gnus-score.el (gnus-score-edit-file-at-point): Fix for + advanced scoring. + +2003-12-30 Simon Josefsson + + * gnus-score.el (gnus-score-edit-file-at-point): Use + gnus-point-at-*, for portability. + +2003-12-30 Reiner Steib + + * gnus-art.el (gnus-treat-body-boundary): Fix doc-string and + custom type. + (gnus-button-mid-or-mail-regexp): Don't be too restrictive. + Suggested by Felix Wiemann . + (gnus-button-alist): Added "M-x ... RET" and "mid:" buttons. + Added comments about relevant RFCs. + + * gnus-sum.el (gnus-summary-mode): Untabify doc-string. + (gnus-summary-goto-article): Allow `%40'. + (gnus-summary-refer-article): Convert `%40' to `@'. + +2003-12-30 Simon Josefsson + + * smime.el (smime-crl-check): New. + (smime-verify-region): Use it. From Arne J,Ax(Brgensen + in <87llpk9v5q.fsf@seamus.arnested.dk> (tiny + change). + +2003-12-30 Reiner Steib + + * gnus-score.el (gnus-score-edit-file-at-point): Consider the + whole match element. From Karl Pfl,Ad(Bsterer . + (gnus-score-find-trace): Use it. Added `f' and `t' commands, + added quick help. With some suggestions from Karl Pfl,Ad(Bsterer + . + + * gnus-util.el (gnus-emacs-version): Added doc-string. + + * mml.el (mml-minibuffer-read-disposition): New function. + (mml-attach-file): Use it. + (mml-preview): Added MIME preview to gnus-buffers. + +2003-12-30 Jesper Harder + + * gnus-sum.el (gnus-summary-make-menu-bar): Add ellipses. + +2003-12-30 Lars Magne Ingebrigtsen + + * gnus-start.el (gnus-get-unread-articles): Inline gnus-server-get-method. + (gnus-get-unread-articles): Cache methods. + (gnus-get-unread-articles-in-group): Indent. + + * gnus.el (gnus-version-number): Bump. + (gnus-secondary-method-p): Extend servers to methods before comparing. + (gnus-secondary-method-p): Revert. + 2003-12-30 Lars Magne Ingebrigtsen * gnus.el: Gnus v5.10.3 is released. diff --git a/lisp/gnus-art.el b/lisp/gnus-art.el index 556d7c3..c89d2c5 100644 --- a/lisp/gnus-art.el +++ b/lisp/gnus-art.el @@ -1273,12 +1273,12 @@ See Info node `(gnus)Customizing Articles' and Info node gnus-treat-from-picon) 'head nil) "Draw a boundary at the end of the headers. -Valid values are nil, t, `head', `last', an integer or a predicate. +Valid values are nil and `head'. See Info node `(gnus)Customizing Articles' for details." :version "21.1" :group 'gnus-article-treat :link '(custom-manual "(gnus)Customizing Articles") - :type gnus-article-treat-custom) + :type gnus-article-treat-head-custom) (defcustom gnus-treat-capitalize-sentences nil "Capitalize sentence-starting words. @@ -5742,7 +5742,8 @@ It should match all directories in the top level of `gnus-ctan-url'." :type 'regexp) (defcustom gnus-button-mid-or-mail-regexp - (concat "\\b\\(\")!;:,{}\n\t ]*@" + (concat "\\b\\(\")!;:,{}\n\t ]*@" + ;; Felix Wiemann in <87oeuomcz9.fsf@news2.ososo.de> gnus-button-valid-fqdn-regexp ">?\\)\\b") "Regular expression that matches a message ID or a mail address." @@ -6052,10 +6053,14 @@ positives are possible." 1 (>= gnus-button-message-level 0) gnus-button-fetch-group 5) ("\\b\\(nntp\\|news\\):\\(//\\)?\\([^'\">\n\t ]+\\)" 0 (>= gnus-button-message-level 0) gnus-button-fetch-group 3) + ;; RFC 2392 (Don't allow `/' in domain part --> CID) + ("\\bmid:\\(//\\)?\\([^'\">\n\t ]+@[^'\">\n\t /]+\\)" + 0 (>= gnus-button-message-level 0) gnus-button-message-id 2) ("\\bin\\( +article\\| +message\\)? +\\(<\\([^\n @<>]+@[^\n @<>]+\\)>\\)" 2 (>= gnus-button-message-level 0) gnus-button-message-id 3) ("\\( \n\t]+\\)>" 0 (>= gnus-button-message-level 0) gnus-url-mailto 2) + ;; RFC 2368 (The mailto URL scheme) ("mailto:\\([-a-z.@_+0-9%=?&]+\\)" 0 (>= gnus-button-message-level 0) gnus-url-mailto 1) ("\\bmailto:\\([^ \n\t]+\\)" @@ -6115,6 +6120,8 @@ positives are possible." 0 (>= gnus-button-emacs-level 9) gnus-button-handle-symbol 1) ("(setq[ \t\n]+\\([a-z][a-z0-9]+-[-a-z0-9]+\\)[ \t\n]+.+)" 1 (>= gnus-button-emacs-level 7) gnus-button-handle-describe-variable 1) + ("\\bM-x[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET" + 1 (>= gnus-button-emacs-level 7) gnus-button-handle-describe-function 1) ("\\b\\(C-h\\|?\\)[ \t\n]+f[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET" 0 (>= gnus-button-emacs-level 1) gnus-button-handle-describe-function 2) ("\\b\\(C-h\\|?\\)[ \t\n]+v[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET" @@ -6123,9 +6130,15 @@ positives are possible." ;; Unlike the other regexps we really have to require quoting ;; here to determine where it ends. 1 (>= gnus-button-emacs-level 1) gnus-button-handle-describe-key 3) - ;; This is how URLs _should_ be embedded in text (RFC 1738)... + ;; This is how URLs _should_ be embedded in text (RFC 1738, RFC 2396)... ("]*\\)>" 1 (>= gnus-button-browse-level 0) gnus-button-embedded-url 1) + ;; RFC 2396 (2.4.3., delims) ... + ("\"URL: *\\([^\"]*\\)\"" + 1 (>= gnus-button-browse-level 0) gnus-button-embedded-url 1) + ;; RFC 2396 (2.4.3., delims) ... + ("\"URL: *\\([^\"]*\\)\"" + 1 (>= gnus-button-browse-level 0) gnus-button-embedded-url 1) ;; Raw URLs. (gnus-button-url-regexp 0 (>= gnus-button-browse-level 0) browse-url 0) diff --git a/lisp/gnus-dired.el b/lisp/gnus-dired.el index cf54427..2cf8af2 100644 --- a/lisp/gnus-dired.el +++ b/lisp/gnus-dired.el @@ -58,9 +58,9 @@ (setq gnus-dired-mode-map (make-sparse-keymap)) (gnus-define-keys gnus-dired-mode-map - "\C-c\C-a" gnus-dired-attach - "\C-c\C-l" gnus-dired-find-file-mailcap - "\C-cP" gnus-dired-print)) + "\C-c\C-m\C-a" gnus-dired-attach + "\C-c\C-m\C-l" gnus-dired-find-file-mailcap + "\C-c\C-m\C-p" gnus-dired-print)) (defun gnus-dired-mode (&optional arg) "Minor mode for intersections of gnus and dired. diff --git a/lisp/gnus-group.el b/lisp/gnus-group.el index a1bd82e..5aa619c 100644 --- a/lisp/gnus-group.el +++ b/lisp/gnus-group.el @@ -528,207 +528,207 @@ simple manner.") (put 'gnus-group-mode 'mode-class 'special) -(when t - (gnus-define-keys gnus-group-mode-map - " " gnus-group-read-group - "=" gnus-group-select-group - "\r" gnus-group-select-group - "\M-\r" gnus-group-quick-select-group - "\M- " gnus-group-visible-select-group - [(meta control return)] gnus-group-select-group-ephemerally - "j" gnus-group-jump-to-group - "n" gnus-group-next-unread-group - "p" gnus-group-prev-unread-group - "\177" gnus-group-prev-unread-group - [delete] gnus-group-prev-unread-group - [backspace] gnus-group-prev-unread-group - "N" gnus-group-next-group - "P" gnus-group-prev-group - "\M-n" gnus-group-next-unread-group-same-level - "\M-p" gnus-group-prev-unread-group-same-level - "," gnus-group-best-unread-group - "." gnus-group-first-unread-group - "u" gnus-group-unsubscribe-current-group - "U" gnus-group-unsubscribe-group - "c" gnus-group-catchup-current - "C" gnus-group-catchup-current-all - "\M-c" gnus-group-clear-data - "l" gnus-group-list-groups - "L" gnus-group-list-all-groups - "m" gnus-group-mail - "i" gnus-group-news - "g" gnus-group-get-new-news - "\M-g" gnus-group-get-new-news-this-group - "R" gnus-group-restart - "r" gnus-group-read-init-file - "B" gnus-group-browse-foreign-server - "b" gnus-group-check-bogus-groups - "F" gnus-group-find-new-groups - "\C-c\C-d" gnus-group-describe-group - "\M-d" gnus-group-describe-all-groups - "\C-c\C-a" gnus-group-apropos - "\C-c\M-\C-a" gnus-group-description-apropos - "a" gnus-group-post-news - "\ek" gnus-group-edit-local-kill - "\eK" gnus-group-edit-global-kill - "\C-k" gnus-group-kill-group - "\C-y" gnus-group-yank-group - "\C-w" gnus-group-kill-region - "\C-x\C-t" gnus-group-transpose-groups - "\C-c\C-l" gnus-group-list-killed - "\C-c\C-x" gnus-group-expire-articles - "\C-c\M-\C-x" gnus-group-expire-all-groups - "V" gnus-version - "s" gnus-group-save-newsrc - "z" gnus-group-suspend - "q" gnus-group-exit - "Q" gnus-group-quit - "?" gnus-group-describe-briefly - "\C-c\C-i" gnus-info-find-node - "\M-e" gnus-group-edit-group-method - "^" gnus-group-enter-server-mode - gnus-mouse-2 gnus-mouse-pick-group - "<" beginning-of-buffer - ">" end-of-buffer - "\C-c\C-b" gnus-bug - "\C-c\C-s" gnus-group-sort-groups - "t" gnus-topic-mode - "\C-c\M-g" gnus-activate-all-groups - "\M-&" gnus-group-universal-argument - "#" gnus-group-mark-group - "\M-#" gnus-group-unmark-group) - - (gnus-define-keys (gnus-group-mark-map "M" gnus-group-mode-map) - "m" gnus-group-mark-group - "u" gnus-group-unmark-group - "w" gnus-group-mark-region - "b" gnus-group-mark-buffer - "r" gnus-group-mark-regexp - "U" gnus-group-unmark-all-groups) - - (gnus-define-keys (gnus-group-sieve-map "D" gnus-group-mode-map) - "u" gnus-sieve-update - "g" gnus-sieve-generate) - - (gnus-define-keys (gnus-group-group-map "G" gnus-group-mode-map) - "d" gnus-group-make-directory-group - "h" gnus-group-make-help-group - "u" gnus-group-make-useful-group - "a" gnus-group-make-archive-group - "k" gnus-group-make-kiboze-group - "l" gnus-group-nnimap-edit-acl - "m" gnus-group-make-group - "E" gnus-group-edit-group - "e" gnus-group-edit-group-method - "p" gnus-group-edit-group-parameters - "v" gnus-group-add-to-virtual - "V" gnus-group-make-empty-virtual - "D" gnus-group-enter-directory - "f" gnus-group-make-doc-group - "w" gnus-group-make-web-group - "r" gnus-group-rename-group - "R" gnus-group-make-rss-group - "c" gnus-group-customize - "x" gnus-group-nnimap-expunge - "\177" gnus-group-delete-group - [delete] gnus-group-delete-group) - - (gnus-define-keys (gnus-group-soup-map "s" gnus-group-group-map) - "b" gnus-group-brew-soup - "w" gnus-soup-save-areas - "s" gnus-soup-send-replies - "p" gnus-soup-pack-packet - "r" nnsoup-pack-replies) - - (gnus-define-keys (gnus-group-sort-map "S" gnus-group-group-map) - "s" gnus-group-sort-groups - "a" gnus-group-sort-groups-by-alphabet - "u" gnus-group-sort-groups-by-unread - "l" gnus-group-sort-groups-by-level - "v" gnus-group-sort-groups-by-score - "r" gnus-group-sort-groups-by-rank - "m" gnus-group-sort-groups-by-method - "n" gnus-group-sort-groups-by-real-name) - - (gnus-define-keys (gnus-group-sort-selected-map "P" gnus-group-group-map) - "s" gnus-group-sort-selected-groups - "a" gnus-group-sort-selected-groups-by-alphabet - "u" gnus-group-sort-selected-groups-by-unread - "l" gnus-group-sort-selected-groups-by-level - "v" gnus-group-sort-selected-groups-by-score - "r" gnus-group-sort-selected-groups-by-rank - "m" gnus-group-sort-selected-groups-by-method - "n" gnus-group-sort-selected-groups-by-real-name) - - (gnus-define-keys (gnus-group-list-map "A" gnus-group-mode-map) - "k" gnus-group-list-killed - "z" gnus-group-list-zombies - "s" gnus-group-list-groups - "u" gnus-group-list-all-groups - "A" gnus-group-list-active - "a" gnus-group-apropos - "d" gnus-group-description-apropos - "m" gnus-group-list-matching - "M" gnus-group-list-all-matching - "l" gnus-group-list-level - "c" gnus-group-list-cached - "?" gnus-group-list-dormant) - - (gnus-define-keys (gnus-group-list-limit-map "/" gnus-group-list-map) - "k" gnus-group-list-limit - "z" gnus-group-list-limit - "s" gnus-group-list-limit - "u" gnus-group-list-limit - "A" gnus-group-list-limit - "m" gnus-group-list-limit - "M" gnus-group-list-limit - "l" gnus-group-list-limit - "c" gnus-group-list-limit - "?" gnus-group-list-limit) - - (gnus-define-keys (gnus-group-list-flush-map "f" gnus-group-list-map) - "k" gnus-group-list-flush - "z" gnus-group-list-flush - "s" gnus-group-list-flush - "u" gnus-group-list-flush - "A" gnus-group-list-flush - "m" gnus-group-list-flush - "M" gnus-group-list-flush - "l" gnus-group-list-flush - "c" gnus-group-list-flush - "?" gnus-group-list-flush) - - (gnus-define-keys (gnus-group-list-plus-map "p" gnus-group-list-map) - "k" gnus-group-list-plus - "z" gnus-group-list-plus - "s" gnus-group-list-plus - "u" gnus-group-list-plus - "A" gnus-group-list-plus - "m" gnus-group-list-plus - "M" gnus-group-list-plus - "l" gnus-group-list-plus - "c" gnus-group-list-plus - "?" gnus-group-list-plus) - - (gnus-define-keys (gnus-group-score-map "W" gnus-group-mode-map) - "f" gnus-score-flush-cache) - - (gnus-define-keys (gnus-group-help-map "H" gnus-group-mode-map) - "c" gnus-group-fetch-charter - "C" gnus-group-fetch-control - "d" gnus-group-describe-group - "f" gnus-group-fetch-faq - "v" gnus-version) - - (gnus-define-keys (gnus-group-sub-map "S" gnus-group-mode-map) - "l" gnus-group-set-current-level - "t" gnus-group-unsubscribe-current-group - "s" gnus-group-unsubscribe-group - "k" gnus-group-kill-group - "y" gnus-group-yank-group - "w" gnus-group-kill-region - "\C-k" gnus-group-kill-level - "z" gnus-group-kill-all-zombies)) +(gnus-define-keys gnus-group-mode-map + " " gnus-group-read-group + "=" gnus-group-select-group + "\r" gnus-group-select-group + "\M-\r" gnus-group-quick-select-group + "\M- " gnus-group-visible-select-group + [(meta control return)] gnus-group-select-group-ephemerally + "j" gnus-group-jump-to-group + "n" gnus-group-next-unread-group + "p" gnus-group-prev-unread-group + "\177" gnus-group-prev-unread-group + [delete] gnus-group-prev-unread-group + [backspace] gnus-group-prev-unread-group + "N" gnus-group-next-group + "P" gnus-group-prev-group + "\M-n" gnus-group-next-unread-group-same-level + "\M-p" gnus-group-prev-unread-group-same-level + "," gnus-group-best-unread-group + "." gnus-group-first-unread-group + "u" gnus-group-unsubscribe-current-group + "U" gnus-group-unsubscribe-group + "c" gnus-group-catchup-current + "C" gnus-group-catchup-current-all + "\M-c" gnus-group-clear-data + "l" gnus-group-list-groups + "L" gnus-group-list-all-groups + "m" gnus-group-mail + "i" gnus-group-news + "g" gnus-group-get-new-news + "\M-g" gnus-group-get-new-news-this-group + "R" gnus-group-restart + "r" gnus-group-read-init-file + "B" gnus-group-browse-foreign-server + "b" gnus-group-check-bogus-groups + "F" gnus-group-find-new-groups + "\C-c\C-d" gnus-group-describe-group + "\M-d" gnus-group-describe-all-groups + "\C-c\C-a" gnus-group-apropos + "\C-c\M-\C-a" gnus-group-description-apropos + "a" gnus-group-post-news + "\ek" gnus-group-edit-local-kill + "\eK" gnus-group-edit-global-kill + "\C-k" gnus-group-kill-group + "\C-y" gnus-group-yank-group + "\C-w" gnus-group-kill-region + "\C-x\C-t" gnus-group-transpose-groups + "\C-c\C-l" gnus-group-list-killed + "\C-c\C-x" gnus-group-expire-articles + "\C-c\M-\C-x" gnus-group-expire-all-groups + "V" gnus-version + "s" gnus-group-save-newsrc + "z" gnus-group-suspend + "q" gnus-group-exit + "Q" gnus-group-quit + "?" gnus-group-describe-briefly + "\C-c\C-i" gnus-info-find-node + "\M-e" gnus-group-edit-group-method + "^" gnus-group-enter-server-mode + gnus-mouse-2 gnus-mouse-pick-group + "<" beginning-of-buffer + ">" end-of-buffer + "\C-c\C-b" gnus-bug + "\C-c\C-s" gnus-group-sort-groups + "t" gnus-topic-mode + "\C-c\M-g" gnus-activate-all-groups + "\M-&" gnus-group-universal-argument + "#" gnus-group-mark-group + "\M-#" gnus-group-unmark-group) + +(gnus-define-keys (gnus-group-mark-map "M" gnus-group-mode-map) + "m" gnus-group-mark-group + "u" gnus-group-unmark-group + "w" gnus-group-mark-region + "b" gnus-group-mark-buffer + "r" gnus-group-mark-regexp + "U" gnus-group-unmark-all-groups) + +(gnus-define-keys (gnus-group-sieve-map "D" gnus-group-mode-map) + "u" gnus-sieve-update + "g" gnus-sieve-generate) + +(gnus-define-keys (gnus-group-group-map "G" gnus-group-mode-map) + "d" gnus-group-make-directory-group + "h" gnus-group-make-help-group + "u" gnus-group-make-useful-group + "a" gnus-group-make-archive-group + "k" gnus-group-make-kiboze-group + "l" gnus-group-nnimap-edit-acl + "m" gnus-group-make-group + "E" gnus-group-edit-group + "e" gnus-group-edit-group-method + "p" gnus-group-edit-group-parameters + "v" gnus-group-add-to-virtual + "V" gnus-group-make-empty-virtual + "D" gnus-group-enter-directory + "f" gnus-group-make-doc-group + "w" gnus-group-make-web-group + "M" gnus-group-read-ephemeral-group + "r" gnus-group-rename-group + "R" gnus-group-make-rss-group + "c" gnus-group-customize + "x" gnus-group-nnimap-expunge + "\177" gnus-group-delete-group + [delete] gnus-group-delete-group) + +(gnus-define-keys (gnus-group-soup-map "s" gnus-group-group-map) + "b" gnus-group-brew-soup + "w" gnus-soup-save-areas + "s" gnus-soup-send-replies + "p" gnus-soup-pack-packet + "r" nnsoup-pack-replies) + +(gnus-define-keys (gnus-group-sort-map "S" gnus-group-group-map) + "s" gnus-group-sort-groups + "a" gnus-group-sort-groups-by-alphabet + "u" gnus-group-sort-groups-by-unread + "l" gnus-group-sort-groups-by-level + "v" gnus-group-sort-groups-by-score + "r" gnus-group-sort-groups-by-rank + "m" gnus-group-sort-groups-by-method + "n" gnus-group-sort-groups-by-real-name) + +(gnus-define-keys (gnus-group-sort-selected-map "P" gnus-group-group-map) + "s" gnus-group-sort-selected-groups + "a" gnus-group-sort-selected-groups-by-alphabet + "u" gnus-group-sort-selected-groups-by-unread + "l" gnus-group-sort-selected-groups-by-level + "v" gnus-group-sort-selected-groups-by-score + "r" gnus-group-sort-selected-groups-by-rank + "m" gnus-group-sort-selected-groups-by-method + "n" gnus-group-sort-selected-groups-by-real-name) + +(gnus-define-keys (gnus-group-list-map "A" gnus-group-mode-map) + "k" gnus-group-list-killed + "z" gnus-group-list-zombies + "s" gnus-group-list-groups + "u" gnus-group-list-all-groups + "A" gnus-group-list-active + "a" gnus-group-apropos + "d" gnus-group-description-apropos + "m" gnus-group-list-matching + "M" gnus-group-list-all-matching + "l" gnus-group-list-level + "c" gnus-group-list-cached + "?" gnus-group-list-dormant) + +(gnus-define-keys (gnus-group-list-limit-map "/" gnus-group-list-map) + "k" gnus-group-list-limit + "z" gnus-group-list-limit + "s" gnus-group-list-limit + "u" gnus-group-list-limit + "A" gnus-group-list-limit + "m" gnus-group-list-limit + "M" gnus-group-list-limit + "l" gnus-group-list-limit + "c" gnus-group-list-limit + "?" gnus-group-list-limit) + +(gnus-define-keys (gnus-group-list-flush-map "f" gnus-group-list-map) + "k" gnus-group-list-flush + "z" gnus-group-list-flush + "s" gnus-group-list-flush + "u" gnus-group-list-flush + "A" gnus-group-list-flush + "m" gnus-group-list-flush + "M" gnus-group-list-flush + "l" gnus-group-list-flush + "c" gnus-group-list-flush + "?" gnus-group-list-flush) + +(gnus-define-keys (gnus-group-list-plus-map "p" gnus-group-list-map) + "k" gnus-group-list-plus + "z" gnus-group-list-plus + "s" gnus-group-list-plus + "u" gnus-group-list-plus + "A" gnus-group-list-plus + "m" gnus-group-list-plus + "M" gnus-group-list-plus + "l" gnus-group-list-plus + "c" gnus-group-list-plus + "?" gnus-group-list-plus) + +(gnus-define-keys (gnus-group-score-map "W" gnus-group-mode-map) + "f" gnus-score-flush-cache) + +(gnus-define-keys (gnus-group-help-map "H" gnus-group-mode-map) + "c" gnus-group-fetch-charter + "C" gnus-group-fetch-control + "d" gnus-group-describe-group + "f" gnus-group-fetch-faq + "v" gnus-version) + +(gnus-define-keys (gnus-group-sub-map "S" gnus-group-mode-map) + "l" gnus-group-set-current-level + "t" gnus-group-unsubscribe-current-group + "s" gnus-group-unsubscribe-group + "k" gnus-group-kill-group + "y" gnus-group-yank-group + "w" gnus-group-kill-region + "\C-k" gnus-group-kill-level + "z" gnus-group-kill-all-zombies) (defun gnus-topic-mode-p () "Return non-nil in `gnus-topic-mode'." @@ -891,6 +891,7 @@ simple manner.") ["Make a kiboze group..." gnus-group-make-kiboze-group t] ["Make a virtual group..." gnus-group-make-empty-virtual t] ["Add a group to a virtual..." gnus-group-add-to-virtual t] + ["Make an ephemeral group..." gnus-group-read-ephemeral-group t] ["Make an RSS group..." gnus-group-make-rss-group t] ["Rename group..." gnus-group-rename-group (gnus-check-backend-function @@ -1464,7 +1465,7 @@ if it is a string, only list groups matching REGEXP." (active (gnus-active group)) (total (if active (1+ (- (cdr active) (car active))) 0)) (info (nth 2 entry)) - (method (gnus-server-get-method group (gnus-info-method info))) + (method (inline (gnus-server-get-method group (gnus-info-method info)))) (marked (gnus-info-marks info)) (mailp (apply 'append (mapcar @@ -1985,6 +1986,14 @@ If SELECT-ARTICLES, only select those articles. If PARAMETERS, use those as the group parameters. Return the name of the group if selection was successful." + (interactive + (list + ;; (gnus-read-group "Group name: ") + (completing-read + "Group: " gnus-active-hashtb + nil nil nil + 'gnus-group-history) + (gnus-read-method "From method: "))) ;; Transform the select method into a unique server. (when (stringp method) (setq method (gnus-server-to-method method))) @@ -3208,15 +3217,18 @@ Uses the process/prefix convention." (interactive (list current-prefix-arg - (string-to-int - (let ((s (read-string - (format "Level (default %s): " - (or (gnus-group-group-level) - gnus-level-default-subscribed))))) - (if (string-match "^\\s-*$" s) - (int-to-string (or (gnus-group-group-level) - gnus-level-default-subscribed)) - s))))) + (progn + (unless (gnus-group-process-prefix current-prefix-arg) + (error "No group on the current line")) + (string-to-int + (let ((s (read-string + (format "Level (default %s): " + (or (gnus-group-group-level) + gnus-level-default-subscribed))))) + (if (string-match "^\\s-*$" s) + (int-to-string (or (gnus-group-group-level) + gnus-level-default-subscribed)) + s)))))) (unless (and (>= level 1) (<= level gnus-level-killed)) (error "Invalid level: %d" level)) (let ((groups (gnus-group-process-prefix n)) diff --git a/lisp/gnus-logic.el b/lisp/gnus-logic.el index e6a1855..c6bc031 100644 --- a/lisp/gnus-logic.el +++ b/lisp/gnus-logic.el @@ -77,6 +77,7 @@ gnus-newsgroup-scored) (when trace (push (cons "A file" rule) + ;; Must be synced with `gnus-score-edit-file-at-point'. gnus-score-trace))))))) (defun gnus-advanced-score-rule (rule) diff --git a/lisp/gnus-nocem.el b/lisp/gnus-nocem.el index 5247d1f..20f3e38 100644 --- a/lisp/gnus-nocem.el +++ b/lisp/gnus-nocem.el @@ -297,7 +297,8 @@ valid issuer, which is much faster if you are selective about the issuers." (while (search-forward "\t" nil t) (cond ((not (ignore-errors - (setq group (let ((obarray gnus-active-hashtb)) (read buf))))) + (setq group (let ((obarray gnus-nocem-real-group-hashtb)) + (read buf))))) ;; An error. ) ((not (symbolp group)) diff --git a/lisp/gnus-score.el b/lisp/gnus-score.el index 3bd29b5..f307539 100644 --- a/lisp/gnus-score.el +++ b/lisp/gnus-score.el @@ -1106,21 +1106,38 @@ EXTRA is the possible non-standard header." 4 (substitute-command-keys "\\\\[gnus-score-edit-exit] to save edits"))) -(defun gnus-score-edit-file-at-point () - "Edit score file at point. Useful especially after `V t'." - (interactive) - (let* ((string (ffap-string-at-point)) - ;; FIXME: Should be the full `match element', not just string at - ;; point. - file) - (save-excursion - (end-of-line) - (setq file (ffap-string-at-point))) - (gnus-score-edit-file file) - (unless (string= string file) - (goto-char (point-min)) - ;; Goto first match - (search-forward string nil t)))) +(defun gnus-score-edit-file-at-point (&optional format) + "Edit score file at point in Score Trace buffers. +If FORMAT, also format the current score file." + (let* ((rule (save-excursion + (beginning-of-line) + (read (current-buffer)))) + (sep "[ \n\r\t]*") + ;; Must be synced with `gnus-score-find-trace': + (reg " -> +") + (file (save-excursion + (end-of-line) + (if (and (re-search-backward reg (gnus-point-at-bol) t) + (re-search-forward reg (gnus-point-at-eol) t)) + (buffer-substring (point) (gnus-point-at-eol)) + nil)))) + (if (or (not file) + (string-match "\\<\\(non-file rule\\|A file\\)\\>" file) + ;; (see `gnus-score-find-trace' and `gnus-score-advanced') + (string= "" file)) + (gnus-error 3 "Can't find a score file in current line.") + (gnus-score-edit-file file) + (when format + (gnus-score-pretty-print)) + (when (consp rule) ;; the rule exists + (setq rule (mapconcat #'(lambda (obj) + (regexp-quote (format "%S" obj))) + rule + sep)) + (goto-char (point-min)) + (re-search-forward rule nil t) + ;; make it easy to use `kill-sexp': + (goto-char (1- (match-beginning 0))))))) (defun gnus-score-load-file (file) ;; Load score file FILE. Returns a list a retrieved score-alists. @@ -2354,7 +2371,10 @@ score in `gnus-newsgroup-scored' by SCORE." (let ((gnus-newsgroup-headers (list (gnus-summary-article-header))) (gnus-newsgroup-scored nil) - trace) + ;; Must be synced with `gnus-score-edit-file-at-point': + (frmt "%S [%s] -> %s\n") + trace + file) (save-excursion (nnheader-set-temp-buffer "*Score Trace*")) (setq gnus-score-trace nil) @@ -2364,18 +2384,44 @@ score in `gnus-newsgroup-scored' by SCORE." 1 "No score rules apply to the current article (default score %d)." gnus-summary-default-score) (set-buffer "*Score Trace*") - ;; ToDo: Use a keymap instead? + ;; Use a keymap instead? (local-set-key "q" (lambda () (interactive) (bury-buffer nil) (gnus-summary-expand-window))) - (local-set-key "e" 'gnus-score-edit-file-at-point) + (local-set-key "e" (lambda () + "Run `gnus-score-edit-file-at-point'." + (interactive) + (gnus-score-edit-file-at-point))) + (local-set-key "f" (lambda () + "Run `gnus-score-edit-file-at-point'." + (interactive) + (gnus-score-edit-file-at-point 'format))) + (local-set-key "t" 'toggle-truncate-lines) (setq truncate-lines t) - (while trace - (insert (format "%S -> %s\n" (cdar trace) - (or (caar trace) "(non-file rule)"))) - (setq trace (cdr trace))) + (dolist (entry trace) + (setq file (or (car entry) + ;; Must be synced with + ;; `gnus-score-edit-file-at-point': + "(non-file rule)")) + (insert + (format frmt + (cdr entry) + ;; Don't use `file-name-sans-extension' to see .SCORE and + ;; .ADAPT directly: + (file-name-nondirectory file) + (abbreviate-file-name file)))) + (insert + "\n\nQuick help: + +Type `e' to edit score file corresponding to the score rule on current line, +`f' to format (pretty print) the score file and edit it, +`t' toggle to truncate long lines in this buffer, +`q' to quit. + +The first sexp on each line is the score rule, followed by the file name of +the score file and its full name, including the directory.") (goto-char (point-min)) (gnus-configure-windows 'score-trace))) (set-buffer gnus-summary-buffer) diff --git a/lisp/gnus-start.el b/lisp/gnus-start.el index c1c5091..cec0656 100644 --- a/lisp/gnus-start.el +++ b/lisp/gnus-start.el @@ -1532,7 +1532,7 @@ newsgroup." ;; If the agent is enabled, we may have to alter the active info. (when (and gnus-agent info) (gnus-agent-possibly-alter-active - (gnus-info-group info) active)) + (gnus-info-group info) active)) ;; Modify the list of read articles according to what articles ;; are available; then tally the unread articles and add the @@ -1620,7 +1620,10 @@ newsgroup." gnus-activate-foreign-newsgroups) (t 0)) level)) - scanned-methods info group active method retrieve-groups) + (methods-cache nil) + (type-cache nil) + scanned-methods info group active method retrieve-groups cmethod + method-type) (gnus-message 6 "Checking new news...") (while newsrc @@ -1639,12 +1642,25 @@ newsgroup." ;; nil for non-foreign groups that the user has requested not be checked ;; t for unchecked foreign groups or bogus groups, or groups that can't ;; be checked, for one reason or other. - (if (and (setq method (gnus-info-method info)) - (not (inline - (gnus-server-equal - gnus-select-method - (setq method (gnus-server-get-method nil method))))) - (not (gnus-secondary-method-p method))) + (when (setq method (gnus-info-method info)) + (if (setq cmethod (assoc method methods-cache)) + (setq method (cdr cmethod)) + (setq cmethod (inline (gnus-server-get-method nil method))) + (push (cons method cmethod) methods-cache) + (setq method cmethod))) + (when (and method + (not (setq method-type (cdr (assoc method type-cache))))) + (setq method-type + (cond + ((gnus-secondary-method-p method) + 'secondary) + ((inline (gnus-server-equal gnus-select-method method)) + 'primary) + (t + 'foreign))) + (push (cons method method-type) type-cache)) + (if (and method + (eq method-type 'foreign)) ;; These groups are foreign. Check the level. (when (and (<= (gnus-info-level info) foreign-level) (setq active (gnus-activate-group group 'scan))) diff --git a/lisp/gnus-sum.el b/lisp/gnus-sum.el index b76a3e5..12cc4d8 100644 --- a/lisp/gnus-sum.el +++ b/lisp/gnus-sum.el @@ -2109,19 +2109,19 @@ increase the score of each group you read." :active (not (gnus-group-read-only-p)) ,@(if (featurep 'xemacs) nil '(:help "Encrypt the message body on disk"))] - ["Extract all parts" gnus-summary-save-parts t] + ["Extract all parts..." gnus-summary-save-parts t] ("Multipart" ["Repair multipart" gnus-summary-repair-multipart t] - ["Pipe part" gnus-article-pipe-part t] + ["Pipe part..." gnus-article-pipe-part t] ["Inline part" gnus-article-inline-part t] ["Encrypt body" gnus-article-encrypt-body :active (not (gnus-group-read-only-p)) ,@(if (featurep 'xemacs) nil '(:help "Encrypt the message body on disk"))] ["View part externally" gnus-article-view-part-externally t] - ["View part with charset" gnus-article-view-part-as-charset t] + ["View part with charset..." gnus-article-view-part-as-charset t] ["Copy part" gnus-article-copy-part t] - ["Save part" gnus-article-save-part t] + ["Save part..." gnus-article-save-part t] ["View part" gnus-article-view-part t])) ("Date" ["Local" gnus-article-date-local t] @@ -2201,20 +2201,20 @@ gnus-summary-show-article-from-menu-as-charset-%s" cs)))) gnus-article-outlook-deuglify-article t]) ) ("Output" - ["Save in default format" gnus-summary-save-article + ["Save in default format..." gnus-summary-save-article ,@(if (featurep 'xemacs) '(t) '(:help "Save article using default method"))] - ["Save in file" gnus-summary-save-article-file + ["Save in file..." gnus-summary-save-article-file ,@(if (featurep 'xemacs) '(t) '(:help "Save article in file"))] - ["Save in Unix mail format" gnus-summary-save-article-mail t] - ["Save in MH folder" gnus-summary-save-article-folder t] - ["Save in VM folder" gnus-summary-save-article-vm t] - ["Save in RMAIL mbox" gnus-summary-save-article-rmail t] - ["Save body in file" gnus-summary-save-article-body-file t] - ["Pipe through a filter" gnus-summary-pipe-output t] + ["Save in Unix mail format..." gnus-summary-save-article-mail t] + ["Save in MH folder..." gnus-summary-save-article-folder t] + ["Save in VM folder..." gnus-summary-save-article-vm t] + ["Save in RMAIL mbox..." gnus-summary-save-article-rmail t] + ["Save body in file..." gnus-summary-save-article-body-file t] + ["Pipe through a filter..." gnus-summary-pipe-output t] ["Add to SOUP packet" gnus-soup-add-article t] - ["Print with Muttprint" gnus-summary-muttprint t] + ["Print with Muttprint..." gnus-summary-muttprint t] ["Print" gnus-summary-print-article t]) ("Backend" ["Respool article..." gnus-summary-respool-article t] @@ -2649,7 +2649,7 @@ and backwards while displaying articles, type `\\[gnus-summary-next-unread-artic respectively. You can also post articles and send mail from this buffer. To -follow up an article, type `\\[gnus-summary-followup]'. To mail a reply to the author +follow up an article, type `\\[gnus-summary-followup]'. To mail a reply to the author of an article, type `\\[gnus-summary-reply]'. There are approx. one gazillion commands you can execute in this @@ -7441,7 +7441,7 @@ is a number, it is the line the article is to be displayed on." t)) (prog1 (if (and (stringp article) - (string-match "@" article)) + (string-match "@\\|%40" article)) (gnus-summary-refer-article article) (when (stringp article) (setq article (string-to-number article))) @@ -8113,6 +8113,9 @@ of what's specified by the `gnus-refer-thread-limit' variable." (setq message-id (concat "<" message-id))) (unless (string-match ">$" message-id) (setq message-id (concat message-id ">"))) + ;; People often post MIDs from URLs, so unhex it: + (unless (string-match "@" message-id) + (setq message-id (gnus-url-unhex-string message-id))) (let* ((header (gnus-id-to-header message-id)) (sparse (and header (gnus-summary-article-sparse-p diff --git a/lisp/gnus-util.el b/lisp/gnus-util.el index abd382d..b0acb08 100644 --- a/lisp/gnus-util.el +++ b/lisp/gnus-util.el @@ -1453,6 +1453,7 @@ predicate on the elements." (defvar xemacs-codename)) (defun gnus-emacs-version () + "Stringified Emacs version." (let ((system-v (cond ((eq gnus-user-agent 'emacs-gnus-config) diff --git a/lisp/gnus.el b/lisp/gnus.el index 80efafd..1be4614 100644 --- a/lisp/gnus.el +++ b/lisp/gnus.el @@ -282,7 +282,7 @@ is restarted, and sometimes reloaded." :link '(custom-manual "(gnus)Exiting Gnus") :group 'gnus) -(defconst gnus-version-number "5.10.3" +(defconst gnus-version-number "5.10.4" "Version number for this version of Gnus.") (defconst gnus-version (format "Gnus v%s" gnus-version-number) @@ -339,7 +339,9 @@ be set in `.emacs' instead." (:type xbm :file "gnus-pointer.xbm" :ascent center)))) gnus-mode-line-image-cache) - 'help-echo "This is Gnus") + 'help-echo (format + "This is %s, %s." + gnus-version (gnus-emacs-version))) str) (list str)) line))) @@ -3490,10 +3492,10 @@ You should probably use `gnus-find-method-for-group' instead." (defsubst gnus-secondary-method-p (method) "Return whether METHOD is a secondary select method." (let ((methods gnus-secondary-select-methods) - (gmethod (gnus-server-get-method nil method))) + (gmethod (inline (gnus-server-get-method nil method)))) (while (and methods (not (gnus-method-equal - (gnus-server-get-method nil (car methods)) + (inline (gnus-server-get-method nil (car methods))) gmethod))) (setq methods (cdr methods))) methods)) @@ -3904,21 +3906,19 @@ Disallow invalid group names." (cons (or default "") 0) 'gnus-group-history))) (let ((match (match-string 0 group))) - ;; `/' may be okay (e.g. for nnimap), so ask the user: - (unless (and (string-match "/" match) + ;; Might be okay (e.g. for nnimap), so ask the user: + (unless (and (not (string-match "^$\\|:" match)) (message-y-or-n-p "Proceed and create group anyway? " t "The group name \"" group "\" contains a forbidden character: \"" match "\". Usually, it's dangerous to create a group with this name, because it's not -supported by all back ends and servers. On some IMAP servers, it's valid to -use the character \"/\". - -If you are really sure, you can proceed anyway and create the group. +supported by all back ends and servers. On IMAP servers it should work, +though. If you are really sure, you can proceed anyway and create the group. You may customize the variable `gnus-invalid-group-regexp', which currently is set to \"" gnus-invalid-group-regexp -"\", if you want to get rid of this query.")) +"\", if you want to get rid of this query permanently.")) (setq prefix (format "Invalid group name: \"%s\". " group) group nil))))) group)) @@ -4058,7 +4058,7 @@ current display is used." (defun gnus (&optional arg dont-connect slave) "Read network news. If ARG is non-nil and a positive number, Gnus will use that as the -startup level. If ARG is non-nil and not a positive number, Gnus will +startup level. If ARG is non-nil and not a positive number, Gnus will prompt the user for the name of an NNTP server to use." (interactive "P") (unless (byte-code-function-p (symbol-function 'gnus)) diff --git a/lisp/message.el b/lisp/message.el index 8a36f51..3bf6a6c 100644 --- a/lisp/message.el +++ b/lisp/message.el @@ -5149,7 +5149,6 @@ If the current line has `message-yank-prefix', insert it on the new line." (error (split-line)))) - (defun message-fill-header (header value) (let ((begin (point)) (fill-column 78) diff --git a/lisp/mml-sec.el b/lisp/mml-sec.el index 757a0f8..c1a494b 100644 --- a/lisp/mml-sec.el +++ b/lisp/mml-sec.el @@ -1,5 +1,5 @@ ;;; mml-sec.el --- A package with security functions for MML documents -;; Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +;; Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. ;; Author: Simon Josefsson @@ -40,8 +40,15 @@ ("pgpmime" mml-pgpmime-sign-buffer list)) "Alist of MIME signer functions.") -(defvar mml-default-sign-method (caar mml-sign-alist) - "Default sign method.") +(defcustom mml-default-sign-method "pgpmime" + "Default sign method. +The string must have an entry in `mml-sign-alist'." + :type '(choice (const "smime") + (const "pgp") + (const "pgpauto") + (const "pgpmime") + string) + :group 'message) (defvar mml-encrypt-alist '(("smime" mml-smime-encrypt-buffer mml-smime-encrypt-query) @@ -50,8 +57,15 @@ ("pgpmime" mml-pgpmime-encrypt-buffer list)) "Alist of MIME encryption functions.") -(defvar mml-default-encrypt-method (caar mml-encrypt-alist) - "Default encryption method.") +(defcustom mml-default-encrypt-method "pgpmime" + "Default encryption method. +The string must have an entry in `mml-encrypt-alist'." + :type '(choice (const "smime") + (const "pgp") + (const "pgpauto") + (const "pgpmime") + string) + :group 'message) (defcustom mml-signencrypt-style-alist '(("smime" separate) @@ -75,7 +89,7 @@ details." (string :tag "User defined")) (choice (const :tag "Separate" separate) (const :tag "Combined" combined))))) - + ;;; Configuration/helper functions (defun mml-signencrypt-style (method &optional style) diff --git a/lisp/mml.el b/lisp/mml.el index 5e35f16..fded446 100644 --- a/lisp/mml.el +++ b/lisp/mml.el @@ -430,8 +430,7 @@ If MML is non-nil, return the buffer up till the correspondent mml tag." (+ (match-beginning 0) 3)))))) (cond ((eq (car cont) 'mml) - (let ((mml-boundary (funcall mml-boundary-function - (incf mml-multipart-number))) + (let ((mml-boundary (mml-compute-boundary cont)) (mml-generate-default-type "text/plain")) (mml-to-mime)) (let ((mm-7bit-chars (concat mm-7bit-chars "\x1b"))) @@ -936,6 +935,19 @@ See Info node `(emacs-mime)Composing'. (setq description nil)) description)) +(defun mml-minibuffer-read-disposition (type &optional default) + (let* ((default (or default + (if (string-match "^text/.*" type) + "inline" + "attachment"))) + (disposition (completing-read "Disposition: " + '(("attachment") ("inline") ("")) + nil + nil))) + (if (not (equal disposition "")) + disposition + default))) + (defun mml-quote-region (beg end) "Quote the MML tags in the region." (interactive "r") @@ -978,7 +990,7 @@ See Info node `(emacs-mime)Composing'. ;;; Attachment functions. -(defun mml-attach-file (file &optional type description) +(defun mml-attach-file (file &optional type description disposition) "Attach a file to the outgoing MIME message. The file is not inserted or encoded until you send the message with `\\[message-send-and-exit]' or `\\[message-send]'. @@ -989,10 +1001,14 @@ description of the attachment." (interactive (let* ((file (mml-minibuffer-read-file "Attach file: ")) (type (mml-minibuffer-read-type file)) - (description (mml-minibuffer-read-description))) - (list file type description))) - (mml-insert-empty-tag 'part 'type type 'filename file - 'disposition "attachment" 'description description)) + (description (mml-minibuffer-read-description)) + (disposition (mml-minibuffer-read-disposition type))) + (list file type description disposition))) + (mml-insert-empty-tag 'part + 'type type + 'filename file + 'disposition (or disposition "attachment") + 'description description)) (defun mml-attach-buffer (buffer &optional type description) "Attach a buffer to the outgoing MIME message. @@ -1061,6 +1077,8 @@ If RAW, don't highlight the article." (switch-to-buffer (generate-new-buffer (concat (if raw "*Raw MIME preview of " "*MIME preview of ") (buffer-name)))) + (when (boundp 'gnus-buffers) + (push (current-buffer) gnus-buffers)) (erase-buffer) (insert-buffer-substring buf) (mml-preview-insert-mail-followup-to) diff --git a/lisp/mml2015.el b/lisp/mml2015.el index fc3cc50..13a4a4d 100644 --- a/lisp/mml2015.el +++ b/lisp/mml2015.el @@ -277,8 +277,7 @@ (defun mml2015-mailcrypt-sign (cont) (mc-sign-generic (message-options-get 'message-sender) nil nil nil nil) - (let ((boundary - (funcall mml-boundary-function (incf mml-multipart-number))) + (let ((boundary (mml-compute-boundary cont)) hash point) (goto-char (point-min)) (unless (re-search-forward "^-----BEGIN PGP SIGNED MESSAGE-----\r?$" nil t) @@ -341,8 +340,7 @@ (goto-char (point-min)) (unless (looking-at "-----BEGIN PGP MESSAGE-----") (error "Fail to encrypt the message")) - (let ((boundary - (funcall mml-boundary-function (incf mml-multipart-number)))) + (let ((boundary (mml-compute-boundary cont))) (insert (format "Content-Type: multipart/encrypted; boundary=\"%s\";\n" boundary)) (insert "\tprotocol=\"application/pgp-encrypted\"\n\n") @@ -544,8 +542,7 @@ mm-security-handle 'gnus-info "Failed"))) (defun mml2015-gpg-sign (cont) - (let ((boundary - (funcall mml-boundary-function (incf mml-multipart-number))) + (let ((boundary (mml-compute-boundary cont)) (text (current-buffer)) signature) (goto-char (point-max)) (unless (bolp) @@ -578,8 +575,7 @@ (goto-char (point-max))))) (defun mml2015-gpg-encrypt (cont &optional sign) - (let ((boundary - (funcall mml-boundary-function (incf mml-multipart-number))) + (let ((boundary (mml-compute-boundary cont)) (text (current-buffer)) cipher) (mm-with-unibyte-current-buffer @@ -807,7 +803,7 @@ (defun mml2015-pgg-sign (cont) (let ((pgg-errors-buffer mml2015-result-buffer) - (boundary (funcall mml-boundary-function (incf mml-multipart-number))) + (boundary (mml-compute-boundary cont)) (pgg-default-user-id (or (message-options-get 'mml-sender) pgg-default-user-id))) (unless (pgg-sign-region (point-min) (point-max)) @@ -829,7 +825,7 @@ (defun mml2015-pgg-encrypt (cont &optional sign) (let ((pgg-errors-buffer mml2015-result-buffer) - (boundary (funcall mml-boundary-function (incf mml-multipart-number)))) + (boundary (mml-compute-boundary cont))) (unless (pgg-encrypt-region (point-min) (point-max) (split-string (or diff --git a/lisp/nnml.el b/lisp/nnml.el index 0767962..0307faf 100644 --- a/lisp/nnml.el +++ b/lisp/nnml.el @@ -621,8 +621,12 @@ marks file will be regenerated properly by Gnus.") (defun nnml-save-mail (group-art) "Called narrowed to an article." - (let (chars headers) + (let (chars headers extension) (setq chars (nnmail-insert-lines)) + (setq extension + (and nnml-use-compressed-files + (> chars 1000) + ".gz")) (nnmail-insert-xref group-art) (run-hooks 'nnmail-prepare-save-mail-hook) (run-hooks 'nnml-prepare-save-mail-hook) @@ -637,7 +641,8 @@ marks file will be regenerated properly by Gnus.") (nnml-possibly-create-directory (caar ga)) (let ((file (concat (nnmail-group-pathname (caar ga) nnml-directory) - (int-to-string (cdar ga))))) + (int-to-string (cdar ga)) + extension))) (if first ;; It was already saved, so we just make a hard link. (funcall nnmail-crosspost-link-function first file t) diff --git a/lisp/smime.el b/lisp/smime.el index b14e24a..af7f955 100644 --- a/lisp/smime.el +++ b/lisp/smime.el @@ -184,6 +184,27 @@ and the files themself should be in PEM format." (const :tag "RC2 128 bits" "-rc2-128")) :group 'smime) +(defcustom smime-crl-check nil + "*Check revocation status of signers certificate using CRLs. +Enabling this will have OpenSSL check the signers certificate +against a certificate revocation list (CRL). + +For this to work the CRL must be up-to-date and since they are +normally updated quite often (ie. several times a day) you +probably need some tool to keep them up-to-date. Unfortunately +Gnus cannot do this for you. + +The CRL should either be appended (in PEM format) to your +`smime-CA-file' or be located in a file (also in PEM format) in +your `smime-certificate-directory' named to the X.509 hash of the +certificate with .r0 as file name extension. + +At least OpenSSL version 0.9.7 is required for this to work." + :type '(choice (const :tag "No check" nil) + (const :tag "Check certificate" "-crl_check") + (const :tag "Check certificate chain" "-crl_check_all")) + :group 'smime) + (defcustom smime-dns-server nil "*DNS server to query certificates from. If nil, use system defaults." @@ -348,6 +369,8 @@ Any details (stdout and stderr) are left in the buffer specified by (expand-file-name smime-CA-directory)))))) (unless CAs (error "No CA configured")) + (if smime-crl-check + (add-to-list 'CAs smime-crl-check)) (if (apply 'smime-call-openssl-region b e (list smime-details-buffer t) "smime" "-verify" "-out" "/dev/null" CAs) t diff --git a/lisp/spam.el b/lisp/spam.el index 1014d7c..4d30052 100644 --- a/lisp/spam.el +++ b/lisp/spam.el @@ -708,16 +708,12 @@ spam-use-* variable.") (defun spam-ham-copy-or-move-routine (copy groups) (gnus-summary-kill-process-mark) - (let ((articles gnus-newsgroup-articles) + (let ((todo (spam-list-articles gnus-newsgroup-articles 'ham)) (backend-supports-deletions (gnus-check-backend-function 'request-move-article gnus-newsgroup-name)) (respool-method (gnus-find-method-for-group gnus-newsgroup-name)) article mark todo deletep respool) - (dolist (article articles) - (when (spam-group-ham-mark-p gnus-newsgroup-name - (gnus-summary-article-mark article)) - (push article todo))) (when (member 'respool groups) (setq respool t) ; boolean for later @@ -1038,12 +1034,20 @@ functions") (let ((mark-check (if (eq classification 'spam) 'spam-group-spam-mark-p 'spam-group-ham-mark-p)) - mark list) + list mark-cache-yes mark-cache-no) (dolist (article articles) - (when (funcall mark-check - gnus-newsgroup-name - (gnus-summary-article-mark article)) - (push article list))) + (let ((mark (gnus-summary-article-mark article))) + (unless (memq mark mark-cache-no) + (if (memq mark mark-cache-yes) + (push article list) + ;; else, we have to actually check the mark + (if (funcall mark-check + gnus-newsgroup-name + mark) + (progn + (push article list) + (push mark mark-cache-yes)) + (push mark mark-cache-no)))))) list)) (defun spam-register-routine (classification diff --git a/texi/ChangeLog b/texi/ChangeLog index 3f340b0..82845ac 100644 --- a/texi/ChangeLog +++ b/texi/ChangeLog @@ -1,6 +1,55 @@ +2004-01-02 Teodor Zlatanov + + * gnus.texi (Top): updated menu with new manual nodes + (The problem of spam): more ranting + (Anti-Spam Basics): "spammers are wise to [filtering on From:]" + (SpamAssassin): mention spam.el + (Hashcash): do not a sentence end proposition with + (Filtering Spam Using The Spam ELisp Package): more and better + explanation, took lots of information out into subsections + (Spam ELisp Package Sequence of Events) + (Spam ELisp Package Filtering of Incoming Mail) + (Spam ELisp Package Global Variables): new or updated content all + around + (Spam ELisp Package Configuration Examples): promised new + section, empty for now + (Blacklists and Whitelists, BBDB Whitelists) + (Gmane Spam Reporting, Bogofilter, spam-stat spam filtering) + (SpamOracle): mention that spam/ham processor variables are being + obsoleted + (Extending the Spam ELisp package): add some new documentation + for adding a new backend to spam.el + +2004-01-02 Reiner Steib + + * gnus.texi (Foreign Groups): Add `gnus-group-read-ephemeral-group'. + (Oort Gnus): Ditto. + +2004-01-02 Lars Magne Ingebrigtsen + + * message.texi (Key Index): Untabified. + + * gnus.texi (RSS): kindex. + +2003-12-30 Reiner Steib + + * gnus.texi (Summary Score Commands): Add `f' to + `gnus-score-find-trace'. + (Score File Editing): Added `V t'. + +2003-12-31 Steve Youngs + + * gnus.texi (XEmacs): Update list of Gnus XEmacs package + requirements. + +2003-12-30 Reiner Steib + + * gnus.texi (Canceling and Superseding): Mention `Cancel-Lock'. + 2003-12-30 Lars Magne Ingebrigtsen * gnus.texi (Maildir): Filled. + (Key Index): Untabified. 2003-12-29 Lars Magne Ingebrigtsen diff --git a/texi/gnus.texi b/texi/gnus.texi index 5508880..30dd97f 100644 --- a/texi/gnus.texi +++ b/texi/gnus.texi @@ -33,7 +33,7 @@ \makeindex \begin{document} -\newcommand{\gnusversionname}{Gnus v5.10.3} +\newcommand{\gnusversionname}{Gnus v5.10.4} \newcommand{\gnuschaptername}{} \newcommand{\gnussectionname}{} @@ -397,7 +397,7 @@ can be gotten by any nefarious means you can think of---@acronym{NNTP}, local spool or your mbox file. All at the same time, if you want to push your luck. -This manual corresponds to Gnus v5.10.3. +This manual corresponds to Gnus v5.10.4. @end ifinfo @@ -573,9 +573,12 @@ Marking Articles * Unread Articles:: Marks for unread articles. * Read Articles:: Marks for read articles. * Other Marks:: Marks that do not affect readedness. -* Setting Marks:: How to set and remove marks. -* Generic Marking Commands:: How to customize the marking. -* Setting Process Marks:: How to mark articles for later processing. + +Marking Articles + +* Setting Marks:: How to set and remove marks. +* Generic Marking Commands:: How to customize the marking. +* Setting Process Marks:: How to mark articles for later processing. Threading @@ -868,17 +871,21 @@ Thwarting Email Spam Filtering Spam Using The Spam ELisp Package -* Blacklists and Whitelists:: -* BBDB Whitelists:: -* Gmane Spam Reporting:: -* Anti-spam Hashcash Payments:: -* Blackholes:: -* Regular Expressions Header Matching:: -* Bogofilter:: -* ifile spam filtering:: -* spam-stat spam filtering:: -* SpamOracle:: -* Extending the spam elisp package:: +* Spam ELisp Package Sequence of Events:: +* Spam ELisp Package Filtering of Incoming Mail:: +* Spam ELisp Package Global Variables:: +* Spam ELisp Package Configuration Examples:: +* Blacklists and Whitelists:: +* BBDB Whitelists:: +* Gmane Spam Reporting:: +* Anti-spam Hashcash Payments:: +* Blackholes:: +* Regular Expressions Header Matching:: +* Bogofilter:: +* ifile spam filtering:: +* spam-stat spam filtering:: +* SpamOracle:: +* Extending the Spam ELisp package:: Filtering Spam Using Statistics with spam-stat @@ -896,7 +903,7 @@ Appendices * Troubleshooting:: What you might try if things do not work. * Gnus Reference Guide:: Rilly, rilly technical stuff. * Emacs for Heathens:: A short introduction to Emacsian terms. -* Frequently Asked Questions:: The Gnus FAQ. +* Frequently Asked Questions:: The Gnus FAQ History @@ -2532,6 +2539,12 @@ Make a new group (@code{gnus-group-make-group}). Gnus will prompt you for a name, a method and possibly an @dfn{address}. For an easier way to subscribe to @acronym{NNTP} groups (@pxref{Browse Foreign Server}). +@item G M +@kindex G M (Group) +@findex gnus-group-read-ephemeral-group +Make an ephemeral group (@code{gnus-group-read-ephemeral-group}). Gnus +will prompt you for a name, a method and an @dfn{address}. + @item G r @kindex G r (Group) @findex gnus-group-rename-group @@ -5547,6 +5560,10 @@ Gnus will use the ``current'' select method when canceling. If you want to use the standard posting method, use the @samp{a} symbolic prefix (@pxref{Symbolic Prefixes}). +Gnus ensures that only you can cancel your own messages using a +@code{Cancel-Lock} header (@pxref{Canceling News, Canceling News, , +message, Message Manual}). + If you discover that you have made some mistakes and want to do some corrections, you can post a @dfn{superseding} article that will replace your original article. @@ -15762,6 +15779,7 @@ changes to a wiki (e.g. @url{http://cliki.net/recent-changes.rdf}). @acronym{RSS} has a quite regular and nice interface, and it's possible to get the information Gnus needs to keep groups updated. +@kindex G R (Summary) Use @kbd{G R} from the summary buffer to subscribe to a feed---you will be prompted for the location of the feed. @@ -18659,9 +18677,9 @@ Display the score of the current article @findex gnus-score-find-trace Display all score rules that have been used on the current article (@code{gnus-score-find-trace}). In the @code{*Score Trace*} buffer, you -can use @kbd{q} to quit. @kbd{e} edits the corresponding score file. -When point is on a string within the match element, @kbd{e} will try to -bring you to this string in the score file. +may type @kbd{e} to edit score file corresponding to the score rule on +current line and @kbd{f} to format (@code{gnus-score-pretty-print}) the +score file and edit it. @item V w @kindex V w (Summary) @@ -19401,8 +19419,8 @@ Type @kbd{M-x gnus-score-mode} to use this mode. @vindex gnus-score-mode-hook @code{gnus-score-menu-hook} is run in score mode buffers. -In the summary buffer you can use commands like @kbd{V f} and @kbd{V -e} to begin editing score files. +In the summary buffer you can use commands like @kbd{V f}, @kbd{V e} and +@kbd{V t} to begin editing score files. @node Adaptive Scoring @@ -22144,13 +22162,14 @@ This is annoying. Here's what you can do about it. First, some background on spam. If you have access to e-mail, you are familiar with spam (technically -termed @acronym{UCE}, Unsolicited Commercial E-mail). Simply put, it exists -because e-mail delivery is very cheap compared to paper mail, so only -a very small percentage of people need to respond to an UCE to make it -worthwhile to the advertiser. Ironically, one of the most common -spams is the one offering a database of e-mail addresses for further -spamming. Senders of spam are usually called @emph{spammers}, but terms like -@emph{vermin}, @emph{scum}, and @emph{morons} are in common use as well. +termed @acronym{UCE}, Unsolicited Commercial E-mail). Simply put, it +exists because e-mail delivery is very cheap compared to paper mail, +so only a very small percentage of people need to respond to an UCE to +make it worthwhile to the advertiser. Ironically, one of the most +common spams is the one offering a database of e-mail addresses for +further spamming. Senders of spam are usually called @emph{spammers}, +but terms like @emph{vermin}, @emph{scum}, @emph{sociopaths}, and +@emph{morons} are in common use as well. Spam comes from a wide variety of sources. It is simply impossible to dispose of all spam without discarding useful messages. A good @@ -22163,34 +22182,39 @@ through the TMDA system. Another problem with TMDA is that it requires its users to have a basic understanding of e-mail delivery and processing. -The simplest approach to filtering spam is filtering. If you get 200 -spam messages per day from @samp{random-address@@vmadmin.com}, you -block @samp{vmadmin.com}. If you get 200 messages about -@samp{VIAGRA}, you discard all messages with @samp{VIAGRA} in the -message. This, unfortunately, is a great way to discard legitimate -e-mail. For instance, the very informative and useful RISKS digest -has been blocked by overzealous mail filters because it -@strong{contained} words that were common in spam messages. -Nevertheless, in isolated cases, with great care, direct filtering of -mail can be useful. +The simplest approach to filtering spam is filtering, at the mail +server or when you sort through incoming mail. If you get 200 spam +messages per day from @samp{random-address@@vmadmin.com}, you block +@samp{vmadmin.com}. If you get 200 messages about @samp{VIAGRA}, you +discard all messages with @samp{VIAGRA} in the message. If you get +lots of spam from China, for example, you try to filter all mail from +Chinese IPs. + +This, unfortunately, is a great way to discard legitimate e-mail. For +instance, the very informative and useful RISKS digest has been +blocked by overzealous mail filters because it @strong{contained} +words that were common in spam messages. The risks of blocking a +whole country from contacting you should also be obvious, so don't do +it if you have the choice. Nevertheless, in isolated cases, with +great care, direct filtering of mail can be useful. Another approach to filtering e-mail is the distributed spam processing, for instance DCC implements such a system. In essence, @var{N} systems around the world agree that a machine @var{X} in -China, Ghana, or California is sending out spam e-mail, and these -@var{N} systems enter @var{X} or the spam e-mail from @var{X} into -a database. The criteria for spam detection vary---it may be the -number of messages sent, the content of the messages, and so on. When -a user of the distributed processing system wants to find out if a -message is spam, he consults one of those @var{N} systems. +Ghana, Estonia, or California is sending out spam e-mail, and these +@var{N} systems enter @var{X} or the spam e-mail from @var{X} into a +database. The criteria for spam detection vary---it may be the number +of messages sent, the content of the messages, and so on. When a user +of the distributed processing system wants to find out if a message is +spam, he consults one of those @var{N} systems. Distributed spam processing works very well against spammers that send a large number of messages at once, but it requires the user to set up fairly complicated checks. There are commercial and free distributed spam processing systems. Distributed spam processing has its risks as well. For instance legitimate e-mail senders have been accused of -sending spam, and their web sites have been shut down for some time -because of the incident. +sending spam, and their web sites and mailing lists have been shut +down for some time because of the incident. The statistical approach to spam filtering is also popular. It is based on a statistical analysis of previous spam messages. Usually @@ -22199,7 +22223,19 @@ words or 3-word combinations thrown into the mix. Statistical analysis of spam works very well in most of the cases, but it can classify legitimate e-mail as spam in some cases. It takes time to run the analysis, the full message must be analyzed, and the user has -to store the database of spam analyses. +to store the database of spam analyses. Statistical analysis on the +server is gaining popularity. This has the advantage of letting the +user Just Read Mail, but has the disadvantage that it's harder to tell +the server that it has misclassified mail. + +Fighting spam is not easy, no matter what anyone says. There is no +magic switch that will distinguish Viagra ads from Mom's e-mails. +Even people are having a hard time telling spam apart from non-spam, +because spammers are actively looking to fool us into thinking they +are Mom, essentially. Spamming is irritating, irresponsible, and +idiotic behavior from a bunch of people who think the world owes them +a favor. We hope the following sections will help you in fighting the +spam plague. @node Anti-Spam Basics @subsection Anti-Spam Basics @@ -22265,6 +22301,7 @@ just press @kbd{r} in the usual way), and I'm not bothered at all with spam. It's a win-win situation. Forging @code{From} headers to point to non-existent domains is yucky, in my opinion. +Be careful with this approach. Spammers are wise to it. @node SpamAssassin @@ -22273,7 +22310,7 @@ to non-existent domains is yucky, in my opinion. @cindex Vipul's Razor @cindex DCC -The days where the hints in the previous section was sufficient in +The days where the hints in the previous section were sufficient in avoiding spam are coming to an end. There are many tools out there that claim to reduce the amount of spam you get. This section could easily become outdated fast, as new products replace old, but @@ -22281,6 +22318,11 @@ fortunately most of these tools seem to have similar interfaces. Even though this section will use SpamAssassin as an example, it should be easy to adapt it to most other tools. +Note that this section does not involve the @code{spam.el} package, +which is discussed in the next section. If you don't care for all +the features of @code{spam.el}, you can make do with these simple +recipes. + If the tool you are using is not installed on the mail server, you need to invoke it yourself. Ideas on how to use the @code{:postscript} mail source parameter (@pxref{Mail Source @@ -22362,7 +22404,7 @@ work only because the tools are constantly maintained and updated as new form of spam appears. This means that a small percentage of spam will always get through. It also means that somewhere, someone needs to read lots of spam to update these tools. Hashcash avoids that, but -instead requires that everyone you communicate with supports the +instead prefers that everyone you contact through e-mail supports the scheme. You can view the two approaches as pragmatic vs dogmatic. The approaches have their own advantages and disadvantages, but as often in the real world, a combination of them is stronger than either @@ -22427,7 +22469,7 @@ a useful contribution, however. The idea behind @file{spam.el} is to have a control center for spam detection and filtering in Gnus. To that end, @file{spam.el} does two things: it -filters incoming mail, and it analyzes mail known to be spam or ham. +filters new mail, and it analyzes mail known to be spam or ham. @dfn{Ham} is the name used throughout @file{spam.el} to indicate non-spam messages. @@ -22444,6 +22486,12 @@ should turn it on before @code{spam-initialize}: So, what happens when you load @file{spam.el}? +First, some hooks will get installed by @code{spam-initialize}. There +are some hooks for @code{spam-stat} so it can save its databases, and +there are hooks so interesting things will happen when you enter and +leave a group. More on the sequence of events later (@pxref{Spam +ELisp Package Sequence of Events}). + You get the following keyboard commands: @table @kbd @@ -22479,6 +22527,225 @@ Also, when you load @file{spam.el}, you will be able to customize its variables. Try @code{customize-group} on the @samp{spam} variable group. +@menu +* Spam ELisp Package Sequence of Events:: +* Spam ELisp Package Filtering of Incoming Mail:: +* Spam ELisp Package Global Variables:: +* Spam ELisp Package Configuration Examples:: +* Blacklists and Whitelists:: +* BBDB Whitelists:: +* Gmane Spam Reporting:: +* Anti-spam Hashcash Payments:: +* Blackholes:: +* Regular Expressions Header Matching:: +* Bogofilter:: +* ifile spam filtering:: +* spam-stat spam filtering:: +* SpamOracle:: +* Extending the Spam ELisp package:: +@end menu + +@node Spam ELisp Package Sequence of Events +@subsubsection Spam ELisp Package Sequence of Events +@cindex spam filtering +@cindex spam filtering sequence of events +@cindex spam + +You must read this section to understand how @code{spam.el} works. +Do not skip, speed-read, or glance through this section. + +There are two @emph{contact points}, if you will, between +@code{spam.el} and the rest of Gnus: checking new mail for spam, and +leaving a group. + +Getting new mail is done in one of two ways. You can either split +your incoming mail or you can classify new articles as ham or spam +when you enter the group. + +Splitting incoming mail is better suited to mail backends such as +@code{nnml} or @code{nnimap} where new mail appears in a single file +called a @dfn{Spool File}. See @xref{Spam ELisp Package Filtering of +Incoming Mail}. + +For backends such as @code{nntp} there is no incoming mail spool, so +an alternate mechanism must be used. This may also happen for +backends where the server is in charge of splitting incoming mail, and +Gnus does not do further splitting. The @code{spam-autodetect} and +@code{spam-autodetect-methods} group parameters (accessible with +@kbd{G c} and @kbd{G p} as usual), and the corresponding variables +@code{gnus-spam-autodetect-methods} and +@code{gnus-spam-autodetect-methods} (accessible with @kbd{M-x +customize-variable} as usual). + +When @code{spam-autodetect} is used, it hooks into the process of +entering a group. Thus, entering a group with unseen or unread +articles becomes the substitute for checking incoming mail. Whether +only unseen articles or all unread articles will be processed is +determined by the @code{spam-autodetect-recheck-messages}. When set +to t, unread messages will be rechecked. + +@code{spam-autodetect} grants the user at once more and less control +of spam filtering. The user will have more control over each group's +spam methods, so for instance the @samp{ding} group may have +@code{spam-use-BBDB} as the autodetection method, while the +@samp{suspect} group may have the @code{spam-use-blacklist} and +@code{spam-use-bogofilter} methods enabled. Every article detected to +be spam will be marked with the spam mark @samp{$} and processed on +exit from the group as normal spam. The user has less control over +the @emph{sequence} of checks, as he might with @code{spam-split}. + +When the newly split mail goes into groups, or messages are +autodetected to be ham or spam, those groups must be exited (after +entering, if needed) for further spam processing to happen. It +matters whether the group is considered a ham group, a spam group, or +is unclassified, based on its @code{spam-content} parameter +(@pxref{Spam ELisp Package Global Variables}). Spam groups have the +additional characteristic that, when entered, any unseen or unread +articles (depending on the @code{spam-mark-only-unseen-as-spam} +variable) will be marked as spam. Thus, mail split into a spam group +gets automatically marked as spam when you enter the group. + +So, when you exit a group, the @code{spam-processors} are applied, if +any are set, and the processed mail is moved to the +@code{ham-process-destination} or the @code{spam-process-destination} +depending on the article's classification. If the +@code{ham-process-destination} or the @code{spam-process-destination}, +whichever is appropriate, are nil, the article is left in the current +group. + +If a spam is found in any group (this can be changed to only non-spam +groups with @code{spam-move-spam-nonspam-groups-only}), it is +processed by the active @code{spam-processors} (@pxref{Spam ELisp +Package Global Variables}) when the group is exited. Furthermore, the +spam is moved to the @code{spam-process-destination} (@pxref{Spam +ELisp Package Global Variables}) for further training or deletion. +You have to load the @code{gnus-registry.el} package and enable the +@code{spam-log-to-registry} variable if you want spam to be processed +no more than once. Thus, spam is detected and processed everywhere, +which is what most people want. + +If a ham mail is found in a ham group, as determineed by the +@code{ham-marks} parameter, it is processed as ham by the active ham +@code{spam-processor} when the group is exited. With the variables +@code{spam-process-ham-in-spam-groups} and +@code{spam-process-ham-in-nonham-groups} the behavior can be further +altered so ham found anywhere can be processed. You have to load the +@code{gnus-registry.el} package and enable the +@code{spam-log-to-registry} variable if you want ham to be processed +no more than once. Thus, ham is detected and processed only when +necessary, which is what most people want. More on this in +@xref{Spam ELisp Package Configuration Examples}. + +If all this seems confusing, don't worry. Soon it will be as natural +as typing Lisp one-liners on a neural interface... err, sorry, that's +50 years in the future yet. Just trust us, it's not so bad. + +@node Spam ELisp Package Filtering of Incoming Mail +@subsubsection Spam ELisp Package Filtering of Incoming Mail +@cindex spam filtering +@cindex spam filtering incoming mail +@cindex spam + +To use the @file{spam.el} facilities for incoming mail filtering, you +must add the following to your fancy split list +@code{nnmail-split-fancy} or @code{nnimap-split-fancy}: + +@example +(: spam-split) +@end example + +Note that the fancy split may be called @code{nnmail-split-fancy} or +@code{nnimap-split-fancy}, depending on whether you use the nnmail or +nnimap back ends to retrieve your mail. + +The @code{spam-split} function will process incoming mail and send the +mail considered to be spam into the group name given by the variable +@code{spam-split-group}. By default that group name is @samp{spam}, +but you can customize @code{spam-split-group}. Make sure the contents +of @code{spam-split-group} are an @emph{unqualified} group name, for +instance in an @code{nnimap} server @samp{your-server} the value +@samp{spam} will turn out to be @samp{nnimap+your-server:spam}. The +value @samp{nnimap+server:spam}, therefore, is wrong and will +actually give you the group +@samp{nnimap+your-server:nnimap+server:spam} which may or may not +work depending on your server's tolerance for strange group names. + +You can also give @code{spam-split} a parameter, +e.g. @samp{'spam-use-regex-headers} or @samp{"maybe-spam"}. Why is +this useful? + +Take these split rules (with @code{spam-use-regex-headers} and +@code{spam-use-blackholes} set): + +@example + nnimap-split-fancy '(| + (any "ding" "ding") + (: spam-split) + ;; default mailbox + "mail") +@end example + +Now, the problem is that you want all ding messages to make it to the +ding folder. But that will let obvious spam (for example, spam +detected by SpamAssassin, and @code{spam-use-regex-headers}) through, +when it's sent to the ding list. On the other hand, some messages to +the ding list are from a mail server in the blackhole list, so the +invocation of @code{spam-split} can't be before the ding rule. + +You can let SpamAssassin headers supersede ding rules, but all other +@code{spam-split} rules (including a second invocation of the +regex-headers check) will be after the ding rule: + +@example + nnimap-split-fancy '(| +;;; all spam detected by spam-use-regex-headers goes to "regex-spam" + (: spam-split "regex-spam" 'spam-use-regex-headers) + (any "ding" "ding") +;;; all other spam detected by spam-split goes to spam-split-group + (: spam-split) + ;; default mailbox + "mail") +@end example + +This lets you invoke specific @code{spam-split} checks depending on +your particular needs, and to target the results of those checks to a +particular spam group. You don't have to throw all mail into all the +spam tests. Another reason why this is nice is that messages to +mailing lists you have rules for don't have to have resource-intensive +blackhole checks performed on them. You could also specify different +spam checks for your nnmail split vs. your nnimap split. Go crazy. + +You should still have specific checks such as +@code{spam-use-regex-headers} set to @code{t}, even if you +specifically invoke @code{spam-split} with the check. The reason is +that when loading @file{spam.el}, some conditional loading is done +depending on what @code{spam-use-xyz} variables you have set. This +is usually not critical, though. + +@emph{Note for IMAP users} + +The boolean variable @code{nnimap-split-download-body} needs to be +set, if you want to split based on the whole message instead of just +the headers. By default, the nnimap back end will only retrieve the +message headers. If you use @code{spam-check-bogofilter}, +@code{spam-check-ifile}, or @code{spam-check-stat} (the splitters that +can benefit from the full message body), you should set this variable. +It is not set by default because it will slow @acronym{IMAP} down, and +that is not an appropriate decision to make on behalf of the user. + +@xref{Splitting in IMAP}. + +@emph{TODO: spam.el needs to provide a uniform way of training all the +statistical databases. Some have that functionality built-in, others +don't.} + +@node Spam ELisp Package Global Variables +@subsubsection Spam ELisp Package Global Variables +@cindex spam filtering +@cindex spam filtering variables +@cindex spam variables +@cindex spam + @vindex gnus-spam-process-newsgroups The concepts of ham processors and spam processors are very important. Ham processors and spam processors for a group can be set with the @@ -22489,6 +22756,10 @@ that later similar mail will also be considered non-spam. Spam processors take mail known to be spam and process it so similar spam will be detected later. +The format of the spam or ham processor entry used to be a symbol, +but now it is a cons cell. See the individual spam processor entries +for more information. + @vindex gnus-spam-newsgroup-contents Gnus learns from the spam you get. You have to collect your spam in one or more spam groups, and set or customize the variable @@ -22533,13 +22804,19 @@ should then adjust the @code{ham-marks} group parameter. @defvar ham-marks You can customize this group or topic parameter to be the list of marks you want to consider ham. By default, the list contains the -deleted, read, killed, kill-filed, and low-score marks. +deleted, read, killed, kill-filed, and low-score marks (the idea is +that these articles have been read, but are not spam). It can be +useful to also include the tick mark in the ham marks. It is not +recommended to make the unread mark a ham mark, because it normally +indicates a lack of classification. But you can do it, and we'll be +happy for you. @end defvar @defvar spam-marks You can customize this group or topic parameter to be the list of marks you want to consider spam. By default, the list contains only -the spam mark. +the spam mark. It is not recommended to change that, but you can if +you really want to. @end defvar When you leave @emph{any} group, regardless of its @@ -22562,11 +22839,15 @@ names (it's easiest to customize this variable with @code{customize-variable gnus-ham-process-destinations}). Each newsgroup specification has the format (REGEXP PROCESSOR) in a standard Lisp list, if you prefer to customize the variable manually. -The ultimate location is a group name. If the +The ultimate location is a group name or names. If the @code{ham-process-destination} parameter is not set, ham articles are left in place. If the @code{spam-mark-ham-unread-before-move-from-spam-group} parameter is -set, the ham articles are marked as unread before being moved. +set, the ham articles are marked as unread before being moved. + +Note that you can use multiples destinations per group or regular +expression! This enables you to send your ham to a regular mail +group and to a @emph{ham training} group. When you leave a @emph{ham} group, all ham-marked articles are sent to a ham processor, which will study these as non-spam samples. @@ -22592,125 +22873,51 @@ the @code{spam-process-destination} group parameter or a match in the regular expressions matched with group names (it's easiest to customize this variable with @code{customize-variable gnus-spam-process-destinations}). Each newsgroup specification has -the repeated format (REGEXP PROCESSOR) and they are all in a standard -Lisp list, if you prefer to customize the variable manually. The -ultimate location is a group name. If the +the repeated format (REGEXP GROUP) and they are all in a standard Lisp +list, if you prefer to customize the variable manually. The ultimate +location is a group name or names. If the @code{spam-process-destination} parameter is not set, the spam -articles are only expired. - -To use the @file{spam.el} facilities for incoming mail filtering, you -must add the following to your fancy split list -@code{nnmail-split-fancy} or @code{nnimap-split-fancy}: - -@example -(: spam-split) -@end example - -Note that the fancy split may be called @code{nnmail-split-fancy} or -@code{nnimap-split-fancy}, depending on whether you use the nnmail or -nnimap back ends to retrieve your mail. - -The @code{spam-split} function will process incoming mail and send the -mail considered to be spam into the group name given by the variable -@code{spam-split-group}. By default that group name is @samp{spam}, -but you can customize @code{spam-split-group}. Make sure the contents -of @code{spam-split-group} are an @emph{unqualified} group name, for -instance in an @code{nnimap} server @samp{your-server} the value -@samp{spam} will turn out to be @samp{nnimap+your-server:spam}. The -value @samp{nnimap+server:spam}, therefore, is wrong and will -actually give you the group -@samp{nnimap+your-server:nnimap+server:spam} which may or may not -work depending on your server's tolerance for strange group names. - -You can also give @code{spam-split} a parameter, -e.g. @samp{'spam-use-regex-headers} or @samp{"maybe-spam"}. Why is -this useful? - -Take these split rules (with @code{spam-use-regex-headers} and -@code{spam-use-blackholes} set): - -@example - nnimap-split-fancy '(| - (any "ding" "ding") - (: spam-split) - ;; default mailbox - "mail") -@end example - -Now, the problem is that you want all ding messages to make it to the -ding folder. But that will let obvious spam (for example, spam -detected by SpamAssassin, and @code{spam-use-regex-headers}) through, -when it's sent to the ding list. On the other hand, some messages to -the ding list are from a mail server in the blackhole list, so the -invocation of @code{spam-split} can't be before the ding rule. - -You can let SpamAssassin headers supersede ding rules, but all other -@code{spam-split} rules (including a second invocation of the -regex-headers check) will be after the ding rule: - -@example - nnimap-split-fancy '(| -;;; all spam detected by spam-use-regex-headers goes to "regex-spam" - (: spam-split "regex-spam" 'spam-use-regex-headers) - (any "ding" "ding") -;;; all other spam detected by spam-split goes to spam-split-group - (: spam-split) - ;; default mailbox - "mail") -@end example - -Basically, this lets you invoke specific @code{spam-split} checks -depending on your particular needs, and to target the results of those -checks to a particular spam group. You don't have to throw all mail -into all the spam tests. Another reason why this is nice is that -messages to mailing lists you have rules for don't have to have -resource-intensive blackhole checks performed on them. You could also -specify different spam checks for your nnmail split vs. your nnimap -split. Go crazy. - -You still have to have specific checks such as -@code{spam-use-regex-headers} set to @code{t}, even if you specifically -invoke @code{spam-split} with the check. The reason is that when -loading @file{spam.el}, some conditional loading is done depending on -what @code{spam-use-xyz} variables you have set. - -@emph{Note for IMAP users} - -The boolean variable @code{nnimap-split-download-body} needs to be -set, if you want to split based on the whole message instead of just -the headers. By default, the nnimap back end will only retrieve the -message headers. If you use @code{spam-check-bogofilter}, -@code{spam-check-ifile}, or @code{spam-check-stat} (the splitters that -can benefit from the full message body), you should set this variable. -It is not set by default because it will slow @acronym{IMAP} down, and -that is not an appropriate decision to make on behalf of the user. - -@xref{Splitting in IMAP}. - -@emph{TODO: Currently, spam.el only supports insertion of articles -into a back end. There is no way to tell spam.el that an article is no -longer spam or ham.} - -@emph{TODO: spam.el needs to provide a uniform way of training all the -statistical databases. Some have that functionality built-in, others -don't.} - -The following are the methods you can use to control the behavior of -@code{spam-split} and their corresponding spam and ham processors: +articles are only expired. The group name is fully qualified, meaning +that if you see @samp{nntp:servername} before the group name in the +group buffer then you need it here as well. + +Note that you can use multiples destinations per group or regular +expression! This enables you to send your spam to multiple @emph{spam +training} groups. + +@vindex spam-log-to-registry +The problem with processing ham and spam is that Gnus doesn't track +this processing by default. Enable the @code{spam-log-to-registry} +variable so @code{spam.el} will use @code{gnus-registry.el} to track +what articles have been processed, and avoid processing articles +multiple times. Keep in mind that if you limit the number of registry +entries, this won't work as well as it does without a limit. + +@vindex spam-mark-only-unseen-as-spam +Set this variable if you want only unseen articles in spam groups to +be marked as spam. By default, it is set. If you set it to nil, +unread articles will also be marked as spam. + +@vindex spam-mark-ham-unread-before-move-from-spam-group +Set this variable if you want ham to be unmarked before it is moved +out of the spam group. This is very useful when you use something +like the tick mark @samp{!} to mark ham - the article will be placed +in your ham-process-destination, unmarked as if it came fresh from +the mail server. + +@vindex spam-autodetect-recheck-messages +When autodetecting spam, this variable tells @code{spam.el} whether +only unseen articles or all unread articles should be checked for +spam. It is recommended that you leave it off. + +@node Spam ELisp Package Configuration Examples +@subsubsection Spam ELisp Package Configuration Examples +@cindex spam filtering +@cindex spam filtering configuration examples +@cindex spam configuration examples +@cindex spam -@menu -* Blacklists and Whitelists:: -* BBDB Whitelists:: -* Gmane Spam Reporting:: -* Anti-spam Hashcash Payments:: -* Blackholes:: -* Regular Expressions Header Matching:: -* Bogofilter:: -* ifile spam filtering:: -* spam-stat spam filtering:: -* SpamOracle:: -* Extending the spam elisp package:: -@end menu +@emph{TODO}: add configuration examples with explanations of daily usage @node Blacklists and Whitelists @subsubsection Blacklists and Whitelists @@ -22755,6 +22962,13 @@ customizing the group parameters or the added to a group's @code{spam-process} parameter, the senders of spam-marked articles will be added to the blacklist. +@emph{WARNING} + +Instead of the obsolete +@code{gnus-group-spam-exit-processor-blacklist}, it is recommended +that you use @code{'(spam spam-use-blacklist)}. Everything will work +the same way, we promise. + @end defvar @defvar gnus-group-ham-exit-processor-whitelist @@ -22767,6 +22981,13 @@ ham-marked articles in @emph{ham} groups will be added to the whitelist. Note that this ham processor has no effect in @emph{spam} or @emph{unclassified} groups. +@emph{WARNING} + +Instead of the obsolete +@code{gnus-group-ham-exit-processor-whitelist}, it is recommended +that you use @code{'(ham spam-use-whitelist)}. Everything will work +the same way, we promise. + @end defvar Blacklists are lists of regular expressions matching addresses you @@ -22826,6 +23047,13 @@ ham-marked articles in @emph{ham} groups will be added to the BBDB. Note that this ham processor has no effect in @emph{spam} or @emph{unclassified} groups. +@emph{WARNING} + +Instead of the obsolete +@code{gnus-group-ham-exit-processor-BBDB}, it is recommended +that you use @code{'(ham spam-use-BBDB)}. Everything will work +the same way, we promise. + @end defvar @node Gmane Spam Reporting @@ -22846,6 +23074,13 @@ HTTP request. Gmane can be found at @uref{http://gmane.org}. +@emph{WARNING} + +Instead of the obsolete +@code{gnus-group-spam-exit-processor-report-gmane}, it is recommended +that you use @code{'(spam spam-use-gmane)}. Everything will work the +same way, we promise. + @end defvar @defvar spam-report-gmane-use-article-number @@ -23007,6 +23242,13 @@ customizing the group parameters or the @code{gnus-spam-process-newsgroups} variable. When this symbol is added to a group's @code{spam-process} parameter, spam-marked articles will be added to the Bogofilter spam database. + +@emph{WARNING} + +Instead of the obsolete +@code{gnus-group-spam-exit-processor-bogofilter}, it is recommended +that you use @code{'(spam spam-use-bogofilter)}. Everything will work +the same way, we promise. @end defvar @defvar gnus-group-ham-exit-processor-bogofilter @@ -23017,6 +23259,13 @@ added to a group's @code{spam-process} parameter, the ham-marked articles in @emph{ham} groups will be added to the Bogofilter database of non-spam messages. Note that this ham processor has no effect in @emph{spam} or @emph{unclassified} groups. + +@emph{WARNING} + +Instead of the obsolete +@code{gnus-group-ham-exit-processor-bogofilter}, it is recommended +that you use @code{'(ham spam-use-bogofilter)}. Everything will work +the same way, we promise. @end defvar @defvar spam-bogofilter-database-directory @@ -23097,6 +23346,13 @@ customizing the group parameters or the @code{gnus-spam-process-newsgroups} variable. When this symbol is added to a group's @code{spam-process} parameter, the spam-marked articles will be added to the spam-stat database of spam messages. + +@emph{WARNING} + +Instead of the obsolete +@code{gnus-group-spam-exit-processor-stat}, it is recommended +that you use @code{'(spam spam-use-stat)}. Everything will work +the same way, we promise. @end defvar @defvar gnus-group-ham-exit-processor-stat @@ -23107,6 +23363,13 @@ added to a group's @code{spam-process} parameter, the ham-marked articles in @emph{ham} groups will be added to the spam-stat database of non-spam messages. Note that this ham processor has no effect in @emph{spam} or @emph{unclassified} groups. + +@emph{WARNING} + +Instead of the obsolete +@code{gnus-group-ham-exit-processor-stat}, it is recommended +that you use @code{'(ham spam-use-stat)}. Everything will work +the same way, we promise. @end defvar This enables @file{spam.el} to cooperate with @file{spam-stat.el}. @@ -23192,6 +23455,13 @@ customizing the group parameter or the @code{gnus-spam-process-newsgroups} variable. When this symbol is added to a group's @code{spam-process} parameter, spam-marked articles will be sent to SpamOracle as spam samples. + +@emph{WARNING} + +Instead of the obsolete +@code{gnus-group-spam-exit-processor-spamoracle}, it is recommended +that you use @code{'(spam spam-use-spamoracle)}. Everything will work +the same way, we promise. @end defvar @defvar gnus-group-ham-exit-processor-spamoracle @@ -23202,25 +23472,32 @@ to a grup's @code{spam-process} parameter, the ham-marked articles in @emph{ham} groups will be sent to the SpamOracle as samples of ham messages. Note that this ham processor has no effect in @emph{spam} or @emph{unclassified} groups. + +@emph{WARNING} + +Instead of the obsolete +@code{gnus-group-ham-exit-processor-spamoracle}, it is recommended +that you use @code{'(ham spam-use-spamoracle)}. Everything will work +the same way, we promise. @end defvar -@emph{Example:} These are the Group Parameters of an group that has been +@emph{Example:} These are the Group Parameters of a group that has been classified as a ham group, meaning that it should only contain ham messages. @example ((spam-contents gnus-group-spam-classification-ham) - (spam-process - (gnus-group-spam-exit-processor-spamoracle))) + (spam-process ((ham spam-use-spamoracle) + (spam spam-use-spamoracle)))) @end example -For this group the @code{gnus-group-spam-exit-processor-spamoracle} is -installed. If the group contains spam message (e.g. because SpamOracle -has not had enough sample messages yet) and the user marks some -messages as spam messages, these messages will be processed by -@code{gnus-group-spam-exit-processor-spamoracle}. This processor sends -the messages to SpamOracle as new samples for spam. - -@node Extending the spam elisp package -@subsubsection Extending the spam elisp package +For this group the @code{spam-use-spamoracle} is installed for both +ham and spam processing. If the group contains spam message +(e.g. because SpamOracle has not had enough sample messages yet) and +the user marks some messages as spam messages, these messages will be +processed by SpamOracle. The processor sends the messages to +SpamOracle as new samples for spam. + +@node Extending the Spam ELisp package +@subsubsection Extending the Spam ELisp package @cindex spam filtering @cindex spam elisp package, extending @cindex extending the spam elisp package @@ -23240,16 +23517,37 @@ code Add @example - (spam-use-blackbox . spam-check-blackbox) + (spam-use-blackbox . spam-check-blackbox) @end example to @code{spam-list-of-checks}. +Add +@example + (gnus-group-ham-exit-processor-blackbox ham spam-use-blackbox) + (gnus-group-spam-exit-processor-blackbox spam spam-use-blackbox) +@end example +to @code{spam-list-of-processors}. + +Add +@example + (spam-use-blackbox spam-blackbox-register-routine + nil + spam-blackbox-unregister-routine + nil) +@end example +to @code{spam-registration-functions}. Write the register/unregister +routines using the bogofilter register/unregister routines as a +start, or other restister/unregister routines more appropriate to +Blackbox. + @item functionality Write the @code{spam-check-blackbox} function. It should return -@samp{nil} or @code{spam-split-group}. See the existing -@code{spam-check-*} functions for examples of what you can do. +@samp{nil} or @code{spam-split-group}, observing the other +conventions. See the existing @code{spam-check-*} functions for +examples of what you can do, and stick to the template unless you +fully understand the reasons why you aren't. Make sure to add @code{spam-use-blackbox} to @code{spam-list-of-statistical-checks} if Blackbox is a statistical @@ -23267,48 +23565,40 @@ code Note you don't have to provide a spam or a ham processor. Only provide them if Blackbox supports spam or ham processing. +Also, ham and spam processors are being phased out as single +variables. Instead the form @code{'(spam spam-use-blackbox)} or +@code{'(ham spam-use-blackbox)} is favored. For now, spam/ham +processor variables are still around but they won't be for long. + @lisp -(defvar gnus-group-spam-exit-processor-blackbox "blackbox" +(defvar gnus-group-spam-exit-processor-blackbox "blackbox-spam" "The Blackbox summary exit spam processor. Only applicable to spam groups.") -(defvar gnus-group-ham-exit-processor-blackbox "blackbox" +(defvar gnus-group-ham-exit-processor-blackbox "blackbox-ham" "The whitelist summary exit ham processor. Only applicable to non-spam (unclassified and ham) groups.") @end lisp @item -functionality +Gnus parameters -@lisp -(defun spam-blackbox-register-spam-routine () - (spam-generic-register-routine - ;; @r{the spam function} - (lambda (article) - (let ((from (spam-fetch-field-from-fast article))) - (when (stringp from) - (blackbox-do-something-with-this-spammer from)))) - ;; @r{the ham function} - nil)) - -(defun spam-blackbox-register-ham-routine () - (spam-generic-register-routine - ;; @r{the spam function} - nil - ;; @r{the ham function} - (lambda (article) - (let ((from (spam-fetch-field-from-fast article))) - (when (stringp from) - (blackbox-do-something-with-this-ham-sender from)))))) -@end lisp - -Write the @code{blackbox-do-something-with-this-ham-sender} and -@code{blackbox-do-something-with-this-spammer} functions. You can add -more complex code than fetching the message sender, but keep in mind -that retrieving the whole message takes significantly longer than the -sender through @code{spam-fetch-field-from-fast}, because the message -senders are kept in memory by Gnus. +Add +@example + (const :tag "Spam: Blackbox" (spam spam-use-blackbox)) + (const :tag "Ham: Blackbox" (ham spam-use-blackbox)) +@end example +to the @code{spam-process} group parameter in @code{gnus.el}. Make +sure you do it twice, once for the parameter and once for the +variable customization. + +Add +@example + (variable-item spam-use-blackbox) +@end example +to the @code{spam-autodetect-methods} group parameter in +@code{gnus.el}. @end enumerate @@ -23451,7 +23741,7 @@ spam or it should go into @samp{mail.misc}. If it is spam, then @lisp (setq nnmail-split-fancy `(| (: spam-stat-split-fancy) - "mail.misc")) + "mail.misc")) @end lisp @defvar spam-stat-split-fancy-spam-group @@ -23465,8 +23755,8 @@ expression are considered potential spam. @lisp (setq nnmail-split-fancy `(| ("Subject" "\\bspam-stat\\b" "mail.emacs") - (: spam-stat-split-fancy) - "mail.misc")) + (: spam-stat-split-fancy) + "mail.misc")) @end lisp If you want to filter for spam first, then you must be careful when @@ -23479,7 +23769,7 @@ mails, when creating the dictionary! (setq nnmail-split-fancy `(| (: spam-stat-split-fancy) ("Subject" "\\bspam-stat\\b" "mail.emacs") - "mail.misc")) + "mail.misc")) @end lisp You can combine this with traditional filtering. Here, we move all @@ -23492,9 +23782,9 @@ dictionary! @lisp (setq nnmail-split-fancy `(| ("Content-Type" "text/html" "mail.spam.filtered") - (: spam-stat-split-fancy) + (: spam-stat-split-fancy) ("Subject" "\\bspam-stat\\b" "mail.emacs") - "mail.misc")) + "mail.misc")) @end lisp @@ -23749,10 +24039,10 @@ but at the common table.@* XEmacs is distributed as a collection of packages. You should install whatever packages the Gnus XEmacs package requires. The current -requirements are @samp{gnus}, @samp{w3}, @samp{mh-e}, -@samp{mailcrypt}, @samp{rmail}, @samp{eterm}, @samp{mail-lib}, -@samp{xemacs-base}, @samp{sh-script} and @samp{fsf-compat}. The -@samp{misc-games} package is required for Morse decoding. +requirements are @samp{gnus}, @samp{mail-lib}, @samp{xemacs-base}, +@samp{eterm}, @samp{sh-script}, @samp{net-utils}, @samp{os-utils}, +@samp{dired}, @samp{mh-e}, @samp{sieve}, @samp{ps-print}, @samp{w3}, +@samp{pgg}, @samp{mailcrypt}, @samp{ecrypto}, and @samp{sasl}. @node History @@ -25155,6 +25445,10 @@ New features in Gnus 5.10: @itemize @bullet @item +@code{gnus-group-read-ephemeral-group} can be called interactively, +using @kbd{G M}. + +@item In draft groups, @kbd{e} is now bound to @code{gnus-draft-edit-message}. Use @kbd{B w} for @code{gnus-summary-edit-article} instead. @@ -25356,10 +25650,10 @@ parameters, a'la: @lisp (setq gnus-parameters '(("mail\\..*" - (gnus-show-threads nil) - (gnus-use-scoring nil)) - ("^nnimap:\\(foo.bar\\)$" - (to-group . "\\1")))) + (gnus-show-threads nil) + (gnus-use-scoring nil)) + ("^nnimap:\\(foo.bar\\)$" + (to-group . "\\1")))) @end lisp @item @@ -25550,7 +25844,7 @@ Add a new format of match like The old format like the lines below is obsolete, but still accepted. @lisp (header "to" "larsi.*org" - (Organization "Somewhere, Inc.")) + (Organization "Somewhere, Inc.")) @end lisp @item @@ -26170,7 +26464,7 @@ Gnus will work. @item Try doing an @kbd{M-x gnus-version}. If you get something that looks -like @samp{Gnus v5.10.3} you have the right files loaded. Otherwise +like @samp{Gnus v5.10.4} you have the right files loaded. Otherwise you have some old @file{.el} files lying around. Delete these. @item diff --git a/texi/message.texi b/texi/message.texi index b3c3f9c..516d5f8 100644 --- a/texi/message.texi +++ b/texi/message.texi @@ -88,7 +88,7 @@ Message mode buffers. * Key Index:: List of Message mode keys. @end menu -This manual corresponds to Message v5.10.3. Message is distributed +This manual corresponds to Message v5.10.4. Message is distributed with the Gnus distribution bearing the same version number as this manual. @@ -1227,7 +1227,7 @@ controlled by the @code{ispell-message-dictionary-alist} variable: @lisp (setq ispell-message-dictionary-alist '(("^Newsgroups:.*\\bde\\." . "deutsch8") - (".*" . "default"))) + (".*" . "default"))) @end lisp @code{ispell} depends on having the external @samp{ispell} command -- 1.7.10.4