NeoMutt  2020-06-26-89-g172cd3
Teaching an old dog new tricks
DOXYGEN
alias.c File Reference

Representation of a single alias to an email address. More...

#include "config.h"
#include <stddef.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <wctype.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "alias.h"
#include "lib.h"
#include "maillist.h"
#include "mutt_globals.h"
#include "muttlib.h"
#include "reverse.h"
#include "send/lib.h"
+ Include dependency graph for alias.c:

Go to the source code of this file.

Functions

static void write_safe_address (FILE *fp, char *s)
 Defang malicious email addresses. More...
 
static void expand_aliases_r (struct AddressList *al, struct ListHead *expn)
 Expand aliases, recursively. More...
 
static void recode_buf (char *buf, size_t buflen)
 Convert some text between two character sets. More...
 
static int check_alias_name (const char *s, char *dest, size_t destlen)
 Sanity-check an alias name. More...
 
static bool string_is_address (const char *str, const char *user, const char *domain)
 Does an email address match a user and domain? More...
 
struct AddressList * alias_lookup (const char *name)
 Find an Alias. More...
 
void mutt_expand_aliases (struct AddressList *al)
 Expand aliases in a List of Addresses. More...
 
void mutt_expand_aliases_env (struct Envelope *env)
 Expand aliases in all the fields of an Envelope. More...
 
struct AddressList * mutt_get_address (struct Envelope *env, const char **prefix)
 Get an Address from an Envelope. More...
 
void alias_create (struct AddressList *al)
 Create a new Alias from an Address. More...
 
bool mutt_addr_is_user (const struct Address *addr)
 Does the address belong to the user. More...
 
struct Aliasalias_new (void)
 Create a new Alias. More...
 
void alias_free (struct Alias **ptr)
 Free an Alias. More...
 
void aliaslist_free (struct AliasList *al)
 Free a List of Aliases. More...
 
void alias_init (void)
 Set up the Alias globals. More...
 
void alias_shutdown (void)
 Clean up the Alias globals. More...
 

Variables

struct AliasList Aliases = TAILQ_HEAD_INITIALIZER(Aliases)
 List of all the user's email aliases. More...
 

Detailed Description

Representation of a single alias to an email address.

Authors
  • Michael R. Elkins
  • Pietro Cerutti
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file alias.c.

Function Documentation

◆ write_safe_address()

static void write_safe_address ( FILE *  fp,
char *  s 
)
static

Defang malicious email addresses.

Parameters
fpFile to write to
sEmail address to defang

if someone has an address like From: Michael /bin/rm -f ~ Elkins me@mu.nosp@m.tt.o.nosp@m.rg and the user creates an alias for this, NeoMutt could wind up executing the backticks because it writes aliases like alias me Michael /bin/rm -f ~ Elkins me@mu.nosp@m.tt.o.nosp@m.rg To avoid this problem, use a backslash () to quote any backticks. We also need to quote backslashes as well, since you could defeat the above by doing From: Michael `/bin/rm -f ~` Elkins me@mu.nosp@m.tt.o.nosp@m.rg since that would get aliased as alias me Michael \`/bin/rm -f ~\` Elkins me@mu.nosp@m.tt.o.nosp@m.rg which still gets evaluated because the double backslash is not a quote.

Additionally, we need to quote ' and " characters - otherwise, neomutt will interpret them on the wrong parsing step.

$ wants to be quoted since it may indicate the start of an environment variable.

Definition at line 81 of file alias.c.

82 {
83  while (*s)
84  {
85  if ((*s == '\\') || (*s == '`') || (*s == '\'') || (*s == '"') || (*s == '$'))
86  fputc('\\', fp);
87  fputc(*s, fp);
88  s++;
89  }
90 }
+ Here is the caller graph for this function:

◆ expand_aliases_r()

static void expand_aliases_r ( struct AddressList *  al,
struct ListHead *  expn 
)
static

Expand aliases, recursively.

