NeoMutt
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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 "browser/lib.h"
#include "editor/lib.h"
#include "history/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.
 
static void expand_aliases_r (struct AddressList *al, struct ListHead *expn)
 Expand aliases, recursively.
 
static void recode_buf (struct Buffer *buf)
 Convert some text between two character sets.
 
static int check_alias_name (const char *s, char *dest, size_t destlen)
 Sanity-check an alias name.
 
static bool string_is_address (const char *str, const char *user, const char *domain)
 Does an email address match a user and domain?
 
struct AddressList * alias_lookup (const char *name)
 Find an Alias.
 
void mutt_expand_aliases (struct AddressList *al)
 Expand aliases in a List of Addresses.
 
void mutt_expand_aliases_env (struct Envelope *env)
 Expand aliases in all the fields of an Envelope.
 
struct AddressList * mutt_get_address (struct Envelope *env, const char **prefix)
 Get an Address from an Envelope.
 
void alias_create (struct AddressList *al, const struct ConfigSubset *sub)
 Create a new Alias from an Address.
 
bool mutt_addr_is_user (const struct Address *addr)
 Does the address belong to the user.
 
struct Aliasalias_new (void)
 Create a new Alias.
 
void alias_free (struct Alias **ptr)
 Free an Alias.
 
void aliaslist_free (struct AliasList *al)
 Free a List of Aliases.
 
void alias_init (void)
 Set up the Alias globals.
 
void alias_cleanup (void)
 Clean up the Alias globals.
 

Variables

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

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: John /bin/rm -f ~ Doe john..nosp@m.doe@.nosp@m.examp.nosp@m.le.c.nosp@m.om and the user creates an alias for this, NeoMutt could wind up executing the backticks because it writes aliases like alias me John /bin/rm -f ~ Doe john..nosp@m.doe@.nosp@m.examp.nosp@m.le.c.nosp@m.om 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: John `/bin/rm -f ~` Doe john..nosp@m.doe@.nosp@m.examp.nosp@m.le.c.nosp@m.om since that would get aliased as alias me John \`/bin/rm -f ~\` Doe john..nosp@m.doe@.nosp@m.examp.nosp@m.le.c.nosp@m.om 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 86 of file alias.c.

87{
88 while (*s)
89 {
90 if ((*s == '\\') || (*s == '`') || (*s == '\'') || (*s == '"') || (*s == '$'))
91 fputc('\\', fp);
92 fputc(*s, fp);
93 s++;
94 }
95}
+ 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 104 of file alias.c.

105{
106 struct Address *a = TAILQ_FIRST(al);
107 while (a)
108 {
109 if (!a->group && !a->personal && a->mailbox && !buf_find_char(a->mailbox, '@'))
110 {
111 struct AddressList *alias = alias_lookup(buf_string(a->mailbox));
112 if (alias)
113 {
114 bool duplicate = false;
115 struct ListNode *np = NULL;
116 STAILQ_FOREACH(np, expn, entries)
117 {
118 if (mutt_str_equal(buf_string(a->mailbox), np->data)) /* alias already found */
119 {
120 mutt_debug(LL_DEBUG1, "loop in alias found for '%s'\n", buf_string(a->mailbox));
121 duplicate = true;
122 break;
123 }
124 }
125
126 if (duplicate)
127 {
128 // We've already seen this alias, so drop it
129 struct Address *next = TAILQ_NEXT(a, entries);
130 TAILQ_REMOVE(al, a, entries);
131 mutt_addr_free(&a);
132 a = next;
133 continue;
134 }
135
136 // Keep a list of aliases that we've already seen
138
139 /* The alias may expand to several addresses,
140 * some of which may themselves be aliases.
141 * Create a copy and recursively expand any aliases within. */
142 struct AddressList copy = TAILQ_HEAD_INITIALIZER(copy);
143 mutt_addrlist_copy(&copy, alias, false);
144 expand_aliases_r(&copy, expn);
145
146 /* Next, move the expanded addresses
147 * from the copy into the original list (before the alias) */
148 struct Address *a2 = NULL, *tmp = NULL;
149 TAILQ_FOREACH_SAFE(a2, &copy, entries, tmp)
150 {
151 TAILQ_INSERT_BEFORE(a, a2, entries);
152 }
153 a = TAILQ_PREV(a, AddressList, entries);
154 // Finally, remove the alias itself
155 struct Address *next = TAILQ_NEXT(a, entries);
156 TAILQ_REMOVE(al, next, entries);
157 mutt_addr_free(&next);
158 }
159 else
160 {
161 struct passwd *pw = getpwnam(buf_string(a->mailbox));
162 if (pw)
163 {
164 char namebuf[256] = { 0 };
165
166 mutt_gecos_name(namebuf, sizeof(namebuf), pw);
167 a->personal = buf_new(namebuf);
168 }
169 }
170 }
171 a = TAILQ_NEXT(a, entries);
172 }
173
174 const char *fqdn = NULL;
175 const bool c_use_domain = cs_subset_bool(NeoMutt->sub, "use_domain");
176 if (c_use_domain && (fqdn = mutt_fqdn(true, NeoMutt->sub)))
177 {
178 /* now qualify all local addresses */
179 mutt_addrlist_qualify(al, fqdn);
180 }
181}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:762
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:677
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:460
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:104
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition: buffer.c:316
const char * buf_find_char(const struct Buffer *buf, const char c)
Return a pointer to a char found in the buffer.
Definition: buffer.c:623
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:542
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
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: logging2.h:43
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user's real name in /etc/passwd.
Definition: muttlib.c:374
#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:705
An email address.
Definition: address.h:36
struct Buffer * personal
Real name of address.
Definition: address.h:37
bool group
Group mailbox?
Definition: address.h:39
struct Buffer * mailbox
Mailbox and host address.
Definition: address.h:38
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ recode_buf()

