Mercurial > emacs
comparison lisp/mail/uce.el @ 22416:a517da228cb9
(uce-message-text): Change the text of message that is sent.
(uce-reply-to-uce): Do not assume all Received lines
are on top of message without headers like `From' or `To'.
(uce-reply-to-uce): Parse Received lines better.
(uce-mail-reader): New user option.
(uce-reply-to uce): Add support for Gnus. User is supposed to set
uce-mail-reader to `gnus' if using Gnus to read mail. The default is
to assume Rmail. There's no magic to determine what mail reader is
currently active, so it is not possible to mix using uce.el with Rmail
and Gnus.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Tue, 09 Jun 1998 23:40:56 +0000 |
parents | 2abd8542d6dd |
children | 198054d3498c |
comparison
equal
deleted
inserted
replaced
22415:c9fa49047eb5 | 22416:a517da228cb9 |
---|---|
1 ;;; uce.el --- facilitate reply to unsolicited commercial email | 1 ;;; uce.el --- facilitate reply to unsolicited commercial email |
2 | 2 |
3 ;; Copyright (C) 1996 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1996, 1998 Free Software Foundation, Inc. |
4 | 4 |
5 ;; Author: stanislav shalunov <shalunov@math.wisc.edu> | 5 ;; Author: stanislav shalunov <shalunov@mccme.ru> |
6 ;; Created: 10 Dec 1996 | 6 ;; Created: 10 Dec 1996 |
7 ;; Version: 1.0 | |
8 ;; Keywords: uce, unsolicited commercial email | 7 ;; Keywords: uce, unsolicited commercial email |
9 | 8 |
10 ;; This file is part of GNU Emacs. | 9 ;; This file is part of GNU Emacs. |
11 | 10 |
12 ;; This program is free software; you can redistribute it and/or | 11 ;; This program is free software; you can redistribute it and/or |
25 ;; Boston, MA 02111-1307, USA. | 24 ;; Boston, MA 02111-1307, USA. |
26 | 25 |
27 ;;; Commentary: | 26 ;;; Commentary: |
28 | 27 |
29 ;; Code in this file provides semi-automatic means of replying to | 28 ;; 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 | 29 ;; UCE's you might get. It works currently only with Rmail and Gnus. |
31 ;; would like to make it work with other mail readers, Rmail-specific | 30 ;; If you would like to make it work with other mail readers, |
32 ;; section is marked below. If you want to play with code, would you | 31 ;; Rmail-specific section is marked below. If you want to play with |
33 ;; please grab the newest version from | 32 ;; code, please let me know about your changes so I can incorporate |
34 ;; http://math.wisc.edu/~shalunov/uce.el and let me know, if you would | 33 ;; them. I'd appreciate it. |
35 ;; like, about your changes so I can incorporate them. I'd appreciate | |
36 ;; it. | |
37 | 34 |
38 ;; Function uce-reply-to-uce, if called when current message in RMAIL | 35 ;; 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 | 36 ;; 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 | 37 ;; scans full headers of message for 1) normal return address of |
41 ;; sender (From, Reply-To lines); and puts these addresses into To: | 38 ;; sender (From, Reply-To lines); and puts these addresses into To: |
73 ;; weird, suggested fix, and added let form. | 70 ;; weird, suggested fix, and added let form. |
74 | 71 |
75 ;; Dec 17, 1996 -- made scanning for host names little bit more clever | 72 ;; Dec 17, 1996 -- made scanning for host names little bit more clever |
76 ;; (obviously bogus stuff like localhost is now ignored). | 73 ;; (obviously bogus stuff like localhost is now ignored). |
77 | 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 | |
78 ;;; Setup: | 82 ;;; Setup: |
79 | 83 |
80 ;; put in your ~./emacs the following line: | 84 ;; put in your ~./emacs the following line: |
81 | 85 |
82 ;; (autoload 'uce-reply-to-uce "uce" "Reply to UCEs" t nil) | 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) | |
83 | 91 |
84 ;; store this file (uce.el) somewhere in load-path and byte-compile it. | 92 ;; store this file (uce.el) somewhere in load-path and byte-compile it. |
85 | 93 |
86 ;;; Variables: | 94 ;;; Variables: |
87 | 95 |
100 ;; nil, left blank. | 108 ;; nil, left blank. |
101 | 109 |
102 ;;; Code: | 110 ;;; Code: |
103 | 111 |
104 (require 'sendmail) | 112 (require 'sendmail) |
105 (require 'rmail) | 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 (defvar uce-mail-reader 'rmail | |
118 "A symbol indicating which mail reader you are using. | |
119 Choose from: gnus, rmail.") | |
106 | 120 |
107 (defgroup uce nil | 121 (defgroup uce nil |
108 "Facilitate reply to unsolicited commercial email." | 122 "Facilitate reply to unsolicited commercial email." |
109 :prefix "uce-" | 123 :prefix "uce-" |
110 :group 'mail) | 124 :group 'mail) |
128 | 142 |
129 If you have any list of people you send unsolicited commercial emails to, | 143 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 | 144 REMOVE me from such list immediately. I suggest that you make this list |
131 just empty. | 145 just empty. |
132 | 146 |
147 ---------------------------------------------------- | |
148 | |
149 If you are not an administrator of any site and still have received | |
150 this message then your email address is being abused by some spammer. | |
151 They fake your address in From: or Reply-To: header. In this case, | |
152 you might want to show this message to your system administrator, and | |
153 ask him/her to investigate this matter. | |
154 | |
133 Note to the postmaster(s): I append the text of UCE in question to | 155 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. | 156 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 | 157 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 | 158 mentioned as original sender's host (I do realize that it may be |
137 was used as mail relay for this message. If message was sent not by | 159 faked, but I think that if your domain name is being abused this way |
138 your user, could you please compare time when this message was sent | 160 you might want to learn about it, and take actions) and to the |
139 (use time in Received: field of the envelope rather than Date: field) | 161 postmaster whose host was used as mail relay for this message. If |
140 with your sendmail logs and see what host was using your sendmail at | 162 message was sent not by your user, could you please compare time when |
141 this moment of time. | 163 this message was sent (use time in Received: field of the envelope |
164 rather than Date: field) with your sendmail logs and see what host was | |
165 using your sendmail at this moment of time. | |
142 | 166 |
143 Thank you." | 167 Thank you." |
144 | 168 |
145 "This is the text that uce-reply-to-uce command will put in reply buffer. | 169 "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 | 170 Some of spamming programs in use will be set up to read all incoming |
183 (defun uce-reply-to-uce (&optional ignored) | 207 (defun uce-reply-to-uce (&optional ignored) |
184 "Send reply to UCE in Rmail. | 208 "Send reply to UCE in Rmail. |
185 UCE stands for unsolicited commercial email. Function will set up reply | 209 UCE stands for unsolicited commercial email. Function will set up reply |
186 buffer with default To: to the sender, his postmaster, his abuse@ | 210 buffer with default To: to the sender, his postmaster, his abuse@ |
187 address, and postmaster of the mail relay used." | 211 address, and postmaster of the mail relay used." |
188 (interactive "P") | 212 (interactive) |
189 (let ((to (mail-strip-quoted-names (mail-fetch-field "from" t))) | 213 (let ((message-buffer |
190 (reply-to (mail-fetch-field "reply-to")) | 214 (cond ((eq uce-mail-reader 'gnus) "*Article*") |
191 temp) | 215 ((eq uce-mail-reader 'rmail) "RMAIL") |
192 ;; Initial setting of the list of recipients of our message; that's | 216 (t (error |
193 ;; what they are pretending to be (and in many cases, really are). | 217 "Variable uce-mail-reader set to unrecognized value"))))) |
194 (if to | 218 (or (get-buffer message-buffer) |
195 (setq to (format "%s" (mail-strip-quoted-names to))) | 219 (error (concat "No buffer " message-buffer ", cannot find UCE"))) |
196 (setq to "")) | 220 (switch-to-buffer message-buffer) |
197 (if reply-to | 221 (let ((to (mail-strip-quoted-names (mail-fetch-field "from" t))) |
198 (setq to (format "%s, %s" to (mail-strip-quoted-names reply-to)))) | 222 (reply-to (mail-fetch-field "reply-to")) |
199 (let (first-at-sign end-of-hostname sender-host) | 223 temp) |
200 (setq first-at-sign (string-match "@" to) | 224 ;; Initial setting of the list of recipients of our message; that's |
201 end-of-hostname (string-match "[ ,>]" to first-at-sign) | 225 ;; what they are pretending to be. |
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 | 226 (if to |
266 (let ((fill-prefix "\t") | 227 (setq to (format "%s" (mail-strip-quoted-names to))) |
267 (address-start (point))) | 228 (setq to "")) |
268 (insert to "\n") | 229 (if reply-to |
269 (fill-region-as-paragraph address-start (point))) | 230 (setq to (format "%s, %s" to (mail-strip-quoted-names reply-to)))) |
270 (newline)) | 231 (let (first-at-sign end-of-hostname sender-host) |
271 (insert "Subject: " uce-subject-line "\n") | 232 (setq first-at-sign (string-match "@" to) |
272 (if uce-default-headers | 233 end-of-hostname (string-match "[ ,>]" to first-at-sign) |
273 (insert uce-default-headers)) | 234 sender-host (substring to first-at-sign end-of-hostname)) |
274 (if mail-default-headers | 235 (if (string-match "\\." sender-host) |
275 (insert mail-default-headers)) | 236 (setq to (format "%s, postmaster%s, abuse%s" |
276 (if mail-default-reply-to | 237 to sender-host sender-host)))) |
277 (insert "Reply-to: " mail-default-reply-to "\n\n")) | 238 (setq mail-send-actions nil) |
278 (mail-sendmail-delimit-header) | 239 (setq mail-reply-buffer nil) |
279 ;; Insert all our text. Then go back to the place where we started. | 240 (cond ((eq uce-mail-reader 'gnus) |
280 (if to (setq to (point))) | 241 (article-hide-headers -1) |
281 ;; Text of ranting. | 242 (copy-region-as-kill (point-min) (point-max)) |
282 (if uce-message-text | 243 (article-hide-headers)) |
283 (insert uce-message-text)) | 244 ((eq uce-mail-reader 'rmail) |
284 ;; Signature. | 245 (save-excursion |
285 (cond ((eq uce-signature t) | 246 (save-restriction |
286 (if (file-exists-p "~/.signature") | 247 (widen) |
287 (progn | 248 (rmail-maybe-set-message-counters) |
288 (insert "\n\n-- \n") | 249 (copy-region-as-kill (rmail-msgbeg rmail-current-message) |
289 (insert-file "~/.signature") | 250 (rmail-msgend rmail-current-message)))))) |
290 ;; Function insert-file leaves point where it was, | 251 (switch-to-buffer "*mail*") |
291 ;; while we want to place signature in the ``middle'' | 252 (erase-buffer) |
292 ;; of the message. | 253 (setq temp (point)) |
293 (exchange-point-and-mark)))) | 254 (yank) |
294 (uce-signature | 255 (goto-char temp) |
295 (insert "\n\n-- \n" uce-signature))) | 256 (if (eq uce-mail-reader 'rmail) |
296 ;; And text of the original message. | 257 (progn |
297 (if uce-uce-separator | 258 (forward-line 2) |
298 (insert "\n\n" uce-uce-separator "\n")) | 259 (while (looking-at "Summary-Line:\\|Mail-From:") |
299 ;; If message doesn't end with a newline, insert it. | 260 (forward-line 1)) |
300 (goto-char (point-max)) | 261 (delete-region temp (point)))) |
301 (or (bolp) (newline))) | 262 ;; Now find the mail hub that first accepted this message. |
302 ;; And go back to the beginning of text. | 263 ;; This should try to find the last Received: header. |
303 (if to (goto-char to)) | 264 ;; Sometimes there may be other headers inbetween Received: headers. |
304 (or to (set-buffer-modified-p nil)) | 265 (cond ((eq uce-mail-reader 'gnus) |
305 ;; Run hooks before we leave buffer for editing. Reasonable usage | 266 ;; Does Gnus always have Lines: in the end? |
306 ;; might be to set up special key bindings, replace standart | 267 (re-search-forward "^Lines:") |
307 ;; functions in mail-mode, etc. | 268 (beginning-of-line)) |
308 (run-hooks 'mail-setup-hook 'uce-setup-hook))) | 269 ((eq uce-mail-reader 'rmail) |
270 (beginning-of-buffer) | |
271 (search-forward "*** EOOH ***\n") | |
272 (beginning-of-line) | |
273 (forward-line -1))) | |
274 (re-search-backward "^Received:") | |
275 (beginning-of-line) | |
276 ;; Is this always good? It's the only thing I saw when I checked | |
277 ;; a few messages. | |
278 (let ((eol (save-excursion (end-of-line) (point)))) | |
279 ;;(if (not (re-search-forward ": \\(from\\|by\\) " eol t)) | |
280 (if (not (re-search-forward "\\(from\\|by\\) " eol t)) | |
281 (progn | |
282 (goto-char eol) | |
283 (if (looking-at "[ \t\n]+\\(from\\|by\\) ") | |
284 (goto-char (match-end 0)) | |
285 (error "Failed to extract hub address"))))) | |
286 (setq temp (point)) | |
287 (search-forward " ") | |
288 (forward-char -1) | |
289 ;; And add its postmaster to the list of addresses. | |
290 (if (string-match "\\." (buffer-substring temp (point))) | |
291 (setq to (format "%s, postmaster@%s" | |
292 to (buffer-substring temp (point))))) | |
293 ;; Also look at the message-id, it helps *very* often. | |
294 (if (and (search-forward "\nMessage-Id: " nil t) | |
295 ;; Not all Message-Id:'s have an `@' sign. | |
296 (let ((bol (point)) | |
297 eol) | |
298 (end-of-line) | |
299 (setq eol (point)) | |
300 (goto-char bol) | |
301 (search-forward "@" eol t))) | |
302 (progn | |
303 (setq temp (point)) | |
304 (search-forward ">") | |
305 (forward-char -1) | |
306 (if (string-match "\\." (buffer-substring temp (point))) | |
307 (setq to (format "%s, postmaster@%s" | |
308 to (buffer-substring temp (point))))))) | |
309 (cond ((eq uce-mail-reader 'gnus) | |
310 ;; Does Gnus always have Lines: in the end? | |
311 (re-search-forward "^Lines:") | |
312 (beginning-of-line)) | |
313 ((eq uce-mail-reader 'rmail) | |
314 (search-forward "\n*** EOOH ***\n") | |
315 (forward-line -1))) | |
316 (setq temp (point)) | |
317 (search-forward "\n\n" nil t) | |
318 (if (eq uce-mail-reader 'gnus) | |
319 (forward-line -1)) | |
320 (delete-region temp (point)) | |
321 ;; End of Rmail dependent section. | |
322 (auto-save-mode auto-save-default) | |
323 (mail-mode) | |
324 (goto-char (point-min)) | |
325 (insert "To: ") | |
326 (save-excursion | |
327 (if to | |
328 (let ((fill-prefix "\t") | |
329 (address-start (point))) | |
330 (insert to "\n") | |
331 (fill-region-as-paragraph address-start (point))) | |
332 (newline)) | |
333 (insert "Subject: " uce-subject-line "\n") | |
334 (if uce-default-headers | |
335 (insert uce-default-headers)) | |
336 (if mail-default-headers | |
337 (insert mail-default-headers)) | |
338 (if mail-default-reply-to | |
339 (insert "Reply-to: " mail-default-reply-to "\n")) | |
340 (insert mail-header-separator "\n") | |
341 ;; Insert all our text. Then go back to the place where we started. | |
342 (if to (setq to (point))) | |
343 ;; Text of ranting. | |
344 (if uce-message-text | |
345 (insert uce-message-text)) | |
346 ;; Signature. | |
347 (cond ((eq uce-signature t) | |
348 (if (file-exists-p "~/.signature") | |
349 (progn | |
350 (insert "\n\n-- \n") | |
351 (insert-file "~/.signature") | |
352 ;; Function insert-file leaves point where it was, | |
353 ;; while we want to place signature in the ``middle'' | |
354 ;; of the message. | |
355 (exchange-point-and-mark)))) | |
356 (uce-signature | |
357 (insert "\n\n-- \n" uce-signature))) | |
358 ;; And text of the original message. | |
359 (if uce-uce-separator | |
360 (insert "\n\n" uce-uce-separator "\n")) | |
361 ;; If message doesn't end with a newline, insert it. | |
362 (goto-char (point-max)) | |
363 (or (bolp) (newline))) | |
364 ;; And go back to the beginning of text. | |
365 (if to (goto-char to)) | |
366 (or to (set-buffer-modified-p nil)) | |
367 ;; Run hooks before we leave buffer for editing. Reasonable usage | |
368 ;; might be to set up special key bindings, replace standart | |
369 ;; functions in mail-mode, etc. | |
370 (run-hooks 'mail-setup-hook 'uce-setup-hook)))) | |
309 | 371 |
310 (defun uce-insert-ranting (&optional ignored) | 372 (defun uce-insert-ranting (&optional ignored) |
311 "Insert text of the usual reply to UCE into current buffer." | 373 "Insert text of the usual reply to UCE into current buffer." |
312 (interactive "P") | 374 (interactive "P") |
313 (insert uce-message-text)) | 375 (insert uce-message-text)) |