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