NeoMutt  2023-03-22
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 "enter/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "alternates.h"
#include "globals.h"
#include "maillist.h"
#include "muttlib.h"
#include "reverse.h"
+ Include dependency graph for alias.c:

Go to the source code of this file.

Functions

static void write_safe_address (FILE *fp, const 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, const struct ConfigSubset *sub)
 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,
const 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 84 of file alias.c.

85{
86 while (*s)
87 {
88 if ((*s == '\\') || (*s == '`') || (*s == '\'') || (*s == '"') || (*s == '$'))
89 fputc('\\', fp);
90 fputc(*s, fp);
91 s++;
92 }
93}
+ 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

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

Definition at line 102 of file alias.c.

103{
104 struct Address *a = TAILQ_FIRST(al);
105 while (a)
106 {
107 if (!a->group && !a->personal && a->mailbox && !strchr(a->mailbox, '@'))
108 {
109 struct AddressList *alias = alias_lookup(a->mailbox);
110 if (alias)
111 {
112 bool duplicate = false;
113 struct ListNode *np = NULL;
114 STAILQ_FOREACH(np, expn, entries)
115 {
116 if (mutt_str_equal(a->mailbox, np->data)) /* alias already found */
117 {
118 mutt_debug(LL_DEBUG1, "loop in alias found for '%s'\n", a->mailbox);
119 duplicate = true;
120 break;
121 }
122 }
123
124 if (duplicate)
125 {
126 // We've already seen this alias, so drop it
127 struct Address *next = TAILQ_NEXT(a, entries);
128 TAILQ_REMOVE(al, a, entries);
129 mutt_addr_free(&a);
130 a = next;
131 continue;
132 }
133
134 // Keep a list of aliases that we've already seen
136
137 /* The alias may expand to several addresses,
138 * some of which may themselves be aliases.
139 * Create a copy and recursively expand any aliases within. */
140 struct AddressList copy = TAILQ_HEAD_INITIALIZER(copy);
141 mutt_addrlist_copy(&copy, alias, false);
142 expand_aliases_r(&copy, expn);
143
144 /* Next, move the expanded addresses
145 * from the copy into the original list (before the alias) */
146 struct Address *a2 = NULL, *tmp = NULL;
147 TAILQ_FOREACH_SAFE(a2, &copy, entries, tmp)
148 {
149 TAILQ_INSERT_BEFORE(a, a2, entries);
150 }
151 a = TAILQ_PREV(a, AddressList, entries);
152 // Finally, remove the alias itself
153 struct Address *next = TAILQ_NEXT(a, entries);
154 TAILQ_REMOVE(al, next, entries);
155 mutt_addr_free(&next);
156 }
157 else
158 {
159 struct passwd *pw = getpwnam(a->mailbox);
160 if (pw)
161 {
162 char namebuf[256] = { 0 };
163
164 mutt_gecos_name(namebuf, sizeof(namebuf), pw);
165 mutt_str_replace(&a->personal, namebuf);
166 }
167 }
168 }
169 a = TAILQ_NEXT(a, entries);
170 }
171
172 const char *fqdn = NULL;
173 const bool c_use_domain = cs_subset_bool(NeoMutt->sub, "use_domain");
174 if (c_use_domain && (fqdn = mutt_fqdn(true, NeoMutt->sub)))
175 {
176 /* now qualify all local addresses */
177 mutt_addrlist_qualify(al, fqdn);
178 }
179}
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
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:650
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:440
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:280
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:102
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition: list.c:45
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user's real name in /etc/passwd.
Definition: muttlib.c:361
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:735
#define TAILQ_PREV(elm, headname, field)
Definition: queue.h:834
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define TAILQ_FIRST(head)
Definition: queue.h:723
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:841
#define TAILQ_NEXT(elm, field)
Definition: queue.h:832
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
#define TAILQ_INSERT_BEFORE(listelm, elm, field)
Definition: queue.h:786
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:696
An email address.
Definition: address.h:36
bool group
Group mailbox?
Definition: address.h:39
char * mailbox
Mailbox and host address.
Definition: address.h:38
char * personal
Real name of address.
Definition: address.h:37
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ 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 189 of file alias.c.

