+
+@node SpamAssassin
+@subsection SpamAssassin, Vipul's Razor, DCC, etc
+@cindex SpamAssassin
+@cindex Vipul's Razor
+@cindex DCC
+
+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
+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
+Specifiers}) follow.
+
+@lisp
+(setq mail-sources
+ '((file :prescript "formail -bs spamassassin < /var/mail/%u")
+ (pop :user "jrl"
+ :server "pophost"
+ :postscript
+ "mv %t /tmp/foo; formail -bs spamc < /tmp/foo > %t")))
+@end lisp
+
+Once you manage to process your incoming spool somehow, thus making
+the mail contain e.g.@: a header indicating it is spam, you are ready to
+filter it out. Using normal split methods (@pxref{Splitting Mail}):
+
+@lisp
+(setq nnmail-split-methods '(("spam" "^X-Spam-Flag: YES")
+ ...))
+@end lisp
+
+Or using fancy split methods (@pxref{Fancy Mail Splitting}):
+
+@lisp
+(setq nnmail-split-methods 'nnmail-split-fancy
+ nnmail-split-fancy '(| ("X-Spam-Flag" "YES" "spam")
+ ...))
+@end lisp
+
+Some people might not like the idea of piping the mail through various
+programs using a @code{:prescript} (if some program is buggy, you
+might lose all mail). If you are one of them, another solution is to
+call the external tools during splitting. Example fancy split method:
+
+@lisp
+(setq nnmail-split-fancy '(| (: kevin-spamassassin)
+ ...))
+(defun kevin-spamassassin ()
+ (save-excursion
+ (save-restriction
+ (widen)
+ (if (eq 1 (call-process-region (point-min) (point-max)
+ "spamc" nil nil nil "-c"))
+ "spam"))))
+@end lisp
+
+Note that with the nnimap backend, message bodies will not be
+downloaded by default. You need to set
+@code{nnimap-split-download-body} to @code{t} to do that
+(@pxref{Splitting in IMAP}).
+
+That is about it. As some spam is likely to get through anyway, you
+might want to have a nifty function to call when you happen to read
+spam. And here is the nifty function:
+
+@lisp
+ (defun my-gnus-raze-spam ()
+ "Submit SPAM to Vipul's Razor, then mark it as expirable."
+ (interactive)
+ (gnus-summary-show-raw-article)
+ (gnus-summary-save-in-pipe "razor-report -f -d")
+ (gnus-summary-mark-as-expirable 1))
+@end lisp
+
+@node Hashcash
+@subsection Hashcash
+@cindex hashcash
+
+A novel technique to fight spam is to require senders to do something
+costly for each message they send. This has the obvious drawback that
+you cannot rely on everyone in the world using this technique,
+since it is not part of the Internet standards, but it may be useful
+in smaller communities.
+
+While the tools in the previous section work well in practice, they
+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 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
+one of them separately.
+
+@cindex X-Hashcash
+The ``something costly'' is to burn CPU time, more specifically to
+compute a hash collision up to a certain number of bits. The
+resulting hashcash cookie is inserted in a @samp{X-Hashcash:}
+header. For more details, and for the external application
+@code{hashcash} you need to install to use this feature, see
+@uref{http://www.cypherspace.org/~adam/hashcash/}. Even more
+information can be found at @uref{http://www.camram.org/}.
+
+If you wish to call hashcash for each message you send, say something
+like:
+
+@lisp
+(require 'hashcash)
+(add-hook 'message-send-hook 'mail-add-payment)
+@end lisp
+
+The @file{hashcash.el} library can be found in the Gnus development
+contrib directory or at
+@uref{http://users.actrix.gen.nz/mycroft/hashcash.el}.
+
+You will need to set up some additional variables as well:
+
+@table @code
+
+@item hashcash-default-payment
+@vindex hashcash-default-payment
+This variable indicates the default number of bits the hash collision
+should consist of. By default this is 0, meaning nothing will be
+done. Suggested useful values include 17 to 29.
+
+@item hashcash-payment-alist
+@vindex hashcash-payment-alist
+Some receivers may require you to spend burn more CPU time than the
+default. This variable contains a list of @samp{(@var{addr}
+@var{amount})} cells, where @var{addr} is the receiver (email address
+or newsgroup) and @var{amount} is the number of bits in the collision
+that is needed. It can also contain @samp{(@var{addr} @var{string}
+@var{amount})} cells, where the @var{string} is the string to use
+(normally the email address or newsgroup name is used).
+
+@item hashcash
+@vindex hashcash
+Where the @code{hashcash} binary is installed.
+
+@end table
+
+Currently there is no built in functionality in Gnus to verify
+hashcash cookies, it is expected that this is performed by your hand
+customized mail filtering scripts. Improvements in this area would be
+a useful contribution, however.
+
+@node Filtering Spam Using The Spam ELisp Package
+@subsection Filtering Spam Using The Spam ELisp Package
+@cindex spam filtering
+@cindex spam
+
+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 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.
+
+First of all, you @strong{must} run the function
+@code{spam-initialize} to autoload @code{spam.el} and to install the
+@code{spam.el} hooks. There is one exception: if you use the
+@code{spam-use-stat} (@pxref{spam-stat spam filtering}) setting, you
+should turn it on before @code{spam-initialize}:
+
+@example
+(setq spam-use-stat t) ;; if needed
+(spam-initialize)
+@end example
+
+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
+
+@item M-d
+@itemx M s x
+@itemx S x
+@kindex M-d
+@kindex S x
+@kindex M s x
+@findex gnus-summary-mark-as-spam
+@code{gnus-summary-mark-as-spam}.
+
+Mark current article as spam, showing it with the @samp{$} mark.
+Whenever you see a spam article, make sure to mark its summary line
+with @kbd{M-d} before leaving the group. This is done automatically
+for unread articles in @emph{spam} groups.
+
+@item M s t
+@itemx S t
+@kindex M s t
+@kindex S t
+@findex spam-bogofilter-score
+@code{spam-bogofilter-score}.
+
+You must have Bogofilter installed for that command to work properly.
+
+@xref{Bogofilter}.
+
+@end table
+
+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::
+* SpamAssassin backend::
+* 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}.
+
+@vindex gnus-spam-autodetect
+@vindex gnus-spam-autodetect-methods
+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} and @code{gnus-spam-autodetect-methods}
+(accessible with @kbd{M-x customize-variable} as usual) can help.
+
+When @code{spam-autodetect} is used (you can turn it on for a
+group/topic or wholesale by regex, as needed), 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 @code{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 @code{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 the
+@code{spam-process-destination} is @code{nil}, the spam is marked as
+expired, which is usually the right thing to do.
+
+If spam can not be moved---because of a read-only backend such as
+@acronym{NNTP}, for example, it will be copied.
+
+If a ham mail is found in a ham group, as determined 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 ham can not be moved---because of a read-only backend such as
+@acronym{NNTP}, for example, it will be copied.
+
+If all this seems confusing, don't worry. Soon it will be as natural
+as typing Lisp one-liners on a neural interface@dots{} 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.
+
+Also, @code{spam-split} will not modify incoming mail in any way.
+
+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. @code{spam-use-regex-headers} or @code{"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)
+ ;; @r{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
+ '(|
+ ;; @r{all spam detected by @code{spam-use-regex-headers} goes to @samp{regex-spam}}
+ (: spam-split "regex-spam" 'spam-use-regex-headers)
+ (any "ding" "ding")
+ ;; @r{all other spam detected by spam-split goes to @code{spam-split-group}}
+ (: spam-split)
+ ;; @r{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
+@code{spam-process} group parameter, or the
+@code{gnus-spam-process-newsgroups} variable. Ham processors take
+mail known to be non-spam (@emph{ham}) and process it in some way so
+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 @sc{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
+@code{spam-junk-mailgroups} as appropriate. You can also declare
+groups to contain spam by setting their group parameter
+@code{spam-contents} to @code{gnus-group-spam-classification-spam}, or
+by customizing the corresponding variable
+@code{gnus-spam-newsgroup-contents}. The @code{spam-contents} group
+parameter and the @code{gnus-spam-newsgroup-contents} variable can
+also be used to declare groups as @emph{ham} groups if you set their
+classification to @code{gnus-group-spam-classification-ham}. If
+groups are not classified by means of @code{spam-junk-mailgroups},
+@code{spam-contents}, or @code{gnus-spam-newsgroup-contents}, they are
+considered @emph{unclassified}. All groups are unclassified by
+default.
+
+@vindex gnus-spam-mark
+@cindex $
+In spam groups, all messages are considered to be spam by default:
+they get the @samp{$} mark (@code{gnus-spam-mark}) when you enter the
+group. If you have seen a message, had it marked as spam, then
+unmarked it, it won't be marked as spam when you enter the group
+thereafter. You can disable that behavior, so all unread messages
+will get the @samp{$} mark, if you set the
+@code{spam-mark-only-unseen-as-spam} parameter to @code{nil}. You
+should remove the @samp{$} mark when you are in the group summary
+buffer for every message that is not spam after all. To remove the
+@samp{$} mark, you can use @kbd{M-u} to ``unread'' the article, or
+@kbd{d} for declaring it read the non-spam way. When you leave a
+group, all spam-marked (@samp{$}) articles are sent to a spam
+processor which will study them as spam samples.
+
+Messages may also be deleted in various other ways, and unless
+@code{ham-marks} group parameter gets overridden below, marks @samp{R}
+and @samp{r} for default read or explicit delete, marks @samp{X} and
+@samp{K} for automatic or explicit kills, as well as mark @samp{Y} for
+low scores, are all considered to be associated with articles which
+are not spam. This assumption might be false, in particular if you
+use kill files or score files as means for detecting genuine spam, you
+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 (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. 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
+@code{spam-contents} classification, all spam-marked articles are sent
+to a spam processor, which will study these as spam samples. If you
+explicit kill a lot, you might sometimes end up with articles marked
+@samp{K} which you never saw, and which might accidentally contain
+spam. Best is to make sure that real spam is marked with @samp{$},
+and nothing else.
+
+@vindex gnus-ham-process-destinations
+When you leave a @emph{spam} group, all spam-marked articles are
+marked as expired after processing with the spam processor. This is
+not done for @emph{unclassified} or @emph{ham} groups. Also, any
+@strong{ham} articles in a spam group will be moved to a location
+determined by either the @code{ham-process-destination} group
+parameter or a match in the @code{gnus-ham-process-destinations}
+variable, which is a list of regular expressions matched with group
+names (it's easiest to customize this variable with @kbd{M-x
+customize-variable @key{RET} gnus-ham-process-destinations}). Each
+group name list is a standard Lisp list, if you prefer to customize
+the variable manually. 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.
+
+If ham can not be moved---because of a read-only backend such as
+@acronym{NNTP}, for example, it will be copied.
+
+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.
+
+@vindex spam-process-ham-in-spam-groups
+By default the variable @code{spam-process-ham-in-spam-groups} is
+@code{nil}. Set it to @code{t} if you want ham found in spam groups
+to be processed. Normally this is not done, you are expected instead
+to send your ham to a ham group and process it there.
+
+@vindex spam-process-ham-in-nonham-groups
+By default the variable @code{spam-process-ham-in-nonham-groups} is
+@code{nil}. Set it to @code{t} if you want ham found in non-ham (spam
+or unclassified) groups to be processed. Normally this is not done,
+you are expected instead to send your ham to a ham group and process
+it there.
+
+@vindex gnus-spam-process-destinations
+When you leave a @emph{ham} or @emph{unclassified} group, all
+@strong{spam} articles are moved to a location determined by either
+the @code{spam-process-destination} group parameter or a match in the
+@code{gnus-spam-process-destinations} variable, which is a list of
+regular expressions matched with group names (it's easiest to
+customize this variable with @kbd{M-x customize-variable @key{RET}
+gnus-spam-process-destinations}). Each group name list is a standard
+Lisp list, if you prefer to customize the variable manually. If the
+@code{spam-process-destination} parameter is not set, the spam
+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.
+
+If spam can not be moved---because of a read-only backend such as
+@acronym{NNTP}, for example, it will be copied.
+
+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
+@code{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 @code{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
+
+@subsubheading Ted's setup
+
+From Ted Zlatanov <tzz@@lifelogs.com>.
+@example
+;; @r{for @code{gnus-registry-split-fancy-with-parent} and spam autodetection}
+;; @r{see @file{gnus-registry.el} for more information}
+(gnus-registry-initialize)
+(spam-initialize)
+
+;; @r{I like @kbd{C-s} for marking spam}
+(define-key gnus-summary-mode-map "\C-s" 'gnus-summary-mark-as-spam)
+
+(setq
+ spam-log-to-registry t ; @r{for spam autodetection}
+ spam-use-BBDB t
+ spam-use-regex-headers t ; @r{catch X-Spam-Flag (SpamAssassin)}
+ ;; @r{all groups with @samp{spam} in the name contain spam}
+ gnus-spam-newsgroup-contents
+ '(("spam" gnus-group-spam-classification-spam))
+ ;; @r{see documentation for these}
+ spam-move-spam-nonspam-groups-only nil
+ spam-mark-only-unseen-as-spam t
+ spam-mark-ham-unread-before-move-from-spam-group t
+ nnimap-split-rule 'nnimap-split-fancy
+ ;; @r{understand what this does before you copy it to your own setup!}
+ nnimap-split-fancy '(|
+ ;; @r{trace references to parents and put in their group}
+ (: gnus-registry-split-fancy-with-parent)
+ ;; @r{this will catch server-side SpamAssassin tags}
+ (: spam-split 'spam-use-regex-headers)
+ (any "ding" "ding")
+ ;; @r{note that spam by default will go to @samp{spam}}
+ (: spam-split)
+ ;; @r{default mailbox}
+ "mail"))
+
+;; @r{my parameters, set with @kbd{G p}}
+
+;; @r{all nnml groups, and all nnimap groups except}
+;; @r{@samp{nnimap+mail.lifelogs.com:train} and}
+;; @r{@samp{nnimap+mail.lifelogs.com:spam}: any spam goes to nnimap training,}
+;; @r{because it must have been detected manually}
+
+((spam-process-destination . "nnimap+mail.lifelogs.com:train"))
+
+;; @r{all @acronym{NNTP} groups}
+;; @r{autodetect spam with the blacklist and ham with the BBDB}
+((spam-autodetect-methods spam-use-blacklist spam-use-BBDB)
+;; @r{send all spam to the training group}
+ (spam-process-destination . "nnimap+mail.lifelogs.com:train"))
+
+;; @r{only some @acronym{NNTP} groups, where I want to autodetect spam}
+((spam-autodetect . t))
+
+;; @r{my nnimap @samp{nnimap+mail.lifelogs.com:spam} group}
+
+;; @r{this is a spam group}
+((spam-contents gnus-group-spam-classification-spam)
+
+ ;; @r{any spam (which happens when I enter for all unseen messages,}
+ ;; @r{because of the @code{gnus-spam-newsgroup-contents} setting above), goes to}
+ ;; @r{@samp{nnimap+mail.lifelogs.com:train} unless I mark it as ham}
+
+ (spam-process-destination "nnimap+mail.lifelogs.com:train")
+
+ ;; @r{any ham goes to my @samp{nnimap+mail.lifelogs.com:mail} folder, but}
+ ;; @r{also to my @samp{nnimap+mail.lifelogs.com:trainham} folder for training}
+
+ (ham-process-destination "nnimap+mail.lifelogs.com:mail"
+ "nnimap+mail.lifelogs.com:trainham")
+ ;; @r{in this group, only @samp{!} marks are ham}
+ (ham-marks
+ (gnus-ticked-mark))
+ ;; @r{remembers senders in the blacklist on the way out---this is}
+ ;; @r{definitely not needed, it just makes me feel better}
+ (spam-process (gnus-group-spam-exit-processor-blacklist)))
+
+;; @r{Later, on the @acronym{IMAP} server I use the @samp{train} group for training}
+;; @r{SpamAssassin to recognize spam, and the @samp{trainham} group fora}
+;; @r{recognizing ham---but Gnus has nothing to do with it.}
+
+@end example
+
+@subsubheading Using @file{spam.el} on an IMAP server with a statistical filter on the server
+From Reiner Steib <reiner.steib@@gmx.de>.
+
+My provider has set up bogofilter (in combination with @acronym{DCC}) on
+the mail server (@acronym{IMAP}). Recognized spam goes to
+@samp{spam.detected}, the rest goes through the normal filter rules,
+i.e. to @samp{some.folder} or to @samp{INBOX}. Training on false
+positives or negatives is done by copying or moving the article to
+@samp{training.ham} or @samp{training.spam} respectively. A cron job on
+the server feeds those to bogofilter with the suitable ham or spam
+options and deletes them from the @samp{training.ham} and
+@samp{training.spam} folders.
+
+With the following entries in @code{gnus-parameters}, @code{spam.el}
+does most of the job for me:
+
+@lisp
+ ("nnimap:spam\\.detected"
+ (gnus-article-sort-functions '(gnus-article-sort-by-chars))
+ (ham-process-destination "nnimap:INBOX" "nnimap:training.ham")
+ (spam-contents gnus-group-spam-classification-spam))
+ ("nnimap:\\(INBOX\\|other-folders\\)"
+ (spam-process-destination . "nnimap:training.spam")
+ (spam-contents gnus-group-spam-classification-ham))
+@end lisp
+
+@itemize
+
+@item @b{The Spam folder:}
+
+In the folder @samp{spam.detected}, I have to check for false positives
+(i.e. legitimate mails, that were wrongly judged as spam by
+bogofilter or DCC).
+
+Because of the @code{gnus-group-spam-classification-spam} entry, all
+messages are marked as spam (with @code{$}). When I find a false
+positive, I mark the message with some other ham mark (@code{ham-marks},
+@ref{Spam ELisp Package Global Variables}). On group exit, those
+messages are copied to both groups, @samp{INBOX} (where I want to have
+the article) and @samp{training.ham} (for training bogofilter) and
+deleted from the @samp{spam.detected} folder.
+
+The @code{gnus-article-sort-by-chars} entry simplifies detection of
+false positives for me. I receive lots of worms (sweN, @dots{}), that all
+have a similar size. Grouping them by size (i.e. chars) makes finding
+other false positives easier. (Of course worms aren't @i{spam}
+(@acronym{UCE}, @acronym{UBE}) strictly speaking. Anyhow, bogofilter is
+an excellent tool for filtering those unwanted mails for me.)
+
+@item @b{Ham folders:}
+
+In my ham folders, I just hit @kbd{S x}
+(@code{gnus-summary-mark-as-spam}) whenever I see an unrecognized spam
+mail (false negative). On group exit, those messages are moved to
+@samp{training.ham}.