Subject: Re: Obsoleting mail/hashcash.el

From: Stefan Kangas <[email-masked]>
Date: Tue, 11 Feb 2025 16:05:06 -0800

tags 76195 + patch
thanks

Stefan Kangas <[email-masked]> writes:

> Severity: wishlist
>
> The mail/hashcash.el library implements an Emacs wrapper around
> hashcash, where the idea was that you added a small amount of "proof of
> work" to an Email header, which if everyone used it would be expensive
> for spammers:
>
>      "The email anti-spam tool, like the proof-of-work algorithm, is
>      also called hashcash and is used to create stamps to attach to mail
>      to add a micro-cost to sending mail to deter spamming.  The main
>      use of the hashcash stamp is as a white-listing hint to help
>      hashcash users avoid losing email due to content based and
>      blacklist based anti-spam systems."  - http://www.hashcash.org
>
> This might be nice in theory, but it is irrelevant as an anti-spam
> measure on today's internet, since almost no one uses it.  Let's not
> mislead users to waste energy using it.
>
> I suggest that we mark it as obsolete.

Here are three proposed patches.
From a15304e0584dff49608f4c784e4b987e67e774fe Mon Sep 17 00:00:00 2001
From: Stefan Kangas <[email-masked]>
Date: Tue, 11 Feb 2025 18:47:27 +0100
Subject: [PATCH 1/3] Drop hashcash support

* lisp/gnus/gnus.el (gnus-install-group-spam-parameters): Remove
'spam-use-hashcash' option.
* lisp/gnus/message.el (message-generate-hashcash): Mark as
obsolete, default to nil unconditionally.
(message-send-mail, message-setup-1, message-resend): Don't
generate hashcash headers.
* lisp/gnus/spam.el (hashcash): Don't require.
(spam-use-hashcash):
(spam-check-hashcash): Mark as obsolete.
(spam-install-hooks): Don't install 'spam-use-hashcash' hook.
* doc/misc/message.texi (Mail Headers): Don't document above
obsoleted variable 'message-generate-hashcash'.
* doc/misc/gnus.texi (Hashcash): Delete section.
(Anti-spam Hashcash Payments): Delete subsection.
(Extending the Spam package): Don't mention Hashcash.  (Bug#76195)
---
 doc/misc/gnus.texi    | 100 +-----------------------------------------
 doc/misc/message.texi |   7 ---
 etc/NEWS              |  10 +++++
 lisp/gnus/gnus.el     |   2 -
 lisp/gnus/message.el  |  29 ++----------
 lisp/gnus/spam.el     |  16 +++----
 6 files changed, 23 insertions(+), 141 deletions(-)

diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index 239aa43703f..205980d5e46 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -874,7 +874,6 @@ Top
 * The problem of spam::         Some background, and some solutions
 * Anti-Spam Basics::            Simple steps to reduce the amount of spam.
 * SpamAssassin::                How to use external anti-spam tools.
-* Hashcash::                    Reduce spam by burning CPU time.
 
 Spam Package
 
@@ -892,7 +891,6 @@ Top
 * Blacklists and Whitelists::
 * BBDB Whitelists::
 * Gmane Spam Reporting::
-* Anti-spam Hashcash Payments::
 * Blackholes::
 * Regular Expressions Header Matching::
 * Bogofilter::
@@ -24318,7 +24316,6 @@ Thwarting Email Spam
 * The problem of spam::         Some background, and some solutions
 * Anti-Spam Basics::            Simple steps to reduce the amount of spam.
 * SpamAssassin::                How to use external anti-spam tools.
-* Hashcash::                    Reduce spam by burning CPU time.
 @end menu
 
 @node The problem of spam
@@ -24540,81 +24537,6 @@ SpamAssassin
   (gnus-summary-mark-as-expirable 1))
 @end lisp
 
-@node Hashcash
-@subsection Hashcash
-@cindex hashcash
-
-One technique to fight spam is to require senders to do something
-costly and demonstrably unique 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.hashcash.org/}.
-
-If you wish to generate hashcash for each message you send, you can
-customize @code{message-generate-hashcash} (@pxref{Mail Headers, ,Mail
-Headers,message, The Message Manual}), as in:
-
-@lisp
-(setq message-generate-hashcash t)
-@end lisp
-
-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 20.  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-program
-@vindex hashcash-program
-Where the @code{hashcash} binary is installed.  This variable should
-be automatically set by @code{executable-find}, but if it's @code{nil}
-(usually because the @code{hashcash} binary is not in your path)
-you'll get a warning when you check hashcash payments and an error
-when you generate hashcash payments.
-
-@end table
-
-Gnus can verify hashcash cookies, although this can also be done by
-hand customized mail filtering scripts.  To verify a hashcash cookie
-in a message, use the @code{mail-check-payment} function in the
-@code{hashcash.el} library.  You can also use the @code{spam.el}
-package with the @code{spam-use-hashcash} back end to validate hashcash
-cookies in incoming mail and filter mail accordingly (@pxref{Anti-spam
-Hashcash Payments}).
-
 @node Spam Package
 @section Spam Package
 @cindex spam filtering
@@ -25245,7 +25167,6 @@ Spam Back Ends
 * Blacklists and Whitelists::
 * BBDB Whitelists::
 * Gmane Spam Reporting::
-* Anti-spam Hashcash Payments::
 * Blackholes::
 * Regular Expressions Header Matching::
 * Bogofilter::
@@ -25441,23 +25362,6 @@ Gmane Spam Reporting
 
 @end defvar
 
-@node Anti-spam Hashcash Payments
-@subsubsection Anti-spam Hashcash Payments
-@cindex spam filtering
-@cindex hashcash, spam filtering
-@cindex spam
-
-@defvar spam-use-hashcash
-
-Similar to @code{spam-use-whitelist} (@pxref{Blacklists and
-Whitelists}), but uses hashcash tokens for whitelisting messages
-instead of the sender address.  Messages without a hashcash payment
-token will be sent to the next spam-split rule.  This is an explicit
-filter, meaning that unless a hashcash token is found, the messages
-are not assumed to be spam or ham.
-
-@end defvar
-
 @node Blackholes
 @subsubsection Blackholes
 @cindex spam filtering
@@ -26008,8 +25912,7 @@ Extending the Spam package
 
 This function will install a back end that can only check incoming mail
 for spam contents.  It can't register or unregister messages.
-@code{spam-use-blackholes} and @code{spam-use-hashcash} are such
-back ends.
+@code{spam-use-blackholes} is such a back end.
 
 @item
 @code{spam-install-statistical-checkonly-backend}
@@ -29061,7 +28964,6 @@ No Gnus
 
 @item Gnus now supports the ``hashcash'' client puzzle anti-spam mechanism.
 Use @code{(setq message-generate-hashcash t)} to enable.
-@xref{Hashcash}.
 
 @item You can now drag and drop attachments to the Message buffer.
 See @code{mml-dnd-protocol-alist} and @code{mml-dnd-attach-options}.
diff --git a/doc/misc/message.texi b/doc/misc/message.texi
index 509bbd5b575..4936f64fa9f 100644
--- a/doc/misc/message.texi
+++ b/doc/misc/message.texi
@@ -1902,13 +1902,6 @@ Mail Headers
 This string is inserted at the end of the headers in all message
 buffers that are initialized as mail.
 
-@item message-generate-hashcash
-@vindex message-generate-hashcash
-Variable that indicates whether @samp{X-Hashcash} headers
-should be computed for the message.  @xref{Hashcash, ,Hashcash,gnus,
-The Gnus Manual}.  If @code{opportunistic}, only generate the headers
-when it doesn't lead to the user having to wait.
-
 @end table

diff --git a/etc/NEWS b/etc/NEWS
index 9fe46d818bd..971fcfcdef5 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -522,6 +522,11 @@ behavior included additional information about the originating message.
 The new variable 'message-header-use-obsolete-in-reply-to', nil by
 default, can be set to a non-nil value to restore the previous behavior.
 
++++
+*** Hashcash support has been removed.
+It is believed to no longer be useful as a method to fight spam.  The
+'message-generate-hashcash' option is now obsolete and has no effect.
+
 ** Gnus
 
 ---
@@ -530,6 +535,11 @@ When called with a prefix argument, accepting, declining, or tentatively
 accepting an icalendar event will prompt for a comment to add to the
 response.
 
++++
+*** Hashcash support has been removed.
+It is believed to no longer be useful as a method to fight spam.  The
+'spam-use-hashcash' hook is now obsolete and has no effect.
+
 ** Button
 
 +++
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index 3099f95ebd3..b1a91f8c3b4 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -1918,7 +1918,6 @@ gnus-install-group-spam-parameters
 	  (variable-item spam-use-bsfilter-headers)
 	  (variable-item spam-use-stat)
 	  (variable-item spam-use-blackholes)
-	  (variable-item spam-use-hashcash)
 	  (variable-item spam-use-bogofilter-headers)
 	  (variable-item spam-use-bogofilter)))
    :function-document
