1% sendmail.sl	-*- mode: slang; mode: fold -*-
2%
3% (Thanks to olesen@weber.me.queensu.ca (mj olesen) for this)
4%
5% Sendmail interface for Unix.
6%
7%  Functions:
8%   mail_send             : send message
9%   mail                  : initiate mail mode
10%   mail_insert_signature : append contents of Mail_Signature_File
11%   mail_kill_buffer      : Delete mail buffer
12%
13%  Variables:
14%   Mail_Reply_To         : Set this to appropriate Reply-To value
15%   Mail_Signature_File   : Filename of signature (~/.signature is default)
16%   SendMail_Cmd          : Name of sendmail program including switches
17%   Mail_Extra_Headers	  : Misc headers to insert
18%
19% You might want something like the following in mail_hook
20%
21% define mail_hook ()
22% {
23%    local_setkey ("mail_send", "^C^C");
24%    local_setkey ("mailalias_expand", "^C^E");
25%    local_setkey ("mail_kill_buffer", "^Xk");
26% }
27
28autoload ("mailalias_expand", "mailalias"); % the mail-alias package
29
30% Create a dummy function if set_line_readonly is not defined.
31!if (is_defined ("set_line_readonly")) eval (".(pop) set_line_readonly");
32
33%{{{ Public Variables
34
35$1 = "~/.signature";
36!if (is_defined ("Mail_Signature_File"))
37{
38   variable Mail_Signature_File = expand_filename ($1);
39}
40
41!if (is_defined ("Mail_Header_Separator_String"))
42  variable Mail_Header_Separator_String =
43"--- Do not modify this line.  Enter your message below ---";
44
45!if (is_defined ("Mail_Extra_Headers"))
46{
47   variable Mail_Extra_Headers = NULL;
48}
49
50
51% The sendmail program
52
53$1 = _stkdepth ();
54NULL;
55"/usr/bin/sendmail";		% places to look
56"/usr/lib/sendmail";
57"/usr/sbin/sendmail";
58
59!if (is_defined ("SendMail_Cmd"))
60{
61   variable SendMail_Cmd;
62
63   while (SendMail_Cmd = (), SendMail_Cmd != NULL)
64     {
65	if (1 == file_status (SendMail_Cmd))
66	  {
67	     SendMail_Cmd = strcat (SendMail_Cmd, " -t -oem -oi -odb");
68	     break;
69	  }
70     }
71
72}
73
74_pop_n (_stkdepth () - $1);
75
76!if (strlen (SendMail_Cmd)) error ("`sendmail' program not found!");
77
78%!% always Reply-To: here instead.
79!if (is_defined ("Mail_Reply_To"))
80{
81   variable Mail_Reply_To = Null_String;
82}
83
84%}}}
85
86%{{{ Private Variables
87
88private variable Mail_Previous_Buffer = Null_String;
89private variable Mail_Previous_Windows = 1;
90private variable Mail_This_Buffer = Null_String;
91private variable Mail_Filename = dircat (getenv ("HOME"), ".__jed_mail__");
92
93%}}}
94
95%{{{ Private Functions
96
97
98define mail_sw2_prev_buf ()
99{
100   if (bufferp (Mail_Previous_Buffer)) sw2buf (Mail_Previous_Buffer);
101   if (1 == Mail_Previous_Windows) onewindow ();
102   if (bufferp (Mail_This_Buffer) and strcmp (Mail_This_Buffer, Mail_Previous_Buffer))
103     pop2buf (Mail_This_Buffer);
104}
105
106%}}}
107
108define mail_send () %{{{
109{
110   variable dir, file, sent, buf = "*mail*";
111   variable sep_mark, fcc_mark, fcc_file;
112
113   if (buf != whatbuf ())
114     error ("not *mail* buffer");
115
116   flush ("Sending...");
117
118   push_spot ();
119
120   bob ();
121   !if (bol_fsearch (Mail_Header_Separator_String))
122     {
123	!if (bol_fsearch ("\n"))
124	  {
125	     pop_spot ();
126	     verror ("Cannot find %s\n", Mail_Header_Separator_String);
127	  }
128     }
129
130   set_line_readonly (0);
131   del_eol ();
132   sep_mark = create_user_mark ();
133
134   bob ();
135   fcc_mark = NULL;
136   if (bol_fsearch ("Fcc: "))
137     {
138	push_mark_eol ();
139	go_right_1 ();
140	fcc_file = strtrim (substr (bufsubstr_delete (), 6, -1));
141	fcc_mark = create_user_mark ();
142     }
143
144
145   mark_buffer ();
146   sent = not (pipe_region (SendMail_Cmd));
147
148   if (fcc_mark != NULL)
149     {
150	if (sent and strlen (fcc_file))
151	  {
152	     variable user = getenv ("USER");
153	     if (user == NULL)
154	       {
155		  user = getenv ("LOGNAME");
156		  if (user == NULL)
157		    user = "user";
158	       }
159	     () = append_string_to_file (sprintf ("From %s %s\n", user, time ()), fcc_file);
160
161	     % Make sure the buffer ends with two newline characters
162	     eob ();
163	     push_mark ();
164	     bskip_chars (" \t\n");
165	     del_region ();
166	     newline (); newline ();
167
168	     mark_buffer ();
169	     () = append_region_to_file (fcc_file);
170	  }
171	goto_user_mark (fcc_mark);
172	vinsert ("Fcc: %s\n", fcc_file);
173
174	% If the marks are on top of one another, make sure sep_mark gets
175	% updated.  I added the binary operations on User Marks just for
176	% this purpose.
177	if (fcc_mark == sep_mark)
178	  move_user_mark (sep_mark);
179     }
180
181   goto_user_mark (sep_mark);
182   insert (Mail_Header_Separator_String);
183
184   pop_spot ();
185
186   if (sent)
187     {
188	set_buffer_modified_flag (0);
189	flush ("Sending...done");
190	(file, dir,,) = getbuf_info ();
191	() = delete_file (make_autosave_filename (dir, file));
192	file = dircat (dir, file);
193	!if (strcmp (Mail_Filename, file))
194	  () = delete_file (Mail_Filename);
195	mail_sw2_prev_buf ();
196	bury_buffer (buf);
197	return;
198     }
199
200   flush ("Error sending message");
201   beep ();
202}
203add_completion ("mail_send");
204
205%}}}
206
207define mail_format_buffer () %{{{
208{
209   variable erase, opt_headers=NULL;
210   if (_NARGS == 2)
211     opt_headers = ();
212   erase = ();
213
214   variable km = "mail_map";
215
216   text_mode ();
217
218   setbuf_info (getbuf_info () & ~(0x40)); %  turn off buried buffer flag
219
220   !if (keymap_p(km)) make_keymap(km);
221   use_keymap(km);
222
223   if (erase == -1)
224     {
225	if (buffer_modified ())
226	  {
227	     !if (get_yes_no("Mail already being composed.  Erase it"))
228	       erase = 0;
229	  }
230     }
231
232   if (erase)
233     {
234	erase_buffer ();
235
236	insert ("To: \nCc: \nBcc: \nSubject: \n");
237	if (strlen (Mail_Reply_To))
238	  vinsert ("Reply-To: %s\n", Mail_Reply_To);
239
240	if (opt_headers != NULL)
241	  {
242	     insert (opt_headers);
243	  }
244
245	if (Mail_Extra_Headers != NULL)
246	  {
247	     insert (Mail_Extra_Headers);
248	     newline ();
249	  }
250	insert (Mail_Header_Separator_String);
251	newline ();
252
253	go_up_1 ();
254	set_line_readonly (1);
255
256	bob (); eol ();
257	set_buffer_modified_flag(0);
258
259     }
260
261   push_spot ();
262   run_mode_hooks("mail_hook");
263   pop_spot ();
264
265   set_buffer_undo(1);
266}
267
268%}}}
269
270define mail_kill_buffer () %{{{
271{
272   call ("kill_buffer");
273   mail_sw2_prev_buf ();
274}
275
276%}}}
277
278define mail () %{{{
279{
280   variable status, dir, file, buf = "*mail*";
281   variable do_format = -1;
282
283   status = bufferp (buf);
284   Mail_Previous_Windows = nwindows ();
285   Mail_This_Buffer = whatbuf ();
286
287   if (BATCH)
288     {
289	% Mail_Previous_Buffer = whatbuf ();
290	sw2buf (buf);
291     }
292   else
293     {
294	Mail_Previous_Buffer = pop2buf_whatbuf (buf);
295     }
296
297   % if buffer is not old, turn autosave on
298   if (status)
299     {
300	(,,,status) = getbuf_info ();
301	if (buffer_modified ())
302	  return;
303     }
304   else
305     {
306	(dir, file) = parse_filename (Mail_Filename);
307	setbuf_info (file, dir, buf, 2);	% autosave
308
309	file = make_autosave_filename(dir, file);
310	if (1 == file_status (file))
311	  {
312	     if (get_yes_no ("An autosave file exists.  Use it"))
313	       {
314		  erase_buffer ();
315		  () = insert_file (file);
316		  do_format = 0;
317	       }
318	  }
319     }
320
321   () = set_buffer_umask (0077);
322   mail_format_buffer (do_format);
323}
324
325%}}}
326
327define mail_insert_signature () %{{{
328{
329   !if (strlen (Mail_Signature_File))
330     return;
331
332   push_spot ();
333   eob ();
334   insert ("\n-- \n");
335   () = insert_file (Mail_Signature_File);
336   pop_spot ();
337}
338
339%}}}
340
341