diff options
| -rw-r--r-- | lisp/mail/uce.el | 338 |
1 files changed, 200 insertions, 138 deletions
diff --git a/lisp/mail/uce.el b/lisp/mail/uce.el index 1cec136da38..3b0956159dd 100644 --- a/lisp/mail/uce.el +++ b/lisp/mail/uce.el | |||
| @@ -1,10 +1,9 @@ | |||
| 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. |
| @@ -27,13 +26,11 @@ | |||
| 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 |
| @@ -75,12 +72,23 @@ | |||
| 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) |
| 83 | 87 | ||
| 88 | ;; If you want to use it with Gnus also use | ||
| 89 | |||
| 90 | ;; (setq uce-mail-reader 'gnus) | ||
| 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: |
| @@ -102,7 +110,13 @@ | |||
| 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." |
| @@ -130,15 +144,25 @@ 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 | ||
| @@ -185,127 +209,165 @@ These are mostly meant for headers that prevent delivery errors reporting." | |||
| 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." |