diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2021-06-06 20:13:44 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2021-06-06 21:11:10 +0300 |
commit | b6818d6d3c2078b595453f982996090de7619ebc (patch) | |
tree | 707e194d399fb0e85f18caf0f7f77974469c6c09 | |
parent | 8530aa4dfe372948c9d1b2e01be0697057589eb5 (diff) | |
download | mailutils-b6818d6d3c2078b595453f982996090de7619ebc.tar.gz mailutils-b6818d6d3c2078b595453f982996090de7619ebc.tar.bz2 |
mail: revamp parsing of adresses in send mode
In particular, this fixes parsing of addresses with comma in the local
part.
* include/mailutils/address.h (MU_ADDRESS_HINT_INITIALIZER): New define.
* libmailutils/address/addrstream.c (mu_stream_format_address): Format
local user names without surrounding angle quotes.
* mail/mail.h (util_header_expand): Rename to util_header_expand_aliases.
All uses changed.
(util_address_expand_aliases): New function.
* mail/send.c (compose_header_set): Expand aliases if inplacealiases
is set.
Avoid useless recursion.
* mail/util.c (send_message): Create addresses via mu_address_create_hint
to avoid appending local domain to the unqualified user names.
(mail_send0): Likewise.
(util_address_expand_aliases): New function.
(util_header_expand): Rename to util_header_expand_aliases. Use
util_address_expand_aliases and regular address parsing functions
instead of wordsplit. Unwrap header values.
-rw-r--r-- | include/mailutils/address.h | 3 | ||||
-rw-r--r-- | libmailutils/address/addrstream.c | 34 | ||||
-rw-r--r-- | mail/mail.h | 3 | ||||
-rw-r--r-- | mail/send.c | 143 | ||||
-rw-r--r-- | mail/util.c | 133 |
5 files changed, 181 insertions, 135 deletions
diff --git a/include/mailutils/address.h b/include/mailutils/address.h index 0f3c97c46..f1f7b8d0a 100644 --- a/include/mailutils/address.h +++ b/include/mailutils/address.h @@ -63,6 +63,9 @@ struct mu_address struct mu_address *next; }; +#define MU_ADDRESS_HINT_INITIALIZER \ + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + extern int mu_address_create_null (mu_address_t *); extern int mu_address_create_hint (mu_address_t *, const char *, diff --git a/libmailutils/address/addrstream.c b/libmailutils/address/addrstream.c index 4bcf181ed..0fbaad28a 100644 --- a/libmailutils/address/addrstream.c +++ b/libmailutils/address/addrstream.c @@ -19,6 +19,7 @@ # include <config.h> #endif #include <stdlib.h> +#include <string.h> #include <mailutils/address.h> #include <mailutils/stream.h> @@ -37,23 +38,34 @@ mu_stream_format_address (mu_stream_t str, mu_address_t addr) if (comma) mu_stream_write (str, ",", 1, NULL); - if (addr->personal) + if (!addr->personal && + !addr->comments && + !addr->domain && + !addr->route) { - mu_stream_printf (str, "\"%s\"", addr->personal); - space++; + /* Local user name: print as is */ + mu_stream_write (str, addr->email, strlen (addr->email), NULL); } - - if (addr->comments) + else { + if (addr->personal) + { + mu_stream_printf (str, "\"%s\"", addr->personal); + space++; + } + + if (addr->comments) + { + if (space) + mu_stream_write (str, " ", 1, NULL); + mu_stream_printf (str, "(%s)", addr->comments); + space++; + } + if (space) mu_stream_write (str, " ", 1, NULL); - mu_stream_printf (str, "(%s)", addr->comments); - space++; + mu_stream_printf (str, "<%s>", addr->email); } - - if (space) - mu_stream_write (str, " ", 1, NULL); - mu_stream_printf (str, "<%s>", addr->email); comma++; } } diff --git a/mail/mail.h b/mail/mail.h index d12e4429c..4482b5148 100644 --- a/mail/mail.h +++ b/mail/mail.h @@ -506,7 +506,8 @@ void util_msgset_iterate (msgset_t *msgset, void util_get_content_type (mu_header_t hdr, char **value, char **args); void util_get_hdr_value (mu_header_t hdr, const char *name, char **value); int util_merge_addresses (char **addr_str, const char *value); -int util_header_expand (mu_header_t *hdr); +void util_address_expand_aliases (mu_address_t *paddr); +int util_header_expand_aliases (mu_header_t *hdr); int util_get_message (mu_mailbox_t mbox, size_t msgno, mu_message_t *msg); int util_get_message_part (mu_mailbox_t mbox, msgset_t *msgset, mu_message_t *ret_msg); diff --git a/mail/send.c b/mail/send.c index 1c33c0de5..da565419e 100644 --- a/mail/send.c +++ b/mail/send.c @@ -889,78 +889,92 @@ 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) + && mailvar_is_true (mailvar_name_inplacealiases)) + { + 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; } @@ -1151,8 +1165,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"), @@ -1327,7 +1343,7 @@ mail_send0 (compose_env_t *env, int save_to) if (mailvar_is_true (mailvar_name_xmailer)) mu_header_set_value (env->header, MU_HEADER_X_MAILER, 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; @@ -1360,8 +1376,9 @@ mail_send0 (compose_env_t *env, int save_to) if (rcpt) { mu_address_t addr = NULL; - - mu_address_create (&addr, rcpt); + struct mu_address hint = MU_ADDRESS_HINT_INITIALIZER; + + mu_address_create_hint (&addr, rcpt, &hint, 0); mu_address_aget_email (addr, 1, &savefile); mu_address_destroy (&addr); if (savefile) diff --git a/mail/util.c b/mail/util.c index bc79ad178..9df98e0f7 100644 --- a/mail/util.c +++ b/mail/util.c @@ -888,13 +888,56 @@ is_address_field (const char *name) return 0; } +void +util_address_expand_aliases (mu_address_t *paddr) +{ + struct mu_address hint; + mu_address_t addr = *paddr; + mu_address_t new_addr = NULL; + int rc; + + memset (&hint, 0, sizeof (hint)); + while (addr) + { + struct mu_address *next = addr->next; + addr->next = NULL; + + if (addr->domain == NULL) + { + char *exp = alias_expand (addr->local_part); + if (exp) + { + mu_address_destroy (&addr); + rc = mu_address_create_hint (&addr, exp, &hint, 0); + if (rc) + { + mu_error (_("Cannot parse address `%s': %s"), + exp, mu_strerror (rc)); + free (exp); + continue; + } + free (exp); + } + } + mu_address_union (&new_addr, addr); + mu_address_destroy (&addr); + + addr = next; + } + *paddr = new_addr; +} + int -util_header_expand (mu_header_t *phdr) +util_header_expand_aliases (mu_header_t *phdr) { size_t i, nfields = 0; mu_header_t hdr; int errcnt = 0, rc; + if (mailvar_is_true (mailvar_name_inplacealiases)) + /* If inplacealiases was set, aliases have been already expanded */ + return 0; + rc = mu_header_create (&hdr, "", 0); if (rc) { @@ -905,84 +948,54 @@ util_header_expand (mu_header_t *phdr) mu_header_get_field_count (*phdr, &nfields); for (i = 1; i <= nfields; i++) { - const char *name, *value; + const char *name; + char *value; if (mu_header_sget_field_name (*phdr, i, &name)) continue; - if (mu_header_sget_field_value (*phdr, i, &value)) + if (mu_header_aget_field_value (*phdr, i, &value)) continue; if (is_address_field (name)) { + struct mu_address hint; const char *s; - mu_address_t addr = NULL; - struct mu_wordsplit ws; - size_t j; - - if (mu_header_sget_value (hdr, name, &s) == 0) - mu_address_create (&addr, s); - - ws.ws_delim = ","; - if (mu_wordsplit (value, &ws, - MU_WRDSF_DELIM|MU_WRDSF_SQUEEZE_DELIMS| - MU_WRDSF_WS| - MU_WRDSF_NOVAR|MU_WRDSF_NOCMD)) + mu_address_t a = NULL; + + mu_string_unfold (value, NULL); + + memset (&hint, 0, sizeof (hint)); + rc = mu_address_create_hint (&a, value, &hint, 0); + if (rc == 0) { - errcnt++; - mu_error (_("cannot split line `%s': %s"), value, - mu_wordsplit_strerror (&ws)); + mu_address_t ha = NULL; + util_address_expand_aliases (&a); + if (mu_header_sget_value (hdr, name, &s) == 0) + mu_address_create_hint (&ha, s, &hint, 0); + mu_address_union (&ha, a); + mu_address_destroy (&a); + a = ha; } else { - for (j = 0; j < ws.ws_wordc; j++) - { - char *exp_mem = NULL; - mu_address_t new_addr; - char *p = ws.ws_wordv[j]; - char *exp; - - if (mailvar_is_true (mailvar_name_inplacealiases)) - /* If inplacealiases was set, the value was a - lready expanded */ - exp = p; - else - { - exp_mem = alias_expand (p); - exp = exp_mem ? exp_mem : p; - } - rc = mu_address_create (&new_addr, exp); - if (rc) - { - errcnt++; - if (exp_mem) - mu_error (_("Cannot parse address `%s'" - " (while expanding `%s'): %s"), - exp, p, mu_strerror (rc)); - else - mu_error (_("Cannot parse address `%s': %s"), - p, mu_strerror (rc)); - } - - mu_address_union (&addr, new_addr); - mu_address_destroy (&new_addr); - free (exp_mem); - } + mu_error (_("Cannot parse address `%s': %s"), + value, mu_strerror (rc)); + } - if (addr) - { - const char *newvalue; + if (a) + { + const char *newvalue; - rc = mu_address_sget_printable (addr, &newvalue); - if (rc == 0 && newvalue) - mu_header_set_value (hdr, name, newvalue, 1); - mu_address_destroy (&addr); - } + rc = mu_address_sget_printable (a, &newvalue); + if (rc == 0 && newvalue) + mu_header_set_value (hdr, name, newvalue, 1); + mu_address_destroy (&a); } - mu_wordsplit_free (&ws); } else mu_header_append (hdr, name, value); + free (value); } if (errcnt == 0) |