190{
191 const char *const c_config_charset = cs_subset_string(NeoMutt->sub, "config_charset");
192 const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
193 if (!c_config_charset || !c_charset)
194 return;
195
196 char *s = mutt_str_dup(buf);
197 if (!s)
198 return;
199 if (mutt_ch_convert_string(&s, c_charset, c_config_charset, MUTT_ICONV_NO_FLAGS) == 0)
200 mutt_str_copy(buf, s, buflen);
201 FREE(&s);
202}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define FREE(x)
Definition: memory.h:43
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:752
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
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:652
+ 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 215 of file alias.c.

216{
217 wchar_t wc = 0;
218 mbstate_t mbstate = { 0 };
219 size_t l;
220 int rc = 0;
221 bool dry = !dest || !destlen;
222
223 if (!dry)
224 destlen--;
225 for (; s && *s && (dry || destlen) && (l = mbrtowc(&wc, s, MB_CUR_MAX, &mbstate)) != 0;
226 s += l, destlen -= l)
227 {
228 bool bad = (l == (size_t) (-1)) || (l == (size_t) (-2)); /* conversion error */
229 bad = bad || (!dry && l > destlen); /* too few room for mb char */
230 if (l == 1)
231 bad = bad || (!strchr("-_+=.", *s) && !iswalnum(wc));
232 else
233 bad = bad || !iswalnum(wc);
234 if (bad)
235 {
236 if (dry)
237 return -1;
238 if (l == (size_t) (-1))
239 memset(&mbstate, 0, sizeof(mbstate_t));
240 *dest++ = '_';
241 rc = -1;
242 }
243 else if (!dry)
244 {
245 memcpy(dest, s, l);
246 dest += l;
247 }
248 }
249 if (!dry)
250 *dest = '\0';
251 return rc;
252}
+ 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 261 of file alias.c.

262{
263 char buf[1024] = { 0 };
264
265 snprintf(buf, sizeof(buf), "%s@%s", NONULL(user), NONULL(domain));
266 if (mutt_istr_equal(str, buf))
267 return true;
268
269 return false;
270}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
#define NONULL(x)
Definition: string2.h:37
+ 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 280 of file alias.c.

281{
282 struct Alias *a = NULL;
283
284 TAILQ_FOREACH(a, &Aliases, entries)
285 {
286 if (mutt_istr_equal(name, a->name))
287 return &a->addr;
288 }
289 return NULL;
290}
struct AliasList Aliases
List of all the user's email aliases.
Definition: alias.c:58
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
A shortcut for an email address or addresses.
Definition: alias.h:34
char * name
Short name.
Definition: alias.h:35
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 298 of file alias.c.

299{
300 struct ListHead expn; /* previously expanded aliases to avoid loops */
301
302 STAILQ_INIT(&expn);
303 expand_aliases_r(al, &expn);
304 mutt_list_free(&expn);
306}
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1372
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
#define STAILQ_INIT(head)
Definition: queue.h:372
+ 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 312 of file alias.c.

313{
315 mutt_expand_aliases(&env->to);
316 mutt_expand_aliases(&env->cc);
320}
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:298
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
struct AddressList reply_to
Email's 'reply-to'.
Definition: envelope.h:64
struct AddressList mail_followup_to
Email's 'mail-followup-to'.
Definition: envelope.h:65
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:61
struct AddressList bcc
Email's 'Bcc' list.
Definition: envelope.h:62
struct AddressList from
Email's 'From' list.
Definition: envelope.h:59
+ 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 330 of file alias.c.

