diff options
Diffstat (limited to 'mail/send.c')
-rw-r--r-- | mail/send.c | 236 |
1 files changed, 153 insertions, 83 deletions
diff --git a/mail/send.c b/mail/send.c index 1c33c0de5..dc9ff5850 100644 --- a/mail/send.c +++ b/mail/send.c @@ -1,5 +1,5 @@ /* GNU Mailutils -- a suite of utilities for electronic mail - Copyright (C) 1999-2021 Free Software Foundation, Inc. + Copyright (C) 1999-2024 Free Software Foundation, Inc. GNU Mailutils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -676,7 +676,7 @@ read_cc_bcc (compose_env_t *env) * m[ail] address... if address is starting with - '/' it is considered a file and the message is saveed to a file; + '/' it is considered a file and the message is saved to a file; '.' it is considered to be a relative path; '|' it is considered to be a pipe, and the message is written to there; @@ -693,6 +693,7 @@ mail_send (int argc, char **argv) compose_env_t env; int status; int save_to = mu_isupper (argv[0][0]); + compose_init (&env); if (argc < 2) @@ -764,7 +765,7 @@ mail_send (int argc, char **argv) COMPOSE_REPLACE); } - status = mail_send0 (&env, save_to); + status = mail_compose_send (&env, save_to); compose_destroy (&env); return status; } @@ -889,78 +890,91 @@ compose_header_set (compose_env_t *env, const char *name, const char *value, int mode) { int status; - char *old_value; - + char *expansion = NULL; + if (!value || value[0] == 0) return EINVAL; + if (is_address_field (name) + && mailvar_is_true (mailvar_name_inplacealiases)) + { + struct mu_address hint = MU_ADDRESS_HINT_INITIALIZER; + mu_address_t a; + + status = mu_address_create_hint (&a, value, &hint, 0); + if (status) + { + mu_error (_("Cannot parse address `%s': %s"), + value, mu_strerror (status)); + return status; + } + util_address_expand_aliases (&a); + status = mu_address_aget_printable (a, &expansion); + mu_address_destroy (&a); + if (status) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_address_aget_printable", + NULL, status); + return status; + } + value = expansion; + } + if (!env->header && (status = mu_header_create (&env->header, NULL, 0)) != 0) { mu_error (_("Cannot create header: %s"), mu_strerror (status)); - return status; } - - switch (mode) + else { - case COMPOSE_REPLACE: - if (is_address_field (name) - && mailvar_is_true (mailvar_name_inplacealiases)) + switch (mode) { - char *exp = alias_expand (value); - status = mu_header_set_value (env->header, name, exp ? exp : value, 1); - free (exp); - } - else - status = mu_header_set_value (env->header, name, value, 1); - break; + case COMPOSE_REPLACE: + status = mu_header_set_value (env->header, name, value, 1); + break; - case COMPOSE_APPEND: - if (is_address_field (name) - && mailvar_is_true (mailvar_name_inplacealiases)) - { - char *exp = alias_expand (value); - status = mu_header_append (env->header, name, exp ? exp : value); - free (exp); - } - else - status = mu_header_append (env->header, name, value); - break; + case COMPOSE_APPEND: + status = mu_header_append (env->header, name, value); + break; - case COMPOSE_SINGLE_LINE: - if (mu_header_aget_value (env->header, name, &old_value) == 0 - && old_value[0]) - { - if (is_address_field (name) - && mailvar_is_true (mailvar_name_inplacealiases)) - { - char *exp = alias_expand (value); - status = util_merge_addresses (&old_value, exp ? exp : value); - if (status == 0) - status = mu_header_set_value (env->header, name, old_value, 1); - free (exp); - } - else - { - size_t size = strlen (old_value) + strlen (value) + 2; - char *p = realloc (old_value, size); - if (!p) - status = ENOMEM; - else - { - old_value = p; - strcat (old_value, ","); - strcat (old_value, value); - status = mu_header_set_value (env->header, name, old_value, - 1); - } - } - free (old_value); + case COMPOSE_SINGLE_LINE: + { + char *old_value; + + if (mu_header_aget_value (env->header, name, &old_value) == 0 + && old_value[0]) + { + if (is_address_field (name)) + { + status = util_merge_addresses (&old_value, value); + if (status == 0) + status = mu_header_set_value (env->header, name, + old_value, 1); + } + else + { + size_t size = strlen (old_value) + strlen (value) + 2; + char *p = realloc (old_value, size); + if (!p) + status = ENOMEM; + else + { + old_value = p; + strcat (old_value, ","); + strcat (old_value, value); + status = mu_header_set_value (env->header, + name, old_value, + 1); + } + } + free (old_value); + } + else + status = mu_header_set_value (env->header, name, value, 1); + } } - else - status = compose_header_set (env, name, value, COMPOSE_REPLACE); } - + free (expansion); return status; } @@ -1130,12 +1144,27 @@ save_dead_message (mu_message_t msg) static int send_message (mu_message_t msg) { + char *mailer_url = NULL; char *sendmail; int status; if (mailvar_get (&sendmail, mailvar_name_sendmail, mailvar_type_string, 0) == 0) { + if (mailvar_is_true (mailvar_name_mailx)) + { + /* + * Mailx compatibility: assume sendmail:// scheme. + */ + if (!mu_is_proto (sendmail)) + { + status = mu_asprintf (&mailer_url, "sendmail://%s", sendmail); + if (status) + return status; + sendmail = mailer_url; + } + } + if (sendmail[0] == '/') status = msg_to_pipe (sendmail, msg); else @@ -1151,8 +1180,10 @@ send_message (mu_message_t msg) if (mailvar_get (&return_address_str, mailvar_name_return_address, mailvar_type_string, 0) == 0) { - status = mu_address_create (&return_address, - return_address_str); + struct mu_address hint = MU_ADDRESS_HINT_INITIALIZER; + status = mu_address_create_hint (&return_address, + return_address_str, + &hint, 0); if (status) { mu_error (_("invalid return address: %s"), @@ -1189,10 +1220,38 @@ send_message (mu_message_t msg) mu_error (_("Variable sendmail not set: no mailer")); status = ENOSYS; } + free (mailer_url); return status; } -/* mail_send0(): shared between mail_send() and mail_reply(); +#define MU_DATETIME_RFC822_LENGTH 31 + +static void +message_add_date (mu_message_t msg) +{ + mu_header_t hdr; + char buf[MU_DATETIME_RFC822_LENGTH+1]; + struct tm ltm; + time_t t; + int rc; + + rc = mu_message_get_header (msg, &hdr); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_header", NULL, rc); + return; + } + + t = time (NULL); + localtime_r (&t, <m); + + mu_strftime (buf, sizeof (buf), MU_DATETIME_FORM_RFC822, <m); + rc = mu_header_set_value (hdr, MU_HEADER_DATE, buf, 1); + if (rc) + mu_diag_funcall (MU_DIAG_ERROR, "mu_header_set_value", MU_HEADER_DATE, rc); +} + +/* mail_compose_send(): shared between mail_send() and mail_reply(); If the variable "record" is set, the outgoing message is saved after being sent. If "save_to" argument is non-zero, @@ -1208,7 +1267,7 @@ send_message (mu_message_t msg) addresses on the command line and message contents on standard input. */ int -mail_send0 (compose_env_t *env, int save_to) +mail_compose_send (compose_env_t *env, int save_to) { int done = 0; int rc; @@ -1265,8 +1324,9 @@ mail_send0 (compose_env_t *env, int save_to) if (strcmp (buf, ".") == 0 && mailvar_is_true (mailvar_name_dot)) done = 1; - else if (mailvar_get (&escape, mailvar_name_escape, - mailvar_type_string, 0) == 0 + else if (interactive + && mailvar_get (&escape, mailvar_name_escape, + mailvar_type_string, 0) == 0 && buf[0] == escape[0]) { if (buf[1] == buf[0]) @@ -1324,10 +1384,10 @@ mail_send0 (compose_env_t *env, int save_to) read_cc_bcc (env); /* Prepare the header */ - if (mailvar_is_true (mailvar_name_xmailer)) - mu_header_set_value (env->header, MU_HEADER_X_MAILER, program_version, 1); + if (mailvar_is_true (mailvar_name_useragent)) + mu_header_set_value (env->header, MU_HEADER_USER_AGENT, program_version, 1); - if (util_header_expand (&env->header) == 0) + if (util_header_expand_aliases (&env->header) == 0) { mu_message_t msg = NULL; int status = 0; @@ -1353,23 +1413,23 @@ mail_send0 (compose_env_t *env, int save_to) if (status) break; + message_add_date (msg); + /* Save outgoing message */ if (save_to) { - char const *rcpt = compose_header_get (env, MU_HEADER_TO, NULL); - if (rcpt) + mu_header_t hdr; + char const *rcpt; + + mu_message_get_header (msg, &hdr); + if (mu_header_sget_value (hdr, MU_HEADER_TO, &rcpt) == 0) { mu_address_t addr = NULL; - - mu_address_create (&addr, rcpt); - mu_address_aget_email (addr, 1, &savefile); + struct mu_address hint = MU_ADDRESS_HINT_INITIALIZER; + + mu_address_create_hint (&addr, rcpt, &hint, 0); + savefile = util_outfilename (addr); mu_address_destroy (&addr); - if (savefile) - { - char *p = strchr (savefile, '@'); - if (p) - *p = 0; - } } } util_save_outgoing (msg, savefile); @@ -1454,8 +1514,18 @@ msg_to_pipe (const char *cmd, mu_message_t msg) { mu_stream_t progstream, msgstream; int status, rc; - - status = mu_command_stream_create (&progstream, cmd, MU_STREAM_WRITE); + char *argv[4]; + + argv[0] = getenv ("SHELL"); + if (!argv[0]) + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = (char*) cmd; + argv[3] = NULL; + status = mu_prog_stream_create (&progstream, + argv[0], + 3, argv, + 0, NULL, MU_STREAM_WRITE); if (status) { mu_error (_("Cannot pipe to %s: %s"), cmd, mu_strerror (status)); |