translated yet).
+2002-06-22 Simon Josefsson <jas@extundo.com>
+
+ * hashcash.el: New file.
+ (hashcash-default-payment, hashcash-payment-alist, hashcash):
+ Defcustom.
+ (hashcash-generate-payment): Update to recent hashcode command
+ line syntax.
+ (hashcash-insert-payment): Use X-Hashcode:.
+ (mail-add-payment): Also look at Newsgroups.
+ (top-level): Add provide and EOF comment.
+ (mail-add-payment): Autoload.
+ (hashcash-insert-payment): s/Hashcode/Hashcash/
+ (mail-add-payment): Doc fix.
+
2002-05-20 Lars Magne Ingebrigtsen <larsi@gnus.org>
* gnus-mdrtn.el (gnus-moderated-groups): Removed (require 'gnus-load).
--- /dev/null
+;;; hashcash.el --- Add hashcash payments to email
+
+;; $Revision: 1.1.2.1 $
+;; Copyright (C) 1997,2001 Paul E. Foley
+
+;; Maintainer: Paul Foley <mycroft@actrix.gen.nz>
+;; Keywords: mail, hashcash
+
+;; Released under the GNU General Public License
+
+;;; Commentary:
+
+;; The hashcash binary is at http://www.cypherspace.org/hashcash/
+;;
+;; Call mail-add-payment to add a hashcash payment to a mail message
+;; in the current buffer.
+;;
+;; To automatically add payments to all outgoing mail:
+;; (add-hook 'message-send-hook 'mail-add-payment)
+
+;;; Code:
+
+(defcustom hashcash-default-payment 0
+ "*The default number of bits to pay to unknown users.
+If this is zero, no payment header will be generated.
+See `hashcash-payment-alist'."
+ :type 'integer)
+
+(defcustom hashcash-payment-alist nil
+ "*An association list mapping email addresses to payment amounts.
+Elements may consist of (ADDR AMOUNT) or (ADDR STRING AMOUNT), where
+ADDR is the email address of the intended recipient and AMOUNT is
+the value of hashcash payment to be made to that user. STRING, if
+present, is the string to be hashed; if not present ADDR will be used.")
+
+(defcustom hashcash "hashcash"
+ "*The path to the hashcash binary.")
+
+(require 'mail-utils)
+
+(defun hashcash-strip-quoted-names (addr)
+ (setq addr (mail-strip-quoted-names addr))
+ (if (and addr (string-match "^[^+@]+\\(\\+[^@]*\\)@" addr))
+ (concat (subseq addr 0 (match-beginning 1)) (subseq addr (match-end 1)))
+ addr))
+
+(defun hashcash-payment-required (addr)
+ "Return the hashcash payment value required for the given address."
+ (let ((val (assoc addr hashcash-payment-alist)))
+ (if val
+ (if (cddr val)
+ (caddr val)
+ (cadr val))
+ hashcash-default-payment)))
+
+(defun hashcash-payment-to (addr)
+ "Return the string with which hashcash payments should collide."
+ (let ((val (assoc addr hashcash-payment-alist)))
+ (if val
+ (if (cddr val)
+ (cadr val)
+ (car val))
+ addr)))
+
+(defun hashcash-generate-payment (str val)
+ "Generate a hashcash payment by finding a VAL-bit collison on STR."
+ (if (> val 0)
+ (save-excursion
+ (set-buffer (get-buffer-create " *hashcash*"))
+ (erase-buffer)
+ (call-process hashcash nil t nil (concat "-b " (number-to-string val))
+ str)
+ (goto-char (point-min))
+ (buffer-substring (point-at-bol) (point-at-eol)))
+ nil))
+
+(defun hashcash-insert-payment (arg)
+ "Insert an X-Hashcash header with a payment for ARG"
+ (interactive "sPay to: ")
+ (let ((pay (hashcash-generate-payment (hashcash-payment-to arg)
+ (hashcash-payment-required arg))))
+ (when pay
+ (insert-before-markers "X-Hashcash: " pay "\n"))))
+
+;;;###autoload
+(defun mail-add-payment (&optional arg)
+ "Add an X-Hashcash: header with a hashcash payment for each recipient address
+Prefix arg sets default payment temporarily."
+ (interactive "P")
+ (let ((hashcash-default-payment (if arg (prefix-numeric-value arg)
+ hashcash-default-payment))
+ (addrlist nil))
+ (save-excursion
+ (save-restriction
+ (goto-char (point-min))
+ (search-forward mail-header-separator)
+ (beginning-of-line)
+ (narrow-to-region (point-min) (point))
+ (let ((to (hashcash-strip-quoted-names (mail-fetch-field "To" nil t)))
+ (cc (hashcash-strip-quoted-names (mail-fetch-field "Cc" nil t)))
+ (ng (hashcash-strip-quoted-names
+ (mail-fetch-field "Newsgroups" nil t))))
+ (when to
+ (setq addrlist (split-string to ",[ \t\n]*")))
+ (when cc
+ (setq addrlist (nconc addrlist (split-string cc ",[ \t\n]*"))))
+ (when ng
+ (setq addrlist (nconc addrlist (split-string ng ",[ \t\n]*")))))
+ (when addrlist
+ (mapc #'hashcash-insert-payment addrlist)))))
+ t)
+
+(provide 'hashcash)
+
+;;; hashcash.el ends here
+2002-06-24 Kai Gro\e,b_\e(Bjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+ * message.el (message-font-lock-keywords): Put colon in header
+ name match.
+
+2002-06-22 Kai Gro\e,b_\e(Bjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+ * message.el (message-font-lock-keywords): Don't use header faces
+ in the body. Thanks to Stefan Monnier for the hint on the
+ implementation.
+
+2002-05-09 Miles Bader <miles@gnu.org>
+
+ * gnus-cite.el (gnus-cite-blank-line-after-header): New variable.
+ (gnus-article-hide-citation): Respect it.
+
+2002-04-12 Juanma Barranquero <lektu@terra.es>
+
+ * pop3.el (pop3-open-server): Fix typo.
+
2002-06-18 Josh Huber <huber@alum.wpi.edu>
* gnus.el (gnus-find-subscribed-addresses): Use add-to-list
;;; gnus-cite.el --- parse citations in articles for Gnus
-;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
;; Free Software Foundation, Inc.
;; Author: Per Abhiddenware
:group 'gnus-cite
:type 'integer)
+(defcustom gnus-cite-blank-line-after-header t
+ "If non-nil, put a blank line between the citation header and the button."
+ :group 'gnus-cite
+ :type 'boolean)
+
;;; Internal Variables:
(defvar gnus-cite-article nil)
end (set-marker (make-marker) end))
(gnus-add-text-properties-when 'article-type nil beg end props)
(goto-char beg)
- (unless (save-excursion (search-backward "\n\n" nil t))
+ (when (and gnus-cite-blank-line-after-header
+ (not (save-excursion (search-backward "\n\n" nil t))))
(insert "\n"))
(put-text-property
(setq start (point-marker))
(defvar message-font-lock-keywords
(let ((content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)\n?"))
`((,(concat "^\\([Tt]o:\\)" content)
- (1 'message-header-name-face)
- (2 'message-header-to-face nil t))
+ (1 (if (message-point-in-header-p) 'message-header-name-face))
+ (2 (if (message-point-in-header-p) 'message-header-to-face) nil t))
(,(concat "^\\([GBF]?[Cc][Cc]:\\|[Rr]eply-[Tt]o:\\|"
"[Mm]ail-[Cc]opies-[Tt]o:\\|"
"[Mm]ail-[Rr]eply-[Tt]o:\\|"
"[Mm]ail-[Ff]ollowup-[Tt]o:\\)" content)
- (1 'message-header-name-face)
- (2 'message-header-cc-face nil t))
+ (1 (if (message-point-in-header-p) 'message-header-name-face))
+ (2 (if (message-point-in-header-p) 'message-header-cc-face) nil t))
(,(concat "^\\([Ss]ubject:\\)" content)
- (1 'message-header-name-face)
- (2 'message-header-subject-face nil t))
+ (1 (if (message-point-in-header-p) 'message-header-name-face))
+ (2 (if (message-point-in-header-p) 'message-header-subject-face) nil t))
(,(concat "^\\([Nn]ewsgroups:\\|Followup-[Tt]o:\\)" content)
- (1 'message-header-name-face)
- (2 'message-header-newsgroups-face nil t))
+ (1 (if (message-point-in-header-p) 'message-header-name-face))
+ (2 (if (message-point-in-header-p) 'message-header-newsgroups-face)
+ nil t))
(,(concat "^\\([A-Z][^: \n\t]+:\\)" content)
- (1 'message-header-name-face)
- (2 'message-header-other-face nil t))
+ (1 (if (message-point-in-header-p) 'message-header-name-face))
+ (2 (if (message-point-in-header-p) 'message-header-other-face) nil t))
(,(concat "^\\(X-[A-Za-z0-9-]+\\|In-Reply-To\\):" content)
- (1 'message-header-name-face)
- (2 'message-header-name-face))
+ (1 (if (message-point-in-header-p) 'message-header-name-face))
+ (2 (if (message-point-in-header-p) 'message-header-name-face)))
,@(if (and mail-header-separator
(not (equal mail-header-separator "")))
`((,(concat "^\\(" (regexp-quote mail-header-separator) "\\)$")
+2002-06-25 Kai Gro\e,b_\e(Bjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+ * gnus.texi (Fancy Mail Splitting): Include all necessary
+ variables in the Lisp example.
+
+2002-06-22 Simon Josefsson <jas@extundo.com>
+
+ * gnus.texi (Pay Hashcash): Add.
+
2002-06-03 Simon Josefsson <jas@extundo.com>
* gnus.texi (Splitting Mail): Add.
* Image Enhancements:: \e$B:G?7$N\e(B Emacs/XEmacs \e$B$O3($rI=<($G$-$k\e(B
* Fuzzy Matching:: \e$BBg$-$JLJLS$C$F2?\e(B?
* Thwarting Email Spam:: \e$BM>7W$J>&6HE*EE;R%a!<%k$rHr$1$kJ}K!\e(B
+* Pay Hashcash:: CPU \e$B;~4V$rHq$d$7$F\e(B spam \e$BB`<#$9$k\e(B
* Various Various:: \e$BK\Ev$K$$$m$$$m$J$b$N\e(B
Formatting Variables
\e$B$i\e(B @code{nnmail-split-fancy-with-parent} \e$B$r;H$C$F$_$F$/$@$5$$!#%3%m%s$r\e(B
\e$B;H$C$F$3$s$JIw$K=q$-$^$9\e(B:
@lisp
-(setq nnmail-split-fancy
+(setq nnmail-treat-duplicates 'warn ; \e$B$^$?$O\e(B 'delete
+ nnmail-cache-accepted-message-ids t
+ nnmail-split-fancy
'(| (: nnmail-split-fancy-with-parent)
;; \e$B;D$j$N?6$jJ,$1J}$O$3$3$K=q$/\e(B
))
* Image Enhancements:: \e$B:G?7$N\e(B Emacs/XEmacs \e$B$O3($rI=<($G$-$k\e(B
* Fuzzy Matching:: \e$BBg$-$JLJLS$C$F2?\e(B?
* Thwarting Email Spam:: \e$BM>7W$J>&6HE*EE;R%a!<%k$rHr$1$kJ}K!\e(B
+* Pay Hashcash:: CPU \e$B;~4V$rHq$d$7$F\e(B spam \e$BB`<#$9$k\e(B
* Various Various:: \e$BK\Ev$K$$$m$$$m$J$b$N\e(B
@end menu
\e$B$3$H$OA4$/$"$j$^$;$s!#F@!9>uBV$G$9!#;d$N0U8+$H$7$F$O!"\e(B@code{From} \e$B%X%C%@!<\e(B
\e$B$K56B$$7$FB8:_$7$J$$%I%a%$%s$KAw$i$;$k$N$O%-%?%J%$$G$9!#\e(B
+@node Pay Hashcash
+@section Pay Hashcash
+@cindex hashcash
+@cindex spam
+
+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 that everyone uses this technique, since it is
+optional, but it may be useful in smaller communities.
+
+@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 @code{hashcash.el} library can be found at
+@uref{http://users.actrix.gen.nz/mycroft/hashcash.el}, or in the Gnus
+development contrib directory.
+
+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{(ADDR AMOUNT)} cells,
+where ADDR is the receiver (email address or newsgroup) and AMOUNT is
+the number of bits in the collision that is needed. It can also
+contain @samp{(ADDR STRING AMOUNT)} cells, where the 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 Various Various
@section \e$B$$$m$$$m$N$$$m$$$m\e(B
@cindex mode lines
* Image Enhancements:: Modern versions of Emacs/XEmacs can display images.
* Fuzzy Matching:: What's the big fuzz?
* Thwarting Email Spam:: A how-to on avoiding unsolicited commercial email.
+* Pay Hashcash:: Reduce spam by burning CPU time.
* Various Various:: Things that are really various.
Formatting Variables
you can include @code{nnmail-split-fancy-with-parent} using the colon
feature, like so:
@lisp
-(setq nnmail-split-fancy
+(setq nnmail-treat-duplicates 'warn ; or 'delete
+ nnmail-cache-accepted-message-ids t
+ nnmail-split-fancy
'(| (: nnmail-split-fancy-with-parent)
;; other splits go here
))
* Image Enhancements:: Modern versions of Emacs/XEmacs can display images.
* Fuzzy Matching:: What's the big fuzz?
* Thwarting Email Spam:: A how-to on avoiding unsolicited commercial email.
+* Pay Hashcash:: Reduce spam by burning CPU time.
* Various Various:: Things that are really various.
@end menu
to non-existent domains is yucky, in my opinion.
+
+@node Pay Hashcash
+@section Pay Hashcash
+@cindex hashcash
+@cindex spam
+
+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 that everyone uses this technique, since it is
+optional, but it may be useful in smaller communities.
+
+@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 @code{hashcash.el} library can be found at
+@uref{http://users.actrix.gen.nz/mycroft/hashcash.el}, or in the Gnus
+development contrib directory.
+
+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{(ADDR AMOUNT)} cells,
+where ADDR is the receiver (email address or newsgroup) and AMOUNT is
+the number of bits in the collision that is needed. It can also
+contain @samp{(ADDR STRING AMOUNT)} cells, where the 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 Various Various
@section Various Various
@cindex mode lines