@@ -1951,7 +1950,6 @@ gnus-install-group-spam-parameters
 	(variable-item spam-use-crm114)
 	(variable-item spam-use-stat)
 	(variable-item spam-use-blackholes)
-	(variable-item spam-use-hashcash)
 	(variable-item spam-use-spamassassin)
 	(variable-item spam-use-spamassassin-headers)
 	(variable-item spam-use-bsfilter)
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el
index 1d035220bba..79391270f49 100644
--- a/lisp/gnus/message.el
+++ b/lisp/gnus/message.el
@@ -1936,20 +1936,16 @@ message-use-idna
 		 (const :tag "Never" nil)
 		 (const :tag "Always" t)))
 
-(defcustom message-generate-hashcash (if (executable-find "hashcash") 'opportunistic)
-  "Whether to generate X-Hashcash: headers.
-If t, always generate hashcash headers.  If `opportunistic',
-only generate hashcash headers if it can be done without the user
-waiting (i.e., only asynchronously).  If nil, don't generate
-hashcash headers.
-
-You must have the \"hashcash\" binary installed, see `hashcash-program'."
+(defcustom message-generate-hashcash nil
+  "This variable is obsolete and does nothing.
+It used to control whether or not to generate \"X-Hashcash:\" headers."
   :version "24.1"
   :group 'message-headers
   :link '(custom-manual "(message)Mail Headers")
   :type '(choice (const :tag "Always" t)
 		 (const :tag "Never" nil)
 		 (const :tag "Opportunistic" opportunistic)))
+(make-obsolete-variable 'message-generate-hashcash nil "31.1")
 
 ;;; Internal variables.
 
@@ -4823,8 +4819,6 @@ message-send-mail-partially
 	    (erase-buffer)))
       (kill-buffer tembuf))))
 
-(declare-function hashcash-wait-async "hashcash" (&optional buffer))
-
 (defun message--check-continuation-headers ()
   (message-check 'continuation-headers
     (goto-char (point-min))
@@ -4894,16 +4888,6 @@ message-send-mail
 	    message-posting-charset))
 	 (headers message-required-mail-headers)
 	 options)
