Clean-up previous feedmail.el merge.
[bpt/emacs.git] / lisp / mail / feedmail.el
CommitLineData
0bb37c1a
KH
1;;; feedmail.el --- assist other email packages to massage outgoing messages
2;;; This file is in the public domain.
3
e8af40ee
PJ
4;; This file is part of GNU Emacs.
5
edd69520 6;; Author: Bill Carpenter <bill@carpenter.ORG>
215cda7c 7;; Version: 11
29a69d04
DL
8;; Keywords: email, queue, mail, sendmail, message, spray, smtp, draft
9;; X-URL: <URL:http://www.carpenter.org/feedmail/feedmail.html>
10
0bb37c1a
KH
11;;; Commentary:
12
13;; A replacement for parts of Emacs' sendmail.el (specifically,
14;; it's what handles your outgoing mail after you hit C-c C-c in mail
15;; mode). See below for a list of additional features, including the
16;; ability to queue messages for later sending. If you are using
17;; fakemail as a subprocess, you can switch to feedmail and eliminate
215cda7c
BC
18;; the use of fakemail.
19
20;; feedmail works with recent versions of Emacs (20.x series) and
21;; XEmacs (tested with 20.4 and later betas). It probably no longer
22;; works with Emacs v18, though I haven't tried that in a long
23;; time. Makoto.Nakagawa@jp.compaq.com reports: "I have a report
24;; that with a help of APEL library, feedmail works fine under emacs
25;; 19.28. You can get APEL from ftp://ftp.m17n.org/pub/mule/apel/.
26;; you need apel-10.2 or later to make feedmail work under emacs
27;; 19.28."
28
29;; Sorry, no manual yet in this release. Look for one with the next
30;; release. Or the one after that. Or maybe later.
bd1cd4c2
KH
31
32;; As far as I'm concerned, anyone can do anything they want with
33;; this specific piece of code. No warranty or promise of support is
34;; offered. This code is hereby released into the public domain.
35
bd1cd4c2
KH
36;; Thanks: My thanks to the many people who have sent me suggestions
37;; and fixes over time, as well as those who have tested many beta
38;; iterations. Some are cited in comments in code fragments below,
39;; but that doesn't correlate well with the list of folks who have
40;; actually helped me along the way.
41
bd1cd4c2
KH
42;; If you use feedmail, I invite you to send me some email about it.
43;; I appreciate feedback about problems you find or suggestions for
44;; improvements or added features (even though I can't predict when
45;; I'll incorporate changes). It's also OK with me if you send me a
46;; note along the lines of "I use feedmail and find it useful" or "I
47;; tried feedmail and didn't find it useful, so I stopped using it".
48;;
49;; It is most useful, when sending a bug report, if you tell me what
0bb37c1a 50;; version of Emacs you are using, what version of feedmail you are
bd1cd4c2
KH
51;; using, and what versions of other email-related elisp packages you
52;; are using. If in doubt about any of that, send the bug report
53;; anyhow.
0bb37c1a 54;;
bd1cd4c2
KH
55;; =====
56;; A NOTE TO THOSE WHO WOULD CHANGE THIS CODE... Since it is PD,
57;; you're within your rights to do whatever you want. If you do
58;; publish a new version with your changes in it, please (1) insert
59;; lisp comments describing the changes, (2) insert lisp comments
60;; that clearly delimit where your changes are, (3) email me a copy
61;; (I can't always consistently follow the relevant usenet groups),
62;; and (4) use a version number that is based on the version you're
63;; changing along with something that indicates you changed it. For
64;; example,
65;;
66;; (defconst feedmail-patch-level "123")
67;; (defconst feedmail-patch-level "123-XYZ-mods")
68;;
69;; The point of the last item, of course, is to try to minimize
70;; confusion. Odds are good that if your idea makes sense to me that
71;; it will show up in some future version of feedmail, though it's
72;; hard to say when releases will tumble out.
73;; =====
74;;
75;; This file requires the mail-utils library.
76;;
77;; This file requires the smtpmail library if you use
215cda7c
BC
78;; feedmail-buffer-to-smtpmail. It requires the smtp library if
79;; you use feedmail-buffer-smtp.
bd1cd4c2
KH
80;;
81;; This file requires the custom library. Unfortunately, there are
82;; two incompatible versions of the custom library. If you don't have
83;; custom or you have the old version, this file will still load and
84;; work properly. If you don't know what custom is all about and want
85;; to edit your user option elisp variables the old fashioned way,
86;; just imagine that all the "defcustom" stuff you see below is really
87;; "defvar", and ignore everthing else. For info about custom, see
88;; <URL:http://www.dina.kvl.dk/~abraham/custom/>.
89;;
90;; This code does in elisp a superset of the stuff that used to be done
91;; by the separate program "fakemail" for processing outbound email.
92;; In other words, it takes over after you hit "C-c C-c" in mail mode.
93;; By appropriate setting of options, you can still use "fakemail",
94;; or you can even revert to sendmail (which is not too popular
95;; locally). See the variables at the top of the elisp for how to
96;; achieve these effects (there are more features than in this bullet
97;; list, so trolling through the variable and function doc strings may
98;; be worth your while):
99;;
100;; --- you can park outgoing messages into a disk-based queue and
101;; stimulate sending them all later (handy for laptop users);
102;; there is also a queue for draft messages
103;;
104;; --- you can get one last look at the prepped outbound message and
105;; be prompted for confirmation
106;;
37aa9115 107;; --- removes Bcc:/Resent-Bcc: headers after getting address info
bd1cd4c2
KH
108;;
109;; --- does smart filling of address headers
110;;
37aa9115 111;; --- calls a routine to process Fcc: lines and removes them
bd1cd4c2
KH
112;;
113;; --- empty headers are removed
114;;
37aa9115 115;; --- can force From: or Sender: line
bd1cd4c2 116;;
37aa9115 117;; --- can generate a Message-Id: line
bd1cd4c2 118;;
37aa9115 119;; --- can generate a Date: line; the date can be the time the
bd1cd4c2
KH
120;; message was written or the time it is being sent
121;;
122;; --- strips comments from address info (both "()" and "<>" are
123;; handled via a call to mail-strip-quoted-names); the
124;; comments are stripped in the simplified address list given
125;; to a subprocess, not in the headers in the mail itself
126;; (they are left unchanged, modulo smart filling)
127;;
128;; --- error info is pumped into a normal buffer instead of the
129;; minibuffer
130;;
131;; --- just before the optional prompt for confirmation, lets you
132;; run a hook on the prepped message and simplified address
133;; list
134;;
135;; --- you can specify something other than /bin/mail for the
136;; subprocess
137;;
37aa9115 138;; --- you can generate/modify an X-Mailer: message header
bd1cd4c2
KH
139;;
140;; After a long list of options below, you will find the function
141;; feedmail-send-it. Hers's the best way to use the stuff in this
142;; file:
143;;
144;; Save this file as feedmail.el somewhere on your elisp
145;; loadpath; byte-compile it. Put the following lines somewhere in
146;; your ~/.emacs stuff:
147;;
148;; (setq send-mail-function 'feedmail-send-it)
149;; (autoload 'feedmail-send-it "feedmail")
150;;
151;; If you plan to use the queue stuff, also use this:
152;;
153;; (setq feedmail-enable-queue t)
154;; (autoload 'feedmail-run-the-queue "feedmail")
155;; (autoload 'feedmail-run-the-queue-no-prompts "feedmail")
156;; (setq auto-mode-alist (cons '("\\.fqm$" . mail-mode) auto-mode-alist))
157;;
215cda7c
BC
158;; though VM users might find it more comfortable to use this instead of
159;; the above example's last line:
160;;
161;; (setq auto-mode-alist (cons '("\\.fqm$" . feedmail-vm-mail-mode) auto-mode-alist))
162;;
163;; If you end up getting asked about killing modified buffers all the time
164;; you are probably being prompted from outside feedmail. You can probably
165;; get cured by doing the defadvice stuff described in the documentation
166;; for the variable feedmail-queue-buffer-file-name below.
167;;
168;; If you are wondering how to send your messages to some SMTP server
169;; (which is not really a feedmail-specific issue), you are probably
170;; looking for smtpmail.el, and it is probably already present in your
171;; emacs installation. Look at smtpmail.el for how to set that up, and
172;; then do this to hook it into feedmail:
173;;
174;; (autoload 'feedmail-buffer-to-smtpmail "feedmail" nil t)
175;; (setq feedmail-buffer-eating-function 'feedmail-buffer-to-smtpmail)
176;;
177;; Alternatively, the FLIM <http://www.m17n.org/FLIM/> project
178;; provides a library called smtp.el. If you want to use that, the above lines
179;; would be:
180;;
181;; (autoload 'feedmail-buffer-to-smtp "feedmail" nil t)
182;; (setq feedmail-buffer-eating-function 'feedmail-buffer-to-smtp)
183;;
0bb37c1a 184;; If you are using the desktop.el library to restore your sessions, you might
bd1cd4c2
KH
185;; like to add the suffix ".fqm" to the list of non-saved things via the variable
186;; desktop-files-not-to-save.
187;;
188;; If you are planning to call feedmail-queue-reminder from your .emacs or
189;; something similar, you might need this:
190;;
191;; (autoload 'feedmail-queue-reminder "feedmail")
192;;
193;; If you ever use rmail-resend and queue messages, you should do this:
194;;
195;; (setq feedmail-queue-alternative-mail-header-separator "")
196;;
197;; If you want to automatically spell-check messages, but not when sending
198;; them from the queue, you could do something like this:
199;;
200;; (autoload 'feedmail-mail-send-hook-splitter "feedmail")
201;; (add-hook 'mail-send-hook 'feedmail-mail-send-hook-splitter)
202;; (add-hook 'feedmail-mail-send-hook 'ispell-message)
203;;
204;; If you are using message-mode to compose and send mail, feedmail will
205;; probably work fine with that (someone else tested it and told me it worked).
206;; Follow the directions above, but make these adjustments instead:
207;;
208;; (setq message-send-mail-function 'feedmail-send-it)
209;; (add-hook 'message-mail-send-hook 'feedmail-mail-send-hook-splitter)
210;;
215cda7c
BC
211;; If you use message-mode and you make use of feedmail's queueing
212;; stuff, you might also like to adjust these variables to appropriate
213;; values for message-mode:
214;;
215;; feedmail-queue-runner-mode-setter
216;; feedmail-queue-runner-message-sender
217;;
218;; If you are using the "cmail" email package, there is some built-in
219;; support for feedmail in recent versions. To enable it, you should:
220;;
221;; (setq cmail-use-feedmail t)
222;;
223;;;;;;;;
224;;
bd1cd4c2
KH
225;; I think the LCD is no longer being updated, but if it were, this
226;; would be a proper LCD record. There is an old version of
227;; feedmail.el in the LCD archive. It works but is missing a lot of
228;; features.
229;;
230;; LCD record:
215cda7c 231;; feedmail|WJCarpenter|bill-feedmail@carpenter.ORG|Outbound mail queue handling|01-??-??|11-beta-??|feedmail.el
bd1cd4c2
KH
232;;
233;; Change log:
234;; original, 31 March 1991
235;; patchlevel 1, 5 April 1991
236;; patchlevel 2, 24 May 1991
237;; 5-may-92 jwz Conditionalized calling expand-mail-aliases, since that
0bb37c1a 238;; function doesn't exist in Lucid Emacs or when using
bd1cd4c2
KH
239;; mail-abbrevs.el.
240;; patchlevel 3, 3 October 1996
241;; added queue stuff; still works in v18
242;; patchlevel 4, issued by someone else
243;; patchlevel 5, issued by someone else
244;; patchlevel 6, not issued as far as I know
245;; patchlevel 7, 20 May 1997
0bb37c1a 246;; abandon futile support of Emacs 18 (sorry if that hurts you)
37aa9115
KH
247;; provide a Date: header by default
248;; provide a default for generating Message-Id: header contents
bd1cd4c2
KH
249;; and use it by default (slightly changed API)
250;; return value from feedmail-run-the-queue
251;; new wrapper function feedmail-run-the-queue-no-prompts
37aa9115
KH
252;; user-mail-address as default for From:
253;; properly deal with Resent-{To,Cc,Bcc}
254;; Bcc and Resent-* now included in smart filling
bd1cd4c2
KH
255;; limited support for a "drafts" directory
256;; user-configurable default message action
257;; allow timeout for confirmation prompt (where available)
37aa9115 258;; move Fcc handling to as late as possible to get max
bd1cd4c2
KH
259;; header munging in the saved file
260;; work around sendmail.el's prompts when working from queue
261;; more reliably detect voluntary user bailouts
262;; offer to save modified buffers visiting queue files
263;; offer to delete old file copies of messages being queued
264;; offer to delete queue files when sending immediately
265;; queue filename convention preserves queue order
266;; default queue and draft directory names that work on VMS
267;; deduced address list now really a list, not a string (API change)
268;; no more address buffer
269;; when sending immediately, brief reminder of queue/draft counts
270;; copy trace of smtpmail stuff to feedmail error buffer on no-go
271;; more granularity on when to confirm sending
272;; pause a bit for errors while running queue
273;; try to clean up some pesky auto-save files from the
274;; queue/draft directories
275;; feedmail-force-expand-mail-aliases in case you can't figure
276;; any other way
277;; cleanup some of my sloppiness about case-fold-search (a strange
278;; variable)
0bb37c1a 279;; best effort following coding conventions from Emacs
bd1cd4c2
KH
280;; elisp manual appendix
281;; "customize" (see custom.el)
282;; when user selects "immediate send", clear action prompt since
283;; hooks may take a while to operate, and user may think the
284;; response didn't take
285;; fixes to the argument conventions for the
286;; feedmail-queue-runner-* functions; allows
287;; feedmail-run-the-queue[-no-prompts] to properly be called
288;; non-interactively
289;; eliminate reliance on directory-sep-char and feedmail-sep-thing
290;; tweak smart filling (reminded of comma problem by levitte@lp.se)
291;; option to control writing in text vs binary mode
6287be55 292;; patchlevel 8, 15 June 1998
bd1cd4c2 293;; reliable re-editing of text-mode (vs binary) queued messages
37aa9115
KH
294;; user option to keep Bcc: in Fcc: copy (keep by default)
295;; user option to delete body from Fcc: copy (keep by default)
bd1cd4c2
KH
296;; feedmail-deduce-bcc-where for envelope (API change for
297;; feedmail-deduce-address list)
298;; feedmail-queue-alternative-mail-header-separator
299;; at message action prompt, "I"/"S" bypass message confirmation prompt
300;; feedmail-mail-send-hook-splitter, feedmail-mail-send-hook,
301;; feedmail-mail-send-hook-queued
302;; user can supply stuff for message action prompt
303;; variable feedmail-queue-runner-confirm-global, function feedmail-run-the-queue-global-prompt
304;; bugfix: absolute argument to directory-files (tracked down for me
305;; by gray@austin.apc.slb.com (Douglas Gray Stephens)); relative
306;; pathnames can tickle stuff in ange-ftp remote directories
307;; (perhaps because feedmail is careless about its working
308;; directory)
309;; feedmail-deduce-envelope-from
310;; always supply envelope "from" (user-mail-address) to sendmail
311;; feedmail-message-id-suffix
312;; feedmail-queue-reminder, feedmail-queue-reminder-alist (after suggestions
313;; and/or code fragments from tonyl@Eng.Sun.COM (Tony Lam) and
314;; burge@newvision.com (Shane Burgess); bumped up the default value of
315;; feedmail-queue-chatty-sit-for since info is more complex sometimes
316;; feedmail-enable-spray (individual transmissions, crude mailmerge)
37aa9115 317;; blank Subject: no longer a special case; see feedmail-nuke-empty-headers
bd1cd4c2
KH
318;; fiddle-plexes data structure used lots of places; see feedmail-fiddle-plex-blurb
319;; feedmail-fiddle-plex-user-list
320;; feedmail-is-a-resend
321;; honor mail-from-style in constructing default for feedmail-from-line
322;; re-implement feedmail-from-line and feedmail-sender-line with
323;; fiddle-plexes; slightly modified semantics for feedmail-sender-line
324;; feedmail-queue-default-file-slug; tidy up some other slug details
325;; feedmail-queue-auto-file-nuke
326;; feedmail-queue-express-to-queue and feedmail-queue-express-to-draft
327;; strong versions of "q"ueue and "d"raft answers (always make a new file)
215cda7c
BC
328;; patchlevel 9, 23 March 2001
329;; feedmail-queue-buffer-file-name to work around undesirable mail-send prompt
330;; at message action prompt, can scroll message buffer with "<" and ">";
331;; C-v no longer scrolls help buffer
332;; conditionalize (discard-input) in message action prompt to avoid killing
333;; define-kbd-macro
334;; fixed error if feedmail-x-mailer-line was nil
335;; feedmail-binmail-template only uses /bin/rmail if it exists
336;; relocate feedmail-queue-alternative-mail-header-separator stuff
337;; added feedmail-vm-mail-mode, which make a good auto-mode-alist entry
338;; for FQM files if you're a VM user
339;; change buffer-substring calls to buffer-substring-no-properties for
340;; speed-up (suggested by Howard Melman <howard@silverstream.com>)
341;; feedmail-sendmail-f-doesnt-sell-me-out to contol "-f" in call to sendmail
342;; in feedmail-buffer-to-sendmail
343;; better trapping of odd conditions during the running of the queue;
344;; thanks to Yigal Hochberg for helping me test much of this by remote
345;; control
346;; feedmail-debug and feedmail-debug-sit-for
347;; feedmail-display-full-frame
348;; feedmail-queue-express-hook
349;; added example function feedmail-spray-via-bbdb
350;; use expand-file-name for setting default directory names
50b23e5a
GM
351;; define feedmail-binmail-gnulinuxish-template as a suggestion for
352;; the value of feedmail-binmail-template on GNU/Linux and maybe other
215cda7c
BC
353;; systems with non-classic /bin/[r]mail behavior
354;; guard against nil user-mail-address in generating MESSAGE-ID:
355;; feedmail-queue-slug-suspect-regexp is now a variable to
356;; accomodate non-ASCII environments (thanks to
357;; Makoto.Nakagawa@jp.compaq.com for this suggestion)
358;; feedmail-buffer-to-smtp, to parallel feedmail-buffer-to-smtpmail
359;; patchlevel 10, 22 April 2001
360;; DATE: and MESSAGE-ID stuff now forces system-time-locale to "C"
361;; (brought to my attention by Makoto.Nakagawa@jp.compaq.com)
362;; patchlevel 11
363;; tweak default FROM: calculation to look at mail-host-address
364;; (suggested by "Jason Eisner" <jason@cs.jhu.edu>)
bd1cd4c2 365;;
215cda7c 366;; todo:
bd1cd4c2
KH
367;; write texinfo manual
368;; maybe partition into multiple files, including files of examples
369;;
370;;; Code:
371
215cda7c 372(defconst feedmail-patch-level "11-beta-1")
bd1cd4c2 373
8c0171c0
GM
374(require 'mail-utils) ; pick up mail-strip-quoted-names
375
376(eval-when-compile
377 (require 'smtpmail)
378 (require 'cl))
379
49267116 380(autoload 'mail-do-fcc "sendmail")
bd1cd4c2
KH
381
382(defgroup feedmail nil
383 "Assist other email packages to massage outgoing messages."
49267116 384 :link '(url-link "http://www.carpenter.org/feedmail/feedmail.html")
adb92798 385 :link '(emacs-commentary-link "feedmail")
bd1cd4c2
KH
386 :group 'mail)
387
388(defgroup feedmail-misc nil
389 "Miscellaneous feedmail options that don't fit in other groups."
390 :group 'feedmail)
391
392(defgroup feedmail-headers nil
393 "Options related to manipulating specific headers or types of headers."
394 :group 'feedmail)
395
396(defgroup feedmail-queue nil
397 "Options related to queuing messages for later sending."
398 :group 'feedmail)
399
215cda7c
BC
400(defgroup feedmail-debug nil
401 "Options related to debug messages for later sending."
402 :group 'feedmail)
403
bd1cd4c2
KH
404
405(defcustom feedmail-confirm-outgoing nil
1fc7dabf 406 "If non-nil, give a y-or-n confirmation prompt before sending mail.
bd1cd4c2
KH
407This is done after the message is completely prepped, and you'll be
408looking at the top of the message in a buffer when you get the prompt.
409If set to the symbol 'queued, give the confirmation prompt only while
410running the queue (however, the prompt is always suppressed if you are
27772f10 411processing the queue via `feedmail-run-the-queue-no-prompts'). If set
bd1cd4c2
KH
412to the symbol 'immediate, give the confirmation prompt only when
413sending immediately. For any other non-nil value, prompt in both
414cases. You can give a timeout for the prompt; see variable
27772f10 415`feedmail-confirm-outgoing-timeout'."
bd1cd4c2
KH
416 :group 'feedmail-misc
417 :type 'boolean
418 )
419
420
215cda7c
BC
421(defcustom feedmail-display-full-frame 'queued
422 "If non-nil, show prepped messages in a full frame.
423If nil, the prepped message will be shown, for confirmation or
424otherwise, in some window in the current frame without resizing
425anything. That may or may not display enough of the message to
426distinguish it from others. If set to the symbol 'queued, take
427this action only when running the queue. If set to the symbol
428'immediate, take this action only when sending immediately. For
429any other non-nil value, take the action in both cases. Even if
430you're not confirming the sending of immediate or queued messages,
431it can still be interesting to see a lot about them as they are
432shuttled robotically onward."
433 :group 'feedmail-misc
434 :type 'boolean
435 )
436
437
bd1cd4c2 438(defcustom feedmail-confirm-outgoing-timeout nil
1fc7dabf 439 "If non-nil, a timeout in seconds at the send confirmation prompt.
bd1cd4c2
KH
440If a positive number, it's a timeout before sending. If a negative
441number, it's a timeout before not sending. This will not work if your
27772f10 442version of Emacs doesn't include the function `y-or-n-p-with-timeout'
0bb37c1a 443\(e.g., some versions of XEmacs\)."
50b23e5a 444 :version "24.1"
bd1cd4c2
KH
445 :group 'feedmail-misc
446 :type '(choice (const nil) integer)
c7d4a777 447 )
bd1cd4c2
KH
448
449
450(defcustom feedmail-nuke-bcc t
1fc7dabf 451 "If non-nil remove Bcc: lines from the message headers.
37aa9115 452In any case, the Bcc: lines do participate in the composed address
bd1cd4c2 453list. You may want to leave them in if you're using sendmail
27772f10 454\(see `feedmail-buffer-eating-function'\)."
bd1cd4c2
KH
455 :group 'feedmail-headers
456 :type 'boolean
c7d4a777 457 )
bd1cd4c2
KH
458
459
460(defcustom feedmail-nuke-resent-bcc t
1fc7dabf 461 "If non-nil remove Resent-Bcc: lines from the message headers.
37aa9115 462In any case, the Resent-Bcc: lines do participate in the composed
bd1cd4c2 463address list. You may want to leave them in if you're using sendmail
27772f10 464\(see `feedmail-buffer-eating-function'\)."
bd1cd4c2
KH
465 :group 'feedmail-headers
466 :type 'boolean
c7d4a777 467 )
bd1cd4c2
KH
468
469
470(defcustom feedmail-deduce-bcc-where nil
1fc7dabf 471 "Where Bcc:/Resent-Bcc: addresses should appear in the envelope list.
bd1cd4c2
KH
472Addresses for the message envelope are deduced by examining
473appropriate address headers in the message. Generally, they will show
474up in the list of deduced addresses in the order that the headers
475happen to appear (duplicate addresses are eliminated in any case).
476This variable can be set to the symbol 'first, in which case the
0bb37c1a 477Bcc:/Resent-Bcc: addresses will appear at the beginning in the list;
bd1cd4c2
KH
478or, it can be set to the symbol 'last, in which case they will appear
479at the end of the list.
480
481Why should you care? Well, maybe you don't, and certainly the same
482things could be accomplished by affecting the order of message headers
37aa9115
KH
483in the outgoing message. Some people use Bcc: as a way of getting
484their own \"come back\" copy of each message they send. If Bcc:
bd1cd4c2
KH
485addresses are not handled first, there can be substantial delays in
486seeing the message again. Some configurations of sendmail, for example,
487seem to try to deliver to each addressee at least once, immediately
488and serially, so slow SMTP conversations can add up to a delay. There
489is an option for either 'first or 'last because you might have a
490delivery agent that processes the addresses backwards."
491 :group 'feedmail-headers
492 :type 'boolean
c7d4a777 493 )
bd1cd4c2
KH
494
495
496(defcustom feedmail-fill-to-cc t
1fc7dabf 497 "If non-nil do smart filling of addressee header lines.
bd1cd4c2
KH
498Smart filling means breaking long lines at appropriate points and
499making continuation lines. Despite the function name, it includes
37aa9115
KH
500To:, Cc:, Bcc: (and their Resent-* forms), as well as From: and
501Reply-To: (though they seldom need it). If nil, the lines are left
bd1cd4c2
KH
502as-is. The filling is done after mail address alias expansion."
503 :group 'feedmail-headers
504 :type 'boolean
c7d4a777 505 )
bd1cd4c2
KH
506
507
508(defcustom feedmail-fill-to-cc-fill-column default-fill-column
1fc7dabf 509 "Fill column used by `feedmail-fill-to-cc'."
bd1cd4c2
KH
510 :group 'feedmail-headers
511 :type 'integer
c7d4a777 512 )
bd1cd4c2
KH
513
514
515(defcustom feedmail-nuke-bcc-in-fcc nil
1fc7dabf 516 "If non-nil remove [Resent-]Bcc: lines in message copies saved via Fcc:.
37aa9115 517This is independent of whether the Bcc: header lines are actually sent
bd1cd4c2 518with the message (see feedmail-nuke-bcc). Though not implied in the name,
37aa9115 519the same Fcc: treatment applies to both Bcc: and Resent-Bcc: lines."
bd1cd4c2
KH
520 :group 'feedmail-headers
521 :type 'boolean
c7d4a777 522 )
bd1cd4c2
KH
523
524
525(defcustom feedmail-nuke-body-in-fcc nil
1fc7dabf 526 "If non-nil remove body of message in copies saved via Fcc:.
afbc4a8a 527If a positive integer value, leave (up to) that many lines of the
37aa9115 528beginning of the body intact. The result is that the Fcc: copy will
bd1cd4c2
KH
529consist only of the message headers, serving as a sort of an outgoing
530message log."
531 :group 'feedmail-headers
532 :type '(choice (const nil) (const t) integer)
c7d4a777 533 )
bd1cd4c2
KH
534
535
536(defcustom feedmail-force-expand-mail-aliases nil
1fc7dabf 537 "If non-nil, force the calling of `expand-mail-aliases'.
bd1cd4c2 538Normally, feedmail tries to figure out if you're using mailalias or
0bb37c1a 539mailabbrevs and only calls `expand-mail-aliases' if it thinks you're
bd1cd4c2
KH
540using the mailalias package. This user option can be used to force
541the issue since there are configurations which fool the figuring
542out."
543 :group 'feedmail-headers
544 :type 'boolean
c7d4a777 545 )
bd1cd4c2
KH
546
547
548(defcustom feedmail-nuke-empty-headers t
1fc7dabf 549 "If non-nil, remove header lines which have no contents.
37aa9115 550A completely empty Subject: header is always removed, regardless of
bd1cd4c2
KH
551the setting of this variable. The only time you would want them left
552in would be if you used some headers whose presence indicated
553something rather than their contents. This is rare in Internet email
554but common in some proprietary systems."
555 :group 'feedmail-headers
556 :type 'boolean
c7d4a777 557 )
bd1cd4c2 558
37aa9115 559;; wjc sez: I think the use of the Sender: line is pretty pointless,
bd1cd4c2
KH
560;; but I left it in to be compatible with sendmail.el and because
561;; maybe some distant mail system needs it. Really, though, if you
562;; want a sender line in your mail, just put one in there and don't
563;; wait for feedmail to do it for you. (Yes, I know all about
564;; RFC-822 and RFC-1123, but are you *really* one of those cases
565;; they're talking about? I doubt it.)
566(defcustom feedmail-sender-line nil
1fc7dabf 567 "If non-nil and the email has no Sender: header, use this value.
bd1cd4c2 568May be nil, in which case nothing in particular is done with respect
37aa9115 569to Sender: lines. By design, will not replace an existing Sender:
bd1cd4c2
KH
570line, but you can achieve that with a fiddle-plex 'replace action.
571NB: it makes no sense to use the value t since there is no sensible
37aa9115 572default for Sender:.
bd1cd4c2
KH
573
574If not nil, it may be a string, a fiddle-plex, or a function which
575returns either nil, t, a string, or a fiddle-plex (or, in fact,
576another function, but let's not be ridiculous). If a string, it
577should be just the contents of the header, not the name of the header
578itself nor the trailing newline. If a function, it will be called
579with no arguments. For an explanation of fiddle-plexes, see the
27772f10 580documentation for the variable `feedmail-fiddle-plex-blurb'. In all
bd1cd4c2 581cases the name element of the fiddle-plex is ignored and is hardwired
215cda7c 582by feedmail to either \"Sender\" or \"Resent-Sender\".
bd1cd4c2
KH
583
584You can probably leave this nil, but if you feel like using it, a good
585value would be a string of a fully-qualified domain name form of your
215cda7c 586address. For example, \"bill@example.net (WJCarpenter)\". The Sender:
37aa9115 587header is fiddled after the From: header is fiddled."
bd1cd4c2
KH
588 :group 'feedmail-headers
589 :type '(choice (const nil) string)
c7d4a777 590 )
bd1cd4c2
KH
591
592
593(defcustom feedmail-force-binary-write t
1fc7dabf 594 "If non-nil, force writing file as binary (this applies to queues and Fcc:).
bd1cd4c2 595On systems where there is a difference between binary and text files,
705e5bd9
SM
596feedmail will temporarily manipulate the value of `buffer-file-type'
597to make the writing as binary. If nil, writing will be in text mode.
598On systems where there is no distinction or where it is controlled by other
599variables or other means, this option has no effect."
bd1cd4c2
KH
600 :group 'feedmail-misc
601 :type 'boolean
c7d4a777 602 )
bd1cd4c2
KH
603
604
605(defcustom feedmail-from-line t
1fc7dabf 606 "If non-nil and the email has no From: header, use this value.
bd1cd4c2
KH
607May be t, in which case a default is computed (and you probably won't
608be happy with it). May be nil, in which case nothing in particular is
37aa9115
KH
609done with respect to From: lines. By design, will not replace an
610existing From: line, but you can achieve that with a fiddle-plex 'replace
bd1cd4c2
KH
611action.
612
613If neither nil nor t, it may be a string, a fiddle-plex, or a function
614which returns either nil, t, a string, or a fiddle-plex (or, in fact,
615another function, but let's not be ridiculous). If a string, it
616should be just the contents of the header, not the name of the header
617itself nor the trailing newline. If a function, it will be called
618with no arguments. For an explanation of fiddle-plexes, see the
27772f10 619documentation for the variable `feedmail-fiddle-plex-blurb'. In all
bd1cd4c2 620cases the name element of the fiddle-plex is ignored and is hardwired
215cda7c 621by feedmail to either \"From\" or \"Resent-From\".
bd1cd4c2
KH
622
623A good value would be a string fully-qualified domain name form of
215cda7c 624your address. For example, \"bill@example.net (WJCarpenter)\". The
bd1cd4c2 625default value of this variable uses the standard elisp variable
0bb37c1a
KH
626`user-mail-address' which should be set on every system but has a decent
627chance of being wrong. It also honors `mail-from-style'. Better to set
bd1cd4c2 628this variable explicitly to the string you want or find some other way
37aa9115 629to arrange for the message to get a From: line."
bd1cd4c2 630 :group 'feedmail-headers
19a2870f 631 :type '(choice (const t) (const nil) string)
c7d4a777 632 )
bd1cd4c2
KH
633
634
215cda7c
BC
635(defcustom feedmail-sendmail-f-doesnt-sell-me-out nil
636 "Says whether the sendmail program issues a warning header if called with \"-f\".
637The sendmail program has a useful feature to let you set the envelope FROM
638address via a command line option, \"-f\". Unfortunately, it also has a widely
639disliked default behavior of selling you out if you do that by inserting
640an unattractive warning in the headers. It looks something like this:
641
642 X-Authentication-Warning: u1.example.com: niceguy set sender to niceguy@example.com using -f
643
644It is possible to configure sendmail to not do this, but such a reconfiguration
645is not an option for many users. As this is the default behavior of most
646sendmail installations, one can mostly only wish it were otherwise. If feedmail
647believes the sendmail program will sell you out this way, it won't use the \"-f\"
648option when calling sendmail. If it doesn't think sendmail will sell you out,
649it will use the \"-f\" \(since it is a handy feature\). You control what
650feedmail thinks with this variable. The default is nil, meaning that feedmail
651will believe that sendmail will sell you out."
50b23e5a 652 :version "24.1"
215cda7c
BC
653 :group 'feedmail-headers
654 :type 'boolean
655)
656
657
bd1cd4c2 658(defcustom feedmail-deduce-envelope-from t
1fc7dabf 659 "If non-nil, deduce message envelope \"from\" from header From: or Sender:.
37aa9115 660In other words, if there is a Sender: header in the message, temporarily
0bb37c1a 661change the value of `user-mail-address' to be the same while the message
37aa9115 662is being sent. If there is no Sender: header, use the From: header,
bd1cd4c2
KH
663if any. Address values are taken from the actual message just before
664it is sent, and the process is independent of the values of
27772f10 665`feedmail-from-line' and/or `feedmail-sender-line'.
bd1cd4c2
KH
666
667There are many and good reasons for having the message header
37aa9115 668From:/Sender: be different from the message envelope \"from\"
bd1cd4c2
KH
669information. However, for most people and for most circumstances, it
670is usual for them to be the same (this is probably especially true for
671the case where the user doesn't understand the difference between the
672two in the first place).
673
674The idea behind this feature is that you can have everything set up
675some normal way for yourself. If for some reason you want to send a
37aa9115 676message with another From: line, you can just type it at the top of
bd1cd4c2
KH
677the message, and feedmail will take care of \"fixing up\" the envelope
678\"from\". This only works for mail senders which make use of
0bb37c1a 679`user-mail-address' as the envelope \"from\" value. For some mail
bd1cd4c2
KH
680senders (e.g., feedmail-buffer-to-bin-mail), there is no simple way to
681influence what they will use as the envelope."
682 :group 'feedmail-headers
683 :type 'boolean
c7d4a777 684 )
bd1cd4c2
KH
685
686
687(defcustom feedmail-x-mailer-line-user-appendage nil
1fc7dabf 688 "See feedmail-x-mailer-line."
bd1cd4c2 689 :group 'feedmail-headers
7b3237a1 690 :type '(choice (const nil) (const t) string)
c7d4a777 691 )
bd1cd4c2
KH
692
693
694(defcustom feedmail-x-mailer-line t
1fc7dabf 695 "Control the form of an X-Mailer: header in an outgoing message.
bd1cd4c2
KH
696Moderately useful for debugging, keeping track of your correspondents'
697mailer preferences, or just wearing your MUA on your sleeve. You
698should probably know that some people are fairly emotional about the
37aa9115 699presence of X-Mailer: lines in email.
bd1cd4c2 700
37aa9115 701If nil, nothing is done about X-Mailer:.
bd1cd4c2 702
37aa9115
KH
703If t, an X-Mailer: header of a predetermined format is produced,
704combining its efforts with any existing X-Mailer: header. If you want
bd1cd4c2
KH
705to take the default construct and just add a little blob of your own
706at the end, define the variable feedmail-x-mailer-line-user-appendage
0bb37c1a 707as that blob string. A value of t is equivalent to using the function
bd1cd4c2
KH
708feedmail-default-x-mailer-generator.
709
710If neither nil nor t, it may be a string, a fiddle-plex, or a function
711which returns either nil, t, a string, or a fiddle-plex (or, in fact,
712another function, but let's not be ridiculous). If a string, it
713should be just the contents of the header, not the name of the header
714itself nor the trailing newline. If a function, it will be called
715with no arguments. For an explanation of fiddle-plexes, see the
27772f10 716documentation for the variable `feedmail-fiddle-plex-blurb'. In all
bd1cd4c2
KH
717cases the name element of the fiddle-plex is ignored and is hardwired
718by feedmail to either \"X-Mailer\" or \"X-Resent-Mailer\"."
719 :group 'feedmail-headers
720 :type '(choice (const t) (const nil) string function)
c7d4a777 721 )
bd1cd4c2
KH
722
723
724(defcustom feedmail-message-id-generator t
1fc7dabf 725 "Specifies the creation of a Message-Id: header field.
bd1cd4c2 726
37aa9115 727If nil, nothing is done about Message-Id:.
bd1cd4c2 728
37aa9115
KH
729If t, a Message-Id: header of a predetermined format is produced, but
730only if there is not already a Message-Id: in the message. A value of
bd1cd4c2
KH
731t is equivalent to using the function feedmail-default-message-id-generator.
732
733If neither nil nor t, it may be a string, a fiddle-plex, or a function
734which returns either nil, t, a string, or a fiddle-plex (or, in fact,
735another function, but let's not be ridiculous). If a string, it
736should be just the contents of the header, not the name of the header
737itself nor the trailing newline. If a function, it will be called
738with one argument: the possibly-nil name of the file associated with
739the message buffer. For an explanation of fiddle-plexes, see the
27772f10 740documentation for the variable `feedmail-fiddle-plex-blurb'. In all
bd1cd4c2 741cases the name element of the fiddle-plex is ignored and is hardwired
37aa9115 742by feedmail to either \"Message-Id\" or \"Resent-Message-Id\".
bd1cd4c2 743
37aa9115 744You should let feedmail generate a Message-Id: for you unless you are sure
bd1cd4c2
KH
745that whatever you give your messages to will do it for you (e.g., most
746configurations of sendmail). Even if the latter case is true, it
747probably won't hurt you to generate your own, and it will then show up
37aa9115 748in the saved message if you use Fcc:."
bd1cd4c2 749 :group 'feedmail-headers
7c2288ea 750 :type '(choice (const t) (const nil) function)
c7d4a777 751 )
bd1cd4c2
KH
752
753
754(defcustom feedmail-message-id-suffix nil
1fc7dabf 755 "If non-nil, used as a suffix for generating unique Message-Id: headers.
0bb37c1a 756The function `feedmail-default-message-id-generator' creates its work based
bd1cd4c2 757on a formatted date-time string, a random number, and a domain-looking suffix.
0bb37c1a
KH
758You can control the suffix used by assigning a string value to this variable.
759If you don't supply one, the value of the variable `user-mail-address' will be
760used. If the value of `feedmail-message-id-suffix' contains an \"@\" character,
761the string will be used verbatim, else an \"@\" character will be prepended
762automatically."
bd1cd4c2 763 :group 'feedmail-headers
19a2870f 764 :type '(choice (const nil) string)
c7d4a777 765 )
bd1cd4c2
KH
766
767;; this was suggested in various forms by several people; first was
768;; Tony DeSimone in Oct 1992; sorry to be so tardy
769(defcustom feedmail-date-generator t
1fc7dabf 770 "Specifies the creation of a Date: header field.
bd1cd4c2 771
37aa9115 772If nil, nothing is done about Date:.
bd1cd4c2 773
37aa9115
KH
774If t, a Date: header of a predetermined format is produced, but only
775if there is not already a Date: in the message. A value of t is
27772f10 776equivalent to using the function `feedmail-default-date-generator'.
bd1cd4c2
KH
777
778If neither nil nor t, it may be a string, a fiddle-plex, or a function
779which returns either nil, t, a string, or a fiddle-plex (or, in fact,
780another function, but let's not be ridiculous). If a string, it
781should be just the contents of the header, not the name of the header
782itself nor the trailing newline. If a function, it will be called
783with one argument: the possibly-nil name of the file associated with
784the message buffer. For an explanation of fiddle-plexes, see the
27772f10 785documentation for the variable `feedmail-fiddle-plex-blurb'. In all
bd1cd4c2
KH
786cases the name element of the fiddle-plex is ignored and is hardwired
787by feedmail to either \"Date\" or \"Resent-Date\".
788
789If you decide to format your own date field, do us all a favor and know
790what you're doing. Study the relevant parts of RFC-822 and RFC-1123.
791Don't make me come up there!
792
37aa9115 793You should let feedmail generate a Date: for you unless you are sure
bd1cd4c2
KH
794that whatever you give your messages to will do it for you (e.g., most
795configurations of sendmail). Even if the latter case is true, it
796probably won't hurt you to generate your own, and it will then show up
37aa9115 797in the saved message if you use Fcc:."
bd1cd4c2 798 :group 'feedmail-headers
7c2288ea 799 :type '(choice (const t) (const nil) function)
c7d4a777 800 )
bd1cd4c2
KH
801
802
803(defcustom feedmail-fiddle-headers-upwardly t
1fc7dabf 804 "Non-nil means fiddled header fields should go at the top of the header.
f0529b5b 805nil means insert them at the bottom. This is mostly a novelty issue since
bd1cd4c2 806the standards define the ordering of header fields to be immaterial and it's
215cda7c 807fairly likely that some MTA/MUA along the way will have its own idea of what the
bd1cd4c2 808order should be, regardless of what you specify."
436de921 809 :group 'feedmail-headers
bd1cd4c2
KH
810 :type 'boolean
811 )
812
813
814(defcustom feedmail-fiddle-plex-user-list nil
815 "If non-nil, should be a list of one or more fiddle-plexes.
816Each element of the list can also be a function which returns a
817fiddle-plex.
818
819feedmail will use this list of fiddle-plexes to manipulate user-specified
820message header fields. It does this after it has completed all normal
27772f10 821message header field manipulation and before calling `feedmail-last-chance-hook'.
bd1cd4c2
KH
822
823For an explanation of fiddle-plexes, see the documentation for the
27772f10 824variable `feedmail-fiddle-plex-blurb'. In contrast to some other fiddle-plex
bd1cd4c2
KH
825manipulation functions, in this context, it makes no sense to have an element
826which is nil, t, or a simple string."
436de921 827 :group 'feedmail-headers
7b3237a1
AS
828 :type '(repeat (choice function)
829 sexp) ; too complex to be described accurately
bd1cd4c2
KH
830 )
831
832
833(defcustom feedmail-enable-spray nil
834 "If non-nil, transmit message separately to each addressee.
835feedmail normally accumulates a list of addressees and passes the message
836along with that list to a buffer-eating function which expects any number
837of addressees. If this variable is non-nil, however, feedmail will
838repeatedly call the same buffer-eating function. Each time, the list of
839addressees will be just one item from the original list. This only affects
0bb37c1a 840the message envelope addresses and doesn't affect what appears in the
bd1cd4c2
KH
841message headers except as noted.
842
843Spray mode is usually pointless, and if you can't think of a good reason for
0bb37c1a 844it, you should avoid it since it is inherently less efficient than normal
bd1cd4c2 845multiple delivery. One reason to use it is to overcome mis-featured mail
37aa9115 846transports which betray your trust by revealing Bcc: addressees in the
bd1cd4c2 847headers of a message. Another use is to do a crude form of mailmerge, for
27772f10 848which see `feedmail-spray-address-fiddle-plex-list'.
bd1cd4c2
KH
849
850If one of the calls to the buffer-eating function results in an error,
215cda7c
BC
851what happens next is carelessly defined, so beware. This should get ironed
852out in some future release, and there could be other API changes for spraying
853as well."
bd1cd4c2
KH
854 :group 'feedmail-spray
855 :type 'boolean
856 )
857
858(defvar feedmail-spray-this-address nil
215cda7c 859 "Do not set this variable, except via `feedmail-spray-address-fiddle-plex-list'.")
bd1cd4c2
KH
860
861(defcustom feedmail-spray-address-fiddle-plex-list nil
862 "User-supplied specification for a crude form of mailmerge capability.
863When spraying is enabled, feedmail composes a list of envelope addresses.
27772f10 864In turn, `feedmail-spray-this-address' is temporarily set to each address
215cda7c 865\(stripped of any comments and angle brackets\) and a function is called which
0bb37c1a
KH
866fiddles message headers according to this variable. See the documentation for
867`feedmail-fiddle-plex-blurb', for an overview of fiddle-plex data structures.
bd1cd4c2
KH
868
869May be nil, in which case nothing in particular is done about message
870headers for specific addresses.
871
37aa9115 872May be t, in which case a \"To:\" header is added to the message with
bd1cd4c2
KH
873the stripped address as the header contents. The fiddle-plex operator
874is 'supplement.
875
876May be a string, in which case the string is assumed to be the name of
877a message header field with the stripped address serving as the value.
878The fiddle-plex operator is 'supplement.
879
880May be a function, in which case it is called with no arguments and is
881expected to return nil, t, a string, another function, or a fiddle-plex.
215cda7c
BC
882The result is used recursively. The function may alter the value of the
883variable feedmail-spray-this-address, perhaps to embellish it with a
884human name. It would be logical in such a case to return as a value a
885string naming a message header like \"TO\" or an appropriately constructed
886fiddle-plex. For an example, see feedmail-spray-via-bbdb.
bd1cd4c2 887
215cda7c
BC
888May be a list of any combination of the foregoing and/or
889fiddle-plexes. (A value for this variable which consists of a single
890fiddle-plex must be nested inside another list to avoid ambiguity.)
891If a list, each item is acted on in turn as described above.
bd1cd4c2
KH
892
893For example,
894
215cda7c 895 (setq feedmail-spray-address-fiddle-plex-list 'feedmail-spray-via-bbdb)
bd1cd4c2
KH
896
897The idea of the example is that, during spray mode, as each message is
898about to be transmitted to an individual address, the function will be
27772f10 899called and will consult `feedmail-spray-this-address' to find the
bd1cd4c2
KH
900stripped envelope email address (no comments or angle brackets). The
901function should return an embellished form of the address.
902
903The recipe for sending form letters is: (1) create a message with all
37aa9115 904addressees on Bcc: headers; (2) tell feedmail to remove Bcc: headers
0bb37c1a 905before sending the message; (3) create a function which will embellish
27772f10
JB
906stripped addresses, if desired; (4) define `feedmail-spray-address-fiddle-plex-list'
907appropriately; (5) send the message with `feedmail-enable-spray' set
bd1cd4c2
KH
908non-nil; (6) stand back and watch co-workers wonder at how efficient
909you are at accomplishing inherently inefficient things."
910 :group 'feedmail-spray
7b3237a1 911 :type 'sexp ; too complex to be described accurately
bd1cd4c2
KH
912 )
913
50b23e5a
GM
914;; FIXME this is a macro?
915(declare-function bbdb-search "ext:bbdb-com"
916 (records &optional name company net notes phone))
917
918(declare-function bbdb-records "ext:bbdb"
919 (&optional dont-check-disk already-in-db-buffer))
bd1cd4c2 920
215cda7c
BC
921(defun feedmail-spray-via-bbdb ()
922 "Example function for use with feedmail spray mode.
923NB: it's up to the user to have the BBDB environment already set up properly
924before using this."
925 (let (net-rec q-net-addy embellish)
926 (setq q-net-addy (concat "^" (regexp-quote feedmail-spray-this-address) "$"))
927 (setq net-rec (bbdb-search (bbdb-records) nil nil q-net-addy))
928 (if (and (car net-rec) (not (cdr net-rec)))
929 (setq net-rec (car net-rec))
930 (setq net-rec nil))
931 (if net-rec (setq embellish (bbdb-dwim-net-address net-rec)))
932 (if embellish
933 (list "To" embellish 'supplement)
934 (list "To" feedmail-spray-this-address 'supplement))))
935
936
bd1cd4c2 937(defcustom feedmail-enable-queue nil
1fc7dabf 938 "If non-nil, provide for stashing outgoing messages in a queue.
bd1cd4c2
KH
939This is the master on/off switch for feedmail message queuing.
940Queuing is quite handy for laptop-based users. It's also handy if you
941get a lot of mail and process it more or less sequentially. For
942example, you might change your mind about contents of a reply based on
943a message you see a bit later.
944
945There is a separate queue for draft messages, intended to prevent
946you from accidentally sending incomplete messages. The queues are
947disk-based and intended for later transmission. The messages are
948queued in their raw state as they appear in the mail-mode buffer and
949can be arbitrarily edited later, before sending, by visiting the
950appropriate file in the queue directory (and setting the buffer to
951mail-mode or whatever). If you visit a file in the queue directory
952and try to queue it again, it will just get saved in its existing file
953name. You can move a message from the draft to the main queue or vice
954versa by pretending to send it and then selecting whichever queue
955directory you want at the prompt. The right thing will happen.
956
957To transmit all the messages in the queue, invoke the command
27772f10 958`feedmail-run-the-queue' or `feedmail-run-the-queue-no-prompts'."
bd1cd4c2
KH
959 :group 'feedmail-queue
960 :type 'boolean
c7d4a777 961 )
bd1cd4c2
KH
962
963
964(defcustom feedmail-queue-runner-confirm-global nil
1fc7dabf 965 "If non-nil, give a y-or-n confirmation prompt before running the queue.
bd1cd4c2 966Prompt even if the queue is about to be processed as a result of a call to
27772f10 967`feedmail-run-the-queue-no-prompts'. This gives you a way to bail out
bd1cd4c2
KH
968without having to answer no to the individual message prompts."
969 :group 'feedmail-queue
970 :type 'boolean)
971
972
bd1cd4c2 973(defcustom feedmail-queue-directory
215cda7c 974 (expand-file-name "~/mail/q")
1fc7dabf 975 "Name of a directory where messages will be queued.
bd1cd4c2 976Directory will be created if necessary. Should be a string that
215cda7c 977doesn't end with a slash. Default is \"~/mail/q\"."
bd1cd4c2
KH
978 :group 'feedmail-queue
979 :type 'string
c7d4a777 980 )
bd1cd4c2
KH
981
982
983(defcustom feedmail-queue-draft-directory
215cda7c 984 (expand-file-name "~/mail/draft")
1fc7dabf 985 "Name of a directory where draft messages will be queued.
bd1cd4c2 986Directory will be created if necessary. Should be a string that
215cda7c 987doesn't end with a slash. Default is \"~/mail/draft\"."
bd1cd4c2
KH
988 :group 'feedmail-queue
989 :type 'string
c7d4a777 990 )
bd1cd4c2
KH
991
992
993(defcustom feedmail-ask-before-queue t
1fc7dabf 994 "If non-nil, feedmail will ask what you want to do with the message.
bd1cd4c2
KH
995Default choices for the message action prompt will include sending it
996immediately, putting it in the main queue, putting it in the draft
997queue, or returning to the buffer to continue editing. Only matters if
998queuing is enabled. If nil, the message is placed in the main queue
999without a prompt."
1000 :group 'feedmail-queue
1001 :type 'boolean
c7d4a777 1002 )
bd1cd4c2
KH
1003
1004
1005(defcustom feedmail-ask-before-queue-prompt "FQM: Message action (q, i, d, e, ?)? [%s]: "
1fc7dabf 1006 "A string which will be used for the message action prompt.
bd1cd4c2 1007If it contains a \"%s\", that will be replaced with the value of
27772f10 1008`feedmail-ask-before-queue-default'."
bd1cd4c2
KH
1009 :group 'feedmail-queue
1010 :type 'string
c7d4a777 1011 )
bd1cd4c2
KH
1012
1013
1014(defcustom feedmail-ask-before-queue-reprompt "FQM: Please type q, i, d, or e; or ? for help [%s]: "
1fc7dabf 1015 "A string which will be used for repompting after invalid input.
bd1cd4c2 1016If it contains a \"%s\", that will be replaced with the value of
27772f10 1017`feedmail-ask-before-queue-default'."
bd1cd4c2
KH
1018 :group 'feedmail-queue
1019 :type 'string
c7d4a777 1020 )
bd1cd4c2
KH
1021
1022
1023(defcustom feedmail-ask-before-queue-default "queue"
1fc7dabf 1024 "Meaning if user hits return in response to the message action prompt.
bd1cd4c2
KH
1025Should be a character or a string; if a string, only the first
1026character is significant. Useful values are those described in
1027the help for the message action prompt."
1028 :group 'feedmail-queue
c7d4a777
KH
1029 :type '(choice string integer) ;use integer to get char
1030 )
bd1cd4c2
KH
1031
1032
1033(defvar feedmail-prompt-before-queue-standard-alist
1034 '((?q . feedmail-message-action-queue)
c7d4a777 1035 (?Q . feedmail-message-action-queue-strong)
bd1cd4c2 1036
c7d4a777
KH
1037 (?d . feedmail-message-action-draft)
1038 (?r . feedmail-message-action-draft)
1039 (?D . feedmail-message-action-draft-strong)
1040 (?R . feedmail-message-action-draft-strong)
bd1cd4c2 1041
c7d4a777
KH
1042 (?e . feedmail-message-action-edit)
1043 (?E . feedmail-message-action-edit)
1044 (?\C-g . feedmail-message-action-edit)
1045 (?n . feedmail-message-action-edit)
1046 (?N . feedmail-message-action-edit)
bd1cd4c2 1047
c7d4a777
KH
1048 (?i . feedmail-message-action-send)
1049 (?I . feedmail-message-action-send-strong)
1050 (?s . feedmail-message-action-send)
1051 (?S . feedmail-message-action-send-strong)
bd1cd4c2 1052
c7d4a777 1053 (?* . feedmail-message-action-toggle-spray)
bd1cd4c2 1054
215cda7c
BC
1055 (?> . feedmail-message-action-scroll-up)
1056 (?< . feedmail-message-action-scroll-down)
1057 (? . feedmail-message-action-scroll-up)
1058 ;; (?\C-v . feedmail-message-action-help)
c7d4a777 1059 (?? . feedmail-message-action-help))
bd1cd4c2
KH
1060 "An alist of choices for the message action prompt.
1061All of the values are function names, except help, which is a special
1062symbol that calls up help for the prompt (the help describes the
1063actions from the standard alist). To customize your own choices,
27772f10 1064define a similar alist called `feedmail-prompt-before-queue-user-alist'.
bd1cd4c2
KH
1065The actual alist used for message action will be the standard alist
1066overlaid with the user-alist. To neutralize an item in the standard
1067alist without providing a replacement, define an appropriate element
1068in the user alist with a value of nil." )
1069
1070
1071(defcustom feedmail-prompt-before-queue-user-alist nil
27772f10 1072 "See `feedmail-prompt-before-queue-standard-alist'."
bd1cd4c2 1073 :group 'feedmail-queue
7b3237a1 1074 :type '(repeat (cons character function))
bd1cd4c2
KH
1075 )
1076
1077
1078(defcustom feedmail-prompt-before-queue-help-supplement nil
1079 "User-provided supplementary help string for the message action prompt.
1080When the message action prompt is shown, the user can as for verbose help,
1081at which point a buffer pops up describing the meaning of possible
1082responses to the prompt. Through various customizations (see, for
27772f10 1083example, `feedmail-prompt-before-queue-user-alist'), the available responses
bd1cd4c2
KH
1084and the prompt itself can be changed. If this variable is set to a string
1085value, that string is written to the help buffer after the standard info.
27772f10 1086It may contain embedded line breaks. It will be printed via `princ'."
bd1cd4c2 1087 :group 'feedmail-queue
7b3237a1 1088 :type '(choice (const nil) string)
bd1cd4c2
KH
1089 )
1090
1091
1092(defcustom feedmail-queue-reminder-alist
1093 '((after-immediate . feedmail-queue-reminder-brief)
c7d4a777
KH
1094 (after-queue . feedmail-queue-reminder-medium)
1095 (after-draft . feedmail-queue-reminder-medium)
1096 (after-run . feedmail-queue-reminder-brief)
1097 (on-demand . feedmail-run-the-queue-global-prompt))
27772f10 1098 "See `feedmail-queue-reminder'."
bd1cd4c2 1099 :group 'feedmail-queue
7b3237a1
AS
1100 :type '(repeat (cons (choice :tag "Event"
1101 (const on-demand)
1102 (const after-immediate)
1103 (const after-queue)
1104 (const after-draft)
1105 (const after-run))
1106 function))
bd1cd4c2
KH
1107 )
1108
1109
1110(defcustom feedmail-queue-chatty t
1fc7dabf 1111 "If non-nil, blat a few status messages and such in the mini-buffer.
bd1cd4c2
KH
1112If nil, just do the work and don't pester people about what's going on.
1113In some cases, though, specific options inspire mini-buffer prompting.
1114That's not affected by this variable setting. Also does not control
1115reporting of error/abnormal conditions."
1116 :group 'feedmail-queue
1117 :type 'boolean
c7d4a777 1118 )
bd1cd4c2
KH
1119
1120
1121(defcustom feedmail-queue-chatty-sit-for 2
1fc7dabf 1122 "Duration of pause after most queue-related messages.
bd1cd4c2
KH
1123After some messages are divulged, it is prudent to pause before
1124something else obliterates them. This value controls the duration of
1125the pause."
1126 :group 'feedmail-queue
1127 :type 'integer
c7d4a777 1128 )
bd1cd4c2
KH
1129
1130
1131(defcustom feedmail-queue-run-orderer nil
1fc7dabf 1132 "If non-nil, name a function which will sort the queued messages.
bd1cd4c2
KH
1133The function is called during a running of the queue for sending, and
1134takes one argument, a list of the files in the queue directory. It
1135may contain the names of non-message files, and it's okay to leave
1136them in the list when reordering it; they get skipped over later.
1137When nil, the default action processes the messages in normal sort
1138order by queued file name, which will typically result in the order
1139they were placed in the queue."
1140 :group 'feedmail-queue
1141 :type '(choice (const nil) function)
c7d4a777 1142 )
bd1cd4c2
KH
1143
1144
1145(defcustom feedmail-queue-use-send-time-for-date nil
1fc7dabf 1146 "If non-nil, use send time for the Date: header value.
bd1cd4c2
KH
1147This variable is used by the default date generating function,
1148feedmail-default-date-generator. If nil, the default, the
1149last-modified timestamp of the queue file is used to create the
37aa9115 1150message Date: header; if there is no queue file, the current time is
215cda7c
BC
1151used. If you are using VM, it might be supplying this header for
1152you. To suppress VM's version
1153
1154 (setq vm-mail-header-insert-date nil)"
bd1cd4c2
KH
1155 :group 'feedmail-queue
1156 :type 'boolean
c7d4a777 1157 )
bd1cd4c2
KH
1158
1159
1160(defcustom feedmail-queue-use-send-time-for-message-id nil
1fc7dabf 1161 "If non-nil, use send time for the Message-Id: header value.
37aa9115 1162This variable is used by the default Message-Id: generating function,
27772f10 1163`feedmail-default-message-id-generator'. If nil, the default, the
bd1cd4c2 1164last-modified timestamp of the queue file is used to create the
37aa9115 1165message Message-Id: header; if there is no queue file, the current time is
215cda7c
BC
1166used. If you are using VM, it might be supplying this header for
1167you. To suppress VM's version
1168
1169 (setq vm-mail-header-insert-date nil)"
bd1cd4c2
KH
1170 :group 'feedmail-queue
1171 :type 'boolean
c7d4a777 1172 )
bd1cd4c2
KH
1173
1174
1175(defcustom feedmail-ask-for-queue-slug nil
1fc7dabf 1176 "If non-nil, prompt user for part of the queue file name.
bd1cd4c2
KH
1177The file will automatically get the FQM suffix and an embedded
1178sequence number for uniqueness, so don't specify that. feedmail will
1179get rid of all characters other than alphanumeric and hyphen in the
1180results. If this variable is nil or if you just hit return in
1181response to the prompt, feedmail queuing will take care of things
1182properly. At the prompt, completion is available if you want to see
1183what filenames are already in use, though, as noted, you will not be
1184typing a complete file name. You probably don't want to be bothered
1185with this prompting since feedmail, by default, uses queue file names
1186based on the subjects of the messages."
1187 :group 'feedmail-queue
1188 :type 'boolean
c7d4a777 1189 )
bd1cd4c2
KH
1190
1191
1192(defcustom feedmail-queue-slug-maker 'feedmail-queue-subject-slug-maker
1fc7dabf 1193 "If non-nil, a function which creates part of the queued file name.
bd1cd4c2
KH
1194Takes a single argument giving the name of the directory into
1195which the message will be queued. The returned string should be just
1196the non-directory filename part, without FQM suffix or uniquifying
1197sequence numbers. The current buffer holds the raw message. The
1198default function creates the slug based on the message subject, if
1199any."
1200 :group 'feedmail-queue
1201 :type '(choice (const nil) function)
c7d4a777 1202 )
bd1cd4c2
KH
1203
1204
215cda7c
BC
1205(defcustom feedmail-queue-slug-suspect-regexp "[^a-z0-9-]+"
1206 "Regular expression for characters/substrings to be replaced.
1207When feedmail creates a filename from a subject string, it puts hyphens
1208in place of strings which may cause problems in filenames. By default,
1209only alphanumeric and hyphen characters are kept, and all others are
1210converted. In non-ASCII environments, it may be more helpful to
1211tweak this regular expression to reflect local or personal language
1212conventions. Substitutions are done repeatedly until the regular expression
1213no longer matches to transformed string. Used by function
1214feedmail-tidy-up-slug and indirectly by feedmail-queue-subject-slug-maker."
50b23e5a 1215 :version "24.1"
215cda7c
BC
1216 :group 'feedmail-queue
1217 :type 'string
1218)
1219
1220
bd1cd4c2 1221(defcustom feedmail-queue-default-file-slug t
1fc7dabf 1222 "Indicates what to use for subject-less messages when forming a file name.
0bb37c1a 1223When feedmail queues a message, it creates a unique file name. By default,
bd1cd4c2
KH
1224the file name is based in part on the subject of the message being queued.
1225If there is no subject, consult this variable. See documentation for the
27772f10 1226function `feedmail-queue-subject-slug-maker'.
bd1cd4c2
KH
1227
1228If t, an innocuous default is used.
1229
1230If a string, it is used directly.
1231
1232If a function, it is called with no arguments from the buffer containing the raw
1233text of the message. It must return a string (which may be empty).
1234
1235If the symbol 'ask, you will be prompted for a string in the mini-buffer.
1236Filename completion is available so that you can inspect what's already been
1237used, but feedmail will do further manipulation on the string you return, so
1238it's not expected to be a complete filename."
1239 :group 'feedmail-queue
7b3237a1 1240 :type '(choice (const :tag "Default" t) string function (const ask))
c7d4a777 1241 )
bd1cd4c2
KH
1242
1243
1244(defcustom feedmail-queue-fqm-suffix ".fqm"
1fc7dabf 1245 "The FQM suffix used to distinguish feedmail queued message files.
bd1cd4c2
KH
1246You probably want this to be a period followed by some letters and/or
1247digits. The distinction is to be able to tell them from other random
27772f10
JB
1248files that happen to be in the `feedmail-queue-directory' or
1249`feedmail-queue-draft-directory'. By the way, FQM stands for feedmail
bd1cd4c2
KH
1250queued message."
1251 :group 'feedmail-queue
1252 :type 'string
c7d4a777 1253 )
bd1cd4c2
KH
1254
1255
1256(defcustom feedmail-nuke-buffer-after-queue nil
1fc7dabf 1257 "If non-nil, silently kill the buffer after a message is queued.
bd1cd4c2
KH
1258You might like that since a side-effect of queueing the message is
1259that its buffer name gets changed to the filename. That means that
1260the buffer won't be reused for the next message you compose. If you
1261are using VM for creating messages, you probably want to leave this
1262nil, since VM has its own options for managing the recycling of
1263message buffers."
1264 :group 'feedmail-queue
1265 :type 'boolean
c7d4a777 1266 )
bd1cd4c2
KH
1267
1268
1269(defcustom feedmail-queue-auto-file-nuke nil
1fc7dabf 1270 "If non-nil, automatically delete queue files when a message is sent.
bd1cd4c2
KH
1271Normally, feedmail will notice such files when you send a message in
1272immediate mode (i.e., not when you're running the queue) and will ask if
1273you want to delete them. Since the answer is usually yes, setting this
0bb37c1a 1274variable to non-nil will tell feedmail to skip the prompt and just delete
bd1cd4c2
KH
1275the file without bothering you."
1276 :group 'feedmail-queue
1277 :type 'boolean
c7d4a777 1278 )
bd1cd4c2
KH
1279
1280
215cda7c
BC
1281(defcustom feedmail-debug nil
1282 "If non-nil, blat a debug messages and such in the mini-buffer.
1283This is intended as an aid to tracing what's going on but is probably
1284of casual real use only to the feedmail developer."
50b23e5a 1285 :version "24.1"
215cda7c
BC
1286 :group 'feedmail-debug
1287 :type 'boolean
1288)
1289
1290
1291(defcustom feedmail-debug-sit-for 0
1292 "Duration of pause after feedmail-debug messages.
1293After some messages are divulged, it may be helpful to pause before
1294something else obliterates them. This value controls the duration of
1295the pause. If the value is nil or 0, the sit-for is not done, which
1296has the effect of not pausing at all. Debug messages can be seen after
1297the fact in the messages buffer."
50b23e5a 1298 :version "24.1"
215cda7c
BC
1299 :group 'feedmail-debug
1300 :type 'integer
1301)
1302
1303
1304(defvar feedmail-queue-buffer-file-name nil
1305 "If non-nil, has the value normally expected of 'buffer-file-name'.
1306You are not intended to set this to something in your configuration. Rather,
1307you might programmatically set it to something via a hook or function
1308advice or whatever. You might like to do this if you are using a mail
1309composition program that eventually uses sendmail.el's 'mail-send'
1310function to process the message. If there is a filename associated
1311with the message buffer, 'mail-send' will ask you for confirmation.
1312There's no trivial way to avoid it. It's unwise to just set the value
1313of 'buffer-file-name' to nil because that will defeat feedmail's file
1314management features. Instead, arrange for this variable to be set to
1315the value of 'buffer-file-name' before setting that to nil. An easy way
1316to do that would be with defadvice on 'mail-send' \(undoing the
1317assignments in a later advice\).
1318
1319feedmail will pretend that 'buffer-file-name', if nil, has the value
1320assigned of 'feedmail-queue-buffer-file-name' and carry out its normal
1321activities. feedmail does not restore the non-nil value of
1322'buffer-file-name'. For safe bookkeeping, the user should insure that
1323feedmail-queue-buffer-file-name is restored to nil.
1324
1325Example 'defadvice' for mail-send:
1326
1327 (defadvice mail-send (before feedmail-mail-send-before-advice activate)
1328 (setq feedmail-queue-buffer-file-name buffer-file-name)
1329 (setq buffer-file-name nil))
1330
1331 (defadvice mail-send (after feedmail-mail-send-after-advice activate)
1332 (if feedmail-queue-buffer-file-name (setq buffer-file-name feedmail-queue-buffer-file-name))
1333 (setq feedmail-queue-buffer-file-name nil))
1334")
1335
bd1cd4c2 1336;; defvars to make byte-compiler happy(er)
0bb37c1a
KH
1337(defvar feedmail-error-buffer nil)
1338(defvar feedmail-prepped-text-buffer nil)
1339(defvar feedmail-raw-text-buffer nil)
1340(defvar feedmail-address-list nil)
bd1cd4c2
KH
1341
1342
7163b71c
RS
1343(defvar feedmail-queue-runner-is-active nil
1344 "*Non-nil means we're inside the logic of the queue-running loop.
1345That is, iterating over all messages in the queue to send them. In
1346that case, the value is the name of the queued message file currently
1347being processed. This can be used for differentiating customized code
1348for different scenarios. Users shouldn't set or change this
1349variable, but may depend on its value as described here.")
1350
1351
bd1cd4c2 1352(defun feedmail-mail-send-hook-splitter ()
27772f10
JB
1353 "Facilitate dividing `mail-send-hook' things into queued and immediate cases.
1354If you have `mail-send-hook' functions that should only be called for sending/
bd1cd4c2 1355queueing messages or only be called for the sending of queued messages, this is
27772f10 1356for you. Add this function to `mail-send-hook' with something like this:
bd1cd4c2
KH
1357
1358 (add-hook 'mail-send-hook 'feedmail-mail-send-hook-splitter)
1359
27772f10
JB
1360Then add the functions you want called to either `feedmail-mail-send-hook-queued'
1361or `feedmail-mail-send-hook', as apprpriate. The distinction is that
1362`feedmail-mail-send-hook' will be called when you send mail from a composition
bd1cd4c2 1363buffer (typically by typing C-c C-c), whether the message is sent immediately
27772f10 1364or placed in the queue or drafts directory. `feedmail-mail-send-hook-queued' is
bd1cd4c2 1365called when messages are being sent from the queue directory, typically via a
27772f10 1366call to `feedmail-run-the-queue'."
215cda7c 1367 (feedmail-say-debug ">in-> feedmail-mail-send-hook-splitter %s" feedmail-queue-runner-is-active)
bd1cd4c2 1368 (if feedmail-queue-runner-is-active
c7d4a777
KH
1369 (run-hooks 'feedmail-mail-send-hook-queued)
1370 (run-hooks 'feedmail-mail-send-hook))
1371 )
bd1cd4c2
KH
1372
1373
1374(defvar feedmail-mail-send-hook nil
27772f10 1375 "*See documentation for `feedmail-mail-send-hook-splitter'.")
bd1cd4c2
KH
1376
1377
1378(defvar feedmail-mail-send-hook-queued nil
27772f10 1379 "*See documentation for `feedmail-mail-send-hook-splitter'.")
bd1cd4c2
KH
1380
1381
1382(defun feedmail-confirm-addresses-hook-example ()
27772f10 1383 "An example of a `feedmail-last-chance-hook'.
bd1cd4c2
KH
1384It shows the simple addresses and gets a confirmation. Use as:
1385 (setq feedmail-last-chance-hook 'feedmail-confirm-addresses-hook-example)."
1386 (save-window-excursion
c7d4a777
KH
1387 (display-buffer (set-buffer (get-buffer-create " F-C-A-H-E")))
1388 (erase-buffer)
1389 (insert (mapconcat 'identity feedmail-address-list " "))
1390 (if (not (y-or-n-p "How do you like them apples? "))
1391 (error "FQM: Sending...gave up in last chance hook")
1392 )))
bd1cd4c2
KH
1393
1394
1395(defcustom feedmail-last-chance-hook nil
1fc7dabf 1396 "User's last opportunity to modify the message on its way out.
215cda7c
BC
1397When this hook runs, the current buffer is already the appropriate
1398buffer. It has already had all the header prepping from the standard
1399package. The next step after running the hook will be to save the
1400message via FCC: processing. The hook might be interested in these:
1401\(1) `feedmail-prepped-text-buffer' contains the header and body of the
1402message, ready to go; (2) `feedmail-address-list' contains a list
bd1cd4c2 1403of simplified recipients of addresses which are to be given to the
27772f10 1404subprocess (the hook may change the list); (3) `feedmail-error-buffer'
bd1cd4c2
KH
1405is an empty buffer intended to soak up errors for display to the user.
1406If the hook allows interactive activity, the user should not send more
1407mail while in the hook since some of the internal buffers will be
215cda7c
BC
1408reused and things will get confused. It's not necessary to
1409arrange for the undoing of any changes you make to the buffer."
bd1cd4c2
KH
1410 :group 'feedmail-misc
1411 :type 'hook
c7d4a777 1412 )
bd1cd4c2 1413
215cda7c
BC
1414(defcustom feedmail-queue-express-hook nil
1415 "Chance to modify a message being sent directly to a queue.
1416Run by feedmail-queue-express-to-queue and feedmail-queue-express-to-draft.
1417For example, you might want to run vm-mime-encode-composition to take
1418care of attachments. If you subsequently edit the message buffer, you
1419can undo the encoding."
50b23e5a 1420 :version "24.1"
215cda7c
BC
1421 :group 'feedmail-queue
1422 :type 'hook
1423)
bd1cd4c2
KH
1424
1425(defcustom feedmail-before-fcc-hook nil
1fc7dabf 1426 "User's last opportunity to modify the message before Fcc action.
bd1cd4c2
KH
1427It has already had all the header prepping from the standard package.
1428The next step after running the hook will be to save the message via
37aa9115 1429Fcc: processing. The hook might be interested in these: (1)
27772f10
JB
1430`feedmail-prepped-text-buffer' contains the header and body of the
1431message, ready to go; (2) `feedmail-address-list' contains a list of
bd1cd4c2 1432simplified recipients of addressees to whom the message was sent (3)
27772f10 1433`feedmail-error-buffer' is an empty buffer intended to soak up errors
bd1cd4c2
KH
1434for display to the user. If the hook allows interactive activity, the
1435user should not send more mail while in the hook since some of the
1436internal buffers will be reused and things will get confused."
1437 :group 'feedmail-misc
1438 :type 'hook
c7d4a777 1439 )
bd1cd4c2
KH
1440
1441(defcustom feedmail-queue-runner-mode-setter
1442 '(lambda (&optional arg) (mail-mode))
1fc7dabf 1443 "A function to set the proper mode of a message file.
0bb37c1a 1444Called when the message is read back out of the queue directory with a single
bd1cd4c2 1445argument, the optional argument used in the call to
27772f10 1446`feedmail-run-the-queue' or `feedmail-run-the-queue-no-prompts'.
bd1cd4c2 1447
0bb37c1a 1448Most people want `mail-mode', so the default value is an anonymous
bd1cd4c2
KH
1449function which is just a wrapper to ignore the supplied argument when
1450calling it, but here's your chance to have something different.
215cda7c
BC
1451If you are a VM user, you might like feedmail-vm-mail-mode, though you
1452really don't need that (and it's not particularly well-tested).
1453
0bb37c1a 1454Called with funcall, not `call-interactively'."
bd1cd4c2
KH
1455 :group 'feedmail-queue
1456 :type 'function
c7d4a777 1457 )
bd1cd4c2
KH
1458
1459
1460(defcustom feedmail-queue-alternative-mail-header-separator nil
1fc7dabf 1461 "Alternative header demarcation for queued messages.
0bb37c1a 1462If you sometimes get alternative values for `mail-header-separator' in
bd1cd4c2 1463queued messages, set the value of this variable to whatever it is.
0bb37c1a 1464For example, `rmail-resend' uses a `mail-header-separator' value of empty
bd1cd4c2
KH
1465string (\"\") when you send/queue a message.
1466
1467When trying to send a queued message, if the value of this variable is
1468non-nil, feedmail will first try to send the message using the value
0bb37c1a
KH
1469of `mail-header-separator'. If it can't find that, it will temporarily
1470set `mail-header-separator' to the value of
27772f10 1471`feedmail-queue-alternative-mail-header-separator' and try again."
bd1cd4c2 1472 :group 'feedmail-queue
7b3237a1 1473 :type '(choice (const nil) string)
c7d4a777 1474 )
bd1cd4c2
KH
1475
1476
215cda7c
BC
1477(defcustom feedmail-queue-runner-message-sender
1478 '(lambda (&optional arg) (mail-send))
1fc7dabf 1479 "Function to initiate sending a message file.
bd1cd4c2
KH
1480Called for each message read back out of the queue directory with a
1481single argument, the optional argument used in the call to
27772f10 1482`feedmail-run-the-queue' or `feedmail-run-the-queue-no-prompts'.
215cda7c
BC
1483Interactively, that argument will be the prefix argument.
1484Most people want `mail-send' (bound to C-c C-s in mail-mode), but here's
1485your chance to have something different. The default value is just a
1486wrapper function which discards the optional argument and calls
1487mail-send. If you are a VM user, you might like vm-mail-send, though
1488you really don't need that. Called with funcall, not call-interactively."
50b23e5a 1489 :version "24.1" ; changed default
bd1cd4c2
KH
1490 :group 'feedmail-queue
1491 :type 'function
c7d4a777 1492 )
bd1cd4c2
KH
1493
1494
1495(defcustom feedmail-queue-runner-cleaner-upper
1496 '(lambda (fqm-file &optional arg)
c7d4a777 1497 (delete-file fqm-file)
215cda7c 1498 (if arg (feedmail-say-chatter "Nuked %s" fqm-file)))
1fc7dabf 1499 "Function that will be called after a message has been sent.
0bb37c1a
KH
1500Not called in the case of errors. This function is called with two
1501arguments: the name of the message queue file for the message just sent,
1502and the optional argument used in the call to `feedmail-run-the-queue'
1503or `feedmail-run-the-queue-no-prompts' (prefix arg if interactive).
1504In any case, the affiliated buffer is killed elsewhere, so don't do that
bd1cd4c2
KH
1505inside this function. Return value is ignored.
1506
1507The default action is an anonymous function which gets rid of the file
1508from the queue directory. With a non-nil second argument, a brief
1509message is give for each file deleted. You could replace this
1510function, for example, to archive all of your sent messages someplace
0bb37c1a 1511\(though there are better ways to get that particular result\)."
bd1cd4c2
KH
1512 :group 'feedmail-queue
1513 :type 'function
c7d4a777 1514 )
bd1cd4c2
KH
1515
1516
bd1cd4c2 1517(defvar feedmail-is-a-resend nil
110c171f 1518 "*Non-nil means the message is a Resend (in the RFC-822 sense).
bd1cd4c2
KH
1519This affects the composition of certain headers. feedmail sets this
1520variable as soon as it starts prepping the message text buffer, so any
1521user-supplied functions can rely on it. Users shouldn't set or change this
1522variable, but may depend on its value as described here.")
1523
1524
1525(defcustom feedmail-buffer-eating-function 'feedmail-buffer-to-binmail
1fc7dabf 1526 "Function used to send the prepped buffer to a subprocess.
bd1cd4c2
KH
1527The function's three (mandatory) arguments are: (1) the buffer
1528containing the prepped message; (2) a buffer where errors should be
1529directed; and (3) a list containing the addresses individually as
215cda7c
BC
1530strings. Popular choices for this are `feedmail-buffer-to-binmail',
1531`feedmail-buffer-to-smtpmail', `feedmail-buffer-to-sendmail', and
1532`feedmail-buffer-to-smtp'. If you use the sendmail form, you probably
1533want to set `feedmail-nuke-bcc' and/or `feedmail-nuke-resent-bcc to nil'.
1534If you use the binmail form, check the value of `feedmail-binmail-template'."
bd1cd4c2
KH
1535 :group 'feedmail-misc
1536 :type 'function
c7d4a777 1537 )
bd1cd4c2 1538
50b23e5a 1539(defconst feedmail-binmail-gnulinuxish-template
215cda7c
BC
1540 (concat
1541 "(echo From "
1542 (if (boundp 'user-login-name) user-login-name "feedmail")
1543 " ; cat -) | /usr/bin/rmail %s")
50b23e5a 1544 "Good candidate for GNU/Linux systems and maybe others.
215cda7c
BC
1545You may need to modify this if your \"rmail\" is in a different place.
1546For example, I hear that in some Debian systems, it's /usr/sbin/rmail.
1547See feedmail-binmail-template documentation."
1548 )
bd1cd4c2 1549
215cda7c
BC
1550(defcustom feedmail-binmail-template (if mail-interactive "/bin/mail %s"
1551 (if (file-exists-p "/bin/rmail")
1552 "/bin/rmail %s" "/bin/mail %s"))
1fc7dabf 1553 "Command template for the subprocess which will get rid of the mail.
bd1cd4c2 1554It can result in any command understandable by /bin/sh. Might not
215cda7c 1555work at all in non-UNIX environments. The single '%s', if present,
bd1cd4c2 1556gets replaced by the space-separated, simplified list of addressees.
27772f10 1557Used in `feedmail-buffer-to-binmail' to form the shell command which
215cda7c
BC
1558will receive the contents of the prepped buffer as stdin. The default
1559value uses /bin/rmail (if it exists) unless `mail-interactive' has been
1560set non-nil.
1561
1562If you'd like your errors to come back as mail instead of immediately
1563in a buffer, try /bin/rmail instead of /bin/mail. If /bin/rmail
1564exists, this can be accomplished by keeping the default nil setting of
1565`mail-interactive'. You might also like to consult local mail experts
1566for any other interesting command line possibilities. Some versions
1567of UNIX have an rmail program which behaves differently than
1568/bin/rmail and complains if feedmail gives it a message on stdin. If
1569you don't know about such things and if there is no local expert to
1570consult, stick with /bin/mail or use one of the other buffer eating
1571functions.
1572
1573The above description applies to \"classic\" UNIX /bin/mail and /bin/rmail.
50b23e5a 1574On most GNU/Linux systems and perhaps other places, /bin/mail behaves
215cda7c
BC
1575completely differently and shouldn't be used at all in this template.
1576Instead of /bin/rmail, there is a /usr/bin/rmail, and it can be used
1577with a wrapper. The wrapper is necessary because /usr/bin/rmail on such
1578systems requires that the first line of the message appearing on standard
1579input have a UNIX-style From_ postmark. If you have such a system, the
1580wrapping can be accomplished by setting the value of `feedmail-binmail-template'
50b23e5a 1581to `feedmail-binmail-gnulinuxish-template'. You should then send some test
215cda7c 1582messages to make sure it works as expected."
50b23e5a
GM
1583 :version "24.1" ; changed default
1584 :group 'feedmail-misc
1585 :type 'string
c7d4a777 1586 )
bd1cd4c2
KH
1587
1588
1589;; feedmail-buffer-to-binmail, feedmail-buffer-to-sendmail, and
1590;; feedmail-buffer-to-smptmail are the only things provided for values
1591;; for the variable feedmail-buffer-eating-function. It's pretty easy
1592;; to write your own, though.
1593(defun feedmail-buffer-to-binmail (prepped errors-to addr-listoid)
1594 "Function which actually calls /bin/mail as a subprocess.
1595Feeds the buffer to it."
215cda7c 1596 (feedmail-say-debug ">in-> feedmail-buffer-to-binmail %s" addr-listoid)
bd1cd4c2
KH
1597 (set-buffer prepped)
1598 (apply
1599 'call-process-region
1600 (append (list (point-min) (point-max) "/bin/sh" nil errors-to nil "-c"
c7d4a777
KH
1601 (format feedmail-binmail-template
1602 (mapconcat 'identity addr-listoid " "))))))
bd1cd4c2
KH
1603
1604
5237a44f
GM
1605(defvar sendmail-program)
1606
bd1cd4c2
KH
1607(defun feedmail-buffer-to-sendmail (prepped errors-to addr-listoid)
1608 "Function which actually calls sendmail as a subprocess.
37aa9115 1609Feeds the buffer to it. Probably has some flaws for Resent-* and other
215cda7c
BC
1610complicated cases. Takes addresses from message headers and
1611might disappoint you with BCC: handling. In case of odd results, consult
1612local gurus."
5237a44f 1613 (require 'sendmail)
215cda7c 1614 (feedmail-say-debug ">in-> feedmail-buffer-to-sendmail %s" addr-listoid)
bd1cd4c2
KH
1615 (set-buffer prepped)
1616 (apply 'call-process-region
5237a44f 1617 (append (list (point-min) (point-max) sendmail-program
c7d4a777
KH
1618 nil errors-to nil "-oi" "-t")
1619 ;; provide envelope "from" to sendmail; results will vary
215cda7c
BC
1620 (if feedmail-sendmail-f-doesnt-sell-me-out
1621 (list "-f" user-mail-address))
c7d4a777
KH
1622 ;; These mean "report errors by mail" and "deliver in background".
1623 (if (null mail-interactive) '("-oem" "-odb")))))
bd1cd4c2
KH
1624
1625;; provided by jam@austin.asc.slb.com (James A. McLaughlin);
1626;; simplified by WJC after more feedmail development;
1627;; idea (but not implementation) of copying smtpmail trace buffer to
1628;; feedmail error buffer from:
1629;; Mon 14-Oct-1996; Douglas Gray Stephens
1630;; modified to insert error for displaying
1631(defun feedmail-buffer-to-smtpmail (prepped errors-to addr-listoid)
49267116 1632 "Function which actually calls `smtpmail-via-smtp' to send buffer as e-mail."
bd1cd4c2
KH
1633 ;; I'm not sure smtpmail.el is careful about the following
1634 ;; return value, but it also uses it internally, so I will fear
1635 ;; no evil.
215cda7c 1636 (feedmail-say-debug ">in-> feedmail-buffer-to-smtpmail %s" addr-listoid)
bd1cd4c2
KH
1637 (require 'smtpmail)
1638 (if (not (smtpmail-via-smtp addr-listoid prepped))
c7d4a777
KH
1639 (progn
1640 (set-buffer errors-to)
1641 (insert "Send via smtpmail failed. Probable SMTP protocol error.\n")
1642 (insert "Look for details below or in the *Messages* buffer.\n\n")
1643 (let ((case-fold-search t)
1644 ;; don't be overconfident about the name of the trace buffer
1645 (tracer (concat "trace.*smtp.*" (regexp-quote smtpmail-smtp-server))))
1646 (mapcar
1647 '(lambda (buffy)
1648 (if (string-match tracer (buffer-name buffy))
1649 (progn
1650 (insert "SMTP Trace from " (buffer-name buffy) "\n---------------")
bf714905 1651 (insert-buffer-substring buffy)
c7d4a777
KH
1652 (insert "\n\n"))))
1653 (buffer-list))))))
bd1cd4c2 1654
50b23e5a
GM
1655(declare-function smtp-via-smtp "ext:smtp" (sender recipients smtp-text-buffer))
1656(defvar smtp-server)
1657
215cda7c
BC
1658;; FLIM's smtp.el pointed out to me by Kenichi Handa <handa@etl.go.jp>
1659(defun feedmail-buffer-to-smtp (prepped errors-to addr-listoid)
1660 "Function which actually calls smtp-via-smtp to send buffer as e-mail."
1661 (feedmail-say-debug ">in-> feedmail-buffer-to-smtp %s" addr-listoid)
1662 (require 'smtp)
1663 (if (not (smtp-via-smtp user-mail-address addr-listoid prepped))
1664 (progn
1665 (set-buffer errors-to)
1666 (insert "Send via smtp failed. Probable SMTP protocol error.\n")
1667 (insert "Look for details below or in the *Messages* buffer.\n\n")
1668 (let ((case-fold-search t)
1669 ;; don't be overconfident about the name of the trace buffer
1670 (tracer (concat "trace.*smtp.*" (regexp-quote smtp-server))))
1671 (mapcar
1672 '(lambda (buffy)
1673 (if (string-match tracer (buffer-name buffy))
1674 (progn
1675 (insert "SMTP Trace from " (buffer-name buffy) "\n---------------")
50b23e5a 1676 (insert-buffer-substring buffy)
215cda7c
BC
1677 (insert "\n\n"))))
1678 (buffer-list))))))
bd1cd4c2
KH
1679
1680;; just a place to park a docstring
1681(defconst feedmail-fiddle-plex-blurb nil
0bb37c1a 1682 "A fiddle-plex is a concise way of specifying header field fiddling.
bd1cd4c2
KH
1683It is a list of up to 4 elements: NAME, VALUE, ACTION, FOLDING. The element
1684VALUE can also be a list sometimes.
1685
0bb37c1a
KH
1686NAME is the name of the header field to be fiddled with. Although case
1687doesn't matter in looking for headers, case of NAME is preserved when a header
1688is inserted via fiddling. It shouldn't include the trailing colon.
bd1cd4c2
KH
1689
1690VALUE is either nil, a simple string, a function returning nil or a string, or,
0bb37c1a 1691as described below for ACTION `combine', a list of up to three values.
bd1cd4c2
KH
1692
1693ACTION describes the nature of the fiddling to be done. Possibilities
0bb37c1a 1694for ACTION (default is `supplement'):
bd1cd4c2 1695
0bb37c1a 1696 `supplement' Leave other like fields as-is, insert this one.
bd1cd4c2 1697
0bb37c1a 1698 `replace' Delete other like fields, if any, and insert this one.
bd1cd4c2 1699
0bb37c1a 1700 `create' Insert this one only if no like field exists.
bd1cd4c2 1701
0bb37c1a 1702 `combine' Combine aggregate values of like fields with this one.
bd1cd4c2
KH
1703 In this case, VALUE has a special form. It is a list
1704 of three items: VAL-PRE, VAL-LIKE, and VAL-POST.
1705 VAL-PRE and VAL-POST are strings or nil. VAL-LIKE may
1706 be either a string or a function (it may also be nil,
1707 but there's not much point to that).
1708
1709 Values of like header fields are aggregated, leading and
1710 trailing whitespace is removed, and embedded
1711 whitespace is left as-is. If there are no like
1712 fields, or the aggregate value is an empty string,
1713 VAL-LIKE is not used. Else, if VAL-LIKE is a function,
1714 it is called with two arguments: NAME and the
0bb37c1a 1715 aggregate like values. Else, if VAL-LIKE is a string, it is
bd1cd4c2
KH
1716 used as a format string where a single \%s will be
1717 replaced by the aggregate values of like fields.
1718
1719 VAL-PRE, the results of using VAL-LIKE, and VAL-POST
1720 are concatenated, and the result, if not nil and not
1721 an empty string, is used as the new value for the
1722 field. Although this description sounds a bit
1723 complicated, the idea is to provide a mechanism for
1724 combining the old value with a new value in a flexible
1725 way. For example, if you wanted to add a new value to
1726 an existing header field by adding a semi-colon and
1727 then starting the new value on a continuation line,
1728 you might specify this:
1729
1730 (nil \"%s;\\n\\t\" \"This is my new value\")
1731
1732FOLDING can be nil, in which case VALUE is used as-is. If FOLDING is
1733non-nil, feedmail \"smart filling\" is done on VALUE just before
0bb37c1a 1734insertion.")
bd1cd4c2 1735
215cda7c
BC
1736(defun feedmail-vm-mail-mode (&optional arg)
1737 "Make something like a buffer that has been created via `vm-mail'.
1738The optional argument is ignored and is just for argument compatibility with
1739`feedmail-queue-runner-mode-setter'. This function is suitable for being
1740applied to a file after you've just read it from disk: for example, a
1741feedmail FQM message file from a queue. You could use something like
1742this:
1743
1744\(setq auto-mode-alist \(cons \'\(\"\\\\.fqm$\" . feedmail-vm-mail-mode\) auto-mode-alist\)\)
1745"
1746 (feedmail-say-debug ">in-> feedmail-vm-mail-mode")
1747 (let ((the-buf (current-buffer)))
1748 (vm-mail)
1749 (delete-region (point-min) (point-max))
50b23e5a 1750 (insert-buffer-substring the-buf)
215cda7c
BC
1751 (setq buffer-file-name (buffer-file-name the-buf))
1752 (set-buffer-modified-p (buffer-modified-p the-buf))
1753 ;; For some versions of emacs, saving the message to a queue
1754 ;; triggers running the mode function on the buffer, and that
1755 ;; leads (through a series of events I don't really understand)
1756 ;; to this function being called while the buffer is still
1757 ;; marked modified even though it is in the process of being
1758 ;; saved. I guess the function gets called during the renaming
1759 ;; that takes place en route to the save.
1760 ;;
1761 ;; This clearing of the marker probably wastes a buffer copy
1762 ;; but it's easy to do and more reliable than figuring out what
1763 ;; each variant of emacs does in this strange case.
1764 (with-current-buffer the-buf
1765 (set-buffer-modified-p nil))
1766 (kill-buffer the-buf)
1767 ))
1768
49267116 1769;;;###autoload
bd1cd4c2 1770(defun feedmail-send-it ()
fc066c54
DL
1771 "Send the current mail buffer using the Feedmail package.
1772This is a suitable value for `send-mail-function'. It can be used
1773with various lower-level mechanisms to provide features such as queueing."
215cda7c
BC
1774 (feedmail-say-debug ">in-> feedmail-send-it")
1775 (save-excursion
1776 (let ((bfn-jiggle nil))
1777 ;; if buffer-file-name is nil, temporarily use the stashed value
1778 (if (and (not buffer-file-name) feedmail-queue-buffer-file-name)
1779 (setq buffer-file-name feedmail-queue-buffer-file-name
1780 bfn-jiggle t))
bd1cd4c2
KH
1781 ;; avoid matching trouble over slash vs backslash by getting canonical
1782 (if feedmail-queue-directory
c7d4a777 1783 (setq feedmail-queue-directory (expand-file-name feedmail-queue-directory)))
bd1cd4c2 1784 (if feedmail-queue-draft-directory
c7d4a777 1785 (setq feedmail-queue-draft-directory (expand-file-name feedmail-queue-draft-directory)))
215cda7c 1786 (if (not feedmail-enable-queue) (feedmail-send-it-immediately-wrapper)
c7d4a777
KH
1787 ;; else, queuing is enabled, should we ask about it or just do it?
1788 (if feedmail-ask-before-queue
1789 (funcall (feedmail-queue-send-edit-prompt))
215cda7c
BC
1790 (feedmail-dump-message-to-queue feedmail-queue-directory 'after-queue)))
1791 ;; put this back
1792 (if bfn-jiggle (setq feedmail-queue-buffer-file-name buffer-file-name))
1793 )))
bd1cd4c2
KH
1794
1795(defun feedmail-message-action-send ()
1796 ;; hooks can make this take a while so clear the prompt
215cda7c 1797 (feedmail-say-debug ">in-> feedmail-message-action-send")
bd1cd4c2 1798 (message "FQM: Immediate send...")
215cda7c 1799 (feedmail-send-it-immediately-wrapper))
bd1cd4c2
KH
1800
1801
1802;; From a VM mailing list discussion and some suggestions from Samuel Mikes <smikes@alumni.hmc.edu>
1803(defun feedmail-queue-express-to-queue ()
1fc7dabf 1804 "Send message directly to the queue, with a minimum of fuss and bother."
bd1cd4c2 1805 (interactive)
215cda7c
BC
1806 (feedmail-say-debug ">in-> feedmail-queue-express-to-queue")
1807 (run-hooks 'feedmail-queue-express-hook)
bd1cd4c2 1808 (let ((feedmail-enable-queue t)
c7d4a777
KH
1809 (feedmail-ask-before-queue nil)
1810 (feedmail-queue-reminder-alist nil)
1811 (feedmail-queue-chatty-sit-for 0))
1812 (feedmail-send-it)
1813 )
1814 )
bd1cd4c2
KH
1815
1816
1817(defun feedmail-queue-express-to-draft ()
1fc7dabf 1818 "Send message directly to the draft queue, with a minimum of fuss and bother."
bd1cd4c2 1819 (interactive)
215cda7c 1820 (feedmail-say-debug ">in-> feedmail-queue-express-to-draft")
bd1cd4c2 1821 (let ((feedmail-queue-directory feedmail-queue-draft-directory))
c7d4a777
KH
1822 (feedmail-queue-express-to-queue)
1823 )
1824 )
bd1cd4c2
KH
1825
1826
1827(defun feedmail-message-action-send-strong ()
215cda7c 1828 (feedmail-say-debug ">in-> feedmail-message-action-send-strong")
bd1cd4c2
KH
1829 (let ((feedmail-confirm-outgoing nil)) (feedmail-message-action-send)))
1830
1831
1832(defun feedmail-message-action-edit ()
215cda7c 1833 (feedmail-say-debug ">in-> feedmail-message-action-edit")
bd1cd4c2
KH
1834 (error "FQM: Message not queued; returning to edit"))
1835
1836
1837(defun feedmail-message-action-draft ()
215cda7c 1838 (feedmail-say-debug ">in-> feedmail-message-action-draft")
bd1cd4c2
KH
1839 (feedmail-dump-message-to-queue feedmail-queue-draft-directory 'after-draft))
1840
1841
1842(defun feedmail-message-action-draft-strong ()
215cda7c 1843 (feedmail-say-debug ">in-> feedmail-message-action-draft-strong")
bd1cd4c2 1844 (let ((buffer-file-name nil))
c7d4a777 1845 (feedmail-message-action-draft)))
bd1cd4c2
KH
1846
1847
1848(defun feedmail-message-action-queue ()
215cda7c 1849 (feedmail-say-debug ">in-> feedmail-message-action-queue")
bd1cd4c2
KH
1850 (feedmail-dump-message-to-queue feedmail-queue-directory 'after-queue))
1851
1852
1853(defun feedmail-message-action-queue-strong ()
215cda7c 1854 (feedmail-say-debug ">in-> feedmail-message-action-queue-strong")
bd1cd4c2 1855 (let ((buffer-file-name nil))
c7d4a777 1856 (feedmail-message-action-queue)))
bd1cd4c2
KH
1857
1858
1859(defun feedmail-message-action-toggle-spray ()
215cda7c 1860 (feedmail-say-debug ">in-> feedmail-message-action-toggle-spray")
bd1cd4c2 1861 (let ((feedmail-enable-spray (not feedmail-enable-spray)))
c7d4a777
KH
1862 (if feedmail-enable-spray
1863 (message "FQM: For this message, spray toggled ON")
1864 (message "FQM: For this message, spray toggled OFF"))
1865 (sit-for 3)
1866 ;; recursion, but harmless
1867 (feedmail-send-it)))
bd1cd4c2
KH
1868
1869
215cda7c
BC
1870(defconst feedmail-p-h-b-n "*FQM Help*")
1871
bd1cd4c2 1872(defun feedmail-message-action-help ()
215cda7c
BC
1873 (feedmail-say-debug ">in-> feedmail-message-action-help")
1874 (let ((d-string " ")
1875 (fqm-help (get-buffer feedmail-p-h-b-n)))
c7d4a777
KH
1876 (if (stringp feedmail-ask-before-queue-default)
1877 (setq d-string feedmail-ask-before-queue-default)
1878 (setq d-string (char-to-string feedmail-ask-before-queue-default)))
215cda7c
BC
1879 (if (and fqm-help (get-buffer-window fqm-help))
1880 (feedmail-scroll-buffer 'up fqm-help)
1881 (feedmail-message-action-help-blat d-string))
c7d4a777
KH
1882 ;; recursive, but no worries (it goes deeper on user action)
1883 (feedmail-send-it)))
bd1cd4c2 1884
215cda7c
BC
1885(defun feedmail-message-action-help-blat (d-string)
1886 (feedmail-say-debug ">in-> feedmail-message-action-help-blat")
1887 (with-output-to-temp-buffer feedmail-p-h-b-n
1888 (princ "You're dispatching a message and feedmail queuing is enabled.
1889Typing ? again will normally scroll this help buffer.
1890
1891Choices:
1892 q QUEUE for later sending \(via feedmail-run-the-queue\)
1893 Q QUEUE! like \"q\", but always make a new file
1894 i IMMEDIATELY send this \(but not the other queued messages\)
1895 I IMMEDIATELY! like \"i\", but skip following confirmation prompt
1896 d DRAFT queue in the draft directory
1897 D DRAFT! like \"d\", but always make a new file
1898 e EDIT return to the message edit buffer \(don't send or queue\)
1899 * SPRAY toggle spray mode \(individual message transmissions\)
1900 > SCROLL UP scroll message up \(toward end of message\)
1901 < SCROLL DOWN scroll message down \(toward beginning of message\)
1902 ? HELP show or scroll this help buffer
1903
1904Synonyms:
1905 s SEND immediately \(same as \"i\"\)
1906 S SEND! immediately \(same as \"I\"\)
1907 r ROUGH draft \(same as \"d\"\)
1908 R ROUGH! draft \(same as \"D\"\)
1909 n NOPE didn't mean it \(same as \"e\"\)
1910 y YUP do the default behavior \(same as \"C-m\"\)
1911 SPC SCROLL UP \(same as \">\"\)
1912
1913The user-configurable default is currently \"")
1914 (princ d-string)
1915 (princ "\". For other possibilities,
1916see the variable feedmail-prompt-before-queue-user-alist.
1917")
1918 (and (stringp feedmail-prompt-before-queue-help-supplement)
1919 (princ feedmail-prompt-before-queue-help-supplement))
1920 (with-current-buffer standard-output
1921 (if (fboundp 'help-mode) (help-mode)))))
1922
1923
1924(defun feedmail-message-action-scroll-up ()
1925 (feedmail-say-debug ">in-> feedmail-message-action-scroll-up")
1926 (feedmail-scroll-buffer 'up)
1927 ;; recursive, but no worries (it goes deeper on user action)
1928 (feedmail-send-it))
1929
1930
1931(defun feedmail-message-action-scroll-down ()
1932 (feedmail-say-debug ">in-> feedmail-message-action-scroll-down")
1933 (feedmail-scroll-buffer 'down)
1934 ;; recursive, but no worries (it goes deeper on user action)
1935 (feedmail-send-it))
1936
bd1cd4c2
KH
1937
1938;;;###autoload
1939(defun feedmail-run-the-queue-no-prompts (&optional arg)
27772f10 1940 "Like `feedmail-run-the-queue', but suppress confirmation prompts."
bd1cd4c2 1941 (interactive "p")
215cda7c 1942 (feedmail-say-debug ">in-> feedmail-run-the-queue-no-prompts")
bd1cd4c2
KH
1943 (let ((feedmail-confirm-outgoing nil)) (feedmail-run-the-queue arg)))
1944
1945;;;###autoload
1946(defun feedmail-run-the-queue-global-prompt (&optional arg)
27772f10 1947 "Like `feedmail-run-the-queue', but with a global confirmation prompt.
0bb37c1a 1948This is generally most useful if run non-interactively, since you can
bd1cd4c2
KH
1949bail out with an appropriate answer to the global confirmation prompt."
1950 (interactive "p")
215cda7c 1951 (feedmail-say-debug ">in-> feedmail-run-the-queue-global-prompts")
bd1cd4c2
KH
1952 (let ((feedmail-queue-runner-confirm-global t)) (feedmail-run-the-queue arg)))
1953
8c3ee88c
GM
1954;; letf fools the byte-compiler.
1955(defvar file-name-buffer-file-type-alist)
1956
bd1cd4c2
KH
1957;;;###autoload
1958(defun feedmail-run-the-queue (&optional arg)
1959 "Visit each message in the feedmail queue directory and send it out.
1960Return value is a list of three things: number of messages sent, number of
1961messages skipped, and number of non-message things in the queue (commonly
1962backup file names and the like)."
1963 (interactive "p")
215cda7c 1964 (feedmail-say-debug ">in-> feedmail-run-the-queue")
bd1cd4c2
KH
1965 ;; avoid matching trouble over slash vs backslash by getting canonical
1966 (if feedmail-queue-directory
c7d4a777 1967 (setq feedmail-queue-directory (expand-file-name feedmail-queue-directory)))
bd1cd4c2 1968 (if feedmail-queue-draft-directory
c7d4a777 1969 (setq feedmail-queue-draft-directory (expand-file-name feedmail-queue-draft-directory)))
bd1cd4c2 1970 (let* ((maybe-file)
c7d4a777
KH
1971 (qlist (feedmail-look-at-queue-directory feedmail-queue-directory))
1972 (dlist (feedmail-look-at-queue-directory feedmail-queue-draft-directory))
1973 (q-cnt (nth 0 qlist))
1974 (q-oth (nth 1 qlist))
1975 (d-cnt (nth 0 dlist))
1976 (d-oth (nth 1 dlist))
1977 (messages-sent 0)
1978 (messages-skipped 0)
1979 (blobby-buffer)
1980 (already-buffer)
c7d4a777
KH
1981 (do-the-run t)
1982 (list-of-possible-fqms))
1983 (if (and (> q-cnt 0) feedmail-queue-runner-confirm-global)
1984 (setq do-the-run
1985 (if (fboundp 'y-or-n-p-with-timeout)
1986 (y-or-n-p-with-timeout (format "FQM: Draft: %dm+%d, Queue: %dm+%d; run the queue? "
1987 d-cnt d-oth q-cnt q-oth)
1988 5 nil)
1989 (y-or-n-p (format "FQM: Draft: %dm+%d, Queue: %dm+%d; run the queue? "
1990 d-cnt d-oth q-cnt q-oth))
1991 )))
1992 (if (not do-the-run)
1993 (setq messages-skipped q-cnt)
1994 (save-window-excursion
1995 (setq list-of-possible-fqms (directory-files feedmail-queue-directory t))
1996 (if feedmail-queue-run-orderer
1997 (setq list-of-possible-fqms (funcall feedmail-queue-run-orderer list-of-possible-fqms)))
3d3cfc90 1998 (mapc
c7d4a777
KH
1999 '(lambda (blobby)
2000 (setq maybe-file (expand-file-name blobby feedmail-queue-directory))
2001 (cond
2002 ((file-directory-p maybe-file) nil) ; don't care about subdirs
2003 ((feedmail-fqm-p blobby)
2004 (setq blobby-buffer (generate-new-buffer (concat "FQM " blobby)))
2005 (setq already-buffer
2006 (if (fboundp 'find-buffer-visiting) ; missing from XEmacs
2007 (find-buffer-visiting maybe-file)
2008 (get-file-buffer maybe-file)))
2009 (if (and already-buffer (buffer-modified-p already-buffer))
2010 (save-window-excursion
2011 (display-buffer (set-buffer already-buffer))
2012 (if (fboundp 'y-or-n-p-with-timeout)
2013 ;; make a guess that the user just forgot to save
2014 (if (y-or-n-p-with-timeout (format "FQM: Visiting %s; save before send? " blobby) 10 t)
2015 (save-buffer))
2016 (if (y-or-n-p (format "FQM: Visiting %s; save before send? " blobby))
2017 (save-buffer))
2018 )))
2019
2020 (set-buffer blobby-buffer)
2021 (setq buffer-offer-save nil)
2022 (buffer-disable-undo blobby-buffer)
2023 (insert-file-contents-literally maybe-file)
215cda7c
BC
2024 (setq buffer-file-type t) ; binary
2025 (goto-char (point-min))
2026 ;; if at least two line-endings with CRLF, translate the file
2027 (if (looking-at ".*\r\n.*\r\n")
2028 (while (search-forward "\r\n" nil t)
2029 (replace-match "\n" nil t)))
2030;; ;; work around text-vs-binary wierdness
2031;; ;; if we don't find the normal M-H-S, try reading the file a different way
2032;; (if (not (feedmail-find-eoh t))
2033;; (let ((file-name-buffer-file-type-alist nil) (default-buffer-file-type nil))
2034;; (erase-buffer)
2035;; (insert-file-contents maybe-file)))
c7d4a777 2036 (funcall feedmail-queue-runner-mode-setter arg)
215cda7c 2037 (condition-case signal-stuff ; don't give up the loop if user skips some
c7d4a777 2038 (let ((feedmail-enable-queue nil)
c7d4a777 2039 (feedmail-queue-runner-is-active maybe-file))
215cda7c
BC
2040 ;; if can't find EOH, this is no message!
2041 (unless (feedmail-find-eoh t)
2042 (feedmail-say-chatter "Skipping %s; no mail-header-separator" maybe-file)
2043 (error "FQM: you should never see this message"))
2044 (feedmail-say-debug "Prepping %s" maybe-file)
2045 ;; the catch is a way out for users to voluntarily skip sending a message
2046 (catch 'skip-me-q (funcall feedmail-queue-runner-message-sender arg))
c7d4a777
KH
2047 (set-buffer blobby-buffer)
2048 (if (buffer-modified-p) ; still modified, means wasn't sent
215cda7c
BC
2049 (progn
2050 (setq messages-skipped (1+ messages-skipped))
2051 (feedmail-say-chatter "%s wasn't sent by %s" maybe-file feedmail-buffer-eating-function))
c7d4a777
KH
2052 (setq messages-sent (1+ messages-sent))
2053 (funcall feedmail-queue-runner-cleaner-upper maybe-file arg)
2054 (if (and already-buffer (not (file-exists-p maybe-file)))
2055 ;; we have gotten rid of the file associated with the
2056 ;; buffer, so update the buffer's notion of that
937e6a56 2057 (with-current-buffer already-buffer
c7d4a777 2058 (setq buffer-file-name nil)))))
215cda7c
BC
2059 ;; the handler for the condition-case
2060 (error (setq messages-skipped (1+ messages-skipped))
2061 (ding t)
2062 (message "FQM: Trapped '%s', message left in queue." (car signal-stuff))
2063 (sit-for 3)
2064 (message "FQM: Trap details: \"%s\""
2065 (mapconcat 'identity (cdr signal-stuff) "\" \""))
2066 (sit-for 3)))
c7d4a777 2067 (kill-buffer blobby-buffer)
215cda7c
BC
2068 (feedmail-say-chatter
2069 "%d to go, %d sent, %d skipped (%d other files ignored)"
2070 (- q-cnt messages-sent messages-skipped)
2071 messages-sent messages-skipped q-oth)
2072 )))
c7d4a777
KH
2073 list-of-possible-fqms)))
2074 (if feedmail-queue-chatty
2075 (progn
215cda7c
BC
2076 (feedmail-say-chatter "%d sent, %d skipped (%d other files ignored)"
2077 messages-sent messages-skipped q-oth)
c7d4a777
KH
2078 (feedmail-queue-reminder 'after-run)
2079 (sit-for feedmail-queue-chatty-sit-for)))
2080 (list messages-sent messages-skipped q-oth)))
bd1cd4c2
KH
2081
2082
2083;;;###autoload
2084(defun feedmail-queue-reminder (&optional what-event)
2085 "Perform some kind of reminder activity about queued and draft messages.
2086Called with an optional symbol argument which says what kind of event
2087is triggering the reminder activity. The default is 'on-demand, which
27772f10 2088is what you typically would use if you were putting this in your Emacs start-up
bd1cd4c2
KH
2089or mail hook code. Other recognized values for WHAT-EVENT (these are passed
2090internally by feedmail):
2091
2092 after-immediate (a message has just been sent in immediate mode)
2093 after-queue (a message has just been queued)
2094 after-draft (a message has just been placed in the draft directory)
2095 after-run (the queue has just been run, possibly sending messages)
2096
27772f10 2097WHAT-EVENT is used as a key into the table `feedmail-queue-reminder-alist'. If
bd1cd4c2 2098the associated value is a function, it is called without arguments and is expected
0bb37c1a 2099to perform the reminder activity. You can supply your own reminder functions
27772f10
JB
2100by redefining `feedmail-queue-reminder-alist'. If you don't want any reminders,
2101you can set `feedmail-queue-reminder-alist' to nil."
bd1cd4c2 2102 (interactive "p")
215cda7c 2103 (feedmail-say-debug ">in-> feedmail-queue-reminder %s" what-event)
bd1cd4c2 2104 (let ((key (if (and what-event (symbolp what-event)) what-event 'on-demand)) entry reminder)
c7d4a777
KH
2105 (setq entry (assoc key feedmail-queue-reminder-alist))
2106 (setq reminder (cdr entry))
2107 (if (fboundp reminder) (funcall reminder)))
bd1cd4c2
KH
2108 )
2109
2110
2111(defun feedmail-queue-reminder-brief ()
215cda7c 2112 "Brief display of draft and queued message counts in minibuffer."
bd1cd4c2 2113 (interactive)
215cda7c 2114 (feedmail-say-debug ">in-> feedmail-queue-reminder-brief")
bd1cd4c2 2115 (let (q-cnt d-cnt q-lis d-lis)
c7d4a777
KH
2116 (setq q-lis (feedmail-look-at-queue-directory feedmail-queue-directory))
2117 (setq d-lis (feedmail-look-at-queue-directory feedmail-queue-draft-directory))
2118 (setq q-cnt (car q-lis))
2119 (setq d-cnt (car d-lis))
2120 (if (or (> q-cnt 0) (> d-cnt 0))
2121 (progn
2122 (message "FQM: [D: %d, Q: %d]" d-cnt q-cnt))))
bd1cd4c2
KH
2123 )
2124
2125
2126(defun feedmail-queue-reminder-medium ()
215cda7c 2127 "Verbose display of draft and queued message counts in minibuffer."
bd1cd4c2 2128 (interactive)
215cda7c 2129 (feedmail-say-debug ">in-> feedmail-queue-reminder-medium")
bd1cd4c2 2130 (let (q-cnt d-cnt q-oth d-oth q-lis d-lis)
c7d4a777
KH
2131 (setq q-lis (feedmail-look-at-queue-directory feedmail-queue-directory))
2132 (setq d-lis (feedmail-look-at-queue-directory feedmail-queue-draft-directory))
2133 (setq q-cnt (car q-lis))
2134 (setq d-cnt (car d-lis))
2135 (setq q-oth (nth 1 q-lis))
2136 (setq d-oth (nth 1 d-lis))
2137 (if (or (> q-cnt 0) (> d-cnt 0))
2138 (progn
2139 (message "FQM: Draft: %dm+%d in \"%s\", Queue: %dm+%d in \"%s\""
2140 d-cnt d-oth (file-name-nondirectory feedmail-queue-draft-directory)
2141 q-cnt q-oth (file-name-nondirectory feedmail-queue-directory)))))
bd1cd4c2
KH
2142 )
2143
2144
2145(defun feedmail-queue-send-edit-prompt ()
215cda7c
BC
2146 "Ask whether to queue, send immediately, or return to editing a message, etc."
2147 (feedmail-say-debug ">in-> feedmail-queue-send-edit-prompt")
2148 (feedmail-queue-send-edit-prompt-inner
2149 feedmail-ask-before-queue-default
2150 feedmail-ask-before-queue-prompt
2151 feedmail-ask-before-queue-reprompt
2152 'feedmail-message-action-help
2153 feedmail-prompt-before-queue-standard-alist
2154 feedmail-prompt-before-queue-user-alist
2155 ))
2156
2157(defun feedmail-queue-runner-prompt ()
2158 "Ask whether to queue, send immediately, or return to editing a message, etc."
2159 (feedmail-say-debug ">in-> feedmail-queue-runner-prompt")
2160 (feedmail-queue-send-edit-prompt-inner
2161 feedmail-ask-before-queue-default
2162 feedmail-ask-before-queue-prompt
2163 feedmail-ask-before-queue-reprompt
2164 'feedmail-message-action-help
2165 feedmail-prompt-before-queue-standard-alist
2166 feedmail-prompt-before-queue-user-alist
2167 ))
2168(defun feedmail-queue-send-edit-prompt-inner (default prompt reprompt helper
2169 standard-alist user-alist)
2170 (feedmail-say-debug ">in-> feedmail-queue-send-edit-prompt-inner")
bd1cd4c2 2171 ;; Some implementation ideas here came from the userlock.el code
215cda7c 2172 (or defining-kbd-macro (discard-input))
bd1cd4c2 2173 (save-window-excursion
c7d4a777 2174 (let ((answer) (d-char) (d-string " "))
215cda7c 2175 (if (stringp default)
c7d4a777 2176 (progn
215cda7c
BC
2177 (setq d-char (string-to-char default)
2178 d-string default))
2179 (setq d-string (char-to-string default))
2180 (setq d-char default)
c7d4a777 2181 )
bd1cd4c2 2182 (while (null answer)
215cda7c 2183 (message prompt d-string)
c7d4a777
KH
2184 (let ((user-sez
2185 (let ((inhibit-quit t) (cursor-in-echo-area t) (echo-keystrokes 0))
2186 (read-char-exclusive))))
2187 (if (= user-sez help-char)
215cda7c 2188 (setq answer '(^ . helper))
c7d4a777
KH
2189 (if (or (eq user-sez ?\C-m) (eq user-sez ?\C-j) (eq user-sez ?y))
2190 (setq user-sez d-char))
2191 ;; these char-to-int things are because of some
2192 ;; incomprensible difference between the two in
2193 ;; byte-compiled stuff between Emacs and XEmacs
2194 ;; (well, I'm sure someone could comprehend it,
2195 ;; but I say 'uncle')
215cda7c 2196 (setq answer (or (assoc user-sez user-alist)
c7d4a777 2197 (and (fboundp 'char-to-int)
215cda7c
BC
2198 (assoc (char-to-int user-sez) user-alist))
2199 (assoc user-sez standard-alist)
c7d4a777 2200 (and (fboundp 'char-to-int)
215cda7c 2201 (assoc (char-to-int user-sez) standard-alist))))
c7d4a777
KH
2202 (if (or (null answer) (null (cdr answer)))
2203 (progn
2204 (beep)
215cda7c 2205 (message reprompt d-string)
c7d4a777
KH
2206 (sit-for 3)))
2207 )))
2208 (cdr answer)
2209 )))
bd1cd4c2 2210
215cda7c 2211(defun feedmail-scroll-buffer (direction &optional buffy)
bd1cd4c2 2212 ;; scrolling fun
215cda7c
BC
2213 ;; emacs convention is that scroll-up moves text up, window down
2214 (feedmail-say-debug ">in-> feedmail-scroll-buffer %s" direction)
bd1cd4c2 2215 (save-selected-window
c7d4a777 2216 (let ((signal-error-on-buffer-boundary nil)
215cda7c 2217 (fqm-window (display-buffer (if buffy buffy (current-buffer)))))
c7d4a777 2218 (select-window fqm-window)
215cda7c 2219 (if (eq direction 'up)
c7d4a777 2220 (if (pos-visible-in-window-p (point-max) fqm-window)
215cda7c
BC
2221 ;; originally just (goto-char (point-min)), but
2222 ;; pos-visible-in-window-p seems oblivious to that
2223 (scroll-down 999999)
2224 (scroll-up))
2225 (if (pos-visible-in-window-p (point-min) fqm-window)
2226 (scroll-up 999999)
2227 (scroll-down))))))
bd1cd4c2 2228
bd1cd4c2
KH
2229
2230(defun feedmail-look-at-queue-directory (queue-directory)
2231 "Find out some things about a queue directory.
2232Result is a list containing a count of queued messages in the
2233directory, a count of other files in the directory, and a high water
2234mark for prefix sequence numbers. Subdirectories are not included in
2235the counts."
215cda7c 2236 (feedmail-say-debug ">in-> feedmail-look-at-queue-directory %s" queue-directory)
bd1cd4c2 2237 (let ((q-cnt 0) (q-oth 0) (high-water 0) (blobbet))
c7d4a777
KH
2238 ;; iterate, counting things we find along the way in the directory
2239 (if (file-directory-p queue-directory)
3d3cfc90 2240 (mapc
c7d4a777
KH
2241 '(lambda (blobby)
2242 (cond
2243 ((file-directory-p blobby) nil) ; don't care about subdirs
2244 ((feedmail-fqm-p blobby)
2245 (setq blobbet (file-name-nondirectory blobby))
2246 (if (string-match "^[0-9][0-9][0-9]-" blobbet)
2247 (let ((water-mark))
027a4b6b 2248 (setq water-mark (string-to-number (substring blobbet 0 3)))
c7d4a777
KH
2249 (if (> water-mark high-water) (setq high-water water-mark))))
2250 (setq q-cnt (1+ q-cnt)))
2251 (t (setq q-oth (1+ q-oth)))
2252 ))
2253 (directory-files queue-directory t)))
2254 (list q-cnt q-oth high-water)))
bd1cd4c2
KH
2255
2256(defun feedmail-tidy-up-slug (slug)
0bb37c1a 2257 "Utility for mapping out suspect characters in a potential filename."
215cda7c 2258 (feedmail-say-debug ">in-> feedmail-tidy-up-slug %s" slug)
bd1cd4c2
KH
2259 ;; even programmers deserve a break sometimes, so cover nil for them
2260 (if (null slug) (setq slug ""))
2261 ;; replace all non-alphanumerics with hyphen for safety
215cda7c 2262 (while (string-match feedmail-queue-slug-suspect-regexp slug) (setq slug (replace-match "-" nil nil slug)))
bd1cd4c2
KH
2263 ;; collapse multiple hyphens to one
2264 (while (string-match "--+" slug) (setq slug (replace-match "-" nil nil slug)))
2265 ;; for tidyness, peel off leading hyphens
2266 (if (string-match "^-*" slug) (setq slug (replace-match "" nil nil slug)))
2267 ;; for tidyness, peel off trailing hyphens
2268 (if (string-match "-*$" slug) (setq slug (replace-match "" nil nil slug)))
2269 slug
c7d4a777 2270 )
bd1cd4c2
KH
2271
2272(defun feedmail-queue-subject-slug-maker (&optional queue-directory)
2273 "Create a name for storing the message in the queue.
2274Optional argument QUEUE-DIRECTORY specifies into which directory the
37aa9115 2275file will be placed. The name is based on the Subject: header (if
bd1cd4c2 2276there is one). If there is no subject,
27772f10 2277`feedmail-queue-default-file-slug' is consulted. Special characters are
bd1cd4c2 2278mapped to mostly alphanumerics for safety."
215cda7c 2279 (feedmail-say-debug ">in-> feedmail-queue-subject-slug-maker %s" queue-directory)
bd1cd4c2 2280 (let ((eoh-marker) (case-fold-search t) (subject "") (s-point))
c7d4a777
KH
2281 (setq eoh-marker (feedmail-find-eoh))
2282 (goto-char (point-min))
2283 ;; get raw subject value (first line, anyhow)
37aa9115 2284 (if (re-search-forward "^Subject:" eoh-marker t)
c7d4a777
KH
2285 (progn (setq s-point (point))
2286 (end-of-line)
215cda7c 2287 (setq subject (buffer-substring-no-properties s-point (point)))))
c7d4a777
KH
2288 (setq subject (feedmail-tidy-up-slug subject))
2289 (if (zerop (length subject))
2290 (setq subject
2291 (cond
2292 ((stringp feedmail-queue-default-file-slug) feedmail-queue-default-file-slug)
2293 ((fboundp feedmail-queue-default-file-slug)
2294 (save-excursion (funcall feedmail-queue-default-file-slug)))
2295 ((eq feedmail-queue-default-file-slug 'ask)
2296 (file-name-nondirectory
2297 (read-file-name "FQM: Message filename slug? "
2298 (file-name-as-directory queue-directory) subject nil subject)))
2299 (t "no subject"))
2300 ))
2301 ;; one more time, with feeling
2302 (feedmail-tidy-up-slug subject)
2303 ))
bd1cd4c2
KH
2304
2305
2306(defun feedmail-create-queue-filename (queue-directory)
215cda7c 2307 (feedmail-say-debug ">in-> feedmail-create-queue-filename %s" queue-directory)
bd1cd4c2 2308 (let ((slug "wjc"))
c7d4a777
KH
2309 (cond
2310 (feedmail-queue-slug-maker
2311 (save-excursion (setq slug (funcall feedmail-queue-slug-maker queue-directory))))
2312 (feedmail-ask-for-queue-slug
2313 (setq slug (file-name-nondirectory
2314 (read-file-name (concat "FQM: Message filename slug? [" slug "]? ")
2315 (file-name-as-directory queue-directory) slug nil slug))))
2316 )
2317 (setq slug (feedmail-tidy-up-slug slug))
2318 (setq slug (format "%03d-%s" (1+ (nth 2 (feedmail-look-at-queue-directory queue-directory))) slug))
2319 (concat
2320 (expand-file-name slug queue-directory)
2321 feedmail-queue-fqm-suffix)
2322 ))
bd1cd4c2
KH
2323
2324
2325(defun feedmail-dump-message-to-queue (queue-directory what-event)
215cda7c 2326 (feedmail-say-debug ">in-> feedmail-dump-message-to-queue %s %s" queue-directory what-event)
bd1cd4c2 2327 (or (file-accessible-directory-p queue-directory)
c7d4a777
KH
2328 ;; progn to get nil result no matter what
2329 (progn (make-directory queue-directory t) nil)
2330 (file-accessible-directory-p queue-directory)
a867ead0 2331 (error "FQM: Message not queued; trouble with directory %s" queue-directory))
bd1cd4c2 2332 (let ((filename)
c7d4a777
KH
2333 (is-fqm)
2334 (is-in-this-dir)
2335 (previous-buffer-file-name buffer-file-name))
2336 (if buffer-file-name
2337 (progn
2338 (setq is-fqm (feedmail-fqm-p buffer-file-name))
2339 (setq is-in-this-dir (string-equal
215cda7c
BC
2340 (directory-file-name
2341 (expand-file-name queue-directory))
c7d4a777
KH
2342 (directory-file-name (expand-file-name (file-name-directory buffer-file-name)))))))
2343 ;; if visiting a queued message, just save
2344 (if (and is-fqm is-in-this-dir)
2345 (setq filename buffer-file-name)
2346 (setq filename (feedmail-create-queue-filename queue-directory)))
2347 ;; make binary file on DOS/Win95/WinNT, etc
705e5bd9
SM
2348 (let ((buffer-file-type feedmail-force-binary-write))
2349 (write-file filename))
c7d4a777
KH
2350 ;; convenient for moving from draft to q, for example
2351 (if (and previous-buffer-file-name (or (not is-fqm) (not is-in-this-dir))
215cda7c
BC
2352 (let (d b s)
2353 (setq b (file-name-nondirectory previous-buffer-file-name))
2354 (setq d (file-name-directory previous-buffer-file-name))
2355 (setq s (substring d (1- (length d))))
2356 (setq d (substring d 0 (1- (length d))))
2357 (setq d (file-name-nondirectory d))
2358 (y-or-n-p (format "FQM: Was previously %s%s%s; delete that? "
2359 d s b))))
c7d4a777
KH
2360 (delete-file previous-buffer-file-name))
2361 (if feedmail-nuke-buffer-after-queue
2362 (let ((a-s-file-name buffer-auto-save-file-name))
2363 ;; be aggressive in nuking auto-save files
2364 (and (kill-buffer (current-buffer))
2365 delete-auto-save-files
2366 (file-exists-p a-s-file-name)
2367 (delete-file a-s-file-name))))
215cda7c 2368 (feedmail-say-chatter "Queued in %s" filename)
c7d4a777
KH
2369 (if feedmail-queue-chatty
2370 (progn
2371 (feedmail-queue-reminder what-event)
2372 (sit-for feedmail-queue-chatty-sit-for)))))
bd1cd4c2
KH
2373
2374
2375;; from a similar function in mail-utils.el
2376(defun feedmail-rfc822-time-zone (time)
215cda7c 2377 (feedmail-say-debug ">in-> feedmail-rfc822-time-zone %s" time)
bd1cd4c2 2378 (let* ((sec (or (car (current-time-zone time)) 0))
c7d4a777 2379 (absmin (/ (abs sec) 60)))
bd1cd4c2
KH
2380 (format "%c%02d%02d" (if (< sec 0) ?- ?+) (/ absmin 60) (% absmin 60))))
2381
2382(defun feedmail-rfc822-date (arg-time)
215cda7c
BC
2383 (feedmail-say-debug ">in-> feedmail-rfc822-date %s" arg-time)
2384 (let ((time (if arg-time arg-time (current-time)))
2385 (system-time-locale "C"))
c7d4a777
KH
2386 (concat
2387 (format-time-string "%a, %e %b %Y %T " time)
2388 (feedmail-rfc822-time-zone time)
2389 )))
bd1cd4c2 2390
215cda7c
BC
2391(defun feedmail-send-it-immediately-wrapper ()
2392 "Wrapper to catch skip-me-i"
2393 (if (eq 'skip-me-i (catch 'skip-me-i (feedmail-send-it-immediately)))
2394 (error "FQM: Sending...abandoned!")))
2395
8c0171c0 2396(declare-function expand-mail-aliases "mailalias" (beg end &optional exclude))
bd1cd4c2
KH
2397
2398(defun feedmail-send-it-immediately ()
2399 "Handle immediate sending, including during a queue run."
215cda7c
BC
2400 (feedmail-say-debug ">in-> feedmail-send-it-immediately")
2401 (let ((feedmail-error-buffer (get-buffer-create " *FQM Outgoing Email Errors*"))
2402 (feedmail-prepped-text-buffer (get-buffer-create " *FQM Outgoing Email Text*"))
2403 (feedmail-raw-text-buffer (current-buffer))
2404 (feedmail-address-list)
2405 (eoh-marker)
2406 (bcc-holder)
2407 (resent-bcc-holder)
2408 (a-re-rtcb "^Resent-\\(To\\|Cc\\|Bcc\\):")
2409 (a-re-rtc "^Resent-\\(To\\|Cc\\):")
2410 (a-re-rb "^Resent-Bcc:")
2411 (a-re-dtcb "^\\(To\\|Cc\\|Bcc\\):")
2412 (a-re-dtc "^\\(To\\|Cc\\):")
2413 (a-re-db "^Bcc:")
2414 ;; to get a temporary changable copy
2415 (mail-header-separator mail-header-separator)
2416 )
bd1cd4c2 2417 (unwind-protect
937e6a56 2418 (save-current-buffer
c7d4a777
KH
2419 (set-buffer feedmail-error-buffer) (erase-buffer)
2420 (set-buffer feedmail-prepped-text-buffer) (erase-buffer)
2421
2422 ;; jam contents of user-supplied mail buffer into our scratch buffer
bf714905 2423 (insert-buffer-substring feedmail-raw-text-buffer)
c7d4a777
KH
2424
2425 ;; require one newline at the end.
2426 (goto-char (point-max))
2427 (or (= (preceding-char) ?\n) (insert ?\n))
2428
2429 (let ((case-fold-search nil))
2430 ;; Change header-delimiter to be what mailers expect (empty line).
2431 ;; leaves match data in place or signals error
215cda7c
BC
2432 (feedmail-say-debug "looking for m-h-s \"%s\""
2433 mail-header-separator)
c7d4a777 2434 (setq eoh-marker (feedmail-find-eoh))
215cda7c
BC
2435 (feedmail-say-debug "found m-h-s %s" eoh-marker)
2436 (setq mail-header-separator "")
2437 (replace-match ""))
2438;; (replace-match "\\1")) ;; might be empty or "\r"
c7d4a777
KH
2439
2440 ;; mail-aliases nil = mail-abbrevs.el
215cda7c 2441 (feedmail-say-debug "expanding mail aliases")
c7d4a777
KH
2442 (if (or feedmail-force-expand-mail-aliases
2443 (and (fboundp 'expand-mail-aliases) mail-aliases))
2444 (expand-mail-aliases (point-min) eoh-marker))
2445
2446 ;; make it pretty
2447 (if feedmail-fill-to-cc (feedmail-fill-to-cc-function eoh-marker))
2448 ;; ignore any blank lines in the header
2449 (goto-char (point-min))
2450 (while (and (re-search-forward "\n\n\n*" eoh-marker t) (< (point) eoh-marker))
2451 (replace-match "\n"))
2452
2453 (let ((case-fold-search t) (addr-regexp))
2454 (goto-char (point-min))
2455 ;; there are some RFC-822 combinations/cases missed here,
2456 ;; but probably good enough and what users expect
2457 ;;
2458 ;; use resent-* stuff only if there is at least one non-empty one
2459 (setq feedmail-is-a-resend
2460 (re-search-forward
2461 ;; header name, followed by optional whitespace, followed by
2462 ;; non-whitespace, followed by anything, followed by newline;
37aa9115
KH
2463 ;; the idea is empty Resent-* headers are ignored
2464 "^\\(Resent-To:\\|Resent-Cc:\\|Resent-Bcc:\\)\\s-*\\S-+.*$"
c7d4a777 2465 eoh-marker t))
37aa9115 2466 ;; if we say so, gather the Bcc stuff before the main course
c7d4a777
KH
2467 (if (eq feedmail-deduce-bcc-where 'first)
2468 (progn (if feedmail-is-a-resend (setq addr-regexp a-re-rb) (setq addr-regexp a-re-db))
2469 (setq feedmail-address-list (feedmail-deduce-address-list feedmail-prepped-text-buffer (point-min) eoh-marker addr-regexp feedmail-address-list))))
2470 ;; the main course
2471 (if (or (eq feedmail-deduce-bcc-where 'first) (eq feedmail-deduce-bcc-where 'last))
37aa9115 2472 ;; handled by first or last cases, so don't get Bcc stuff
c7d4a777
KH
2473 (progn (if feedmail-is-a-resend (setq addr-regexp a-re-rtc) (setq addr-regexp a-re-dtc))
2474 (setq feedmail-address-list (feedmail-deduce-address-list feedmail-prepped-text-buffer (point-min) eoh-marker addr-regexp feedmail-address-list)))
37aa9115 2475 ;; not handled by first or last cases, so also get Bcc stuff
c7d4a777
KH
2476 (progn (if feedmail-is-a-resend (setq addr-regexp a-re-rtcb) (setq addr-regexp a-re-dtcb))
2477 (setq feedmail-address-list (feedmail-deduce-address-list feedmail-prepped-text-buffer (point-min) eoh-marker addr-regexp feedmail-address-list))))
37aa9115 2478 ;; if we say so, gather the Bcc stuff after the main course
c7d4a777
KH
2479 (if (eq feedmail-deduce-bcc-where 'last)
2480 (progn (if feedmail-is-a-resend (setq addr-regexp a-re-rb) (setq addr-regexp a-re-db))
2481 (setq feedmail-address-list (feedmail-deduce-address-list feedmail-prepped-text-buffer (point-min) eoh-marker addr-regexp feedmail-address-list))))
2482 (if (not feedmail-address-list) (error "FQM: Sending...abandoned, no addressees"))
2483 ;; not needed, but meets user expectations
2484 (setq feedmail-address-list (nreverse feedmail-address-list))
37aa9115
KH
2485 ;; Find and handle any Bcc fields.
2486 (setq bcc-holder (feedmail-accume-n-nuke-header eoh-marker "^Bcc:"))
2487 (setq resent-bcc-holder (feedmail-accume-n-nuke-header eoh-marker "^Resent-Bcc:"))
c7d4a777
KH
2488 (if (and bcc-holder (not feedmail-nuke-bcc))
2489 (progn (goto-char (point-min))
2490 (insert bcc-holder)))
2491 (if (and resent-bcc-holder (not feedmail-nuke-resent-bcc))
2492 (progn (goto-char (point-min))
2493 (insert resent-bcc-holder)))
2494 (goto-char (point-min))
2495
2496 ;; fiddle about, fiddle about, fiddle about....
2497 (feedmail-fiddle-from)
2498 (feedmail-fiddle-sender)
2499 (feedmail-fiddle-x-mailer)
2500 (feedmail-fiddle-message-id
2501 (or feedmail-queue-runner-is-active (buffer-file-name feedmail-raw-text-buffer)))
2502 (feedmail-fiddle-date
2503 (or feedmail-queue-runner-is-active (buffer-file-name feedmail-raw-text-buffer)))
2504 (feedmail-fiddle-list-of-fiddle-plexes feedmail-fiddle-plex-user-list)
2505
2506 ;; don't send out a blank headers of various sorts
2507 ;; (this loses on continued line with a blank first line)
2508 (goto-char (point-min))
2509 (and feedmail-nuke-empty-headers ; hey, who's an empty-header?
2510 (while (re-search-forward "^[A-Za-z0-9-]+:[ \t]*\n" eoh-marker t)
2511 (replace-match ""))))
2512
215cda7c 2513 (feedmail-say-debug "last chance hook: %s" feedmail-last-chance-hook)
c7d4a777
KH
2514 (run-hooks 'feedmail-last-chance-hook)
2515
215cda7c 2516 (save-window-excursion
37aa9115 2517 (let ((fcc (feedmail-accume-n-nuke-header eoh-marker "^Fcc:"))
c7d4a777
KH
2518 (also-file)
2519 (confirm (cond
2520 ((eq feedmail-confirm-outgoing 'immediate)
2521 (not feedmail-queue-runner-is-active))
2522 ((eq feedmail-confirm-outgoing 'queued) feedmail-queue-runner-is-active)
215cda7c
BC
2523 (t feedmail-confirm-outgoing)))
2524 (fullframe (cond
2525 ((eq feedmail-display-full-frame 'immediate)
2526 (not feedmail-queue-runner-is-active))
2527 ((eq feedmail-display-full-frame 'queued) feedmail-queue-runner-is-active)
2528 (t feedmail-display-full-frame))))
2529 (if fullframe
2530 (progn
2531 (switch-to-buffer feedmail-prepped-text-buffer t)
2532 (delete-other-windows)))
c7d4a777
KH
2533 (if (or (not confirm) (feedmail-one-last-look feedmail-prepped-text-buffer))
2534 (let ((user-mail-address (feedmail-envelope-deducer eoh-marker)))
215cda7c 2535 (feedmail-say-debug "give it to buffer-eater")
c7d4a777 2536 (feedmail-give-it-to-buffer-eater)
215cda7c 2537 (feedmail-say-debug "gave it to buffer-eater")
c7d4a777
KH
2538 (if (and (not feedmail-queue-runner-is-active) (setq also-file (buffer-file-name feedmail-raw-text-buffer)))
2539 (progn ; if a file but not running the queue, offer to delete it
2540 (setq also-file (expand-file-name also-file))
937e6a56
SM
2541 (when (or feedmail-queue-auto-file-nuke
2542 (y-or-n-p
2543 (format "FQM: Delete message file %s? "
2544 also-file)))
2545 ;; if we delete the affiliated file, get rid
2546 ;; of the file name association and make sure we
2547 ;; don't annoy people with a prompt on exit
2548 (delete-file also-file)
2549 (with-current-buffer feedmail-raw-text-buffer
2550 (setq buffer-offer-save nil)
2551 (setq buffer-file-name nil)))))
bd1cd4c2 2552 (goto-char (point-min))
37aa9115 2553 ;; re-insert and handle any Fcc fields (and, optionally, any Bcc).
705e5bd9
SM
2554 (if fcc (letf (((default-value 'buffer-file-type)
2555 feedmail-force-binary-write))
c7d4a777
KH
2556 (insert fcc)
2557 (if (not feedmail-nuke-bcc-in-fcc)
2558 (progn (if bcc-holder (insert bcc-holder))
2559 (if resent-bcc-holder (insert resent-bcc-holder))))
2560
2561 (run-hooks 'feedmail-before-fcc-hook)
2562
2563 (if feedmail-nuke-body-in-fcc
2564 (progn (goto-char eoh-marker)
2565 (if (natnump feedmail-nuke-body-in-fcc)
2566 (forward-line feedmail-nuke-body-in-fcc))
2567 (delete-region (point) (point-max))
2568 ))
2569 (mail-do-fcc eoh-marker)
2570 )))
215cda7c
BC
2571 ;; user bailed out of one-last-look
2572 (if feedmail-queue-runner-is-active
2573 (throw 'skip-me-q 'skip-me-q)
2574 (throw 'skip-me-i 'skip-me-i))
2575 )))) ; unwind-protect body (save-excursion)
c7d4a777
KH
2576
2577 ;; unwind-protect cleanup forms
2578 (kill-buffer feedmail-prepped-text-buffer)
2579 (set-buffer feedmail-error-buffer)
2580 (if (zerop (buffer-size)) (kill-buffer feedmail-error-buffer)
2581 (progn (display-buffer feedmail-error-buffer)
2582 ;; read fast ... the meter is running
215cda7c
BC
2583 (if feedmail-queue-runner-is-active
2584 (progn
2585 (ding t)
2586 (feedmail-say-chatter "Sending...failed")))
c7d4a777
KH
2587 (error "FQM: Sending...failed")))
2588 (set-buffer feedmail-raw-text-buffer))
2589 ) ; let
bd1cd4c2 2590 (if (and feedmail-queue-chatty (not feedmail-queue-runner-is-active))
c7d4a777
KH
2591 (progn
2592 (feedmail-queue-reminder 'after-immediate)
2593 (sit-for feedmail-queue-chatty-sit-for)))
bd1cd4c2
KH
2594 )
2595
2596
2597(defun feedmail-fiddle-header (name value &optional action folding)
2598 "Internal feedmail function for jamming fields into message header.
2599NAME, VALUE, ACTION, and FOLDING are the four elements of a
2600fiddle-plex, as described in the documentation for the variable
27772f10 2601`feedmail-fiddle-plex-blurb'."
215cda7c
BC
2602 (feedmail-say-debug ">in-> feedmail-fiddle-header %s %s %s %s"
2603 name value action folding)
bd1cd4c2 2604 (let ((case-fold-search t)
c7d4a777
KH
2605 (header-colon (concat (regexp-quote name) ":"))
2606 header-regexp eoh-marker has-like ag-like val-like that-point)
2607 (setq header-regexp (concat "^" header-colon))
2608 (setq eoh-marker (feedmail-find-eoh))
2609 (goto-char (point-min))
2610 (setq has-like (re-search-forward header-regexp eoh-marker t))
2611
2612 (if (not action) (setq action 'supplement))
2613 (cond
2614 ((eq action 'supplement)
2615 ;; trim leading/trailing whitespace
2616 (if (string-match "\\`[ \t\n]+" value)
2617 (setq value (substring value (match-end 0))))
2618 (if (string-match "[ \t\n]+\\'" value)
2619 (setq value (substring value 0 (match-beginning 0))))
2620 (if (> (length value) 0)
2621 (progn
2622 (if feedmail-fiddle-headers-upwardly
2623 (goto-char (point-min))
2624 (goto-char eoh-marker))
2625 (setq that-point (point))
2626 (insert name ": " value "\n")
2627 (if folding (feedmail-fill-this-one that-point (point))))))
2628
2629 ((eq action 'replace)
2630 (if has-like (feedmail-accume-n-nuke-header eoh-marker header-regexp))
2631 (feedmail-fiddle-header name value 'supplement folding))
2632
2633 ((eq action 'create)
2634 (if (not has-like) (feedmail-fiddle-header name value 'supplement folding)))
2635
2636 ((eq action 'combine)
2637 (setq val-like (nth 1 value))
2638 (setq ag-like (or (feedmail-accume-n-nuke-header eoh-marker header-regexp) ""))
2639 ;; get rid of initial header name from first instance (front of string)
2640 (if (string-match (concat header-regexp "[ \t\n]+") ag-like)
2641 (setq ag-like (replace-match "" t t ag-like)))
2642 ;; get rid of embedded header names from subsequent instances
2643 (while (string-match (concat "\n" header-colon "[ \t\n]+") ag-like)
2644 (setq ag-like (replace-match "\n\t" t t ag-like)))
2645 ;; trim leading/trailing whitespace
2646 (if (string-match "\\`[ \t\n]+" ag-like)
2647 (setq ag-like (substring ag-like (match-end 0))))
2648 (if (string-match "[ \t\n]+\\'" ag-like)
2649 (setq ag-like (substring ag-like 0 (match-beginning 0))))
2650 ;; if ag-like is not nil and not an empty string, transform it via a function
2651 ;; call or format operation
2652 (if (> (length ag-like) 0)
2653 (setq ag-like
2654 (cond
2655 ((and (symbolp val-like) (fboundp val-like))
2656 (funcall val-like name ag-like))
2657 ((stringp val-like)
2658 (format val-like ag-like))
2659 (t nil))))
2660 (feedmail-fiddle-header name (concat (nth 0 value) ag-like (nth 2 value)) 'supplement folding)))
2661 ))
bd1cd4c2
KH
2662
2663(defun feedmail-give-it-to-buffer-eater ()
215cda7c 2664 (feedmail-say-debug ">in-> feedmail-give-it-to-buffer-eater")
bd1cd4c2 2665 (save-excursion
c7d4a777
KH
2666 (if feedmail-enable-spray
2667 (mapcar
2668 '(lambda (feedmail-spray-this-address)
2669 (let ((spray-buffer (get-buffer-create " *FQM Outgoing Email Spray*")))
937e6a56 2670 (with-current-buffer spray-buffer
c7d4a777
KH
2671 (erase-buffer)
2672 ;; not life's most efficient methodology, but spraying isn't
2673 ;; an every-5-minutes event either
bf714905 2674 (insert-buffer-substring feedmail-prepped-text-buffer)
937e6a56
SM
2675 ;; There's a good case to me made that each separate
2676 ;; transmission of a message in the spray should
2677 ;; have a distinct Message-Id:. There is also a less
2678 ;; compelling argument in the other direction.
2679 ;; I think they technically should have distinct
2680 ;; Message-Id:s, but I doubt that anyone cares,
2681 ;; practically. If someone complains about it, I'll
2682 ;; add it.
c7d4a777
KH
2683 (feedmail-fiddle-list-of-spray-fiddle-plexes feedmail-spray-address-fiddle-plex-list)
2684 ;; this (let ) is just in case some buffer eater
2685 ;; is cheating and using the global variable name instead
2686 ;; of its argument to find the buffer
2687 (let ((feedmail-prepped-text-buffer spray-buffer))
2688 (funcall feedmail-buffer-eating-function
bd1cd4c2
KH
2689 feedmail-prepped-text-buffer
2690 feedmail-error-buffer
c7d4a777
KH
2691 (list feedmail-spray-this-address))))
2692 (kill-buffer spray-buffer)
2693 ))
2694 feedmail-address-list)
215cda7c
BC
2695 (feedmail-say-debug "calling buffer-eater %s"
2696 feedmail-buffer-eating-function)
c7d4a777
KH
2697 (funcall feedmail-buffer-eating-function
2698 feedmail-prepped-text-buffer
2699 feedmail-error-buffer
2700 feedmail-address-list))))
bd1cd4c2
KH
2701
2702
2703(defun feedmail-envelope-deducer (eoh-marker)
27772f10 2704 "If `feedmail-deduce-envelope-from' is false, simply return `user-mail-address'.
37aa9115 2705Else, look for Sender: or From: (or Resent-*) and
bd1cd4c2 2706return that value."
215cda7c 2707 (feedmail-say-debug ">in-> feedmail-envelope-deducer %s" eoh-marker)
bd1cd4c2 2708 (if (not feedmail-deduce-envelope-from)
c7d4a777
KH
2709 user-mail-address
2710 (let ((from-list))
2711 (setq from-list
2712 (feedmail-deduce-address-list
37aa9115 2713 (current-buffer) (point-min) eoh-marker (if feedmail-is-a-resend "^Resent-Sender:" "^Sender:")
c7d4a777
KH
2714 from-list))
2715 (if (not from-list)
bd1cd4c2 2716 (setq from-list
c7d4a777 2717 (feedmail-deduce-address-list
37aa9115 2718 (current-buffer) (point-min) eoh-marker (if feedmail-is-a-resend "^Resent-From:" "^From:")
c7d4a777
KH
2719 from-list)))
2720 (if (and from-list (car from-list)) (car from-list) user-mail-address))))
bd1cd4c2
KH
2721
2722
2723(defun feedmail-fiddle-from ()
37aa9115 2724 "Fiddle From:."
215cda7c 2725 (feedmail-say-debug ">in-> feedmail-fiddle-from")
bd1cd4c2
KH
2726 ;; default is to fall off the end of the list and do nothing
2727 (cond
2728 ;; nil means do nothing
2729 ((eq nil feedmail-from-line) nil)
2730 ;; t is the same a using the default computation, so compute it and recurse
2731 ;; user-full-name suggested by kpc@ptolemy.arc.nasa.gov (=Kimball Collins)
2732 ;; improvement using user-mail-address suggested by
2733 ;; gray@austin.apc.slb.com (Douglas Gray Stephens)
215cda7c
BC
2734 ;; improvement using mail-host-address suggested by "Jason Eisner" <jason@cs.jhu.edu>
2735 ;; ((this situation really is hopeless, though)
bd1cd4c2 2736 ((eq t feedmail-from-line)
c7d4a777
KH
2737 (let ((feedmail-from-line
2738 (let ((at-stuff
215cda7c
BC
2739 (if user-mail-address user-mail-address
2740 (concat (user-login-name) "@"
2741 (or mail-host-address (system-name))))))
c7d4a777
KH
2742 (cond
2743 ((eq mail-from-style nil) at-stuff)
2744 ((eq mail-from-style 'parens) (concat at-stuff " (" (user-full-name) ")"))
2745 ((eq mail-from-style 'angles) (concat "\"" (user-full-name) "\" <" at-stuff ">"))
2746 ))))
2747 (feedmail-fiddle-from)))
bd1cd4c2
KH
2748
2749 ;; if it's a string, simply make a fiddle-plex out of it and recurse
2750 ((stringp feedmail-from-line)
c7d4a777
KH
2751 (let ((feedmail-from-line (list "ignored" feedmail-from-line 'create)))
2752 (feedmail-fiddle-from)))
bd1cd4c2
KH
2753
2754 ;; if it's a function, call it and recurse with the resulting value
2755 ((and (symbolp feedmail-from-line) (fboundp feedmail-from-line))
c7d4a777
KH
2756 (let ((feedmail-from-line (funcall feedmail-from-line)))
2757 (feedmail-fiddle-from)))
bd1cd4c2
KH
2758
2759 ;; if it's a list, it must be a fiddle-plex -- so fiddle, man, fiddle
2760 ((listp feedmail-from-line)
c7d4a777
KH
2761 (feedmail-fiddle-header
2762 (if feedmail-is-a-resend "Resent-From" "From")
2763 (nth 1 feedmail-from-line) ; value
2764 (nth 2 feedmail-from-line) ; action
2765 (nth 3 feedmail-from-line))))) ; folding
bd1cd4c2
KH
2766
2767
2768(defun feedmail-fiddle-sender ()
37aa9115 2769 "Fiddle Sender:."
215cda7c 2770 (feedmail-say-debug ">in-> feedmail-fiddle-sender")
bd1cd4c2
KH
2771 ;; default is to fall off the end of the list and do nothing
2772 (cond
2773 ;; nil means do nothing
2774 ((eq nil feedmail-sender-line) nil)
2775 ;; t is not allowed, but handled it just to avoid bugs later
2776 ((eq t feedmail-sender-line) nil)
2777
2778 ;; if it's a string, simply make a fiddle-plex out of it and recurse
2779 ((stringp feedmail-sender-line)
c7d4a777
KH
2780 (let ((feedmail-sender-line (list "ignored" feedmail-sender-line 'create)))
2781 (feedmail-fiddle-sender)))
bd1cd4c2
KH
2782
2783 ;; if it's a function, call it and recurse with the resulting value
2784 ((and (symbolp feedmail-sender-line) (fboundp feedmail-sender-line))
c7d4a777
KH
2785 (let ((feedmail-sender-line (funcall feedmail-sender-line)))
2786 (feedmail-fiddle-sender)))
bd1cd4c2
KH
2787
2788 ;; if it's a list, it must be a fiddle-plex -- so fiddle, man, fiddle
2789 ((listp feedmail-sender-line)
c7d4a777
KH
2790 (feedmail-fiddle-header
2791 (if feedmail-is-a-resend "Resent-Sender" "Sender")
2792 (nth 1 feedmail-sender-line) ; value
2793 (nth 2 feedmail-sender-line) ; action
2794 (nth 3 feedmail-sender-line))))) ; folding
bd1cd4c2
KH
2795
2796
2797(defun feedmail-default-date-generator (maybe-file)
37aa9115 2798 "Default function for generating Date: header contents."
215cda7c
BC
2799 (feedmail-say-debug ">in-> feedmail-default-date-generator")
2800 (when maybe-file
2801 (feedmail-say-debug (concat "4 cre " (feedmail-rfc822-date (nth 4 (file-attributes maybe-file)))))
2802 (feedmail-say-debug (concat "5 mod " (feedmail-rfc822-date (nth 5 (file-attributes maybe-file)))))
2803 (feedmail-say-debug (concat "6 sta " (feedmail-rfc822-date (nth 6 (file-attributes maybe-file))))))
bd1cd4c2 2804 (let ((date-time))
c7d4a777
KH
2805 (if (and (not feedmail-queue-use-send-time-for-date) maybe-file)
2806 (setq date-time (nth 5 (file-attributes maybe-file))))
2807 (feedmail-rfc822-date date-time))
bd1cd4c2
KH
2808 )
2809
2810
2811(defun feedmail-fiddle-date (maybe-file)
27772f10 2812 "Fiddle Date:. See documentation of `feedmail-date-generator'."
215cda7c 2813 (feedmail-say-debug ">in-> feedmail-fiddle-date")
bd1cd4c2
KH
2814 ;; default is to fall off the end of the list and do nothing
2815 (cond
2816 ;; nil means do nothing
2817 ((eq nil feedmail-date-generator) nil)
2818 ;; t is the same a using the function feedmail-default-date-generator, so let it and recurse
2819 ((eq t feedmail-date-generator)
c7d4a777
KH
2820 (let ((feedmail-date-generator (feedmail-default-date-generator maybe-file)))
2821 (feedmail-fiddle-date maybe-file)))
bd1cd4c2
KH
2822
2823 ;; if it's a string, simply make a fiddle-plex out of it and recurse
2824 ((stringp feedmail-date-generator)
c7d4a777
KH
2825 (let ((feedmail-date-generator (list "ignored" feedmail-date-generator 'create)))
2826 (feedmail-fiddle-date maybe-file)))
bd1cd4c2
KH
2827
2828 ;; if it's a function, call it and recurse with the resulting value
2829 ((and (symbolp feedmail-date-generator) (fboundp feedmail-date-generator))
c7d4a777
KH
2830 (let ((feedmail-date-generator (funcall feedmail-date-generator maybe-file)))
2831 (feedmail-fiddle-date maybe-file)))
bd1cd4c2
KH
2832
2833 ;; if it's a list, it must be a fiddle-plex -- so fiddle, man, fiddle
2834 ((listp feedmail-date-generator)
c7d4a777
KH
2835 (feedmail-fiddle-header
2836 (if feedmail-is-a-resend "Resent-Date" "Date")
2837 (nth 1 feedmail-date-generator) ; value
2838 (nth 2 feedmail-date-generator) ; action
2839 (nth 3 feedmail-date-generator))))) ; folding
bd1cd4c2
KH
2840
2841
2842(defun feedmail-default-message-id-generator (maybe-file)
37aa9115 2843 "Default function for generating Message-Id: header contents.
bd1cd4c2 2844Based on a date and a sort of random number for tie breaking. Unless
27772f10 2845`feedmail-message-id-suffix' is defined, uses `user-mail-address', so be
215cda7c
BC
2846sure it's set. If both are nil, creates a quasi-random suffix that is
2847probably not appropriate for you."
2848 (feedmail-say-debug ">in-> feedmail-default-message-id-generator %s"
2849 maybe-file)
bd1cd4c2 2850 (let ((date-time)
215cda7c 2851 (system-time-locale "C")
c7d4a777 2852 (end-stuff (if feedmail-message-id-suffix feedmail-message-id-suffix user-mail-address)))
215cda7c 2853 (if (not end-stuff) (setq end-stuff (format "%d.example.com" (random))))
c7d4a777
KH
2854 (if (string-match "^\\(.*\\)@" end-stuff)
2855 (setq end-stuff
2856 (concat (if (equal (match-beginning 1) (match-end 1)) "" "-") end-stuff))
2857 (setq end-stuff (concat "@" end-stuff)))
2858 (if (and (not feedmail-queue-use-send-time-for-message-id) maybe-file)
2859 (setq date-time (nth 5 (file-attributes maybe-file))))
2860 (format "<%d-%s%s%s>"
2861 (mod (random) 10000)
2862 (format-time-string "%a%d%b%Y%H%M%S" date-time)
2863 (feedmail-rfc822-time-zone date-time)
2864 end-stuff))
bd1cd4c2
KH
2865 )
2866
2867(defun feedmail-fiddle-message-id (maybe-file)
27772f10 2868 "Fiddle Message-Id:. See documentation of `feedmail-message-id-generator'."
215cda7c 2869 (feedmail-say-debug ">in-> feedmail-fiddle-message-id %s" maybe-file)
bd1cd4c2
KH
2870 ;; default is to fall off the end of the list and do nothing
2871 (cond
2872 ;; nil means do nothing
2873 ((eq nil feedmail-message-id-generator) nil)
2874 ;; t is the same a using the function feedmail-default-message-id-generator, so let it and recurse
2875 ((eq t feedmail-message-id-generator)
c7d4a777
KH
2876 (let ((feedmail-message-id-generator (feedmail-default-message-id-generator maybe-file)))
2877 (feedmail-fiddle-message-id maybe-file)))
bd1cd4c2
KH
2878
2879 ;; if it's a string, simply make a fiddle-plex out of it and recurse
2880 ((stringp feedmail-message-id-generator)
c7d4a777
KH
2881 (let ((feedmail-message-id-generator (list "ignored" feedmail-message-id-generator 'create)))
2882 (feedmail-fiddle-message-id maybe-file)))
bd1cd4c2
KH
2883
2884 ;; if it's a function, call it and recurse with the resulting value
2885 ((and (symbolp feedmail-message-id-generator) (fboundp feedmail-message-id-generator))
c7d4a777
KH
2886 (let ((feedmail-message-id-generator (funcall feedmail-message-id-generator maybe-file)))
2887 (feedmail-fiddle-message-id maybe-file)))
bd1cd4c2
KH
2888
2889 ;; if it's a list, it must be a fiddle-plex -- so fiddle, man, fiddle
2890 ((listp feedmail-message-id-generator)
c7d4a777 2891 (feedmail-fiddle-header
37aa9115 2892 (if feedmail-is-a-resend "Resent-Message-Id" "Message-Id")
c7d4a777
KH
2893 (nth 1 feedmail-message-id-generator) ; value
2894 (nth 2 feedmail-message-id-generator) ; action
2895 (nth 3 feedmail-message-id-generator))))) ; folding
bd1cd4c2
KH
2896
2897
2898(defun feedmail-default-x-mailer-generator ()
37aa9115 2899 "Default function for generating X-Mailer: header contents."
bd1cd4c2
KH
2900 (concat
2901 (let ((case-fold-search t)) (if (string-match "emacs" emacs-version) "" "emacs "))
2902 emacs-version " (via feedmail " feedmail-patch-level
2903 (if feedmail-queue-runner-is-active " Q" " I")
2904 (if feedmail-enable-spray "S" "")
2905 (if feedmail-x-mailer-line-user-appendage ") " ")")
2906 feedmail-x-mailer-line-user-appendage))
2907
2908
2909(defun feedmail-fiddle-x-mailer ()
27772f10 2910 "Fiddle X-Mailer:. See documentation of `feedmail-x-mailer-line'."
215cda7c 2911 (feedmail-say-debug ">in-> feedmail-fiddle-x-mailer")
bd1cd4c2
KH
2912 ;; default is to fall off the end of the list and do nothing
2913 (cond
215cda7c
BC
2914 ;; nil means do nothing
2915 ((eq nil feedmail-x-mailer-line) nil)
bd1cd4c2
KH
2916 ;; t is the same a using the function feedmail-default-x-mailer-generator, so let it and recurse
2917 ((eq t feedmail-x-mailer-line)
c7d4a777
KH
2918 (let ((feedmail-x-mailer-line (feedmail-default-x-mailer-generator)))
2919 (feedmail-fiddle-x-mailer)))
bd1cd4c2
KH
2920
2921 ;; if it's a string, simply make a fiddle-plex out of it and recurse
2922 ((stringp feedmail-x-mailer-line)
c7d4a777
KH
2923 (let ((feedmail-x-mailer-line (list "ignored" (list feedmail-x-mailer-line ";\n\t%s") 'combine)))
2924 (feedmail-fiddle-x-mailer)))
bd1cd4c2
KH
2925
2926 ;; if it's a function, call it and recurse with the resulting value
2927 ((and (symbolp feedmail-x-mailer-line) (fboundp feedmail-x-mailer-line))
c7d4a777
KH
2928 (let ((feedmail-x-mailer-line (funcall feedmail-x-mailer-line)))
2929 (feedmail-fiddle-x-mailer)))
bd1cd4c2
KH
2930
2931 ;; if it's a list, it must be a fiddle-plex -- so fiddle, man, fiddle
2932 ((listp feedmail-x-mailer-line)
c7d4a777
KH
2933 (feedmail-fiddle-header
2934 (if feedmail-is-a-resend "X-Resent-Mailer" "X-Mailer")
2935 (nth 1 feedmail-x-mailer-line) ; value
2936 (nth 2 feedmail-x-mailer-line) ; action
2937 (nth 3 feedmail-x-mailer-line))))) ; folding
bd1cd4c2
KH
2938
2939
2940(defun feedmail-fiddle-spray-address (addy-plex)
27772f10 2941 "Fiddle header for single spray address. Uses `feedmail-spray-this-address'."
215cda7c 2942 (feedmail-say-debug ">in-> feedmail-fiddle-spray-address %s" addy-plex)
bd1cd4c2
KH
2943 ;; default is to fall off the end of the list and do nothing
2944 (cond
2945 ;; nil means do nothing
2946 ((eq nil addy-plex) nil)
37aa9115 2947 ;; t means the same as using "To:" and unembellished addy
bd1cd4c2 2948 ((eq t addy-plex)
c7d4a777
KH
2949 (let ((addy-plex (list "To" feedmail-spray-this-address)))
2950 (feedmail-fiddle-spray-address addy-plex)))
bd1cd4c2
KH
2951
2952 ;; if it's a string, simply make a fiddle-plex out of it and recurse, assuming
37aa9115 2953 ;; the string names a header field (e.g., "To")
bd1cd4c2 2954 ((stringp addy-plex)
c7d4a777
KH
2955 (let ((addy-plex (list addy-plex feedmail-spray-this-address)))
2956 (feedmail-fiddle-spray-address addy-plex)))
bd1cd4c2
KH
2957
2958 ;; if it's a function, call it and recurse with the resulting value
2959 ((and (symbolp addy-plex) (fboundp addy-plex))
c7d4a777
KH
2960 (let ((addy-plex (funcall addy-plex)))
2961 (feedmail-fiddle-spray-address addy-plex)))
bd1cd4c2
KH
2962
2963 ;; if it's a list, it must be a fiddle-plex -- so fiddle, man, fiddle
2964 ((listp addy-plex)
c7d4a777
KH
2965 (feedmail-fiddle-header
2966 (nth 0 addy-plex) ; name
2967 (nth 1 addy-plex) ; value
2968 (nth 2 addy-plex) ; action
2969 (nth 3 addy-plex))))) ; folding
bd1cd4c2
KH
2970
2971
2972(defun feedmail-fiddle-list-of-spray-fiddle-plexes (list-of-fiddle-plexes)
2973 "Fiddling based on a list of fiddle-plexes for spraying."
215cda7c 2974 (feedmail-say-debug ">in-> feedmail-fiddle-list-of-spray-fiddle-plexes")
bd1cd4c2
KH
2975 ;; default is to fall off the end of the list and do nothing
2976 (let ((lofp list-of-fiddle-plexes) fp)
0bb37c1a
KH
2977 (if (listp lofp)
2978 (while lofp
2979 (setq fp (car lofp))
2980 (setq lofp (cdr lofp))
2981 (feedmail-fiddle-spray-address fp))
2982 (feedmail-fiddle-spray-address lofp))))
bd1cd4c2
KH
2983
2984
2985(defun feedmail-fiddle-list-of-fiddle-plexes (list-of-fiddle-plexes)
2986 "Fiddling based on a list of fiddle-plexes. Values t, nil, and string are pointless."
215cda7c 2987 (feedmail-say-debug ">in-> feedmail-fiddle-list-of-fiddle-plexes")
bd1cd4c2
KH
2988 ;; default is to fall off the end of the list and do nothing
2989 (let ((lofp list-of-fiddle-plexes) fp)
0bb37c1a
KH
2990 (while lofp
2991 (setq fp (car lofp))
2992 (setq lofp (cdr lofp))
2993 (cond
bd1cd4c2 2994
0bb37c1a
KH
2995 ;; if it's a function, call it and recurse with the resulting value
2996 ((and (symbolp fp) (fboundp fp))
2997 (let ((lofp (list (funcall fp)))) (feedmail-fiddle-list-of-fiddle-plexes lofp)))
bd1cd4c2 2998
0bb37c1a
KH
2999 ;; if it's a list, it must be a fiddle-plex -- so fiddle, man, fiddle
3000 ((listp fp)
3001 (feedmail-fiddle-header
3002 (nth 0 fp)
c7d4a777
KH
3003 (nth 1 fp) ; value
3004 (nth 2 fp) ; action
3005 (nth 3 fp))))))) ; folding
bd1cd4c2
KH
3006
3007
3008(defun feedmail-accume-n-nuke-header (header-end header-regexp)
3009 "Delete headers matching a regexp and their continuation lines.
3010There may be multiple such lines, and each may have arbitrarily
3011many continuation lines. Return an accumulation of the deleted
3012headers, including the intervening newlines."
215cda7c
BC
3013 (feedmail-say-debug ">in-> feedmail-accume-n-nuke-header %s %s"
3014 header-end header-regexp)
bd1cd4c2 3015 (let ((case-fold-search t) (dropout))
0bb37c1a
KH
3016 (save-excursion
3017 (goto-char (point-min))
3018 ;; iterate over all matching lines
3019 (while (re-search-forward header-regexp header-end t)
3020 (forward-line 1)
215cda7c 3021 (setq dropout (concat dropout (buffer-substring-no-properties (match-beginning 0) (point))))
0bb37c1a
KH
3022 (delete-region (match-beginning 0) (point))
3023 ;; get rid of any continuation lines
3024 (while (and (looking-at "^[ \t].*\n") (< (point) header-end))
3025 (forward-line 1)
215cda7c 3026 (setq dropout (concat dropout (buffer-substring-no-properties (match-beginning 0) (point))))
0bb37c1a 3027 (replace-match ""))))
c7d4a777 3028 (identity dropout)))
bd1cd4c2
KH
3029
3030(defun feedmail-fill-to-cc-function (header-end)
3031 "Smart filling of address headers (don't be fooled by the name).
3032The filling tries to avoid splitting lines except at commas. This
3033avoids, in particular, splitting within parenthesized comments in
37aa9115
KH
3034addresses. Headers filled include From:, Reply-To:, To:, Cc:, Bcc:,
3035Resent-To:, Resent-Cc:, and Resent-Bcc:."
215cda7c 3036 (feedmail-say-debug ">in-> feedmail-fill-to-cc-function")
bd1cd4c2 3037 (let ((case-fold-search t)
c7d4a777
KH
3038 this-line
3039 this-line-end)
3040 (save-excursion
3041 (goto-char (point-min))
37aa9115 3042 ;; iterate over all To:/Cc:, etc, lines
c7d4a777
KH
3043 (while
3044 (re-search-forward
37aa9115 3045 "^\\(From:\\|Reply-To:\\|To:\\|Cc:\\|Bcc:\\|Resent-To:\\|Resent-Cc:\\|Resent-Bcc:\\)"
c7d4a777
KH
3046 header-end t)
3047 (setq this-line (match-beginning 0))
3048 ;; replace 0 or more leading spaces with a single space
3049 (and (looking-at "[ \t]*") (replace-match " "))
3050 (forward-line 1)
3051 ;; get any continuation lines
3052 (while (and (looking-at "[ \t]+") (< (point) header-end))
3053 (forward-line 1))
3054 (setq this-line-end (point-marker))
3055 (save-excursion (feedmail-fill-this-one this-line this-line-end))
3056 ))))
bd1cd4c2
KH
3057
3058
3059(defun feedmail-fill-this-one (this-line this-line-end)
3060 "In-place smart filling of the region bounded by the two arguments."
215cda7c 3061 (feedmail-say-debug ">in-> feedmail-fill-this-one")
bd1cd4c2 3062 (let ((fill-prefix "\t")
c7d4a777
KH
3063 (fill-column feedmail-fill-to-cc-fill-column))
3064 ;; The general idea is to break only on commas. Collapse
3065 ;; multiple whitespace to a single blank; change
3066 ;; all the blanks to something unprintable; change the
3067 ;; commas to blanks; fill the region; change it back.
3068 (goto-char this-line)
3069 (while (re-search-forward "\\s-+" (1- this-line-end) t)
3070 (replace-match " "))
3071
3072 (subst-char-in-region this-line this-line-end ? 2 t) ; blank->C-b
3073 (subst-char-in-region this-line this-line-end ?, ? t) ; comma->blank
3074
3075 (fill-region-as-paragraph this-line this-line-end)
3076
3077 (subst-char-in-region this-line this-line-end ? ?, t) ; comma<-blank
3078 (subst-char-in-region this-line this-line-end 2 ? t) ; blank<-C-b
3079
3080 ;; look out for missing commas before continuation lines
3081 (goto-char this-line)
3082 (while (re-search-forward "\\([^,]\\)\n\t[ ]*" this-line-end t)
3083 (replace-match "\\1,\n\t"))
3084 ))
3085
3086
bd1cd4c2
KH
3087(defun feedmail-deduce-address-list (message-buffer header-start header-end addr-regexp address-list)
3088 "Get address list with all comments and other excitement trimmed.
3089Addresses are collected only from headers whose names match the fourth
27772f10 3090argument. Returns a list of strings. Duplicate addresses will have
bd1cd4c2 3091been weeded out."
215cda7c 3092 (feedmail-say-debug ">in-> feedmail-deduce-address-list %s %s" addr-regexp address-list)
bd1cd4c2 3093 (let ((simple-address)
c7d4a777
KH
3094 (address-blob)
3095 (this-line)
3096 (this-line-end))
3097 (unwind-protect
937e6a56
SM
3098 (with-current-buffer (get-buffer-create " *FQM scratch*")
3099 (erase-buffer)
c7d4a777
KH
3100 (insert-buffer-substring message-buffer header-start header-end)
3101 (goto-char (point-min))
3102 (let ((case-fold-search t))
3103 (while (re-search-forward addr-regexp (point-max) t)
3104 (replace-match "")
3105 (setq this-line (match-beginning 0))
3106 (forward-line 1)
3107 ;; get any continuation lines
3108 (while (and (looking-at "^[ \t]+") (< (point) (point-max)))
3109 (forward-line 1))
3110 (setq this-line-end (point-marker))
3111 ;; only keep if we don't have it already
3112 (setq address-blob
215cda7c 3113 (mail-strip-quoted-names (buffer-substring-no-properties this-line this-line-end)))
c7d4a777
KH
3114 (while (string-match "\\([, \t\n\r]*\\)\\([^, \t\n\r]+\\)" address-blob)
3115 (setq simple-address (substring address-blob (match-beginning 2) (match-end 2)))
3116 (setq address-blob (replace-match "" t t address-blob))
3117 (if (not (member simple-address address-list))
3118 (add-to-list 'address-list simple-address)))
3119 ))
3120 (kill-buffer nil)))
3121 (identity address-list)))
bd1cd4c2
KH
3122
3123
3124(defun feedmail-one-last-look (feedmail-prepped-text-buffer)
3125 "Offer the user one last chance to give it up."
215cda7c 3126 (feedmail-say-debug ">in-> feedmail-one-last-look")
bd1cd4c2 3127 (save-excursion
c7d4a777
KH
3128 (save-window-excursion
3129 (switch-to-buffer feedmail-prepped-text-buffer)
3130 (if (and (fboundp 'y-or-n-p-with-timeout) (numberp feedmail-confirm-outgoing-timeout))
3131 (y-or-n-p-with-timeout
3132 "FQM: Send this email? "
3133 (abs feedmail-confirm-outgoing-timeout)
3134 (> feedmail-confirm-outgoing-timeout 0))
3135 (y-or-n-p "FQM: Send this email? "))
3136 )))
bd1cd4c2
KH
3137
3138(defun feedmail-fqm-p (might-be)
3139 "Internal; does filename end with FQM suffix?"
215cda7c 3140 (feedmail-say-debug ">in-> feedmail-fqm-p %s" might-be)
bd1cd4c2
KH
3141 (string-match (concat (regexp-quote feedmail-queue-fqm-suffix) "$") might-be))
3142
215cda7c
BC
3143(defun feedmail-say-debug (format &optional a1 a2 a3 a4 a5 a6 a7 a8 a9)
3144 "Internal; emits debug messages in standard format."
3145 (when feedmail-debug
3146 (funcall 'message (concat "FQM DB: " format) a1 a2 a3 a4 a5 a6 a7 a8 a9)
3147 (and feedmail-debug-sit-for (not (= 0 feedmail-debug-sit-for))
3148 (sit-for feedmail-debug-sit-for))))
3149
3150(defun feedmail-say-chatter (format &optional a1 a2 a3 a4 a5 a6 a7 a8 a9)
3151 "Internal; emits queue chatter messages in standard format."
3152 (when feedmail-queue-chatty
3153 (funcall 'message (concat "FQM: " format) a1 a2 a3 a4 a5 a6 a7 a8 a9)
3154 (and feedmail-queue-chatty-sit-for (not (= 0 feedmail-queue-chatty-sit-for))
3155 (sit-for feedmail-queue-chatty-sit-for))))
bd1cd4c2
KH
3156
3157(defun feedmail-find-eoh (&optional noerror)
3158 "Internal; finds the end of message header fields, returns mark just before it"
215cda7c
BC
3159 ;; all this funny business with line endings is to account for CRLF
3160 ;; weirdness that I don't think I'll ever figure out
3161 (feedmail-say-debug ">in-> feedmail-find-eoh %s" noerror)
3162 (let ((mhs mail-header-separator)
3163 (alt-mhs feedmail-queue-alternative-mail-header-separator)
3164 r-mhs r-alt-mhs)
3165 (setq r-mhs (concat "^" (regexp-quote mhs) "$"))
3166 (setq r-alt-mhs (concat "^" (regexp-quote (or alt-mhs "")) "$"))
bd1cd4c2 3167 (save-excursion
c7d4a777 3168 (goto-char (point-min))
215cda7c
BC
3169 (if (or (re-search-forward r-mhs nil t)
3170 (and alt-mhs (re-search-forward r-alt-mhs nil t)))
3171 (progn
3172 (beginning-of-line)
3173 (point-marker))
3174 (if noerror
3175 nil
3176 (error "FQM: Can't find message-header-separator or alternate"))))))
bd1cd4c2
KH
3177
3178(provide 'feedmail)
e8af40ee 3179
bd1cd4c2 3180;;; feedmail.el ends here