static void recode_buf ( struct Buffer buf)
static

Convert some text between two character sets.

Parameters
bufBuffer to convert

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

Definition at line 190 of file alias.c.

191{
192 const char *const c_config_charset = cs_subset_string(NeoMutt->sub, "config_charset");
193 if (!c_config_charset || !cc_charset())
194 return;
195
196 char *s = buf_strdup(buf);
197 if (!s)
198 return;
199 if (mutt_ch_convert_string(&s, cc_charset(), c_config_charset, MUTT_ICONV_NO_FLAGS) == 0)
200 buf_strcpy(buf, s);
201 FREE(&s);
202}
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:407
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
const char * cc_charset(void)
Get the cached value of $charset.
Definition: config_cache.c:115
#define FREE(x)
Definition: memory.h:45
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:826
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
+ 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 == ICONV_ILLEGAL_SEQ) || (l == ICONV_BUF_TOO_SMALL); /* 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 == ICONV_ILLEGAL_SEQ)
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}
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition: charset.h:105
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition: charset.h:103
+ 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:810
#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:60
#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:1398
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:570
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 = buf_pool_get();
373 struct Buffer *fixed = buf_pool_get();
374 struct Buffer *prompt = NULL;
375 struct Buffer *tmp = buf_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 buf_copy(tmp, addr->mailbox);
388 pc = strchr(buf_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. */
395 check_alias_name(buf_string(tmp), buf->data, buf->dsize);
396
397retry_name:
398 /* L10N: prompt to add a new alias */
399 if ((mw_get_field(_("Alias as: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
400 buf_is_empty(buf))
401 {
402 goto done;
403 }
404
405 /* check to see if the user already has an alias defined */
406 if (alias_lookup(buf_string(buf)))
407 {
408 mutt_error(_("You already have an alias defined with that name"));
409 goto done;
410 }
411
412 if (check_alias_name(buf_string(buf), fixed->data, fixed->dsize))
413 {
414 switch (query_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
415 {
416 case MUTT_YES:
417 buf_copy(buf, fixed);
418 goto retry_name;
419 case MUTT_ABORT:
420 goto done;
421 default:; // do nothing
422 }
423 }
424
425 struct Alias *alias = alias_new();
426 alias->name = buf_strdup(buf);
427
429
430 if (addr && addr->mailbox)
431 buf_copy(buf, addr->mailbox);
432 else
433 buf_reset(buf);
434
435 mutt_addrlist_to_intl(al, NULL);
436
437 do
438 {
439 if ((mw_get_field(_("Address: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
440 buf_is_empty(buf))
441 {
442 alias_free(&alias);
443 goto done;
444 }
445
446 mutt_addrlist_parse(&alias->addr, buf_string(buf));
447 if (TAILQ_EMPTY(&alias->addr))
448 mutt_beep(false);
449 if (mutt_addrlist_to_intl(&alias->addr, &err))
450 {
451 mutt_error(_("Bad IDN: '%s'"), err);
452 FREE(&err);
453 continue;
454 }
455 } while (TAILQ_EMPTY(&alias->addr));
456
457 if (addr && addr->personal && !mutt_is_mail_list(addr))
458 buf_copy(buf, addr->personal);
459 else
460 buf_reset(buf);
461
462 if (mw_get_field(_("Personal name: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
463 {
464 alias_free(&alias);
465 goto done;
466 }
467 buf_copy(TAILQ_FIRST(&alias->addr)->personal, buf);
468
469 buf_reset(buf);
470 if (mw_get_field(_("Comment: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) == 0)
471 {
472 mutt_str_replace(&alias->comment, buf_string(buf));
473 }
474
475 buf_reset(buf);
476 mutt_addrlist_write(&alias->addr, buf, true);
477 prompt = buf_pool_get();
478 if (alias->comment)
479 {
480 buf_printf(prompt, "[%s = %s # %s] %s", alias->name, buf_string(buf),
481 alias->comment, _("Accept?"));
482 }
483 else
484 {
485 buf_printf(prompt, "[%s = %s] %s", alias->name, buf_string(buf), _("Accept?"));
486 }
487 if (query_yesorno(buf_string(prompt), MUTT_YES) != MUTT_YES)
488 {
489 alias_free(&alias);
490 goto done;
491 }
492
493 alias_reverse_add(alias);
494 TAILQ_INSERT_TAIL(&Aliases, alias, entries);
495
496 const char *const c_alias_file = cs_subset_path(sub, "alias_file");
497 buf_strcpy(buf, c_alias_file);
498
499 struct FileCompletionData cdata = { false, NULL, NULL, NULL };
500 if (mw_get_field(_("Save to file: "), buf, MUTT_COMP_CLEAR, HC_FILE,
501 &CompleteMailboxOps, &cdata) != 0)
502 {
503 goto done;
504 }
505 mutt_expand_path(buf->data, buf->dsize);
506 fp_alias = fopen(buf_string(buf), "a+");
507 if (!fp_alias)
508 {
509 mutt_perror("%s", buf_string(buf));
510 goto done;
511 }
512
513 /* terminate existing file with \n if necessary */
514 if (!mutt_file_seek(fp_alias, 0, SEEK_END))
515 {
516 goto done;
517 }
518 if (ftell(fp_alias) > 0)
519 {
520 if (!mutt_file_seek(fp_alias, -1, SEEK_CUR))
521 {
522 goto done;
523 }
524 if (fread(buf->data, 1, 1, fp_alias) != 1)
525 {
526 mutt_perror(_("Error reading alias file"));
527 goto done;
528 }
529 if (!mutt_file_seek(fp_alias, 0, SEEK_END))
530 {
531 goto done;
532 }
533 if (buf->data[0] != '\n')
534 fputc('\n', fp_alias);
535 }
536
537 if (check_alias_name(alias->name, NULL, 0))
538 mutt_file_quote_filename(alias->name, buf->data, buf->dsize);
539 else
540 buf_strcpy(buf, alias->name);
541
542 recode_buf(buf);
543 fprintf(fp_alias, "alias %s ", buf_string(buf));
544 buf_reset(buf);
545
546 mutt_addrlist_write(&alias->addr, buf, false);
547 recode_buf(buf);
548 write_safe_address(fp_alias, buf_string(buf));
549 if (alias->comment)
550 fprintf(fp_alias, " # %s", alias->comment);
551 fputc('\n', fp_alias);
552 if (mutt_file_fsync_close(&fp_alias) != 0)
553 mutt_perror(_("Trouble adding alias"));
554 else
555 mutt_message(_("Alias added"));
556
557done:
558 mutt_file_fclose(&fp_alias);
559 buf_pool_release(&buf);
560 buf_pool_release(&fixed);
561 buf_pool_release(&prompt);
562 buf_pool_release(&tmp);
563}
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1379
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1207
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:478
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1294
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
static void recode_buf(struct Buffer *buf)
Convert some text between two character sets.
Definition: alias.c:190
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:630
static void write_safe_address(FILE *fp, const char *s)
Defang malicious email addresses.
Definition: alias.c:86
const struct CompleteOps CompleteMailboxOps
Auto-Completion of Files / Mailboxes.
Definition: complete.c:160
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:173
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:572
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:169
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:69
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
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:891
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:733
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:168
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition: window.c:275
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_perror(...)
Definition: logging2.h:93
@ HC_FILE
Files.
Definition: lib.h:52
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:54
#define _(a)
Definition: message.h:28
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:327
#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:56
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:126
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
@ 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 query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:330
#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
Input for the file completion function.
Definition: curs_lib.h:49
+ 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 570 of file alias.c.

571{
572 if (!addr)
573 {
574 mutt_debug(LL_DEBUG5, "no, NULL address\n");
575 return false;
576 }
577 if (!addr->mailbox)
578 {
579 mutt_debug(LL_DEBUG5, "no, no mailbox\n");
580 return false;
581 }
582
584 {
585 mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", buf_string(addr->mailbox), Username);
586 return true;
587 }
589 {
590 mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
592 return true;
593 }
594 const char *fqdn = mutt_fqdn(false, NeoMutt->sub);
595 if (string_is_address(buf_string(addr->mailbox), Username, fqdn))
596 {
597 mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
598 Username, NONULL(fqdn));
599 return true;
600 }
601 fqdn = mutt_fqdn(true, NeoMutt->sub);
602 if (string_is_address(buf_string(addr->mailbox), Username, fqdn))
603 {
604 mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
605 Username, NONULL(fqdn));
606 return true;
607 }
608
609 const struct Address *c_from = cs_subset_address(NeoMutt->sub, "from");
610 if (c_from && mutt_istr_equal(buf_string(c_from->mailbox), buf_string(addr->mailbox)))
611 {
612 mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", buf_string(addr->mailbox),
613 buf_string(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:155
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
Definition: config_type.c:262
char * ShortHostname
Short version of the hostname.
Definition: globals.c:40
char * Username
User's login name.
Definition: globals.c:42
@ LL_DEBUG5
Log at debug level 5.
Definition: logging2.h:47
+ 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:1461
@ NT_ALIAS_DELETE
Alias is about to be deleted.
Definition: alias.h:55
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:48
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:173
@ 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:42
+ 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_cleanup()

void alias_cleanup ( 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 60 of file alias.c.