331{
332 struct AddressList *al = NULL;
333 const char *pfx = NULL;
334
336 {
337 if (!TAILQ_EMPTY(&env->to) && !mutt_is_mail_list(TAILQ_FIRST(&env->to)))
338 {
339 pfx = "To";
340 al = &env->to;
341 }
342 else
343 {
344 pfx = "Cc";
345 al = &env->cc;
346 }
347 }
348 else if (!TAILQ_EMPTY(&env->reply_to) && !mutt_is_mail_list(TAILQ_FIRST(&env->reply_to)))
349 {
350 pfx = "Reply-To";
351 al = &env->reply_to;
352 }
353 else
354 {
355 al = &env->from;
356 pfx = "From";
357 }
358
359 if (prefix)
360 *prefix = pfx;
361
362 return al;
363}
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:574
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:44
#define TAILQ_EMPTY(head)
Definition: queue.h:721
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_create()

void alias_create ( struct AddressList *  al,
const struct ConfigSubset sub 
)

Create a new Alias from an Address.

Parameters
alAddress to use
subConfig items

Definition at line 370 of file alias.c.

371{
372 struct Buffer *buf = mutt_buffer_pool_get();
373 struct Buffer *fixed = mutt_buffer_pool_get();
374 struct Buffer *prompt = NULL;
375 struct Buffer *tmp = mutt_buffer_pool_get();
376
377 struct Address *addr = NULL;
378 char *pc = NULL;
379 char *err = NULL;
380 FILE *fp_alias = NULL;
381
382 if (al)
383 {
384 addr = TAILQ_FIRST(al);
385 if (addr && addr->mailbox)
386 {
387 mutt_buffer_strcpy(tmp, addr->mailbox);
388 pc = strchr(mutt_buffer_string(tmp), '@');
389 if (pc)
390 *pc = '\0';
391 }
392 }
393
394 /* Don't suggest a bad alias name in the event of a strange local part. */
396
397retry_name:
398 /* L10N: prompt to add a new alias */
399 if ((mutt_buffer_get_field(_("Alias as: "), buf, MUTT_COMP_NO_FLAGS, false,
400 NULL, NULL, NULL) != 0) ||
402 {
403 goto done;
404 }
405
406 /* check to see if the user already has an alias defined */
408 {
409 mutt_error(_("You already have an alias defined with that name"));
410 goto done;
411 }
412
413 if (check_alias_name(mutt_buffer_string(buf), fixed->data, fixed->dsize))
414 {
415 switch (mutt_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
416 {
417 case MUTT_YES:
418 mutt_buffer_copy(buf, fixed);
419 goto retry_name;
420 case MUTT_ABORT:
421 goto done;
422 default:; // do nothing
423 }
424 }
425
426 struct Alias *alias = alias_new();
427 alias->name = mutt_buffer_strdup(buf);
428
430
431 if (addr && addr->mailbox)
432 mutt_buffer_strcpy(buf, addr->mailbox);
433 else
435
436 mutt_addrlist_to_intl(al, NULL);
437
438 do
439 {
440 if ((mutt_buffer_get_field(_("Address: "), buf, MUTT_COMP_NO_FLAGS, false,
441 NULL, NULL, NULL) != 0) ||
443 {
444 alias_free(&alias);
445 goto done;
446 }
447
449 if (TAILQ_EMPTY(&alias->addr))
450 mutt_beep(false);
451 if (mutt_addrlist_to_intl(&alias->addr, &err))
452 {
453 mutt_error(_("Bad IDN: '%s'"), err);
454 FREE(&err);
455 continue;
456 }
457 } while (TAILQ_EMPTY(&alias->addr));
458
459 if (addr && addr->personal && !mutt_is_mail_list(addr))
460 mutt_buffer_strcpy(buf, addr->personal);
461 else
463
464 if (mutt_buffer_get_field(_("Personal name: "), buf, MUTT_COMP_NO_FLAGS,
465 false, NULL, NULL, NULL) != 0)
466 {
467 alias_free(&alias);
468 goto done;
469 }
470 mutt_str_replace(&TAILQ_FIRST(&alias->addr)->personal, mutt_buffer_string(buf));
471
473 if (mutt_buffer_get_field(_("Comment: "), buf, MUTT_COMP_NO_FLAGS, false,
474 NULL, NULL, NULL) == 0)
475 {
477 }
478
480 mutt_addrlist_write(&alias->addr, buf, true);
481 prompt = mutt_buffer_pool_get();
482 if (alias->comment)
483 {
484 mutt_buffer_printf(prompt, "[%s = %s # %s] %s", alias->name,
485 mutt_buffer_string(buf), alias->comment, _("Accept?"));
486 }
487 else
488 {
489 mutt_buffer_printf(prompt, "[%s = %s] %s", alias->name,
490 mutt_buffer_string(buf), _("Accept?"));
491 }
493 {
494 alias_free(&alias);
495 goto done;
496 }
497
498 alias_reverse_add(alias);
499 TAILQ_INSERT_TAIL(&Aliases, alias, entries);
500
501 const char *const c_alias_file = cs_subset_path(sub, "alias_file");
502 mutt_buffer_strcpy(buf, c_alias_file);
503
504 if (mutt_buffer_get_field(_("Save to file: "), buf, MUTT_COMP_FILE | MUTT_COMP_CLEAR,
505 false, NULL, NULL, NULL) != 0)
506 {
507 goto done;
508 }
509 mutt_expand_path(buf->data, buf->dsize);
510 fp_alias = fopen(mutt_buffer_string(buf), "a+");
511 if (!fp_alias)
512 {
514 goto done;
515 }
516
517 /* terminate existing file with \n if necessary */
518 if (!mutt_file_seek(fp_alias, 0, SEEK_END))
519 {
520 goto done;
521 }
522 if (ftell(fp_alias) > 0)
523 {
524 if (!mutt_file_seek(fp_alias, -1, SEEK_CUR))
525 {
526 goto done;
527 }
528 if (fread(buf->data, 1, 1, fp_alias) != 1)
529 {
530 mutt_perror(_("Error reading alias file"));
531 goto done;
532 }
533 if (!mutt_file_seek(fp_alias, 0, SEEK_END))
534 {
535 goto done;
536 }
537 if (buf->data[0] != '\n')
538 fputc('\n', fp_alias);
539 }
540
541 if (check_alias_name(alias->name, NULL, 0))
542 mutt_file_quote_filename(alias->name, buf->data, buf->dsize);
543 else
544 mutt_buffer_strcpy(buf, alias->name);
545
546 recode_buf(buf->data, buf->dsize);
547 fprintf(fp_alias, "alias %s ", mutt_buffer_string(buf));
549
550 mutt_addrlist_write(&alias->addr, buf, false);
551 recode_buf(buf->data, buf->dsize);
553 if (alias->comment)
554 fprintf(fp_alias, " # %s", alias->comment);
555 fputc('\n', fp_alias);
556 if (mutt_file_fsync_close(&fp_alias) != 0)
557 mutt_perror(_("Trouble adding alias"));
558 else
559 mutt_message(_("Alias added"));
560
561done:
562 mutt_file_fclose(&fp_alias);
567}
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1353
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1184
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1270
void alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:641
static int check_alias_name(const char *s, char *dest, size_t destlen)
Sanity-check an alias name.
Definition: alias.c:215
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:630
static void recode_buf(char *buf, size_t buflen)
Convert some text between two character sets.
Definition: alias.c:189
static void write_safe_address(FILE *fp, const char *s)
Defang malicious email addresses.
Definition: alias.c:84
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:298
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:365
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:500
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:485
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:129
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: window.c:178
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:151
size_t mutt_file_quote_filename(const char *filename, char *buf, size_t buflen)
Quote a filename to survive the shell's quoting rules.
Definition: file.c:864
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:706
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:167
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#define mutt_perror(...)
Definition: logging.h:88
#define _(a)
Definition: message.h:28
#define MUTT_COMP_FILE
File completion (in browser)
Definition: mutt.h:58
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:55
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:65
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:123
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition: quad.h:37
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:194
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:809
void alias_reverse_add(struct Alias *alias)
Add an email address lookup for an Alias.
Definition: reverse.c:61
char * comment
Free-form comment string.
Definition: alias.h:37
String manipulation buffer.
Definition: buffer.h:34
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
+ 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
trueThe given address belongs to the user

Definition at line 574 of file alias.c.

575{
576 if (!addr)
577 {
578 mutt_debug(LL_DEBUG5, "no, NULL address\n");
579 return false;
580 }
581 if (!addr->mailbox)
582 {
583 mutt_debug(LL_DEBUG5, "no, no mailbox\n");
584 return false;
585 }
586
587 if (mutt_istr_equal(addr->mailbox, Username))
588 {
589 mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", addr->mailbox, Username);
590 return true;
591 }
593 {
594 mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", addr->mailbox, Username, ShortHostname);
595 return true;
596 }
597 const char *fqdn = mutt_fqdn(false, NeoMutt->sub);
598 if (string_is_address(addr->mailbox, Username, fqdn))
599 {
600 mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
601 return true;
602 }
603 fqdn = mutt_fqdn(true, NeoMutt->sub);
604 if (string_is_address(addr->mailbox, Username, fqdn))
605 {
606 mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
607 return true;
608 }
609
610 const struct Address *c_from = cs_subset_address(NeoMutt->sub, "from");
611 if (c_from && mutt_istr_equal(c_from->mailbox, addr->mailbox))
612 {
613 mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", addr->mailbox, c_from->mailbox);
614 return true;
615 }
616
618 return true;
619
620 mutt_debug(LL_DEBUG5, "no, all failed\n");
621 return false;
622}
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:261
bool mutt_alternates_match(const char *addr)
Compare an Address to the Un/Alternates lists.
Definition: alternates.c:151
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
Definition: helpers.c:49
char * ShortHostname
Short version of the hostname.
Definition: globals.c:39
char * Username
User's login name.
Definition: globals.c:41
@ LL_DEBUG5
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 630 of file alias.c.

631{
632 struct Alias *a = mutt_mem_calloc(1, sizeof(struct Alias));
633 TAILQ_INIT(&a->addr);
634 return a;
635}
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:765
+ 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 641 of file alias.c.

642{
643 if (!ptr || !*ptr)
644 return;
645
646 struct Alias *alias = *ptr;
647
648 mutt_debug(LL_NOTIFY, "NT_ALIAS_DELETE: %s\n", alias->name);
649 struct EventAlias ev_a = { alias };
651
652 FREE(&alias->name);
653 FREE(&alias->comment);
655 FREE(ptr);
656}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1435
@ NT_ALIAS_DELETE
Alias is about to be deleted.
Definition: alias.h:55
@ LL_NOTIFY
Log of notifications.
Definition: logging.h:45
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171
@ NT_ALIAS
Alias has changed, NotifyAlias, EventAlias.
Definition: notify_type.h:37
An alias-change event.
Definition: alias.h:64
struct Alias * alias
Alias that changed.
Definition: alias.h:65
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
+ 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 662 of file alias.c.

663{
664 if (!al)
665 return;
666
667 struct Alias *np = NULL, *tmp = NULL;
668 TAILQ_FOREACH_SAFE(np, al, entries, tmp)
669 {
670 TAILQ_REMOVE(al, np, entries);
671 alias_free(&np);
672 }
673 TAILQ_INIT(al);
674}
+ 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 679 of file alias.c.

680{
682}
void alias_reverse_init(void)
Set up the Reverse Alias Hash Table.
Definition: reverse.c:42
+ 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 687 of file alias.c.

688{
689 struct Alias *np = NULL;
690 TAILQ_FOREACH(np, &Aliases, entries)
691 {
693 }
696}
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:662
void alias_reverse_shutdown(void)
Clear up the Reverse Alias Hash Table.
Definition: reverse.c:52
void alias_reverse_delete(struct Alias *alias)
Remove an email address lookup for an Alias.
Definition: reverse.c:83
+ 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 58 of file alias.c.