Parameters
[in]alAddress List
[out]expnAlias List
Return values
ptrAddress List with aliases expanded

ListHead expn is used as temporary storage for already-expanded aliases.

Definition at line 100 of file alias.c.

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 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
#define TAILQ_INSERT_BEFORE(listelm, elm, field)
Definition: queue.h:779
#define TAILQ_FIRST(head)
Definition: queue.h:716
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
#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
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
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:277
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:834
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition: list.c:45
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
char * personal
Real name of address.
Definition: address.h:36
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:650
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
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
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:451
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:100
#define TAILQ_NEXT(elm, field)
Definition: queue.h:825
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ recode_buf()

static void recode_buf ( char *  buf,
size_t  buflen 
)
static

Convert some text between two character sets.

Parameters
bufBuffer to convert
buflenLength of buffer

The 'from' charset is controlled by the 'charset' config variable. The 'to' charset is controlled by the 'config_charset' config variable.

Definition at line 186 of file alias.c.

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 }
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:754
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
WHERE char * C_ConfigCharset
Config: Character set that the config files are in.
Definition: mutt_globals.h:90
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
#define FREE(x)
Definition: memory.h:40
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ check_alias_name()

static int check_alias_name ( const char *  s,
char *  dest,
size_t  destlen 
)
static

Sanity-check an alias name.

Parameters
sAlias to check
destBuffer for the result
destlenLength of buffer
Return values
0Success
-1Error

Only characters which are non-special to both the RFC822 and the neomutt configuration parser are permitted.

Definition at line 210 of file alias.c.

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 }
+ Here is the caller graph for this function:

◆ string_is_address()

static bool string_is_address ( const char *  str,
const char *  user,
const char *  domain 
)
static

Does an email address match a user and domain?

Parameters
strAddress string to test
userUser name
domainDomain name
Return values
trueThey match

Definition at line 258 of file alias.c.

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 }
#define NONULL(x)
Definition: string2.h:37
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_lookup()

struct AddressList* alias_lookup ( const char *  name)

Find an Alias.

Parameters
nameAlias name to find
Return values
ptrAddress for the Alias
NULLNo such Alias
Note
The search is case-insensitive

Definition at line 277 of file alias.c.

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 }
A shortcut for an email address or addresses.
Definition: alias.h:33
char * name
Short name.
Definition: alias.h:35
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:55
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_expand_aliases()

void mutt_expand_aliases ( struct AddressList *  al)

Expand aliases in a List of Addresses.

Parameters
alAddressList

Duplicate addresses are dropped

Definition at line 295 of file alias.c.

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 }
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1398
#define STAILQ_INIT(head)
Definition: queue.h:369
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:100
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_expand_aliases_env()

void mutt_expand_aliases_env ( struct Envelope env)

Expand aliases in all the fields of an Envelope.

Parameters
envEnvelope to expand

Definition at line 309 of file alias.c.

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 }
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:295
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:63
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_address()

struct AddressList* mutt_get_address ( struct Envelope env,
const char **  prefix 
)

Get an Address from an Envelope.

Parameters
[in]envEnvelope to examine
[out]prefixPrefix for the Address, e.g. "To:"
Return values
ptrAddressList in the Envelope
Note
The caller must NOT free the returned AddressList

Definition at line 327 of file alias.c.

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 }
#define TAILQ_FIRST(head)
Definition: queue.h:716
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
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
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:545
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
#define TAILQ_EMPTY(head)
Definition: queue.h:714
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_create()

void alias_create ( struct AddressList *  al)

Create a new Alias from an Address.

Parameters
alAddress to use

Definition at line 366 of file alias.c.

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 }
A shortcut for an email address or addresses.
Definition: alias.h:33
char * name
Short name.
Definition: alias.h:35
#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
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:169
User aborted the question (with Ctrl-G)
Definition: quad.h:38
#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
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
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:97
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:128
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:377
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
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 Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:606
void alias_reverse_add(struct Alias *alias)
Add an email address lookup for an Alias.
Definition: reverse.c:43
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:55
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
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
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
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1297
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
#define FREE(x)
Definition: memory.h:40
#define TAILQ_EMPTY(head)
Definition: queue.h:714
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
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
static void recode_buf(char *buf, size_t buflen)
Convert some text between two character sets.
Definition: alias.c:186
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_addr_is_user()

