NeoMutt  2018-07-16 +2481-68dcde
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/mutt.h"
40 #include "address/lib.h"
41 #include "config/lib.h"
42 #include "email/lib.h"
43 #include "mutt.h"
44 #include "alias.h"
45 #include "addrbook.h"
46 #include "curs_lib.h"
47 #include "globals.h"
48 #include "hdrline.h"
49 #include "mutt_curses.h"
50 #include "muttlib.h"
51 #include "sendlib.h"
52 
61 static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
62 {
63  struct Address *a = TAILQ_FIRST(al);
64  while (a)
65  {
66  if (!a->group && !a->personal && a->mailbox && !strchr(a->mailbox, '@'))
67  {
68  struct AddressList *alias = mutt_alias_lookup(a->mailbox);
69  if (alias)
70  {
71  bool duplicate = false;
72  struct ListNode *np = NULL;
73  STAILQ_FOREACH(np, expn, entries)
74  {
75  if (mutt_str_strcmp(a->mailbox, np->data) == 0) /* alias already found */
76  {
77  mutt_debug(LL_DEBUG1, "loop in alias found for '%s'\n", a->mailbox);
78  duplicate = true;
79  break;
80  }
81  }
82 
83  if (duplicate)
84  {
85  // We've already seen this alias, so drop it
86  struct Address *next = TAILQ_NEXT(a, entries);
87  TAILQ_REMOVE(al, a, entries);
88  mutt_addr_free(&a);
89  a = next;
90  continue;
91  }
92 
93  // Keep a list of aliases that we've already seen
95 
96  /* The alias may expand to several addresses,
97  * some of which may themselves be aliases.
98  * Create a copy and recursively expand any aliases within. */
99  struct AddressList copy = TAILQ_HEAD_INITIALIZER(copy);
100  mutt_addrlist_copy(&copy, alias, false);
101  expand_aliases_r(&copy, expn);
102 
103  /* Next, move the expanded addresses
104  * from the copy into the original list (before the alias) */
105  struct Address *a2 = NULL, *tmp = NULL;
106  TAILQ_FOREACH_SAFE(a2, &copy, entries, tmp)
107  {
108  TAILQ_INSERT_BEFORE(a, a2, entries);
109  }
110  a = TAILQ_PREV(a, AddressList, entries);
111  // Finally, remove the alias itself
112  struct Address *next = TAILQ_NEXT(a, entries);
113  TAILQ_REMOVE(al, next, entries);
114  mutt_addr_free(&next);
115  }
116  else
117  {
118  struct passwd *pw = getpwnam(a->mailbox);
119  if (pw)
120  {
121  char namebuf[256];
122 
123  mutt_gecos_name(namebuf, sizeof(namebuf), pw);
124  mutt_str_replace(&a->personal, namebuf);
125  }
126  }
127  }
128  a = TAILQ_NEXT(a, entries);
129  }
130 
131  const char *fqdn = NULL;
132  if (C_UseDomain && (fqdn = mutt_fqdn(true)))
133  {
134  /* now qualify all local addresses */
135  mutt_addrlist_qualify(al, fqdn);
136  }
137 }
138 
145 struct Alias *mutt_alias_new(void)
146 {
147  struct Alias *a = mutt_mem_calloc(1, sizeof(struct Alias));
148  TAILQ_INIT(&a->addr);
149  return a;
150 }
151 
176 static void write_safe_address(FILE *fp, char *s)
177 {
178  while (*s)
179  {
180  if ((*s == '\\') || (*s == '`') || (*s == '\'') || (*s == '"') || (*s == '$'))
181  fputc('\\', fp);
182  fputc(*s, fp);
183  s++;
184  }
185 }
186 
195 static void recode_buf(char *buf, size_t buflen)
196 {
197  if (!C_ConfigCharset || !C_Charset)
198  return;
199 
200  char *s = mutt_str_strdup(buf);
201  if (!s)
202  return;
204  mutt_str_strfcpy(buf, s, buflen);
205  FREE(&s);
206 }
207 
219 static int check_alias_name(const char *s, char *dest, size_t destlen)
220 {
221  wchar_t wc;
222  mbstate_t mb;
223  size_t l;
224  int rc = 0;
225  bool dry = !dest || !destlen;
226 
227  memset(&mb, 0, sizeof(mbstate_t));
228 
229  if (!dry)
230  destlen--;
231  for (; s && *s && (dry || destlen) && (l = mbrtowc(&wc, s, MB_CUR_MAX, &mb)) != 0;
232  s += l, destlen -= l)
233  {
234  bool bad = (l == (size_t)(-1)) || (l == (size_t)(-2)); /* conversion error */
235  bad = bad || (!dry && l > destlen); /* too few room for mb char */
236  if (l == 1)
237  bad = bad || (!strchr("-_+=.", *s) && !iswalnum(wc));
238  else
239  bad = bad || !iswalnum(wc);
240  if (bad)
241  {
242  if (dry)
243  return -1;
244  if (l == (size_t)(-1))
245  memset(&mb, 0, sizeof(mbstate_t));
246  *dest++ = '_';
247  rc = -1;
248  }
249  else if (!dry)
250  {
251  memcpy(dest, s, l);
252  dest += l;
253  }
254  }
255  if (!dry)
256  *dest = '\0';
257  return rc;
258 }
259 
267 static bool string_is_address(const char *str, const char *u, const char *d)
268 {
269  char buf[1024];
270 
271  snprintf(buf, sizeof(buf), "%s@%s", NONULL(u), NONULL(d));
272  if (mutt_str_strcasecmp(str, buf) == 0)
273  return true;
274 
275  return false;
276 }
277 
286 struct AddressList *mutt_alias_lookup(const char *s)
287 {
288  struct Alias *a = NULL;
289 
290  TAILQ_FOREACH(a, &Aliases, entries)
291  {
292  if (mutt_str_strcasecmp(s, a->name) == 0)
293  return &a->addr;
294  }
295  return NULL;
296 }
297 
304 void mutt_expand_aliases(struct AddressList *al)
305 {
306  struct ListHead expn; /* previously expanded aliases to avoid loops */
307 
308  STAILQ_INIT(&expn);
309  expand_aliases_r(al, &expn);
310  mutt_list_free(&expn);
312 }
313 
319 {
320  mutt_expand_aliases(&env->from);
321  mutt_expand_aliases(&env->to);
322  mutt_expand_aliases(&env->cc);
323  mutt_expand_aliases(&env->bcc);
326 }
327 
336 struct AddressList *mutt_get_address(struct Envelope *env, const char **pfxp)
337 {
338  struct AddressList *al = NULL;
339  const char *pfx = NULL;
340 
341  if (mutt_addr_is_user(TAILQ_FIRST(&env->from)))
342  {
343  if (!TAILQ_EMPTY(&env->to) && !mutt_is_mail_list(TAILQ_FIRST(&env->to)))
344  {
345  pfx = "To";
346  al = &env->to;
347  }
348  else
349  {
350  pfx = "Cc";
351  al = &env->cc;
352  }
353  }
354  else if (!TAILQ_EMPTY(&env->reply_to) && !mutt_is_mail_list(TAILQ_FIRST(&env->reply_to)))
355  {
356  pfx = "Reply-To";
357  al = &env->reply_to;
358  }
359  else
360  {
361  al = &env->from;
362  pfx = "From";
363  }
364 
365  if (pfxp)
366  *pfxp = pfx;
367 
368  return al;
369 }
370 
376 void mutt_alias_create(struct Envelope *cur, struct AddressList *al)
377 {
378  struct Address *addr = NULL;
379  char buf[1024], tmp[1024] = { 0 }, prompt[128];
380  char *pc = NULL;
381  char *err = NULL;
382  char fixed[1024];
383 
384  if (cur)
385  {
386  al = mutt_get_address(cur, NULL);
387  }
388 
389  if (al)
390  {
391  addr = TAILQ_FIRST(al);
392  if (addr && addr->mailbox)
393  {
394  mutt_str_strfcpy(tmp, addr->mailbox, sizeof(tmp));
395  pc = strchr(tmp, '@');
396  if (pc)
397  *pc = '\0';
398  }
399  }
400 
401  /* Don't suggest a bad alias name in the event of a strange local part. */
402  check_alias_name(tmp, buf, sizeof(buf));
403 
404 retry_name:
405  /* L10N: prompt to add a new alias */
406  if ((mutt_get_field(_("Alias as: "), buf, sizeof(buf), 0) != 0) || !buf[0])
407  return;
408 
409  /* check to see if the user already has an alias defined */
410  if (mutt_alias_lookup(buf))
411  {
412  mutt_error(_("You already have an alias defined with that name"));
413  return;
414  }
415 
416  if (check_alias_name(buf, fixed, sizeof(fixed)))
417  {
418  switch (mutt_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
419  {
420  case MUTT_YES:
421  mutt_str_strfcpy(buf, fixed, sizeof(buf));
422  goto retry_name;
423  case MUTT_ABORT:
424  return;
425  default:; // do nothing
426  }
427  }
428 
429  struct Alias *alias = mutt_alias_new();
430  alias->name = mutt_str_strdup(buf);
431 
433 
434  if (addr && addr->mailbox)
435  mutt_str_strfcpy(buf, addr->mailbox, sizeof(buf));
436  else
437  buf[0] = '\0';
438 
439  mutt_addrlist_to_intl(al, NULL);
440 
441  do
442  {
443  if ((mutt_get_field(_("Address: "), buf, sizeof(buf), 0) != 0) || !buf[0])
444  {
445  mutt_alias_free(&alias);
446  return;
447  }
448 
449  mutt_addrlist_parse(&alias->addr, buf);
450  if (TAILQ_EMPTY(&alias->addr))
451  BEEP();
452  if (mutt_addrlist_to_intl(&alias->addr, &err))
453  {
454  mutt_error(_("Bad IDN: '%s'"), err);
455  FREE(&err);
456  continue;
457  }
458  } while (TAILQ_EMPTY(&alias->addr));
459 
460  if (addr && addr->personal && !mutt_is_mail_list(addr))
461  mutt_str_strfcpy(buf, addr->personal, sizeof(buf));
462  else
463  buf[0] = '\0';
464 
465  if (mutt_get_field(_("Personal name: "), buf, sizeof(buf), 0) != 0)
466  {
467  mutt_alias_free(&alias);
468  return;
469  }
470  mutt_str_replace(&TAILQ_FIRST(&alias->addr)->personal, buf);
471 
472  buf[0] = '\0';
473  mutt_addrlist_write(buf, sizeof(buf), &alias->addr, true);
474  snprintf(prompt, sizeof(prompt), _("[%s = %s] Accept?"), alias->name, buf);
475  if (mutt_yesorno(prompt, MUTT_YES) != MUTT_YES)
476  {
477  mutt_alias_free(&alias);
478  return;
479  }
480 
481  mutt_alias_add_reverse(alias);
482  TAILQ_INSERT_TAIL(&Aliases, alias, entries);
483 
484  mutt_str_strfcpy(buf, C_AliasFile, sizeof(buf));
485  if (mutt_get_field(_("Save to file: "), buf, sizeof(buf), MUTT_FILE) != 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_strfcpy(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(buf, sizeof(buf), &alias->addr, false);
522  recode_buf(buf, sizeof(buf));
523  write_safe_address(fp_alias, buf);
524  fputc('\n', fp_alias);
525  if (mutt_file_fsync_close(&fp_alias) != 0)
526  mutt_perror(_("Trouble adding alias"));
527  else
528  mutt_message(_("Alias added"));
529 
530  return;
531 
532 fseek_err:
533  mutt_perror(_("Error seeking in alias file"));
534  mutt_file_fclose(&fp_alias);
535 }
536 
542 struct Address *mutt_alias_reverse_lookup(const struct Address *a)
543 {
544  if (!a || !a->mailbox)
545  return NULL;
546 
548 }
549 
555 {
556  if (!t)
557  return;
558 
559  /* Note that the address mailbox should be converted to intl form
560  * before using as a key in the hash. This is currently done
561  * by all callers, but added here mostly as documentation. */
562  mutt_addrlist_to_intl(&t->addr, NULL);
563 
564  struct Address *a = NULL;
565  TAILQ_FOREACH(a, &t->addr, entries)
566  {
567  if (!a->group && a->mailbox)
569  }
570 }
571 
577 {
578  if (!t)
579  return;
580 
581  /* If the alias addresses were converted to local form, they won't
582  * match the hash entries. */
583  mutt_addrlist_to_intl(&t->addr, NULL);
584 
585  struct Address *a = NULL;
586  TAILQ_FOREACH(a, &t->addr, entries)
587  {
588  if (!a->group && a->mailbox)
590  }
591 }
592 
604 int mutt_alias_complete(char *buf, size_t buflen)
605 {
606  struct Alias *a = NULL, *tmp = NULL;
607  struct AliasList a_list = TAILQ_HEAD_INITIALIZER(a_list);
608  char bestname[8192] = { 0 };
609 
610  if (buf[0] != '\0') /* avoid empty string as strstr argument */
611  {
612  TAILQ_FOREACH(a, &Aliases, entries)
613  {
614  if (a->name && (strncmp(a->name, buf, strlen(buf)) == 0))
615  {
616  if (bestname[0] == '\0') /* init */
617  {
618  mutt_str_strfcpy(bestname, a->name,
619  MIN(mutt_str_strlen(a->name) + 1, sizeof(bestname)));
620  }
621  else
622  {
623  int i;
624  for (i = 0; a->name[i] && (a->name[i] == bestname[i]); i++)
625  ;
626  bestname[i] = '\0';
627  }
628  }
629  }
630 
631  if (bestname[0] != '\0')
632  {
633  if (mutt_str_strcmp(bestname, buf) != 0)
634  {
635  /* we are adding something to the completion */
636  mutt_str_strfcpy(buf, bestname, mutt_str_strlen(bestname) + 1);
637  return 1;
638  }
639 
640  /* build alias list and show it */
641  TAILQ_FOREACH(a, &Aliases, entries)
642  {
643  if (a->name && (strncmp(a->name, buf, strlen(buf)) == 0))
644  {
645  tmp = mutt_mem_calloc(1, sizeof(struct Alias));
646  memcpy(tmp, a, sizeof(struct Alias));
647  TAILQ_INSERT_TAIL(&a_list, tmp, entries);
648  }
649  }
650  }
651  }
652 
653  bestname[0] = '\0';
654  mutt_alias_menu(bestname, sizeof(bestname), !TAILQ_EMPTY(&a_list) ? &a_list : &Aliases);
655  if (bestname[0] != '\0')
656  mutt_str_strfcpy(buf, bestname, buflen);
657 
658  /* free the alias list */
659  TAILQ_FOREACH_SAFE(a, &a_list, entries, tmp)
660  {
661  TAILQ_REMOVE(&a_list, a, entries);
662  FREE(&a);
663  }
664 
665  /* remove any aliases marked for deletion */
666  TAILQ_FOREACH_SAFE(a, &Aliases, entries, tmp)
667  {
668  if (a->del)
669  {
670  TAILQ_REMOVE(&Aliases, a, entries);
671  mutt_alias_free(&a);
672  }
673  }
674 
675  return 0;
676 }
677 
683 bool mutt_addr_is_user(const struct Address *addr)
684 {
685  if (!addr)
686  {
687  mutt_debug(LL_DEBUG5, "no, NULL address\n");
688  return false;
689  }
690  if (!addr->mailbox)
691  {
692  mutt_debug(LL_DEBUG5, "no, no mailbox\n");
693  return false;
694  }
695 
696  if (mutt_str_strcasecmp(addr->mailbox, Username) == 0)
697  {
698  mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", addr->mailbox, Username);
699  return true;
700  }
702  {
703  mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", addr->mailbox, Username, ShortHostname);
704  return true;
705  }
706  const char *fqdn = mutt_fqdn(false);
707  if (string_is_address(addr->mailbox, Username, fqdn))
708  {
709  mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
710  return true;
711  }
712  fqdn = mutt_fqdn(true);
713  if (string_is_address(addr->mailbox, Username, fqdn))
714  {
715  mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
716  return true;
717  }
718 
719  if (C_From && (mutt_str_strcasecmp(C_From->mailbox, addr->mailbox) == 0))
720  {
721  mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", addr->mailbox, C_From->mailbox);
722  return true;
723  }
724 
725  if (mutt_regexlist_match(&Alternates, addr->mailbox))
726  {
727  mutt_debug(LL_DEBUG5, "yes, %s matched by alternates\n", addr->mailbox);
728  if (mutt_regexlist_match(&UnAlternates, addr->mailbox))
729  mutt_debug(LL_DEBUG5, "but, %s matched by unalternates\n", addr->mailbox);
730  else
731  return true;
732  }
733 
734  mutt_debug(LL_DEBUG5, "no, all failed\n");
735  return false;
736 }
737 
742 void mutt_alias_free(struct Alias **ptr)
743 {
744  if (!ptr || !*ptr)
745  return;
746 
747  struct Alias *a = *ptr;
748 
750  FREE(&a->name);
751  mutt_addrlist_clear(&(a->addr));
752  FREE(ptr);
753 }
754 
759 void mutt_aliaslist_free(struct AliasList *a_list)
760 {
761  struct Alias *a = NULL, *tmp = NULL;
762  TAILQ_FOREACH_SAFE(a, a_list, entries, tmp)
763  {
764  TAILQ_REMOVE(a_list, a, entries);
765  mutt_alias_free(&a);
766  }
767  TAILQ_INIT(a_list);
768 }
void mutt_alias_delete_reverse(struct Alias *t)
Remove an email address lookup for an Alias.
Definition: alias.c:576
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:780
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:444
#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
Define wrapper functions around Curses/Slang.
struct AddressList * mutt_alias_lookup(const char *s)
Find an Alias.
Definition: alias.c:286
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:304
#define TAILQ_FIRST(head)
Definition: queue.h:717
#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:759
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:719
GUI miscellaneous curses (window drawing) routines.
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:457
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:166
User aborted the question (with Ctrl-G)
Definition: quad.h:37
#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:336
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1298
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:1381
void mutt_expand_aliases_env(struct Envelope *env)
Expand aliases in all the fields of an Envelope.
Definition: alias.c:318
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:101
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:727
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:379
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:729
#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:666
size_t mutt_addrlist_write(char *buf, size_t buflen, const struct AddressList *al, bool display)
Write an Address to a buffer.
Definition: address.c:1137
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:439
Representation of a single alias to an email address.
WHERE char * C_AliasFile
Config: Save new aliases to this file.
Definition: globals.h:101
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:86
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:109
Some miscellaneous functions.
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:1318
WHERE bool C_UseDomain
Config: Qualify local addresses using this domain.
Definition: globals.h:270
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:332
#define STAILQ_INIT(head)
Definition: queue.h:370
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:193
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:150
WHERE struct Address * C_From
Config: Default &#39;From&#39; address to use, if isn&#39;t otherwise set.
Definition: globals.h:99
struct Alias * mutt_alias_new(void)
Create a new Alias.
Definition: alias.c:145
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
#define TAILQ_INIT(head)
Definition: queue.h:759
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:542
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:821
void mutt_alias_create(struct Envelope *cur, struct AddressList *al)
Create a new Alias from an Envelope or an Address.
Definition: alias.c:376
#define BEEP()
Definition: mutt_curses.h:80
void mutt_alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:742
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:750
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:267
static int check_alias_name(const char *s, char *dest, size_t destlen)
Sanity-check an alias name.
Definition: alias.c:219
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:803
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:788
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
int mutt_alias_complete(char *buf, size_t buflen)
alias completion routine
Definition: alias.c:604
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:2527
#define MUTT_FILE
Do file completion.
Definition: mutt.h:66
static void write_safe_address(FILE *fp, char *s)
Defang malicious email addresses.
Definition: alias.c:176
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:640
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:1216
Log at debug level 1.
Definition: logging.h:56
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
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:628
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:61
void mutt_alias_add_reverse(struct Alias *t)
Add an email address lookup for an Alias.
Definition: alias.c:554
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:683
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:816
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Miscellaneous functions for sending an email.
#define TAILQ_EMPTY(head)
Definition: queue.h:715
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:40
Log at debug level 5.
Definition: logging.h:60
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:352
A List node for strings.
Definition: list.h:33
#define TAILQ_PREV(elm, headname, field)
Definition: queue.h:818
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:631
Convenience wrapper for the library headers.
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
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:195