NeoMutt  2019-12-07-168-gc45f47
Teaching an old dog new tricks
DOXYGEN
alias.c
Go to the documentation of this file.
1 
30 #include "config.h"
31 #include <stddef.h>
32 #include <pwd.h>
33 #include <stdbool.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <wchar.h>
38 #include <wctype.h>
39 #include "mutt/lib.h"
40 #include "address/lib.h"
41 #include "config/lib.h"
42 #include "email/lib.h"
43 #include "gui/lib.h"
44 #include "mutt.h"
45 #include "alias.h"
46 #include "addrbook.h"
47 #include "globals.h"
48 #include "hdrline.h"
49 #include "muttlib.h"
50 #include "sendlib.h"
51 
60 static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
61 {
62  struct Address *a = TAILQ_FIRST(al);
63  while (a)
64  {
65  if (!a->group && !a->personal && a->mailbox && !strchr(a->mailbox, '@'))
66  {
67  struct AddressList *alias = mutt_alias_lookup(a->mailbox);
68  if (alias)
69  {
70  bool duplicate = false;
71  struct ListNode *np = NULL;
72  STAILQ_FOREACH(np, expn, entries)
73  {
74  if (mutt_str_strcmp(a->mailbox, np->data) == 0) /* alias already found */
75  {
76  mutt_debug(LL_DEBUG1, "loop in alias found for '%s'\n", a->mailbox);
77  duplicate = true;
78  break;
79  }
80  }
81 
82  if (duplicate)
83  {
84  // We've already seen this alias, so drop it
85  struct Address *next = TAILQ_NEXT(a, entries);
86  TAILQ_REMOVE(al, a, entries);
87  mutt_addr_free(&a);
88  a = next;
89  continue;
90  }
91 
92  // Keep a list of aliases that we've already seen
94 
95  /* The alias may expand to several addresses,
96  * some of which may themselves be aliases.
97  * Create a copy and recursively expand any aliases within. */
98  struct AddressList copy = TAILQ_HEAD_INITIALIZER(copy);
99  mutt_addrlist_copy(&copy, alias, false);
100  expand_aliases_r(&copy, expn);
101 
102  /* Next, move the expanded addresses
103  * from the copy into the original list (before the alias) */
104  struct Address *a2 = NULL, *tmp = NULL;
105  TAILQ_FOREACH_SAFE(a2, &copy, entries, tmp)
106  {
107  TAILQ_INSERT_BEFORE(a, a2, entries);
108  }
109  a = TAILQ_PREV(a, AddressList, entries);
110  // Finally, remove the alias itself
111  struct Address *next = TAILQ_NEXT(a, entries);
112  TAILQ_REMOVE(al, next, entries);
113  mutt_addr_free(&next);
114  }
115  else
116  {
117  struct passwd *pw = getpwnam(a->mailbox);
118  if (pw)
119  {
120  char namebuf[256];
121 
122  mutt_gecos_name(namebuf, sizeof(namebuf), pw);
123  mutt_str_replace(&a->personal, namebuf);
124  }
125  }
126  }
127  a = TAILQ_NEXT(a, entries);
128  }
129 
130  const char *fqdn = NULL;
131  if (C_UseDomain && (fqdn = mutt_fqdn(true)))
132  {
133  /* now qualify all local addresses */
134  mutt_addrlist_qualify(al, fqdn);
135  }
136 }
137 
144 struct Alias *mutt_alias_new(void)
145 {
146  struct Alias *a = mutt_mem_calloc(1, sizeof(struct Alias));
147  TAILQ_INIT(&a->addr);
148  return a;
149 }
150 
175 static void write_safe_address(FILE *fp, char *s)
176 {
177  while (*s)
178  {
179  if ((*s == '\\') || (*s == '`') || (*s == '\'') || (*s == '"') || (*s == '$'))
180  fputc('\\', fp);
181  fputc(*s, fp);
182  s++;
183  }
184 }
185 
194 static void recode_buf(char *buf, size_t buflen)
195 {
196  if (!C_ConfigCharset || !C_Charset)
197  return;
198 
199  char *s = mutt_str_strdup(buf);
200  if (!s)
201  return;
203  mutt_str_strfcpy(buf, s, buflen);
204  FREE(&s);
205 }
206 
218 static int check_alias_name(const char *s, char *dest, size_t destlen)
219 {
220  wchar_t wc;
221  mbstate_t mb;
222  size_t l;
223  int rc = 0;
224  bool dry = !dest || !destlen;
225 
226  memset(&mb, 0, sizeof(mbstate_t));
227 
228  if (!dry)
229  destlen--;
230  for (; s && *s && (dry || destlen) && (l = mbrtowc(&wc, s, MB_CUR_MAX, &mb)) != 0;
231  s += l, destlen -= l)
232  {
233  bool bad = (l == (size_t)(-1)) || (l == (size_t)(-2)); /* conversion error */
234  bad = bad || (!dry && l > destlen); /* too few room for mb char */
235  if (l == 1)
236  bad = bad || (!strchr("-_+=.", *s) && !iswalnum(wc));
237  else
238  bad = bad || !iswalnum(wc);
239  if (bad)
240  {
241  if (dry)
242  return -1;
243  if (l == (size_t)(-1))
244  memset(&mb, 0, sizeof(mbstate_t));
245  *dest++ = '_';
246  rc = -1;
247  }
248  else if (!dry)
249  {
250  memcpy(dest, s, l);
251  dest += l;
252  }
253  }
254  if (!dry)
255  *dest = '\0';
256  return rc;
257 }
258 
266 static bool string_is_address(const char *str, const char *u, const char *d)
267 {
268  char buf[1024];
269 
270  snprintf(buf, sizeof(buf), "%s@%s", NONULL(u), NONULL(d));
271  if (mutt_str_strcasecmp(str, buf) == 0)
272  return true;
273 
274  return false;
275 }
276 
285 struct AddressList *mutt_alias_lookup(const char *s)
286 {
287  struct Alias *a = NULL;
288 
289  TAILQ_FOREACH(a, &Aliases, entries)
290  {
291  if (mutt_str_strcasecmp(s, a->name) == 0)
292  return &a->addr;
293  }
294  return NULL;
295 }
296 
303 void mutt_expand_aliases(struct AddressList *al)
304 {
305  struct ListHead expn; /* previously expanded aliases to avoid loops */
306 
307  STAILQ_INIT(&expn);
308  expand_aliases_r(al, &expn);
309  mutt_list_free(&expn);
311 }
312 
318 {
319  mutt_expand_aliases(&env->from);
320  mutt_expand_aliases(&env->to);
321  mutt_expand_aliases(&env->cc);
322  mutt_expand_aliases(&env->bcc);
325 }
326 
335 struct AddressList *mutt_get_address(struct Envelope *env, const char **pfxp)
336 {
337  struct AddressList *al = NULL;
338  const char *pfx = NULL;
339 
340  if (mutt_addr_is_user(TAILQ_FIRST(&env->from)))
341  {
342  if (!TAILQ_EMPTY(&env->to) && !mutt_is_mail_list(TAILQ_FIRST(&env->to)))
343  {
344  pfx = "To";
345  al = &env->to;
346  }
347  else
348  {
349  pfx = "Cc";
350  al = &env->cc;
351  }
352  }
353  else if (!TAILQ_EMPTY(&env->reply_to) && !mutt_is_mail_list(TAILQ_FIRST(&env->reply_to)))
354  {
355  pfx = "Reply-To";
356  al = &env->reply_to;
357  }
358  else
359  {
360  al = &env->from;
361  pfx = "From";
362  }
363 
364  if (pfxp)
365  *pfxp = pfx;
366 
367  return al;
368 }
369 
375 void mutt_alias_create(struct Envelope *cur, struct AddressList *al)
376 {
377  struct Address *addr = NULL;
378  char buf[1024], tmp[1024] = { 0 }, prompt[128];
379  char *pc = NULL;
380  char *err = NULL;
381  char fixed[1024];
382 
383  if (cur)
384  {
385  al = mutt_get_address(cur, NULL);
386  }
387 
388  if (al)
389  {
390  addr = TAILQ_FIRST(al);
391  if (addr && addr->mailbox)
392  {
393  mutt_str_strfcpy(tmp, addr->mailbox, sizeof(tmp));
394  pc = strchr(tmp, '@');
395  if (pc)
396  *pc = '\0';
397  }
398  }
399 
400  /* Don't suggest a bad alias name in the event of a strange local part. */
401  check_alias_name(tmp, buf, sizeof(buf));
402 
403 retry_name:
404  /* L10N: prompt to add a new alias */
405  if ((mutt_get_field(_("Alias as: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0) ||
406  !buf[0])
407  {
408  return;
409  }
410 
411  /* check to see if the user already has an alias defined */
412  if (mutt_alias_lookup(buf))
413  {
414  mutt_error(_("You already have an alias defined with that name"));
415  return;
416  }
417 
418  if (check_alias_name(buf, fixed, sizeof(fixed)))
419  {
420  switch (mutt_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
421  {
422  case MUTT_YES:
423  mutt_str_strfcpy(buf, fixed, sizeof(buf));
424  goto retry_name;
425  case MUTT_ABORT:
426  return;
427  default:; // do nothing
428  }
429  }
430 
431  struct Alias *alias = mutt_alias_new();
432  alias->name = mutt_str_strdup(buf);
433 
435 
436  if (addr && addr->mailbox)
437  mutt_str_strfcpy(buf, addr->mailbox, sizeof(buf));
438  else
439  buf[0] = '\0';
440 
441  mutt_addrlist_to_intl(al, NULL);
442 
443  do
444  {
445  if ((mutt_get_field(_("Address: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0) ||
446  !buf[0])
447  {
448  mutt_alias_free(&alias);
449  return;
450  }
451 
452  mutt_addrlist_parse(&alias->addr, buf);
453  if (TAILQ_EMPTY(&alias->addr))
454  mutt_beep(false);
455  if (mutt_addrlist_to_intl(&alias->addr, &err))
456  {
457  mutt_error(_("Bad IDN: '%s'"), err);
458  FREE(&err);
459  continue;
460  }
461  } while (TAILQ_EMPTY(&alias->addr));
462 
463  if (addr && addr->personal && !mutt_is_mail_list(addr))
464  mutt_str_strfcpy(buf, addr->personal, sizeof(buf));
465  else
466  buf[0] = '\0';
467 
468  if (mutt_get_field(_("Personal name: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0)
469  {
470  mutt_alias_free(&alias);
471  return;
472  }
473  mutt_str_replace(&TAILQ_FIRST(&alias->addr)->personal, buf);
474 
475  buf[0] = '\0';
476  mutt_addrlist_write(&alias->addr, buf, sizeof(buf), true);
477  snprintf(prompt, sizeof(prompt), _("[%s = %s] Accept?"), alias->name, buf);
478  if (mutt_yesorno(prompt, MUTT_YES) != MUTT_YES)
479  {
480  mutt_alias_free(&alias);
481  return;
482  }
483 
484  mutt_alias_add_reverse(alias);
485  TAILQ_INSERT_TAIL(&Aliases, alias, entries);
486 
487  mutt_str_strfcpy(buf, C_AliasFile, sizeof(buf));
488  if (mutt_get_field(_("Save to file: "), buf, sizeof(buf), MUTT_FILE) != 0)
489  return;
490  mutt_expand_path(buf, sizeof(buf));
491  FILE *fp_alias = fopen(buf, "a+");
492  if (!fp_alias)
493  {
494  mutt_perror(buf);
495  return;
496  }
497 
498  /* terminate existing file with \n if necessary */
499  if (fseek(fp_alias, 0, SEEK_END))
500  goto fseek_err;
501  if (ftell(fp_alias) > 0)
502  {
503  if (fseek(fp_alias, -1, SEEK_CUR) < 0)
504  goto fseek_err;
505  if (fread(buf, 1, 1, fp_alias) != 1)
506  {
507  mutt_perror(_("Error reading alias file"));
508  mutt_file_fclose(&fp_alias);
509  return;
510  }
511  if (fseek(fp_alias, 0, SEEK_END) < 0)
512  goto fseek_err;
513  if (buf[0] != '\n')
514  fputc('\n', fp_alias);
515  }
516 
517  if (check_alias_name(alias->name, NULL, 0))
518  mutt_file_quote_filename(alias->name, buf, sizeof(buf));
519  else
520  mutt_str_strfcpy(buf, alias->name, sizeof(buf));
521  recode_buf(buf, sizeof(buf));
522  fprintf(fp_alias, "alias %s ", buf);
523  buf[0] = '\0';
524  mutt_addrlist_write(&alias->addr, buf, sizeof(buf), false);
525  recode_buf(buf, sizeof(buf));
526  write_safe_address(fp_alias, buf);
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 struct Address *mutt_alias_reverse_lookup(const struct Address *a)
546 {
547  if (!a || !a->mailbox)
548  return NULL;
549 
551 }
552 
558 {
559  if (!t)
560  return;
561 
562  /* Note that the address mailbox should be converted to intl form
563  * before using as a key in the hash. This is currently done
564  * by all callers, but added here mostly as documentation. */
565  mutt_addrlist_to_intl(&t->addr, NULL);
566 
567  struct Address *a = NULL;
568  TAILQ_FOREACH(a, &t->addr, entries)
569  {
570  if (!a->group && a->mailbox)
572  }
573 }
574 
580 {
581  if (!t)
582  return;
583 
584  /* If the alias addresses were converted to local form, they won't
585  * match the hash entries. */
586  mutt_addrlist_to_intl(&t->addr, NULL);
587 
588  struct Address *a = NULL;
589  TAILQ_FOREACH(a, &t->addr, entries)
590  {
591  if (!a->group && a->mailbox)
593  }
594 }
595 
607 int mutt_alias_complete(char *buf, size_t buflen)
608 {
609  struct Alias *a = NULL, *tmp = NULL;
610  struct AliasList a_list = TAILQ_HEAD_INITIALIZER(a_list);
611  char bestname[8192] = { 0 };
612 
613  if (buf[0] != '\0') /* avoid empty string as strstr argument */
614  {
615  TAILQ_FOREACH(a, &Aliases, entries)
616  {
617  if (a->name && (strncmp(a->name, buf, strlen(buf)) == 0))
618  {
619  if (bestname[0] == '\0') /* init */
620  {
621  mutt_str_strfcpy(bestname, a->name,
622  MIN(mutt_str_strlen(a->name) + 1, sizeof(bestname)));
623  }
624  else
625  {
626  int i;
627  for (i = 0; a->name[i] && (a->name[i] == bestname[i]); i++)
628  ;
629  bestname[i] = '\0';
630  }
631  }
632  }
633 
634  if (bestname[0] != '\0')
635  {
636  if (mutt_str_strcmp(bestname, buf) != 0)
637  {
638  /* we are adding something to the completion */
639  mutt_str_strfcpy(buf, bestname, mutt_str_strlen(bestname) + 1);
640  return 1;
641  }
642 
643  /* build alias list and show it */
644  TAILQ_FOREACH(a, &Aliases, entries)
645  {
646  if (a->name && (strncmp(a->name, buf, strlen(buf)) == 0))
647  {
648  tmp = mutt_mem_calloc(1, sizeof(struct Alias));
649  memcpy(tmp, a, sizeof(struct Alias));
650  TAILQ_INSERT_TAIL(&a_list, tmp, entries);
651  }
652  }
653  }
654  }
655 
656  bestname[0] = '\0';
657  mutt_alias_menu(bestname, sizeof(bestname), !TAILQ_EMPTY(&a_list) ? &a_list : &Aliases);
658  if (bestname[0] != '\0')
659  mutt_str_strfcpy(buf, bestname, buflen);
660 
661  /* free the alias list */
662  TAILQ_FOREACH_SAFE(a, &a_list, entries, tmp)
663  {
664  TAILQ_REMOVE(&a_list, a, entries);
665  FREE(&a);
666  }
667 
668  /* remove any aliases marked for deletion */
669  TAILQ_FOREACH_SAFE(a, &Aliases, entries, tmp)
670  {
671  if (a->del)
672  {
673  TAILQ_REMOVE(&Aliases, a, entries);
674  mutt_alias_free(&a);
675  }
676  }
677 
678  return 0;
679 }
680 
686 bool mutt_addr_is_user(const struct Address *addr)
687 {
688  if (!addr)
689  {
690  mutt_debug(LL_DEBUG5, "no, NULL address\n");
691  return false;
692  }
693  if (!addr->mailbox)
694  {
695  mutt_debug(LL_DEBUG5, "no, no mailbox\n");
696  return false;
697  }
698 
699  if (mutt_str_strcasecmp(addr->mailbox, Username) == 0)
700  {
701  mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", addr->mailbox, Username);
702  return true;
703  }
705  {
706  mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", addr->mailbox, Username, ShortHostname);
707  return true;
708  }
709  const char *fqdn = mutt_fqdn(false);
710  if (string_is_address(addr->mailbox, Username, fqdn))
711  {
712  mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
713  return true;
714  }
715  fqdn = mutt_fqdn(true);
716  if (string_is_address(addr->mailbox, Username, fqdn))
717  {
718  mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
719  return true;
720  }
721 
722  if (C_From && (mutt_str_strcasecmp(C_From->mailbox, addr->mailbox) == 0))
723  {
724  mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", addr->mailbox, C_From->mailbox);
725  return true;
726  }
727 
728  if (mutt_regexlist_match(&Alternates, addr->mailbox))
729  {
730  mutt_debug(LL_DEBUG5, "yes, %s matched by alternates\n", addr->mailbox);
731  if (mutt_regexlist_match(&UnAlternates, addr->mailbox))
732  mutt_debug(LL_DEBUG5, "but, %s matched by unalternates\n", addr->mailbox);
733  else
734  return true;
735  }
736 
737  mutt_debug(LL_DEBUG5, "no, all failed\n");
738  return false;
739 }
740 
745 void mutt_alias_free(struct Alias **ptr)
746 {
747  if (!ptr || !*ptr)
748  return;
749 
750  struct Alias *a = *ptr;
751 
753  FREE(&a->name);
754  mutt_addrlist_clear(&(a->addr));
755  FREE(ptr);
756 }
757 
762 void mutt_aliaslist_free(struct AliasList *a_list)
763 {
764  struct Alias *a = NULL, *tmp = NULL;
765  TAILQ_FOREACH_SAFE(a, a_list, entries, tmp)
766  {
767  TAILQ_REMOVE(a_list, a, entries);
768  mutt_alias_free(&a);
769  }
770  TAILQ_INIT(a_list);
771 }
void mutt_alias_delete_reverse(struct Alias *t)
Remove an email address lookup for an Alias.
Definition: alias.c:579
Convenience wrapper for the gui headers.
A shortcut for an email address.
Definition: alias.h:37
WHERE char * Username
User&#39;s login name.
Definition: globals.h:52
#define TAILQ_INSERT_BEFORE(listelm, elm, field)
Definition: queue.h:779
char * name
Short name.
Definition: alias.h:39
void mutt_hash_delete(struct Hash *table, const char *strkey, const void *data)
Remove an element from a Hash table.
Definition: hash.c:443
#define NONULL(x)
Definition: string2.h:37
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:748
struct AddressList * mutt_alias_lookup(const char *s)
Find an Alias.
Definition: alias.c:285
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:303
#define TAILQ_FIRST(head)
Definition: queue.h:716
#define MIN(a, b)
Definition: memory.h:31
#define mutt_perror(...)
Definition: logging.h:85
void mutt_aliaslist_free(struct AliasList *a_list)
Free a List of Aliases.
Definition: alias.c:762
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.
String processing routines to generate the mail index.
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
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:168
User aborted the question (with Ctrl-G)
Definition: quad.h:38
#define mutt_message(...)
Definition: logging.h:83
struct AddressList * mutt_get_address(struct Envelope *env, const char **pfxp)
Get an Address from an Envelope.
Definition: alias.c:335
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:1299
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:1382
void mutt_expand_aliases_env(struct Envelope *env)
Expand aliases in all the fields of an Envelope.
Definition: alias.c:317
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:114
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:728
void * mutt_hash_find(const struct Hash *table, const char *strkey)
Find the HashElem data in a Hash table element using a key.
Definition: hash.c:378
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:728
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:440
Representation of a single alias to an email address.
WHERE char * C_AliasFile
Config: Save new aliases to this file.
Definition: globals.h:96
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:90
Convenience wrapper for the config headers.
Hundreds of global variables to back the user variables.
Email Address Handling.
WHERE char * C_ConfigCharset
Config: Character set that the config files are in.
Definition: globals.h:104
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:97
Some miscellaneous functions.
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:132
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1319
WHERE bool C_UseDomain
Config: Qualify local addresses using this domain.
Definition: globals.h:259
bool del
Is it deleted?
Definition: alias.h:42
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:376
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:62
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
void mutt_alias_menu(char *buf, size_t buflen, struct AliasList *aliases)
Display a menu of Aliases.
Definition: addrbook.c:224
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
WHERE struct Address * C_From
Config: Default &#39;From&#39; address to use, if isn&#39;t otherwise set.
Definition: globals.h:94
struct Alias * mutt_alias_new(void)
Create a new Alias.
Definition: alias.c:144
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:191
struct Address * mutt_alias_reverse_lookup(const struct Address *a)
Does the user have an alias for the given address.
Definition: alias.c:545
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:834
void mutt_alias_create(struct Envelope *cur, struct AddressList *al)
Create a new Alias from an Envelope or an Address.
Definition: alias.c:375
void mutt_alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:745
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
static bool string_is_address(const char *str, const char *u, const char *d)
Does an email address match a user and domain?
Definition: alias.c:266
static int check_alias_name(const char *s, char *dest, size_t destlen)
Sanity-check an alias name.
Definition: alias.c:218
#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:46
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:790
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
int mutt_alias_complete(char *buf, size_t buflen)
alias completion routine
Definition: alias.c:607
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2530
#define MUTT_FILE
Do file completion.
Definition: mutt.h:64
static void write_safe_address(FILE *fp, char *s)
Defang malicious email addresses.
Definition: alias.c:175
char * personal
Real name of address.
Definition: address.h:36
WHERE struct Hash * ReverseAliases
Hash table of aliases (email address -> alias)
Definition: globals.h:59
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:641
char * data
String.
Definition: list.h:35
Address book handling aliases.
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1217
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:380
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:60
void mutt_alias_add_reverse(struct Alias *t)
Add an email address lookup for an Alias.
Definition: alias.c:557
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:50
#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:686
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:54
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
#define TAILQ_NEXT(elm, field)
Definition: queue.h:825
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Miscellaneous functions for sending an email.
#define TAILQ_EMPTY(head)
Definition: queue.h:714
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:40
Log at debug level 5.
Definition: logging.h:44
Convenience wrapper for the library headers.
struct HashElem * mutt_hash_insert(struct Hash *table, const char *strkey, void *data)
Add a new element to the Hash table (with string keys)
Definition: hash.c:351
A List node for strings.
Definition: list.h:33
#define TAILQ_PREV(elm, headname, field)
Definition: queue.h:827
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
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:1138
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:638
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:194