bool mutt_addr_is_user ( const struct Address addr)

Does the address belong to the user.

Parameters
addrAddress to check
Return values
trueif the given address belongs to the user

Definition at line 545 of file alias.c.

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 }
#define NONULL(x)
Definition: string2.h:37
char * mailbox
Mailbox and host address.
Definition: address.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:36
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:53
bool mutt_regexlist_match(struct RegexList *rl, const char *str)
Does a string match any Regex in the list?
Definition: regex.c:190
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:51
WHERE struct Address * C_From
Config: Default &#39;From&#39; address to use, if isn&#39;t otherwise set.
Definition: mutt_globals.h:82
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:1179
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
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Log at debug level 5.
Definition: logging.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_new()

struct Alias* alias_new ( void  )

Create a new Alias.

Return values
ptrNewly allocated Alias

Free the result with alias_free()

Definition at line 606 of file alias.c.

607 {
608  struct Alias *a = mutt_mem_calloc(1, sizeof(struct Alias));
609  TAILQ_INIT(&a->addr);
610  return a;
611 }
A shortcut for an email address or addresses.
Definition: alias.h:33
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define TAILQ_INIT(head)
Definition: queue.h:758
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_free()

void alias_free ( struct Alias **  ptr)

Free an Alias.

Parameters
[out]ptrAlias to free

Definition at line 617 of file alias.c.

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 }
A shortcut for an email address or addresses.
Definition: alias.h:33
char * name
Short name.
Definition: alias.h:35
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1461
Alias has changed, NotifyAlias, EventAlias.
Definition: notify_type.h:42
An alias-change event.
Definition: alias.h:59
Container for Accounts, Notifications.
Definition: neomutt.h:36
char * comment
Free-form comment string.
Definition: alias.h:37
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
An Alias is about to be deleted.
Definition: alias.h:53
#define FREE(x)
Definition: memory.h:40
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ aliaslist_free()

void aliaslist_free ( struct AliasList *  al)

Free a List of Aliases.

Parameters
alAliasList to free

Definition at line 637 of file alias.c.

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 }
A shortcut for an email address or addresses.
Definition: alias.h:33
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:728
#define TAILQ_INIT(head)
Definition: queue.h:758
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:834
void alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:617
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_init()

void alias_init ( void  )

Set up the Alias globals.

Definition at line 651 of file alias.c.

652 {
653  /* reverse alias keys need to be strdup'ed because of idna conversions */
656 }
#define MUTT_HASH_STRCASECMP
use strcasecmp() to compare keys
Definition: hash.h:98
struct HashTable * ReverseAliases
Hash Table of aliases (email address -> alias)
Definition: reverse.c:37
#define MUTT_HASH_ALLOW_DUPS
allow duplicate keys to be inserted
Definition: hash.h:100
#define MUTT_HASH_STRDUP_KEYS
make a copy of the keys
Definition: hash.h:99
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:251
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_shutdown()

void alias_shutdown ( void  )

Clean up the Alias globals.

Definition at line 661 of file alias.c.

662 {
663  struct Alias *np = NULL;
664  TAILQ_FOREACH(np, &Aliases, entries)
665  {
667  }
670 }
A shortcut for an email address or addresses.
Definition: alias.h:33
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:447
struct HashTable * ReverseAliases
Hash Table of aliases (email address -> alias)
Definition: reverse.c:37
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:55
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:637
void alias_reverse_delete(struct Alias *alias)
Remove an email address lookup for an Alias.
Definition: reverse.c:65
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ Aliases

struct AliasList Aliases = TAILQ_HEAD_INITIALIZER(Aliases)

List of all the user's email aliases.

Definition at line 55 of file alias.c.