summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2021-06-06 20:13:44 +0300
committerSergey Poznyakoff <gray@gnu.org>2021-06-06 21:11:10 +0300
commitb6818d6d3c2078b595453f982996090de7619ebc (patch)
tree707e194d399fb0e85f18caf0f7f77974469c6c09
parent8530aa4dfe372948c9d1b2e01be0697057589eb5 (diff)
downloadmailutils-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.h3
-rw-r--r--libmailutils/address/addrstream.c34
-rw-r--r--mail/mail.h3
-rw-r--r--mail/send.c143
-rw-r--r--mail/util.c133
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)

Return to:

Send suggestions and report system problems to the System administrator.