NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
sendmail.h File Reference

Send email using sendmail. More...

#include <stdbool.h>
+ Include dependency graph for sendmail.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int mutt_invoke_sendmail (struct Mailbox *m, struct AddressList *from, struct AddressList *to, struct AddressList *cc, struct AddressList *bcc, const char *msg, bool eightbit, struct ConfigSubset *sub)
 Run sendmail.
 

Detailed Description

Send email using sendmail.

Authors
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file sendmail.h.

Function Documentation

◆ mutt_invoke_sendmail()

int mutt_invoke_sendmail ( struct Mailbox * m,
struct AddressList * from,
struct AddressList * to,
struct AddressList * cc,
struct AddressList * bcc,
const char * msg,
bool eightbit,
struct ConfigSubset * sub )

Run sendmail.

Parameters
mMailbox
fromThe sender
toRecipients
ccRecipients
bccRecipients
msgFile containing message
eightbitMessage contains 8bit chars
subConfig Subset
Return values
0Success
-1Failure
See also
$inews_command

Definition at line 299 of file sendmail.c.

303{
304 char *ps = NULL;
305 char *path = NULL;
306 char *s = NULL;
307 char *childout = NULL;
308 struct StringArray args = ARRAY_HEAD_INITIALIZER;
309 struct StringArray extra_args = ARRAY_HEAD_INITIALIZER;
310 int i;
311
312 if (OptNewsSend)
313 {
314 struct Buffer *cmd = buf_pool_get();
315
316 const struct Expando *c_inews_command = cs_subset_expando(sub, "inews_command");
318 cmd->dsize, NeoMutt->env, cmd);
319 if (buf_is_empty(cmd))
320 {
321 i = nntp_post(m, msg);
322 unlink(msg);
323 buf_pool_release(&cmd);
324 return i;
325 }
326
327 s = buf_strdup(cmd);
328 buf_pool_release(&cmd);
329 }
330 else
331 {
332 const char *const c_sendmail = cs_subset_string(sub, "sendmail");
333 s = mutt_str_dup(c_sendmail);
334 }
335
336 if (!s)
337 {
338 mutt_error(_("$sendmail must be set in order to send mail"));
339 return -1;
340 }
341
342 ps = s;
343 i = 0;
344 while ((ps = strtok(ps, " ")))
345 {
346 if (i)
347 {
348 if (mutt_str_equal(ps, "--"))
349 break;
350 ARRAY_ADD(&args, ps);
351 }
352 else
353 {
354 path = mutt_str_dup(ps);
355 ps = strrchr(ps, '/');
356 if (ps)
357 ps++;
358 else
359 ps = path;
360 ARRAY_ADD(&args, ps);
361 }
362 ps = NULL;
363 i++;
364 }
365
366 if (!OptNewsSend)
367 {
368 /* If $sendmail contained a "--", we save the recipients to append to
369 * args after other possible options added below. */
370 if (ps)
371 {
372 ps = NULL;
373 while ((ps = strtok(ps, " ")))
374 {
375 ARRAY_ADD(&extra_args, ps);
376 ps = NULL;
377 }
378 }
379
380 const bool c_use_8bit_mime = cs_subset_bool(sub, "use_8bit_mime");
381 if (eightbit && c_use_8bit_mime)
382 ARRAY_ADD(&args, "-B8BITMIME");
383
384 const bool c_use_envelope_from = cs_subset_bool(sub, "use_envelope_from");
385 if (c_use_envelope_from)
386 {
387 const struct Address *c_envelope_from_address = cs_subset_address(sub, "envelope_from_address");
388 if (c_envelope_from_address)
389 {
390 ARRAY_ADD(&args, "-f");
391 add_args_one(&args, c_envelope_from_address);
392 }
393 else if (!TAILQ_EMPTY(from) && !TAILQ_NEXT(TAILQ_FIRST(from), entries))
394 {
395 ARRAY_ADD(&args, "-f");
396 add_args(&args, from);
397 }
398 }
399
400 const char *const c_dsn_notify = cs_subset_string(sub, "dsn_notify");
401 if (c_dsn_notify)
402 {
403 ARRAY_ADD(&args, "-N");
404 ARRAY_ADD(&args, c_dsn_notify);
405 }
406
407 const char *const c_dsn_return = cs_subset_string(sub, "dsn_return");
408 if (c_dsn_return)
409 {
410 ARRAY_ADD(&args, "-R");
411 ARRAY_ADD(&args, c_dsn_return);
412 }
413 ARRAY_ADD(&args, "--");
414 const char **e = NULL;
415 ARRAY_FOREACH(e, &extra_args)
416 {
417 ARRAY_ADD(&args, *e);
418 }
419 add_args(&args, to);
420 add_args(&args, cc);
421 add_args(&args, bcc);
422 }
423
424 ARRAY_ADD(&args, NULL);
425
426 const short c_sendmail_wait = cs_subset_number(sub, "sendmail_wait");
427 i = send_msg(path, &args, msg, OptGui ? &childout : NULL, c_sendmail_wait);
428
429 /* Some user's $sendmail command uses gpg for password decryption,
430 * and is set up to prompt using ncurses pinentry. If we
431 * mutt_endwin() it leaves other users staring at a blank screen.
432 * So instead, just force a hard redraw on the next refresh. */
433 if (OptGui)
434 {
436 }
437
438 if (i != (EX_OK & 0xff))
439 {
440 if (i != S_BKG)
441 {
442 const char *e = mutt_str_sysexit(i);
443 mutt_error(_("Error sending message, child exited %d (%s)"), i, NONULL(e));
444 if (childout)
445 {
446 struct stat st = { 0 };
447
448 if ((stat(childout, &st) == 0) && (st.st_size > 0))
449 {
450 struct PagerData pdata = { 0 };
451 struct PagerView pview = { &pdata };
452
453 pdata.fname = childout;
454
455 pview.banner = _("Output of the delivery process");
456 pview.flags = MUTT_PAGER_NONE;
457 pview.mode = PAGER_MODE_OTHER;
458
459 mutt_do_pager(&pview, NULL);
460 }
461 }
462 }
463 }
464 else if (childout)
465 {
466 unlink(childout);
467 }
468
469 FREE(&childout);
470 FREE(&path);
471 FREE(&s);
472 ARRAY_FREE(&args);
473 ARRAY_FREE(&extra_args);
474
475 if (i == (EX_OK & 0xff))
476 i = 0;
477 else if (i == S_BKG)
478 i = 1;
479 else
480 i = -1;
481 return i;
482}
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:157
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:298
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:577
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition curs_lib.c:101
int mutt_do_pager(struct PagerView *pview, struct Email *e)
Display some page-able text to the user (help or attachment)
Definition do_pager.c:122
int expando_filter(const struct Expando *exp, const struct ExpandoRenderCallback *erc, void *data, MuttFormatFlags flags, int max_cols, char **env_list, struct Buffer *buf)
Render an Expando and run the result through a filter.
Definition filter.c:139
const struct ExpandoRenderCallback NntpRenderCallbacks[]
Callbacks for Newsrc Expandos.
bool OptGui
(pseudo) when the gui (and curses) are started
Definition globals.c:48
bool OptNewsSend
(pseudo) used to change behavior when posting
Definition globals.c:54
#define mutt_error(...)
Definition logging2.h:94
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define _(a)
Definition message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
const char * mutt_str_sysexit(int err_num)
Return a string matching an error code.
Definition string.c:173
int nntp_post(struct Mailbox *m, const char *msg)
Post article.
Definition nntp.c:1952
#define MUTT_PAGER_NONE
No flags are set.
Definition lib.h:63
@ PAGER_MODE_OTHER
Pager is invoked via 3rd path. Non-email content is likely to be shown.
Definition lib.h:143
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define TAILQ_FIRST(head)
Definition queue.h:780
#define TAILQ_NEXT(elm, field)
Definition queue.h:889
#define TAILQ_EMPTY(head)
Definition queue.h:778
@ MUTT_FORMAT_NONE
No flags are set.
Definition render.h:37
static int send_msg(const char *path, struct StringArray *args, const char *msg, char **tempfile, int wait_time)
Invoke sendmail in a subshell.
Definition sendmail.c:89
static void add_args(struct StringArray *args, struct AddressList *al)
Add a list of Addresses to a dynamic array.
Definition sendmail.c:272
static void add_args_one(struct StringArray *args, const struct Address *addr)
Add an Address to a dynamic array.
Definition sendmail.c:258
#define EX_OK
Definition sendmail.c:58
#define NONULL(x)
Definition string2.h:44
#define S_BKG
Definition string2.h:48
An email address.
Definition address.h:35
String manipulation buffer.
Definition buffer.h:36
size_t dsize
Length of data.
Definition buffer.h:39
Parsed Expando trees.
Definition expando.h:41
Container for Accounts, Notifications.
Definition neomutt.h:41
char ** env
Private copy of the environment variables.
Definition neomutt.h:57
Data to be displayed by PagerView.
Definition lib.h:162
const char * fname
Name of the file to read.
Definition lib.h:166
Paged view into some data.
Definition lib.h:173
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition lib.h:174
enum PagerMode mode
Pager mode.
Definition lib.h:175
PagerFlags flags
Additional settings to tweak pager's function.
Definition lib.h:176
const char * banner
Title to display in status bar.
Definition lib.h:177
+ Here is the call graph for this function:
+ Here is the caller graph for this function: