NeoMutt  2020-06-26-89-g172cd3
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 "maillist.h"
50 #include "mutt_globals.h"
51 #include "muttlib.h"
52 #include "reverse.h"
53 #include "send/lib.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 
100 static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
101 {
102  struct Address *a = TAILQ_FIRST(al);
103  while (a)
104  {
105  if (!a->group && !a->personal && a->mailbox && !strchr(a->mailbox, '@'))
106  {
107  struct AddressList *alias = alias_lookup(a->mailbox);
108  if (alias)
109  {
110  bool duplicate = false;
111  struct ListNode *np = NULL;
112  STAILQ_FOREACH(np, expn, entries)
113  {
114  if (mutt_str_equal(a->mailbox, np->data)) /* alias already found */
115  {
116  mutt_debug(LL_DEBUG1, "loop in alias found for '%s'\n", a->mailbox);
117  duplicate = true;
118  break;
119  }
120  }
121 
122  if (duplicate)
123  {
124  // We've already seen this alias, so drop it
125  struct Address *next = TAILQ_NEXT(a, entries);
126  TAILQ_REMOVE(al, a, entries);
127  mutt_addr_free(&a);
128  a = next;
129  continue;
130  }
131 
132  // Keep a list of aliases that we've already seen
134 
135  /* The alias may expand to several addresses,
136  * some of which may themselves be aliases.
137  * Create a copy and recursively expand any aliases within. */
138  struct AddressList copy = TAILQ_HEAD_INITIALIZER(copy);
139  mutt_addrlist_copy(&copy, alias, false);
140  expand_aliases_r(&copy, expn);
141 
142  /* Next, move the expanded addresses
143  * from the copy into the original list (before the alias) */
144  struct Address *a2 = NULL, *tmp = NULL;
145  TAILQ_FOREACH_SAFE(a2, &copy, entries, tmp)
146  {
147  TAILQ_INSERT_BEFORE(a, a2, entries);
148  }
149  a = TAILQ_PREV(a, AddressList, entries);
150  // Finally, remove the alias itself
151  struct Address *next = TAILQ_NEXT(a, entries);
152  TAILQ_REMOVE(al, next, entries);
153  mutt_addr_free(&next);
154  }
155  else
156  {
157  struct passwd *pw = getpwnam(a->mailbox);
158  if (pw)
159  {
160  char namebuf[256];
161 
162  mutt_gecos_name(namebuf, sizeof(namebuf), pw);
163  mutt_str_replace(&a->personal, namebuf);
164  }
165  }
166  }
167  a = TAILQ_NEXT(a, entries);
168  }
169 
170  const char *fqdn = NULL;
171  if (C_UseDomain && (fqdn = mutt_fqdn(true, NeoMutt->sub)))
172  {
173  /* now qualify all local addresses */
174  mutt_addrlist_qualify(al, fqdn);
175  }
176 }
177 
186 static void recode_buf(char *buf, size_t buflen)
187 {
188  if (!C_ConfigCharset || !C_Charset)
189  return;
190 
191  char *s = mutt_str_dup(buf);
192  if (!s)
193  return;
195  mutt_str_copy(buf, s, buflen);
196  FREE(&s);
197 }
198 
210 static int check_alias_name(const char *s, char *dest, size_t destlen)
211 {
212  wchar_t wc;
213  mbstate_t mb;
214  size_t l;
215  int rc = 0;
216  bool dry = !dest || !destlen;
217 
218  memset(&mb, 0, sizeof(mbstate_t));
219 
220  if (!dry)
221  destlen--;
222  for (; s && *s && (dry || destlen) && (l = mbrtowc(&wc, s, MB_CUR_MAX, &mb)) != 0;
223  s += l, destlen -= l)
224  {
225  bool bad = (l == (size_t)(-1)) || (l == (size_t)(-2)); /* conversion error */
226  bad = bad || (!dry && l > destlen); /* too few room for mb char */
227  if (l == 1)
228  bad = bad || (!strchr("-_+=.", *s) && !iswalnum(wc));
229  else
230  bad = bad || !iswalnum(wc);
231  if (bad)
232  {
233  if (dry)
234  return -1;
235  if (l == (size_t)(-1))
236  memset(&mb, 0, sizeof(mbstate_t));
237  *dest++ = '_';
238  rc = -1;
239  }
240  else if (!dry)
241  {
242  memcpy(dest, s, l);
243  dest += l;
244  }
245  }
246  if (!dry)
247  *dest = '\0';
248  return rc;
249 }
250 
258 static bool string_is_address(const char *str, const char *user, const char *domain)
259 {
260  char buf[1024];
261 
262  snprintf(buf, sizeof(buf), "%s@%s", NONULL(user), NONULL(domain));
263  if (mutt_istr_equal(str, buf))
264  return true;
265 
266  return false;
267 }
268 
277 struct AddressList *alias_lookup(const char *name)
278 {
279  struct Alias *a = NULL;
280 
281  TAILQ_FOREACH(a, &Aliases, entries)
282  {
283  if (mutt_istr_equal(name, a->name))
284  return &a->addr;
285  }
286  return NULL;
287 }
288 
295 void mutt_expand_aliases(struct AddressList *al)
296 {
297  struct ListHead expn; /* previously expanded aliases to avoid loops */
298 
299  STAILQ_INIT(&expn);
300  expand_aliases_r(al, &expn);
301  mutt_list_free(&expn);
303 }
304 
310 {
311  mutt_expand_aliases(&env->from);
312  mutt_expand_aliases(&env->to);
313  mutt_expand_aliases(&env->cc);
314  mutt_expand_aliases(&env->bcc);
317 }
318 
327 struct AddressList *mutt_get_address(struct Envelope *env, const char **prefix)
328 {
329  struct AddressList *al = NULL;
330  const char *pfx = NULL;
331 
332  if (mutt_addr_is_user(TAILQ_FIRST(&env->from)))
333  {
334  if (!TAILQ_EMPTY(&env->to) && !mutt_is_mail_list(TAILQ_FIRST(&env->to)))
335  {
336  pfx = "To";
337  al = &env->to;
338  }
339  else
340  {
341  pfx = "Cc";
342  al = &env->cc;
343  }
344  }
345  else if (!TAILQ_EMPTY(&env->reply_to) && !mutt_is_mail_list(TAILQ_FIRST(&env->reply_to)))
346  {
347  pfx = "Reply-To";
348  al = &env->reply_to;
349  }
350  else
351  {
352  al = &env->from;
353  pfx = "From";
354  }
355 
356  if (prefix)
357  *prefix = pfx;
358 
359  return al;
360 }
361 
366 void alias_create(struct AddressList *al)
367 {
368  struct Address *addr = NULL;
369  char buf[1024], tmp[1024] = { 0 }, prompt[2048];
370  char *pc = NULL;
371  char *err = NULL;
372  char fixed[1024];
373 
374  if (al)
375  {
376  addr = TAILQ_FIRST(al);
377  if (addr && addr->mailbox)
378  {
379  mutt_str_copy(tmp, addr->mailbox, sizeof(tmp));
380  pc = strchr(tmp, '@');
381  if (pc)
382  *pc = '\0';
383  }
384  }
385 
386  /* Don't suggest a bad alias name in the event of a strange local part. */
387  check_alias_name(tmp, buf, sizeof(buf));
388 
389 retry_name:
390  /* L10N: prompt to add a new alias */
391  if ((mutt_get_field(_("Alias as: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0) ||
392  (buf[0] == '\0'))
393  {
394  return;
395  }
396 
397  /* check to see if the user already has an alias defined */
398  if (alias_lookup(buf))
399  {
400  mutt_error(_("You already have an alias defined with that name"));
401  return;
402  }
403 
404  if (check_alias_name(buf, fixed, sizeof(fixed)))
405  {
406  switch (mutt_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
407  {
408  case MUTT_YES:
409  mutt_str_copy(buf, fixed, sizeof(buf));
410  goto retry_name;
411  case MUTT_ABORT:
412  return;
413  default:; // do nothing
414  }
415  }
416 
417  struct Alias *alias = alias_new();
418  alias->name = mutt_str_dup(buf);
419 
421 
422  if (addr && addr->mailbox)
423  mutt_str_copy(buf, addr->mailbox, sizeof(buf));
424  else
425  buf[0] = '\0';
426 
427  mutt_addrlist_to_intl(al, NULL);
428 
429  do
430  {
431  if ((mutt_get_field(_("Address: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0) ||
432  (buf[0] == '\0'))
433  {
434  alias_free(&alias);
435  return;
436  }
437 
438  mutt_addrlist_parse(&alias->addr, buf);
439  if (TAILQ_EMPTY(&alias->addr))
440  mutt_beep(false);
441  if (mutt_addrlist_to_intl(&alias->addr, &err))
442  {
443  mutt_error(_("Bad IDN: '%s'"), err);
444  FREE(&err);
445  continue;
446  }
447  } while (TAILQ_EMPTY(&alias->addr));
448 
449  if (addr && addr->personal && !mutt_is_mail_list(addr))
450  mutt_str_copy(buf, addr->personal, sizeof(buf));
451  else
452  buf[0] = '\0';
453 
454  if (mutt_get_field(_("Personal name: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0)
455  {
456  alias_free(&alias);
457  return;
458  }
459  mutt_str_replace(&TAILQ_FIRST(&alias->addr)->personal, buf);
460 
461  buf[0] = '\0';
462  if (mutt_get_field(_("Comment: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) == 0)
463  mutt_str_replace(&alias->comment, buf);
464 
465  buf[0] = '\0';
466  mutt_addrlist_write(&alias->addr, buf, sizeof(buf), true);
467  if (alias->comment)
468  {
469  snprintf(prompt, sizeof(prompt), "[%s = %s # %s] %s", alias->name, buf,
470  alias->comment, _("Accept?"));
471  }
472  else
473  {
474  snprintf(prompt, sizeof(prompt), "[%s = %s] %s", alias->name, buf, _("Accept?"));
475  }
476  if (mutt_yesorno(prompt, MUTT_YES) != MUTT_YES)
477  {
478  alias_free(&alias);
479  return;
480  }
481 
482  alias_reverse_add(alias);
483  TAILQ_INSERT_TAIL(&Aliases, alias, entries);
484 
485  mutt_str_copy(buf, C_AliasFile, sizeof(buf));
486  if (mutt_get_field(_("Save to file: "), buf, sizeof(buf), MUTT_FILE | MUTT_CLEAR) != 0)
487  return;
488  mutt_expand_path(buf, sizeof(buf));
489  FILE *fp_alias = fopen(buf, "a+");
490  if (!fp_alias)
491  {
492  mutt_perror(buf);
493  return;
494  }
495 
496  /* terminate existing file with \n if necessary */
497  if (fseek(fp_alias, 0, SEEK_END))
498  goto fseek_err;
499  if (ftell(fp_alias) > 0)
500  {
501  if (fseek(fp_alias, -1, SEEK_CUR) < 0)
502  goto fseek_err;
503  if (fread(buf, 1, 1, fp_alias) != 1)
504  {
505  mutt_perror(_("Error reading alias file"));
506  mutt_file_fclose(&fp_alias);
507  return;
508  }
509  if (fseek(fp_alias, 0, SEEK_END) < 0)
510  goto fseek_err;
511  if (buf[0] != '\n')
512  fputc('\n', fp_alias);
513  }
514 
515  if (check_alias_name(alias->name, NULL, 0))
516  mutt_file_quote_filename(alias->name, buf, sizeof(buf));
517  else
518  mutt_str_copy(buf, alias->name, sizeof(buf));
519  recode_buf(buf, sizeof(buf));
520  fprintf(fp_alias, "alias %s ", buf);
521  buf[0] = '\0';
522  mutt_addrlist_write(&alias->addr, buf, sizeof(buf), false);
523  recode_buf(buf, sizeof(buf));
524  write_safe_address(fp_alias, buf);
525  if (alias->comment)
526  fprintf(fp_alias, " # %s", alias->comment);
527  fputc('\n', fp_alias);
528  if (mutt_file_fsync_close(&fp_alias) != 0)
529  mutt_perror(_("Trouble adding alias"));
530  else
531  mutt_message(_("Alias added"));
532 
533  return;
534 
535 fseek_err:
536  mutt_perror(_("Error seeking in alias file"));
537  mutt_file_fclose(&fp_alias);
538 }
539 
545 bool mutt_addr_is_user(const struct Address *addr)
546 {
547  if (!addr)
548  {
549  mutt_debug(LL_DEBUG5, "no, NULL address\n");
550  return false;
551  }
552  if (!addr->mailbox)
553  {
554  mutt_debug(LL_DEBUG5, "no, no mailbox\n");
555  return false;
556  }
557 
558  if (mutt_istr_equal(addr->mailbox, Username))
559  {
560  mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", addr->mailbox, Username);
561  return true;
562  }
564  {
565  mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", addr->mailbox, Username, ShortHostname);
566  return true;
567  }
568  const char *fqdn = mutt_fqdn(false, NeoMutt->sub);
569  if (string_is_address(addr->mailbox, Username, fqdn))
570  {
571  mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
572  return true;
573  }
574  fqdn = mutt_fqdn(true, NeoMutt->sub);
575  if (string_is_address(addr->mailbox, Username, fqdn))
576  {
577  mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
578  return true;
579  }
580 
581  if (C_From && mutt_istr_equal(C_From->mailbox, addr->mailbox))
582  {
583  mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", addr->mailbox, C_From->mailbox);
584  return true;
585  }
586 
587  if (mutt_regexlist_match(&Alternates, addr->mailbox))
588  {
589  mutt_debug(LL_DEBUG5, "yes, %s matched by alternates\n", addr->mailbox);
590  if (mutt_regexlist_match(&UnAlternates, addr->mailbox))
591  mutt_debug(LL_DEBUG5, "but, %s matched by unalternates\n", addr->mailbox);
592  else
593  return true;
594  }
595 
596  mutt_debug(LL_DEBUG5, "no, all failed\n");
597  return false;
598 }
599 
606 struct Alias *alias_new(void)
607 {
608  struct Alias *a = mutt_mem_calloc(1, sizeof(struct Alias));
609  TAILQ_INIT(&a->addr);
610  return a;
611 }
612 
617 void alias_free(struct Alias **ptr)
618 {
619  if (!ptr || !*ptr)
620  return;
621 
622  struct Alias *alias = *ptr;
623 
624  struct EventAlias ea = { alias };
626 
627  FREE(&alias->name);
628  FREE(&alias->comment);
629  mutt_addrlist_clear(&(alias->addr));
630  FREE(ptr);
631 }
632 
637 void aliaslist_free(struct AliasList *al)
638 {
639  struct Alias *np = NULL, *tmp = NULL;
640  TAILQ_FOREACH_SAFE(np, al, entries, tmp)
641  {
642  TAILQ_REMOVE(al, np, entries);
643  alias_free(&np);
644  }
645  TAILQ_INIT(al);
646 }
647 
651 void alias_init(void)
652 {
653  /* reverse alias keys need to be strdup'ed because of idna conversions */
656 }
657 
661 void alias_shutdown(void)
662 {
663  struct Alias *np = NULL;
664  TAILQ_FOREACH(np, &Aliases, entries)
665  {
667  }
670 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
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:366
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:754
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:295
#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
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
User aborted the question (with Ctrl-G)
Definition: quad.h:38
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:447
#define mutt_message(...)
Definition: logging.h:83
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1379
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:1461
void mutt_expand_aliases_env(struct Envelope *env)
Expand aliases in all the fields of an Envelope.
Definition: alias.c:309
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:42
#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:375
void alias_init(void)
Set up the Alias globals.
Definition: alias.c:651
#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:170
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:53
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:97
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:1398
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:377
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:277
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:606
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
void alias_shutdown(void)
Clean up the Alias globals.
Definition: alias.c:661
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
#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:327
WHERE char * C_ConfigCharset
Config: Character set that the config files are in.
Definition: mutt_globals.h:90
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:51
static int check_alias_name(const char *s, char *dest, size_t destlen)
Sanity-check an alias name.
Definition: alias.c:210
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:82
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
Handle mailing lists.
void alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:617
#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
WHERE char * C_AliasFile
Config: Save new aliases to this file.
Definition: mutt_globals.h:86
char * personal
Real name of address.
Definition: address.h:36
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:637
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:1179
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:1297
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:721
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:451
#define mutt_error(...)
Definition: logging.h:84
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:100
#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:545
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:258
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
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
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:1147
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:186
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:137