NeoMutt  2020-09-25
Teaching an old dog new tricks
DOXYGEN
alias.c
Go to the documentation of this file.
1 
31 #include "config.h"
32 #include <stddef.h>
33 #include <pwd.h>
34 #include <stdbool.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <wchar.h>
39 #include <wctype.h>
40 #include "mutt/lib.h"
41 #include "address/lib.h"
42 #include "config/lib.h"
43 #include "email/lib.h"
44 #include "core/lib.h"
45 #include "gui/lib.h"
46 #include "mutt.h"
47 #include "alias.h"
48 #include "lib.h"
49 #include "send/lib.h"
50 #include "maillist.h"
51 #include "mutt_globals.h"
52 #include "muttlib.h"
53 #include "reverse.h"
54 
55 struct AliasList Aliases = TAILQ_HEAD_INITIALIZER(Aliases);
56 
81 static void write_safe_address(FILE *fp, char *s)
82 {
83  while (*s)
84  {
85  if ((*s == '\\') || (*s == '`') || (*s == '\'') || (*s == '"') || (*s == '$'))
86  fputc('\\', fp);
87  fputc(*s, fp);
88  s++;
89  }
90 }
91 
99 static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
100 {
101  struct Address *a = TAILQ_FIRST(al);
102  while (a)
103  {
104  if (!a->group && !a->personal && a->mailbox && !strchr(a->mailbox, '@'))
105  {
106  struct AddressList *alias = alias_lookup(a->mailbox);
107  if (alias)
108  {
109  bool duplicate = false;
110  struct ListNode *np = NULL;
111  STAILQ_FOREACH(np, expn, entries)
112  {
113  if (mutt_str_equal(a->mailbox, np->data)) /* alias already found */
114  {
115  mutt_debug(LL_DEBUG1, "loop in alias found for '%s'\n", a->mailbox);
116  duplicate = true;
117  break;
118  }
119  }
120 
121  if (duplicate)
122  {
123  // We've already seen this alias, so drop it
124  struct Address *next = TAILQ_NEXT(a, entries);
125  TAILQ_REMOVE(al, a, entries);
126  mutt_addr_free(&a);
127  a = next;
128  continue;
129  }
130 
131  // Keep a list of aliases that we've already seen
133 
134  /* The alias may expand to several addresses,
135  * some of which may themselves be aliases.
136  * Create a copy and recursively expand any aliases within. */
137  struct AddressList copy = TAILQ_HEAD_INITIALIZER(copy);
138  mutt_addrlist_copy(&copy, alias, false);
139  expand_aliases_r(&copy, expn);
140 
141  /* Next, move the expanded addresses
142  * from the copy into the original list (before the alias) */
143  struct Address *a2 = NULL, *tmp = NULL;
144  TAILQ_FOREACH_SAFE(a2, &copy, entries, tmp)
145  {
146  TAILQ_INSERT_BEFORE(a, a2, entries);
147  }
148  a = TAILQ_PREV(a, AddressList, entries);
149  // Finally, remove the alias itself
150  struct Address *next = TAILQ_NEXT(a, entries);
151  TAILQ_REMOVE(al, next, entries);
152  mutt_addr_free(&next);
153  }
154  else
155  {
156  struct passwd *pw = getpwnam(a->mailbox);
157  if (pw)
158  {
159  char namebuf[256];
160 
161  mutt_gecos_name(namebuf, sizeof(namebuf), pw);
162  mutt_str_replace(&a->personal, namebuf);
163  }
164  }
165  }
166  a = TAILQ_NEXT(a, entries);
167  }
168 
169  const char *fqdn = NULL;
170  if (C_UseDomain && (fqdn = mutt_fqdn(true, NeoMutt->sub)))
171  {
172  /* now qualify all local addresses */
173  mutt_addrlist_qualify(al, fqdn);
174  }
175 }
176 
185 static void recode_buf(char *buf, size_t buflen)
186 {
187  if (!C_ConfigCharset || !C_Charset)
188  return;
189 
190  char *s = mutt_str_dup(buf);
191  if (!s)
192  return;
194  mutt_str_copy(buf, s, buflen);
195  FREE(&s);
196 }
197 
209 static int check_alias_name(const char *s, char *dest, size_t destlen)
210 {
211  wchar_t wc;
212  mbstate_t mb;
213  size_t l;
214  int rc = 0;
215  bool dry = !dest || !destlen;
216 
217  memset(&mb, 0, sizeof(mbstate_t));
218 
219  if (!dry)
220  destlen--;
221  for (; s && *s && (dry || destlen) && (l = mbrtowc(&wc, s, MB_CUR_MAX, &mb)) != 0;
222  s += l, destlen -= l)
223  {
224  bool bad = (l == (size_t)(-1)) || (l == (size_t)(-2)); /* conversion error */
225  bad = bad || (!dry && l > destlen); /* too few room for mb char */
226  if (l == 1)
227  bad = bad || (!strchr("-_+=.", *s) && !iswalnum(wc));
228  else
229  bad = bad || !iswalnum(wc);
230  if (bad)
231  {
232  if (dry)
233  return -1;
234  if (l == (size_t)(-1))
235  memset(&mb, 0, sizeof(mbstate_t));
236  *dest++ = '_';
237  rc = -1;
238  }
239  else if (!dry)
240  {
241  memcpy(dest, s, l);
242  dest += l;
243  }
244  }
245  if (!dry)
246  *dest = '\0';
247  return rc;
248 }
249 
257 static bool string_is_address(const char *str, const char *user, const char *domain)
258 {
259  char buf[1024];
260 
261  snprintf(buf, sizeof(buf), "%s@%s", NONULL(user), NONULL(domain));
262  if (mutt_istr_equal(str, buf))
263  return true;
264 
265  return false;
266 }
267 
276 struct AddressList *alias_lookup(const char *name)
277 {
278  struct Alias *a = NULL;
279 
280  TAILQ_FOREACH(a, &Aliases, entries)
281  {
282  if (mutt_istr_equal(name, a->name))
283  return &a->addr;
284  }
285  return NULL;
286 }
287 
294 void mutt_expand_aliases(struct AddressList *al)
295 {
296  struct ListHead expn; /* previously expanded aliases to avoid loops */
297 
298  STAILQ_INIT(&expn);
299  expand_aliases_r(al, &expn);
300  mutt_list_free(&expn);
302 }
303 
309 {
310  mutt_expand_aliases(&env->from);
311  mutt_expand_aliases(&env->to);
312  mutt_expand_aliases(&env->cc);
313  mutt_expand_aliases(&env->bcc);
316 }
317 
326 struct AddressList *mutt_get_address(struct Envelope *env, const char **prefix)
327 {
328  struct AddressList *al = NULL;
329  const char *pfx = NULL;
330 
331  if (mutt_addr_is_user(TAILQ_FIRST(&env->from)))
332  {
333  if (!TAILQ_EMPTY(&env->to) && !mutt_is_mail_list(TAILQ_FIRST(&env->to)))
334  {
335  pfx = "To";
336  al = &env->to;
337  }
338  else
339  {
340  pfx = "Cc";
341  al = &env->cc;
342  }
343  }
344  else if (!TAILQ_EMPTY(&env->reply_to) && !mutt_is_mail_list(TAILQ_FIRST(&env->reply_to)))
345  {
346  pfx = "Reply-To";
347  al = &env->reply_to;
348  }
349  else
350  {
351  al = &env->from;
352  pfx = "From";
353  }
354 
355  if (prefix)
356  *prefix = pfx;
357 
358  return al;
359 }
360 
365 void alias_create(struct AddressList *al)
366 {
367  struct Address *addr = NULL;
368  char buf[1024], tmp[1024] = { 0 }, prompt[2048];
369  char *pc = NULL;
370  char *err = NULL;
371  char fixed[1024];
372 
373  if (al)
374  {
375  addr = TAILQ_FIRST(al);
376  if (addr && addr->mailbox)
377  {
378  mutt_str_copy(tmp, addr->mailbox, sizeof(tmp));
379  pc = strchr(tmp, '@');
380  if (pc)
381  *pc = '\0';
382  }
383  }
384 
385  /* Don't suggest a bad alias name in the event of a strange local part. */
386  check_alias_name(tmp, buf, sizeof(buf));
387 
388 retry_name:
389  /* L10N: prompt to add a new alias */
390  if ((mutt_get_field(_("Alias as: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0) ||
391  (buf[0] == '\0'))
392  {
393  return;
394  }
395 
396  /* check to see if the user already has an alias defined */
397  if (alias_lookup(buf))
398  {
399  mutt_error(_("You already have an alias defined with that name"));
400  return;
401  }
402 
403  if (check_alias_name(buf, fixed, sizeof(fixed)))
404  {
405  switch (mutt_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
406  {
407  case MUTT_YES:
408  mutt_str_copy(buf, fixed, sizeof(buf));
409  goto retry_name;
410  case MUTT_ABORT:
411  return;
412  default:; // do nothing
413  }
414  }
415 
416  struct Alias *alias = alias_new();
417  alias->name = mutt_str_dup(buf);
418 
420 
421  if (addr && addr->mailbox)
422  mutt_str_copy(buf, addr->mailbox, sizeof(buf));
423  else
424  buf[0] = '\0';
425 
426  mutt_addrlist_to_intl(al, NULL);
427 
428  do
429  {
430  if ((mutt_get_field(_("Address: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0) ||
431  (buf[0] == '\0'))
432  {
433  alias_free(&alias);
434  return;
435  }
436 
437  mutt_addrlist_parse(&alias->addr, buf);
438  if (TAILQ_EMPTY(&alias->addr))
439  mutt_beep(false);
440  if (mutt_addrlist_to_intl(&alias->addr, &err))
441  {
442  mutt_error(_("Bad IDN: '%s'"), err);
443  FREE(&err);
444  continue;
445  }
446  } while (TAILQ_EMPTY(&alias->addr));
447 
448  if (addr && addr->personal && !mutt_is_mail_list(addr))
449  mutt_str_copy(buf, addr->personal, sizeof(buf));
450  else
451  buf[0] = '\0';
452 
453  if (mutt_get_field(_("Personal name: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0)
454  {
455  alias_free(&alias);
456  return;
457  }
458  mutt_str_replace(&TAILQ_FIRST(&alias->addr)->personal, buf);
459 
460  buf[0] = '\0';
461  if (mutt_get_field(_("Comment: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) == 0)
462  mutt_str_replace(&alias->comment, buf);
463 
464  buf[0] = '\0';
465  mutt_addrlist_write(&alias->addr, buf, sizeof(buf), true);
466  if (alias->comment)
467  {
468  snprintf(prompt, sizeof(prompt), "[%s = %s # %s] %s", alias->name, buf,
469  alias->comment, _("Accept?"));
470  }
471  else
472  {
473  snprintf(prompt, sizeof(prompt), "[%s = %s] %s", alias->name, buf, _("Accept?"));
474  }
475  if (mutt_yesorno(prompt, MUTT_YES) != MUTT_YES)
476  {
477  alias_free(&alias);
478  return;
479  }
480 
481  alias_reverse_add(alias);
482  TAILQ_INSERT_TAIL(&Aliases, alias, entries);
483 
484  mutt_str_copy(buf, C_AliasFile, sizeof(buf));
485  if (mutt_get_field(_("Save to file: "), buf, sizeof(buf), MUTT_FILE | MUTT_CLEAR) != 0)
486  return;
487  mutt_expand_path(buf, sizeof(buf));
488  FILE *fp_alias = fopen(buf, "a+");
489  if (!fp_alias)
490  {
491  mutt_perror(buf);
492  return;
493  }
494 
495  /* terminate existing file with \n if necessary */
496  if (fseek(fp_alias, 0, SEEK_END))
497  goto fseek_err;
498  if (ftell(fp_alias) > 0)
499  {
500  if (fseek(fp_alias, -1, SEEK_CUR) < 0)
501  goto fseek_err;
502  if (fread(buf, 1, 1, fp_alias) != 1)
503  {
504  mutt_perror(_("Error reading alias file"));
505  mutt_file_fclose(&fp_alias);
506  return;
507  }
508  if (fseek(fp_alias, 0, SEEK_END) < 0)
509  goto fseek_err;
510  if (buf[0] != '\n')
511  fputc('\n', fp_alias);
512  }
513 
514  if (check_alias_name(alias->name, NULL, 0))
515  mutt_file_quote_filename(alias->name, buf, sizeof(buf));
516  else
517  mutt_str_copy(buf, alias->name, sizeof(buf));
518  recode_buf(buf, sizeof(buf));
519  fprintf(fp_alias, "alias %s ", buf);
520  buf[0] = '\0';
521  mutt_addrlist_write(&alias->addr, buf, sizeof(buf), false);
522  recode_buf(buf, sizeof(buf));
523  write_safe_address(fp_alias, buf);
524  if (alias->comment)
525  fprintf(fp_alias, " # %s", alias->comment);
526  fputc('\n', fp_alias);
527  if (mutt_file_fsync_close(&fp_alias) != 0)
528  mutt_perror(_("Trouble adding alias"));
529  else
530  mutt_message(_("Alias added"));
531 
532  return;
533 
534 fseek_err:
535  mutt_perror(_("Error seeking in alias file"));
536  mutt_file_fclose(&fp_alias);
537 }
538 
544 bool mutt_addr_is_user(const struct Address *addr)
545 {
546  if (!addr)
547  {
548  mutt_debug(LL_DEBUG5, "no, NULL address\n");
549  return false;
550  }
551  if (!addr->mailbox)
552  {
553  mutt_debug(LL_DEBUG5, "no, no mailbox\n");
554  return false;
555  }
556 
557  if (mutt_istr_equal(addr->mailbox, Username))
558  {
559  mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", addr->mailbox, Username);
560  return true;
561  }
563  {
564  mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", addr->mailbox, Username, ShortHostname);
565  return true;
566  }
567  const char *fqdn = mutt_fqdn(false, NeoMutt->sub);
568  if (string_is_address(addr->mailbox, Username, fqdn))
569  {
570  mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
571  return true;
572  }
573  fqdn = mutt_fqdn(true, NeoMutt->sub);
574  if (string_is_address(addr->mailbox, Username, fqdn))
575  {
576  mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
577  return true;
578  }
579 
580  if (C_From && mutt_istr_equal(C_From->mailbox, addr->mailbox))
581  {
582  mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", addr->mailbox, C_From->mailbox);
583  return true;
584  }
585 
586  if (mutt_regexlist_match(&Alternates, addr->mailbox))
587  {
588  mutt_debug(LL_DEBUG5, "yes, %s matched by alternates\n", addr->mailbox);
589  if (mutt_regexlist_match(&UnAlternates, addr->mailbox))
590  mutt_debug(LL_DEBUG5, "but, %s matched by unalternates\n", addr->mailbox);
591  else
592  return true;
593  }
594 
595  mutt_debug(LL_DEBUG5, "no, all failed\n");
596  return false;
597 }
598 
605 struct Alias *alias_new(void)
606 {
607  struct Alias *a = mutt_mem_calloc(1, sizeof(struct Alias));
608  TAILQ_INIT(&a->addr);
609  return a;
610 }
611 
616 void alias_free(struct Alias **ptr)
617 {
618  if (!ptr || !*ptr)
619  return;
620 
621  struct Alias *alias = *ptr;
622 
623  struct EventAlias ea = { alias };
625 
626  FREE(&alias->name);
627  FREE(&alias->comment);
628  mutt_addrlist_clear(&(alias->addr));
629  FREE(ptr);
630 }
631 
636 void aliaslist_free(struct AliasList *al)
637 {
638  struct Alias *np = NULL, *tmp = NULL;
639  TAILQ_FOREACH_SAFE(np, al, entries, tmp)
640  {
641  TAILQ_REMOVE(al, np, entries);
642  alias_free(&np);
643  }
644  TAILQ_INIT(al);
645 }
646 
650 void alias_init(void)
651 {
652  /* reverse alias keys need to be strdup'ed because of idna conversions */
655 }
656 
660 void alias_shutdown(void)
661 {
662  struct Alias *np = NULL;
663  TAILQ_FOREACH(np, &Aliases, entries)
664  {
666  }
669 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
Convenience wrapper for the gui headers.
A shortcut for an email address or addresses.
Definition: alias.h:33
#define TAILQ_INSERT_BEFORE(listelm, elm, field)
Definition: queue.h:779
char * name
Short name.
Definition: alias.h:35
#define NONULL(x)
Definition: string2.h:37
void alias_create(struct AddressList *al)
Create a new Alias from an Address.
Definition: alias.c:365
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:294
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:62
#define TAILQ_FIRST(head)
Definition: queue.h:716
#define mutt_perror(...)
Definition: logging.h:85
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:63
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:754
Structs that make up an email.
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
Convenience wrapper for the send headers.
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:169
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:447
#define mutt_message(...)
Definition: logging.h:83
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1386
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1468
void mutt_expand_aliases_env(struct Envelope *env)
Expand aliases in all the fields of an Envelope.
Definition: alias.c:308
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list? - Implements addr_predicate_t.
Definition: maillist.c:45
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:737
Alias has changed, NotifyAlias, EventAlias.
Definition: notify_type.h:43
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:728
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
void alias_init(void)
Set up the Alias globals.
Definition: alias.c:650
#define _(a)
Definition: message.h:28
An alias-change event.
Definition: alias.h:59
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
WHERE bool C_UseDomain
Config: Qualify local addresses using this domain.
Definition: mutt_globals.h:167
char * C_AliasFile
Config: Save new aliases to this file.
Definition: config.c:45
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:440
Container for Accounts, Notifications.
Definition: neomutt.h:36
Representation of a single alias to an email address.
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
Convenience wrapper for the config headers.
Email Address Handling.
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:52
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:99
Some miscellaneous functions.
#define MUTT_HASH_STRCASECMP
use strcasecmp() to compare keys
Definition: hash.h:98
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:128
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1405
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:379
Many unsorted constants and some structs.
#define STAILQ_INIT(head)
Definition: queue.h:369
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:276
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct HashTable * ReverseAliases
Hash Table of aliases (email address -> alias)
Definition: reverse.c:37
Convenience wrapper for the core headers.
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:605
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
#define TAILQ_INIT(head)
Definition: queue.h:758
bool mutt_regexlist_match(struct RegexList *rl, const char *str)
Does a string match any Regex in the list?
Definition: regex.c:190
void alias_reverse_add(struct Alias *alias)
Add an email address lookup for an Alias.
Definition: reverse.c:43
User aborted the question (with Ctrl-G)
Definition: quad.h:38
void alias_shutdown(void)
Clean up the Alias globals.
Definition: alias.c:660
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:834
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:55
#define MUTT_HASH_ALLOW_DUPS
allow duplicate keys to be inserted
Definition: hash.h:100
struct AddressList * mutt_get_address(struct Envelope *env, const char **prefix)
Get an Address from an Envelope.
Definition: alias.c:326
WHERE char * C_ConfigCharset
Config: Character set that the config files are in.
Definition: mutt_globals.h:88
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:50
static int check_alias_name(const char *s, char *dest, size_t destlen)
Sanity-check an alias name.
Definition: alias.c:209
char * comment
Free-form comment string.
Definition: alias.h:37
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:802
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition: list.c:45
size_t mutt_file_quote_filename(const char *filename, char *buf, size_t buflen)
Quote a filename to survive the shell&#39;s quoting rules.
Definition: file.c:793
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
WHERE struct Address * C_From
Config: Default &#39;From&#39; address to use, if isn&#39;t otherwise set.
Definition: mutt_globals.h:81
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
Handle mailing lists.
void alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:616
#define MUTT_FILE
Do file completion.
Definition: mutt.h:58
static void write_safe_address(FILE *fp, char *s)
Defang malicious email addresses.
Definition: alias.c:81
char * personal
Real name of address.
Definition: address.h:36
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:636
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:650
An Alias is about to be deleted.
Definition: alias.h:53
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:1181
char * data
String.
Definition: list.h:36
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1304
Log at debug level 1.
Definition: logging.h:40
bool group
Group mailbox?
Definition: address.h:38
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user&#39;s real name in /etc/passwd.
Definition: muttlib.c:362
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
#define mutt_error(...)
Definition: logging.h:84
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:99
#define FREE(x)
Definition: memory.h:40
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:544
static bool string_is_address(const char *str, const char *user, const char *domain)
Does an email address match a user and domain?
Definition: alias.c:257
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
#define TAILQ_NEXT(elm, field)
Definition: queue.h:825
Hundreds of global variables to back the user variables.
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define TAILQ_EMPTY(head)
Definition: queue.h:714
#define MUTT_HASH_STRDUP_KEYS
make a copy of the keys
Definition: hash.h:99
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
Log at debug level 5.
Definition: logging.h:44
Convenience wrapper for the library headers.
void alias_reverse_delete(struct Alias *alias)
Remove an email address lookup for an Alias.
Definition: reverse.c:65
A List node for strings.
Definition: list.h:34
#define TAILQ_PREV(elm, headname, field)
Definition: queue.h:827
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:251
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1150
Manage alias reverse lookups.
The header of an Email.
Definition: envelope.h:54
static void recode_buf(char *buf, size_t buflen)
Convert some text between two character sets.
Definition: alias.c:185
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:152