-    (when (and message-generate-hashcash
-	       (not (eq message-generate-hashcash 'opportunistic)))
-      (message "Generating hashcash...")
-      (require 'hashcash)
-      ;; Wait for calculations already started to finish...
-      (hashcash-wait-async)
-      ;; ...and do calculations not already done.  mail-add-payment
-      ;; will leave existing X-Hashcash headers alone.
-      (mail-add-payment)
-      (message "Generating hashcash...done"))
     (save-restriction
       (message-narrow-to-headers)
       ;; Generate the Mail-Followup-To header if the header is not there...
@@ -6956,9 +6940,6 @@ message-setup-1
     (message-narrow-to-headers)
     (run-hooks 'message-header-setup-hook))
   (setq buffer-undo-list nil)
-  (when message-generate-hashcash
-    ;; Generate hashcash headers for recipients already known
-    (mail-add-payment-async))
   ;; Gnus posting styles are applied via buffer-local `message-setup-hook'
   ;; values.
   (run-hooks 'message-setup-hook)
@@ -8012,7 +7993,6 @@ message-resend
 	(let ((inhibit-read-only t))
 	  (erase-buffer)))
       (let ((message-this-is-mail t)
-	    message-generate-hashcash
 	    message-setup-hook)
 	(message-setup `((To . ,address))))
       ;; Insert our usual headers.
@@ -8061,7 +8041,6 @@ message-resend
 	    (sendmail-coding-system 'raw-text)
 	    (select-safe-coding-system-function nil)
 	    message-required-mail-headers
-	    message-generate-hashcash
 	    rfc2047-encode-encoded-words
             ;; If `message-sendmail-envelope-from' is `header' then
             ;; the envelope-from will be the original sender's
diff --git a/lisp/gnus/spam.el b/lisp/gnus/spam.el
index 5c25df049e3..6f3ccd7f2ad 100644
--- a/lisp/gnus/spam.el
+++ b/lisp/gnus/spam.el
@@ -4,7 +4,7 @@
 
 ;; Author: Lars Magne Ingebrigtsen <[email-masked]>
 ;; Maintainer: Ted Zlatanov <[email-masked]>
-;; Keywords: network, spam, mail, bogofilter, BBDB, dspam, dig, whitelist, blacklist, gmane, hashcash, spamassassin, bsfilter, ifile, stat, crm114, spamoracle
+;; Keywords: network, spam, mail, bogofilter, BBDB, dspam, dig, whitelist, blacklist, gmane, spamassassin, bsfilter, ifile, stat, crm114, spamoracle
 
 ;; This file is part of GNU Emacs.
 
@@ -46,8 +46,7 @@
 (require 'dig)
 
 (eval-when-compile
-  (require 'cl-lib)
-  (require 'hashcash))
+  (require 'cl-lib))
 
 ;; autoload spam-report
 (autoload 'spam-report-gmane "spam-report")
@@ -202,9 +201,12 @@ spam-use-blackholes
   :group 'spam)
 
 (defcustom spam-use-hashcash nil
-  "Whether hashcash payments should be detected by `spam-split'."
+  "This variable is obsolete and does nothing.
+It used to control whether hashcash payments should be detected by
+`spam-split'."
   :type 'boolean
   :group 'spam)
+(make-obsolete-variable 'spam-use-hashcash nil "31.1")
 
 (defcustom spam-use-regex-headers nil
   "Whether a header regular expression match should be used by `spam-split'.
@@ -294,7 +296,6 @@ spam-install-hooks
                                spam-use-whitelist
                                spam-use-whitelist-exclusive
                                spam-use-blackholes
-                               spam-use-hashcash
                                spam-use-regex-headers
                                spam-use-regex-body
                                spam-use-bogofilter
@@ -1014,9 +1015,6 @@ spam-install-statistical-checkonly-backend
 (spam-install-checkonly-backend 'spam-use-blackholes
                                 #'spam-check-blackholes)
 
-(spam-install-checkonly-backend 'spam-use-hashcash
-                                #'spam-check-hashcash)
-
 (spam-install-checkonly-backend 'spam-use-spamassassin-headers
                                 #'spam-check-spamassassin-headers)
 
@@ -2024,6 +2022,8 @@ spam-check-blackholes
 
 (defun spam-check-hashcash ()
   "Check the headers for hashcash payments."
+  (declare (obsolete nil "31.1"))
+  (require 'hashcash)
   (ignore-errors (mail-check-payment)))  ;mail-check-payment returns a boolean
 
 ;;}}}
-- 
2.48.1

From bc2118f30aea37e7c3d88e388416725a80770d7d Mon Sep 17 00:00:00 2001
From: Stefan Kangas <[email-masked]>
Date: Tue, 11 Feb 2025 18:49:25 +0100
Subject: [PATCH 2/3] Move hashcash.el to lisp/obsolete

* lisp/mail/hashcash.el: Move from here...
* lisp/obsolete/hashcash.el: ...to here.  (Bug#76195)
---
 lisp/{mail => obsolete}/hashcash.el | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename lisp/{mail => obsolete}/hashcash.el (100%)

diff --git a/lisp/mail/hashcash.el b/lisp/obsolete/hashcash.el
similarity index 100%
rename from lisp/mail/hashcash.el
rename to lisp/obsolete/hashcash.el
-- 
2.48.1

From 6e535aa4f7b73116a9b25e24b3a4217bd53cb89b Mon Sep 17 00:00:00 2001
From: Stefan Kangas <[email-masked]>
Date: Tue, 11 Feb 2025 18:51:43 +0100
Subject: [PATCH 3/3] Add Obsolete-since header to hashcash.el

* lisp/obsolete/hashcash.el: Add Obsolete-since header.  (Bug#76195)
---
 etc/NEWS                  | 6 ++++++
 lisp/obsolete/hashcash.el | 1 +
 2 files changed, 7 insertions(+)

diff --git a/etc/NEWS b/etc/NEWS
index 971fcfcdef5..7f5466442b7 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1161,6 +1161,12 @@ This macro adds the current buffer to 'inhibit-auto-revert-buffers',
 runs its body, and removes the current buffer from
 'inhibit-auto-revert-buffers' afterwards.
 
+** Miscellaneous
+
+*** hashcash.el is now obsolete.
+It is believed to no longer be useful as a method to fight spam.
+
+
 
 * New Modes and Packages in Emacs 31.1
 
diff --git a/lisp/obsolete/hashcash.el b/lisp/obsolete/hashcash.el
index fac336bb6cc..cd111b8d8c5 100644
--- a/lisp/obsolete/hashcash.el
+++ b/lisp/obsolete/hashcash.el
@@ -5,6 +5,7 @@
 ;; Written by: Paul Foley <[email-masked]> (1997-2002)
 ;; Maintainer: [email-masked]
 ;; Keywords: mail, hashcash
+;; Obsolete-since: 31.1
 
 ;; This file is part of GNU Emacs.
 
-- 
2.48.1