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