NeoMutt  2023-03-22
Teaching an old dog new tricks
DOXYGEN
alias.c
Go to the documentation of this file.
1
31#include "config.h"
32#include <stddef.h>
33#include <pwd.h>
34#include <stdbool.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <wchar.h>
39#include <wctype.h>
40#include "mutt/lib.h"
41#include "address/lib.h"
42#include "config/lib.h"
43#include "email/lib.h"
44#include "core/lib.h"
45#include "gui/lib.h"
46#include "mutt.h"
47#include "alias.h"
48#include "lib.h"
49#include "enter/lib.h"
50#include "question/lib.h"
51#include "send/lib.h"
52#include "alternates.h"
53#include "globals.h" // IWYU pragma: keep
54#include "maillist.h"
55#include "muttlib.h"
56#include "reverse.h"
57
59
84static void write_safe_address(FILE *fp, const char *s)
85{
86 while (*s)
87 {
88 if ((*s == '\\') || (*s == '`') || (*s == '\'') || (*s == '"') || (*s == '$'))
89 fputc('\\', fp);
90 fputc(*s, fp);
91 s++;
92 }
93}
94
102static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
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}
180
189static void recode_buf(char *buf, size_t buflen)
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}
203
215static int check_alias_name(const char *s, char *dest, size_t destlen)
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}
253
261static bool string_is_address(const char *str, const char *user, const char *domain)
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}
271
280struct AddressList *alias_lookup(const char *name)
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}
291
298void mutt_expand_aliases(struct AddressList *al)
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}
307
313{
315 mutt_expand_aliases(&env->to);
316 mutt_expand_aliases(&env->cc);
320}
321
330struct AddressList *mutt_get_address(struct Envelope *env, const char **prefix)
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}
364
370void alias_create(struct AddressList *al, const struct ConfigSubset *sub)
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}
568
574bool mutt_addr_is_user(const struct Address *addr)
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}
623
630struct Alias *alias_new(void)
631{
632 struct Alias *a = mutt_mem_calloc(1, sizeof(struct Alias));
633 TAILQ_INIT(&a->addr);
634 return a;
635}
636
641void alias_free(struct Alias **ptr)
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}
657
662void aliaslist_free(struct AliasList *al)
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}
675
679void alias_init(void)
680{
682}
683
688{
689 struct Alias *np = NULL;
690 TAILQ_FOREACH(np, &Aliases, entries)
691 {
693 }
696}
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_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1435
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:440
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 mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1372
Email Address Handling.
void alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:641
struct AliasList Aliases
List of all the user's email aliases.
Definition: alias.c:58
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
static int check_alias_name(const char *s, char *dest, size_t destlen)
Sanity-check an alias name.
Definition: alias.c:215
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:280
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:298
void alias_create(struct AddressList *al, const struct ConfigSubset *sub)
Create a new Alias from an Address.
Definition: alias.c:370
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:574
void alias_init(void)
Set up the Alias globals.
Definition: alias.c:679
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:630
void mutt_expand_aliases_env(struct Envelope *env)
Expand aliases in all the fields of an Envelope.
Definition: alias.c:312
struct AddressList * mutt_get_address(struct Envelope *env, const char **prefix)
Get an Address from an Envelope.
Definition: alias.c:330
static void recode_buf(char *buf, size_t buflen)
Convert some text between two character sets.
Definition: alias.c:189
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:662
void alias_shutdown(void)
Clean up the Alias globals.
Definition: alias.c:687
static void write_safe_address(FILE *fp, const char *s)
Defang malicious email addresses.
Definition: alias.c:84
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:102
Representation of a single alias to an email address.
@ NT_ALIAS_DELETE
Alias is about to be deleted.
Definition: alias.h:55
bool mutt_alternates_match(const char *addr)
Compare an Address to the Un/Alternates lists.
Definition: alternates.c:151
Alternate address handling.
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_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
Definition: helpers.c:49
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:129
Structs that make up an email.
Enter a string.
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
char * ShortHostname
Short version of the hostname.
Definition: globals.c:39
char * Username
User's login name.
Definition: globals.c:41
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 mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
#define mutt_perror(...)
Definition: logging.h:88
Convenience wrapper for the gui headers.
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition: list.c:45
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
@ LL_DEBUG5
Log at debug level 5.
Definition: logging.h:44
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
@ LL_NOTIFY
Log of notifications.
Definition: logging.h:45
Handle mailing lists.
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#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
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
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
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
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
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
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
Many unsorted constants and some structs.
#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_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user's real name in /etc/passwd.
Definition: muttlib.c:361
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:123
Some miscellaneous functions.
@ NT_ALIAS
Alias has changed, NotifyAlias, EventAlias.
Definition: notify_type.h:37
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
Ask the user a question.
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:194
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:735
#define STAILQ_INIT(head)
Definition: queue.h:372
#define TAILQ_INIT(head)
Definition: queue.h:765
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:809
#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_EMPTY(head)
Definition: queue.h:721
#define TAILQ_INSERT_BEFORE(listelm, elm, field)
Definition: queue.h:786
void alias_reverse_add(struct Alias *alias)
Add an email address lookup for an Alias.
Definition: reverse.c:61
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
void alias_reverse_init(void)
Set up the Reverse Alias Hash Table.
Definition: reverse.c:42
Manage alias reverse lookups.
Convenience wrapper for the send headers.
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:696
Key value store.
#define NONULL(x)
Definition: string2.h:37
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 shortcut for an email address or addresses.
Definition: alias.h:34
char * comment
Free-form comment string.
Definition: alias.h:37
char * name
Short name.
Definition: alias.h:35
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
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
A set of inherited config items.
Definition: subset.h:47
The header of an Email.
Definition: envelope.h:57
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
An alias-change event.
Definition: alias.h:64
struct Alias * alias
Alias that changed.
Definition: alias.h:65
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 Notify * notify
Notifications handler.
Definition: neomutt.h:38
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39