Add 2010 to copyright years.
[bpt/emacs.git] / lisp / mail / uce.el
CommitLineData
bf078b46
RS
1;;; uce.el --- facilitate reply to unsolicited commercial email
2
9f08b141 3;; Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
114f9c96 4;; 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
bf078b46 5
dc99d85e 6;; Author: stanislav shalunov <shalunov@mccme.ru>
bf078b46 7;; Created: 10 Dec 1996
9f08b141 8;; Keywords: mail, uce, unsolicited commercial email
bf078b46
RS
9
10;; This file is part of GNU Emacs.
11
b1fc2b50 12;; GNU Emacs is free software: you can redistribute it and/or modify
2be7dabc 13;; it under the terms of the GNU General Public License as published by
b1fc2b50
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
2be7dabc
GM
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
bf078b46
RS
21
22;; You should have received a copy of the GNU General Public License
b1fc2b50 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
bf078b46
RS
24
25;;; Commentary:
26
9f08b141
GM
27;; The code in this file provides a semi-automatic means of replying
28;; to unsolicited commercial email (UCE) you might get. Currently, it
29;; only works with Rmail and Gnus. If you would like to make it work
30;; with other mail readers, see the mail-client dependent section of
31;; uce-reply-to-uce. Please let me know about your changes so I can
32;; incorporate them. I'd appreciate it.
33
34;; The command uce-reply-to-uce, if called when the current message
35;; buffer is a UCE, will setup a reply *mail* buffer as follows. It
36;; scans the full headers of the message for: 1) the normal return
37;; address of the sender (From, Reply-To lines), and puts these
38;; addresses into the To: header, along with abuse@offenders.host; 2)
39;; the mailhub that first saw this message, and adds the address of
40;; its postmaster into the To: header; and 3), finally, it looks at
41;; the Message-Id and adds the postmaster of that host to the list of
42;; addresses.
43
44;; Then, we add an "Errors-To: nobody@localhost" header, so that if
45;; some of these addresses are not actually correct, we will never see
bf078b46
RS
46;; bounced mail. Also, mail-self-blind and mail-archive-file-name
47;; take no effect: the ideology is that we don't want to save junk or
48;; replies to junk.
49
9f08b141
GM
50;; Then we insert a template into the buffer (a customizable message
51;; that explains what has happened), customizable signature, and the
bf078b46 52;; original message with full headers and envelope for postmasters.
9f08b141 53;; Then the buffer is left for editing.
bf078b46 54
9f08b141
GM
55;; The reason that the function uce-reply-to-uce is mail-client
56;; dependent is that we want the full headers of the original message,
57;; nothing stripped. If we use the normal means of inserting the
58;; original message into the *mail* buffer, headers like Received:
59;; (not really headers, but envelope lines) will be stripped, while
60;; they bear valuable information for us and postmasters. I do wish
61;; that there would be some portable way to write this function, but I
62;; am not aware of any.
bf078b46 63
9f08b141
GM
64;; Usage:
65
66;; Place uce.el in your load-path (and optionally byte-compile it).
67;; Add the following line to your ~/.emacs:
68;; (autoload 'uce-reply-to-uce "uce" "Reply to UCEs" t nil)
69;; If you want to use it with Gnus rather than Rmail:
70;; (setq uce-mail-reader 'gnus)
71
72;; Options:
73
74;; uce-message-text is a template that will be inserted into buffer.
75;; It has a reasonable default. If you want to write some scarier
76;; one, please do so and send it to me. Please keep it polite.
77
78;; uce-signature behaves just like mail-signature. If nil, nothing is
79;; inserted, if t, file ~/.signature is used, if a string, its
80;; contents are inserted into buffer.
81
82;; uce-uce-separator is a line that separates your message from the
83;; UCE that you enclose.
84
85;; uce-subject-line will be used as the subject of the outgoing message.
86
87
88;;; Change Log:
bf078b46
RS
89
90;; Dec 10, 1996 -- posted draft version to gnu.sources.emacs
91
92;; Dec 11, 1996 -- fixed some typos, and Francesco Potorti`
93;; <F.Potorti@cnuce.cnr.it> pointed out that my use of defvar was
94;; weird, suggested fix, and added let form.
95
96;; Dec 17, 1996 -- made scanning for host names little bit more clever
97;; (obviously bogus stuff like localhost is now ignored).
98
dc99d85e
RS
99;; Nov 11, 1997 -- incorporated changes from Mikael Djurfeldt
100;; <mdj@nada.kth.se> to make uce.el work with Gnus. Changed the text
101;; of message that is sent.
102
103;; Dec 3, 1997 -- changes from Gareth Jones <gdj1@gdjones.demon.co.uk>
104;; handling Received headers following some line like `From:'.
105
db214408
GM
106;; Aug 16, 2000 -- changes from Detlev Zundel
107;; <detlev.zundel@stud.uni-karlsruhe.de> to make uce.el work with the
108;; latest Gnus. Lars told him it should work for all versions of Gnus
109;; younger than three years.
bf078b46 110
bf078b46
RS
111
112;;; Code:
113
ea9a034c
JB
114(defvar gnus-original-article-buffer)
115(defvar mail-reply-buffer)
ea9a034c 116
bf078b46 117(require 'sendmail)
dc99d85e
RS
118;; Those sections of code which are dependent upon
119;; RMAIL are only evaluated if we have received a message with RMAIL...
a1506d29 120;;(require 'rmail)
dc99d85e 121
0b5bb3ec
SE
122(defgroup uce nil
123 "Facilitate reply to unsolicited commercial email."
124 :prefix "uce-"
125 :group 'mail)
126
e13d531d
RS
127(defcustom uce-mail-reader 'rmail
128 "A symbol indicating which mail reader you are using.
129Choose from: `gnus', `rmail'."
130 :type '(choice (const gnus) (const rmail))
131 :version "20.3"
132 :group 'uce)
133
0b5bb3ec 134(defcustom uce-setup-hook nil
bf078b46 135 "Hook to run after UCE rant message is composed.
e13d531d 136This hook is run after `mail-setup-hook', which is run as well."
0b5bb3ec
SE
137 :type 'hook
138 :group 'uce)
bf078b46 139
a1506d29 140(defcustom uce-message-text
bf078b46
RS
141 "Recently, I have received an Unsolicited Commercial E-mail from you.
142I do not like UCE's and I would like to inform you that sending
143unsolicited messages to someone while he or she may have to pay for
144reading your message may be illegal. Anyway, it is highly annoying
145and not welcome by anyone. It is rude, after all.
146
147If you think that this is a good way to advertise your products or
148services you are mistaken. Spamming will only make people hate you, not
149buy from you.
150
a1506d29
JB
151If you have any list of people you send unsolicited commercial emails to,
152REMOVE me from such list immediately. I suggest that you make this list
bf078b46
RS
153just empty.
154
dc99d85e
RS
155 ----------------------------------------------------
156
157If you are not an administrator of any site and still have received
158this message then your email address is being abused by some spammer.
159They fake your address in From: or Reply-To: header. In this case,
160you might want to show this message to your system administrator, and
161ask him/her to investigate this matter.
162
bf078b46 163Note to the postmaster(s): I append the text of UCE in question to
dc99d85e 164this message; I would like to hear from you about action(s) taken.
bf078b46 165This message has been sent to postmasters at the host that is
dc99d85e
RS
166mentioned as original sender's host (I do realize that it may be
167faked, but I think that if your domain name is being abused this way
168you might want to learn about it, and take actions) and to the
169postmaster whose host was used as mail relay for this message. If
170message was sent not by your user, could you please compare time when
171this message was sent (use time in Received: field of the envelope
172rather than Date: field) with your sendmail logs and see what host was
173using your sendmail at this moment of time.
bf078b46
RS
174
175Thank you."
176
e13d531d 177 "This is the text that `uce-reply-to-uce' command will put in reply buffer.
bf078b46
RS
178Some of spamming programs in use will be set up to read all incoming
179to spam address email, and will remove people who put the word `remove'
180on beginning of some line from the spamming list. So, when you set it
181up, it might be a good idea to actually use this feature.
182
0b5bb3ec 183Value nil means insert no text by default, lets you type it in."
9f08b141 184 :type '(choice (const nil) string)
0b5bb3ec 185 :group 'uce)
bf078b46 186
0b5bb3ec 187(defcustom uce-uce-separator
bf078b46
RS
188 "----- original unsolicited commercial email follows -----"
189 "Line that will begin quoting of the UCE.
0b5bb3ec
SE
190Value nil means use no separator."
191 :type '(choice (const nil) string)
192 :group 'uce)
bf078b46 193
0b5bb3ec 194(defcustom uce-signature mail-signature
a1506d29 195"Text to put as your signature after the note to UCE sender.
e13d531d 196Value nil means none, t means insert `~/.signature' file (if it happens
bf078b46 197to exist), if this variable is a string this string will be inserted
0b5bb3ec
SE
198as your signature."
199 :type '(choice (const nil) (const t) string)
200 :group 'uce)
bf078b46 201
0b5bb3ec 202(defcustom uce-default-headers
bf078b46
RS
203 "Errors-To: nobody@localhost\nPrecedence: bulk\n"
204 "Additional headers to use when responding to a UCE with \\[uce-reply-to-uce].
0b5bb3ec 205These are mostly meant for headers that prevent delivery errors reporting."
9f08b141 206 :type '(choice (const nil) string)
0b5bb3ec 207 :group 'uce)
bf078b46 208
0b5bb3ec 209(defcustom uce-subject-line
bf078b46 210 "Spam alert: unsolicited commercial e-mail"
0b5bb3ec
SE
211 "Subject of the message that will be sent in response to a UCE."
212 :type 'string
213 :group 'uce)
bf078b46 214
9f08b141
GM
215;; End of user options.
216
217
218(defvar rmail-buffer)
219(declare-function rmail-msg-is-pruned "rmail" ())
2b54af74 220(declare-function mail-strip-quoted-names "mail-utils" (address))
73e72da4 221(declare-function rmail-maybe-set-message-counters "rmail" ())
73e72da4
DN
222(declare-function rmail-toggle-header "rmail" (&optional arg))
223
9f08b141 224;;;###autoload
bf078b46 225(defun uce-reply-to-uce (&optional ignored)
9f08b141
GM
226 "Compose a reply to unsolicited commercial email (UCE).
227Sets up a reply buffer addressed to: the sender, his postmaster,
228his abuse@ address, and the postmaster of the mail relay used.
229You might need to set `uce-mail-reader' before using this."
dc99d85e 230 (interactive)
9f08b141 231 ;; Start of mail-client dependent section.
dc99d85e 232 (let ((message-buffer
db214408 233 (cond ((eq uce-mail-reader 'gnus) gnus-original-article-buffer)
9f08b141 234 ((eq uce-mail-reader 'rmail) (bound-and-true-p rmail-buffer))
a1506d29 235 (t (error
f04f5c76 236 "Variable uce-mail-reader set to unrecognized value"))))
9f08b141
GM
237 pruned)
238 (or (and message-buffer (get-buffer message-buffer))
239 (error "No mail buffer, cannot find UCE"))
dc99d85e 240 (switch-to-buffer message-buffer)
f04f5c76 241 ;; We need the message with headers pruned.
9f08b141
GM
242 ;; Why? All we do is get the from and reply-to headers. ?
243 (and (eq uce-mail-reader 'rmail)
244 (not (setq pruned (rmail-msg-is-pruned)))
245 (rmail-toggle-header 1))
dc99d85e
RS
246 (let ((to (mail-strip-quoted-names (mail-fetch-field "from" t)))
247 (reply-to (mail-fetch-field "reply-to"))
248 temp)
249 ;; Initial setting of the list of recipients of our message; that's
250 ;; what they are pretending to be.
9f08b141
GM
251 (setq to (if to
252 (format "%s" (mail-strip-quoted-names to))
253 ""))
dc99d85e
RS
254 (if reply-to
255 (setq to (format "%s, %s" to (mail-strip-quoted-names reply-to))))
256 (let (first-at-sign end-of-hostname sender-host)
257 (setq first-at-sign (string-match "@" to)
258 end-of-hostname (string-match "[ ,>]" to first-at-sign)
259 sender-host (substring to first-at-sign end-of-hostname))
260 (if (string-match "\\." sender-host)
a1506d29 261 (setq to (format "%s, postmaster%s, abuse%s"
dc99d85e
RS
262 to sender-host sender-host))))
263 (setq mail-send-actions nil)
264 (setq mail-reply-buffer nil)
9f08b141
GM
265 (when (eq uce-mail-reader 'rmail)
266 (rmail-toggle-header 0)
267 (rmail-maybe-set-message-counters)) ; why?
268 (copy-region-as-kill (point-min) (point-max))
269 ;; Restore the initial header state we found.
270 (and pruned (rmail-toggle-header 1))
dc99d85e
RS
271 (switch-to-buffer "*mail*")
272 (erase-buffer)
dc99d85e 273 (yank)
9f08b141
GM
274 (goto-char (point-min))
275 ;; Delete any internal Rmail headers.
276 (when (eq uce-mail-reader 'rmail)
277 (search-forward "\n\n")
278 (while (re-search-backward "^X-RMAIL" nil t)
279 (delete-region (point) (line-beginning-position 2)))
280 (goto-char (point-min)))
dc99d85e
RS
281 ;; Now find the mail hub that first accepted this message.
282 ;; This should try to find the last Received: header.
283 ;; Sometimes there may be other headers inbetween Received: headers.
284 (cond ((eq uce-mail-reader 'gnus)
285 ;; Does Gnus always have Lines: in the end?
286 (re-search-forward "^Lines:")
287 (beginning-of-line))
288 ((eq uce-mail-reader 'rmail)
9f08b141 289 (search-forward "\n\n")))
dc99d85e 290 (re-search-backward "^Received:")
dc99d85e
RS
291 ;; Is this always good? It's the only thing I saw when I checked
292 ;; a few messages.
9f08b141
GM
293 ;;(if (not (re-search-forward ": \\(from\\|by\\) " eol t))
294 (unless (re-search-forward "\\(from\\|by\\) " (line-end-position) 'move)
295 (if (looking-at "[ \t\n]+\\(from\\|by\\) ")
296 (goto-char (match-end 0))
297 (error "Failed to extract hub address")))
dc99d85e
RS
298 (setq temp (point))
299 (search-forward " ")
300 (forward-char -1)
301 ;; And add its postmaster to the list of addresses.
302 (if (string-match "\\." (buffer-substring temp (point)))
a1506d29 303 (setq to (format "%s, postmaster@%s"
dc99d85e
RS
304 to (buffer-substring temp (point)))))
305 ;; Also look at the message-id, it helps *very* often.
9f08b141
GM
306 (and (search-forward "\nMessage-Id: " nil t)
307 ;; Not all Message-Id:'s have an `@' sign.
308 (search-forward "@" (line-end-position) t)
309 (progn
310 (setq temp (point))
311 (search-forward ">")
312 (forward-char -1)
313 (if (string-match "\\." (buffer-substring temp (point)))
314 (setq to (format "%s, postmaster@%s"
315 to (buffer-substring temp (point)))))))
316 (when (eq uce-mail-reader 'gnus)
317 ;; Does Gnus always have Lines: in the end?
318 (re-search-forward "^Lines:")
319 (beginning-of-line)
320 (setq temp (point))
321 (search-forward "\n\n" nil t)
322 (forward-line -1)
323 (delete-region temp (point)))
324 ;; End of mail-client dependent section.
dc99d85e
RS
325 (auto-save-mode auto-save-default)
326 (mail-mode)
327 (goto-char (point-min))
328 (insert "To: ")
329 (save-excursion
330 (if to
331 (let ((fill-prefix "\t")
332 (address-start (point)))
333 (insert to "\n")
334 (fill-region-as-paragraph address-start (point)))
335 (newline))
336 (insert "Subject: " uce-subject-line "\n")
337 (if uce-default-headers
338 (insert uce-default-headers))
339 (if mail-default-headers
340 (insert mail-default-headers))
341 (if mail-default-reply-to
342 (insert "Reply-to: " mail-default-reply-to "\n"))
343 (insert mail-header-separator "\n")
344 ;; Insert all our text. Then go back to the place where we started.
345 (if to (setq to (point)))
346 ;; Text of ranting.
347 (if uce-message-text
348 (insert uce-message-text))
349 ;; Signature.
350 (cond ((eq uce-signature t)
351 (if (file-exists-p "~/.signature")
352 (progn
353 (insert "\n\n-- \n")
38926103 354 (forward-char (cadr (insert-file-contents "~/.signature"))))))
dc99d85e
RS
355 (uce-signature
356 (insert "\n\n-- \n" uce-signature)))
357 ;; And text of the original message.
358 (if uce-uce-separator
359 (insert "\n\n" uce-uce-separator "\n"))
360 ;; If message doesn't end with a newline, insert it.
361 (goto-char (point-max))
362 (or (bolp) (newline)))
363 ;; And go back to the beginning of text.
364 (if to (goto-char to))
365 (or to (set-buffer-modified-p nil))
366 ;; Run hooks before we leave buffer for editing. Reasonable usage
9f08b141 367 ;; might be to set up special key bindings, replace standard
dc99d85e
RS
368 ;; functions in mail-mode, etc.
369 (run-hooks 'mail-setup-hook 'uce-setup-hook))))
a1506d29 370
bf078b46
RS
371(defun uce-insert-ranting (&optional ignored)
372 "Insert text of the usual reply to UCE into current buffer."
373 (interactive "P")
374 (insert uce-message-text))
375
376(provide 'uce)
377
cbee283d 378;; arch-tag: 44b68c87-9b29-47bd-822c-3feee3883221
bf078b46 379;;; uce.el ends here