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