Thanks to visit codestin.com
Credit goes to code.neomutt.org

NeoMutt  2025-12-11-189-gceedb6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
lib.h File Reference

Email Aliases. More...

#include <stdbool.h>
#include "core/lib.h"
#include "expando.h"
+ Include dependency graph for lib.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void alias_init (void)
 Set up the Alias globals.
 
void alias_init_keys (struct SubMenu *sm_generic)
 Initialise the Alias Keybindings - Implements ::init_keys_api.
 
void alias_cleanup (void)
 Clean up the Alias globals.
 
void alias_create (struct AddressList *al, const struct ConfigSubset *sub)
 Create a new Alias from an Address.
 
struct AddressList * alias_lookup (const char *name)
 Find an Alias.
 
bool mutt_addr_is_user (const struct Address *addr)
 Does the address belong to the user.
 
void mutt_expand_aliases_env (struct Envelope *env)
 Expand aliases in all the fields of an Envelope.
 
void mutt_expand_aliases (struct AddressList *al)
 Expand aliases in a List of Addresses.
 
struct AddressList * mutt_get_address (struct Envelope *env, const char **prefix)
 Get an Address from an Envelope.
 
enum CommandResult parse_alias (const struct Command *cmd, struct Buffer *line, struct Buffer *err)
 Parse the 'alias' command - Implements Command::parse() -.
 
enum CommandResult parse_unalias (const struct Command *cmd, struct Buffer *line, struct Buffer *err)
 Parse the 'unalias' command - Implements Command::parse() -.
 
void alias_tags_to_buffer (struct TagList *tl, struct Buffer *buf)
 Write a comma-separated list of tags to a Buffer.
 
void parse_alias_comments (struct Alias *alias, const char *com)
 Parse the alias/query comment field.
 
void parse_alias_tags (const char *tags, struct TagList *tl)
 Parse a comma-separated list of tags.
 
int alias_complete (struct Buffer *buf, struct ConfigSubset *sub)
 Alias completion routine.
 
void alias_dialog (struct Mailbox *m, struct ConfigSubset *sub)
 Open the aliases dialog.
 
int query_complete (struct Buffer *buf, struct ConfigSubset *sub)
 Perform auto-complete using an Address Query.
 
void query_index (struct Mailbox *m, struct ConfigSubset *sub)
 Perform an Alias Query and display the results.
 
struct Addressalias_reverse_lookup (const struct Address *addr)
 Does the user have an alias for the given address.
 

Variables

const struct CompleteOps CompleteAliasOps
 Auto-Completion of Aliases.
 

Detailed Description

Email Aliases.

Authors
  • 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 lib.h.

Function Documentation

◆ alias_init()

void alias_init ( void )

Set up the Alias globals.

Definition at line 709 of file alias.c.

710{
712}
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_init_keys()

void alias_init_keys ( struct SubMenu * sm_generic)

Initialise the Alias Keybindings - Implements ::init_keys_api.

Definition at line 127 of file functions.c.

128{
129 struct MenuDefinition *md = NULL;
130 struct SubMenu *sm = NULL;
131
133 md = km_register_menu(MENU_ALIAS, "alias");
134 km_menu_add_submenu(md, sm);
135 km_menu_add_submenu(md, sm_generic);
137
139 md = km_register_menu(MENU_QUERY, "query");
140 km_menu_add_submenu(md, sm);
141 km_menu_add_submenu(md, sm_generic);
143}
const struct MenuFuncOp OpQuery[]
Functions for the external Query Menu.
Definition functions.c:74
static const struct MenuOpSeq QueryDefaultBindings[]
Key bindings for the external Query Menu.
Definition functions.c:108
static const struct MenuOpSeq AliasDefaultBindings[]
Key bindings for the Alias Menu.
Definition functions.c:91
static const struct MenuFuncOp OpAlias[]
Functions for the Alias Menu.
Definition functions.c:58
void km_menu_add_submenu(struct MenuDefinition *md, struct SubMenu *sm)
Add a SubMenu to a Menu Definition.
Definition init.c:123
struct SubMenu * km_register_submenu(const struct MenuFuncOp functions[])
Register a submenu.
Definition init.c:91
struct MenuDefinition * km_register_menu(int menu, const char *name)
Register a menu.
Definition init.c:107
void km_menu_add_bindings(struct MenuDefinition *md, const struct MenuOpSeq bindings[])
Add Keybindings to a Menu.
Definition init.c:136
Functions for a Dialog or Window.
Definition menu.h:81
Collection of related functions.
Definition menu.h:69
@ MENU_QUERY
Select from results of external query.
Definition type.h:48
@ MENU_ALIAS
Select an email address by its alias.
Definition type.h:34
+ 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 717 of file alias.c.

718{
719 struct Alias **ap = NULL;
721 {
723 }
726}
struct AliasArray Aliases
List of all the user's email aliases.
Definition alias.c:59
void aliaslist_clear(struct AliasArray *aa)
Empty a List of Aliases.
Definition alias.c:693
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
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
A shortcut for an email address or addresses.
Definition alias.h:35
+ 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 366 of file alias.c.

367{
368 struct Buffer *buf = buf_pool_get();
369 struct Buffer *fixed = buf_pool_get();
370 struct Buffer *prompt = NULL;
371 struct Buffer *tmp = buf_pool_get();
372
373 struct Address *addr = NULL;
374 char *pc = NULL;
375 char *err = NULL;
376 FILE *fp_alias = NULL;
377
378 if (al)
379 {
380 addr = TAILQ_FIRST(al);
381 if (addr && addr->mailbox)
382 {
383 buf_copy(tmp, addr->mailbox);
384 pc = strchr(buf_string(tmp), '@');
385 if (pc)
386 *pc = '\0';
387 }
388 }
389
390 /* Don't suggest a bad alias name in the event of a strange local part. */
391 check_alias_name(buf_string(tmp), buf);
392
393retry_name:
394 /* L10N: prompt to add a new alias */
395 if ((mw_get_field(_("Alias as: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
396 buf_is_empty(buf))
397 {
398 goto done;
399 }
400
401 /* check to see if the user already has an alias defined */
402 if (alias_lookup(buf_string(buf)))
403 {
404 mutt_error(_("You already have an alias defined with that name"));
405 goto done;
406 }
407
408 if (check_alias_name(buf_string(buf), fixed))
409 {
410 switch (query_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
411 {
412 case MUTT_YES:
413 buf_copy(buf, fixed);
414 goto retry_name;
415 case MUTT_ABORT:
416 goto done;
417 default:; // do nothing
418 }
419 }
420
421 struct Alias *alias = alias_new();
422 alias->name = buf_strdup(buf);
423
425
426 if (addr && addr->mailbox)
427 buf_copy(buf, addr->mailbox);
428 else
429 buf_reset(buf);
430
431 mutt_addrlist_to_intl(al, NULL);
432
433 do
434 {
435 if ((mw_get_field(_("Address: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
436 buf_is_empty(buf))
437 {
438 alias_free(&alias);
439 goto done;
440 }
441
442 mutt_addrlist_parse(&alias->addr, buf_string(buf));
443 if (TAILQ_EMPTY(&alias->addr))
444 mutt_beep(false);
445 if (mutt_addrlist_to_intl(&alias->addr, &err))
446 {
447 mutt_error(_("Bad IDN: '%s'"), err);
448 FREE(&err);
449 continue;
450 }
451 } while (TAILQ_EMPTY(&alias->addr));
452
453 if (addr && addr->personal && !mutt_is_mail_list(addr))
454 buf_copy(buf, addr->personal);
455 else
456 buf_reset(buf);
457
458 if (mw_get_field(_("Personal name: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
459 {
460 alias_free(&alias);
461 goto done;
462 }
463
464 TAILQ_FIRST(&alias->addr)->personal = buf_new(buf_string(buf));
465
466 buf_reset(buf);
467 if (mw_get_field(_("Comment: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) == 0)
468 {
469 mutt_str_replace(&alias->comment, buf_string(buf));
470 }
471
472 buf_reset(buf);
473 if (mw_get_field(_("Tags (comma-separated): "), buf, MUTT_COMP_NO_FLAGS,
474 HC_OTHER, NULL, NULL) == 0)
475 {
476 parse_alias_tags(buf_string(buf), &alias->tags);
477 }
478
479 buf_reset(buf);
480 mutt_addrlist_write(&alias->addr, buf, true);
481 prompt = buf_pool_get();
482
483 buf_printf(prompt, "alias %s %s", alias->name, buf_string(buf));
484
485 bool has_tags = STAILQ_FIRST(&alias->tags);
486
487 if (alias->comment || has_tags)
488 buf_addstr(prompt, " #");
489
490 if (alias->comment)
491 buf_add_printf(prompt, " %s", alias->comment);
492
493 if (has_tags)
494 {
495 if (STAILQ_FIRST(&alias->tags))
496 {
497 buf_addstr(prompt, " tags:");
498 alias_tags_to_buffer(&alias->tags, prompt);
499 }
500 }
501
502 buf_add_printf(prompt, "\n%s", _("Accept?"));
503
504 if (query_yesorno(buf_string(prompt), MUTT_YES) != MUTT_YES)
505 {
506 alias_free(&alias);
507 goto done;
508 }
509
510 alias_reverse_add(alias);
511 ARRAY_ADD(&Aliases, alias);
512
513 const char *const c_alias_file = cs_subset_path(sub, "alias_file");
514 buf_strcpy(buf, c_alias_file);
515
516 struct FileCompletionData cdata = { false, NULL, NULL, NULL, NULL };
517 if (mw_get_field(_("Save to file: "), buf, MUTT_COMP_CLEAR, HC_FILE,
518 &CompleteFileOps, &cdata) != 0)
519 {
520 goto done;
521 }
522 expand_path(buf, false);
523 fp_alias = mutt_file_fopen(buf_string(buf), "a+");
524 if (!fp_alias)
525 {
526 mutt_perror("%s", buf_string(buf));
527 goto done;
528 }
529
530 /* terminate existing file with \n if necessary */
531 if (ftell(fp_alias) > 0)
532 {
533 if (!mutt_file_seek(fp_alias, -1, SEEK_CUR))
534 {
535 goto done;
536 }
537 if (fread(buf->data, 1, 1, fp_alias) != 1)
538 {
539 mutt_perror(_("Error reading alias file"));
540 goto done;
541 }
542 if (!mutt_file_seek(fp_alias, 0, SEEK_END))
543 {
544 goto done;
545 }
546 if (buf_at(buf, 0) != '\n')
547 fputc('\n', fp_alias);
548 }
549
550 if (check_alias_name(alias->name, NULL))
551 buf_quote_filename(buf, alias->name, true);
552 else
553 buf_strcpy(buf, alias->name);
554
555 recode_buf(buf);
556 fprintf(fp_alias, "alias %s ", buf_string(buf));
557 buf_reset(buf);
558
559 mutt_addrlist_write(&alias->addr, buf, false);
560 recode_buf(buf);
561 write_safe_address(fp_alias, buf_string(buf));
562 if (alias->comment)
563 fprintf(fp_alias, " # %s", alias->comment);
564 if (STAILQ_FIRST(&alias->tags))
565 {
566 fprintf(fp_alias, " tags:");
567
568 struct Tag *tag = NULL;
569 STAILQ_FOREACH(tag, &alias->tags, entries)
570 {
571 fprintf(fp_alias, "%s", tag->name);
572 if (STAILQ_NEXT(tag, entries))
573 fprintf(fp_alias, ",");
574 }
575 }
576 fputc('\n', fp_alias);
577 if (mutt_file_fsync_close(&fp_alias) != 0)
578 mutt_perror(_("Trouble adding alias"));
579 else
580 mutt_message(_("Alias added"));
581
582done:
583 mutt_file_fclose(&fp_alias);
584 buf_pool_release(&buf);
585 buf_pool_release(&fixed);
586 buf_pool_release(&prompt);
587 buf_pool_release(&tmp);
588}
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition address.c:1378
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition address.c:1206
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition address.c:480
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition address.c:1293
void parse_alias_tags(const char *tags, struct TagList *tl)
Parse a comma-separated list of tags.
Definition commands.c:64
void alias_tags_to_buffer(struct TagList *tl, struct Buffer *buf)
Write a comma-separated list of tags to a Buffer.
Definition commands.c:48
void alias_free(struct Alias **ptr)
Free an Alias.
Definition alias.c:668
static int check_alias_name(const char *s, struct Buffer *dest)
Sanity-check an alias name.
Definition alias.c:213
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition alias.c:274
static void recode_buf(struct Buffer *buf)
Convert some text between two character sets.
Definition alias.c:189
struct Alias * alias_new(void)
Create a new Alias.
Definition alias.c:656
static void write_safe_address(FILE *fp, const char *s)
Defang malicious email addresses.
Definition alias.c:85
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:157
const struct CompleteOps CompleteFileOps
Auto-Completion of Files.
Definition complete.c:152
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition buffer.c:204
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition buffer.c:668
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition buffer.c:304
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition buffer.c:601
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition helpers.c:168
void mutt_beep(bool force)
Irritate the user.
Definition curs_lib.c:68
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition wdata.h:43
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition wdata.h:44
void buf_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell's quoting rules.
Definition file.c:811
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition file.c:656
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition file.c:132
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_file_fopen(PATH, MODE)
Definition file.h:138
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list?
Definition maillist.c:44
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:271
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
#define mutt_perror(...)
Definition logging2.h:95
@ HC_FILE
Files.
Definition lib.h:58
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:60
#define FREE(x)
Definition memory.h:63
#define _(a)
Definition message.h:28
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:121
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
@ 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:326
#define STAILQ_FIRST(head)
Definition queue.h:388
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
#define TAILQ_FIRST(head)
Definition queue.h:780
#define TAILQ_EMPTY(head)
Definition queue.h:778
#define STAILQ_NEXT(elm, field)
Definition queue.h:439
void alias_reverse_add(struct Alias *alias)
Add an email address lookup for an Alias.
Definition reverse.c:61
An email address.
Definition address.h:35
struct Buffer * mailbox
Mailbox and host address.
Definition address.h:37
struct TagList tags
Tags.
Definition alias.h:39
char * comment
Free-form comment string.
Definition alias.h:38
char * name
Short name.
Definition alias.h:36
struct AddressList addr
List of Addresses the Alias expands to.
Definition alias.h:37
String manipulation buffer.
Definition buffer.h:36
char * data
Pointer to data.
Definition buffer.h:37
Input for the file completion function.
Definition curs_lib.h:39
LinkedList Tag Element.
Definition tags.h:42
char * name
Tag name.
Definition tags.h:43
+ 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 274 of file alias.c.

275{
276 struct Alias **ap = NULL;
277
279 {
280 struct Alias *a = *ap;
281
282 if (mutt_istr_equal(name, a->name))
283 return &a->addr;
284 }
285 return NULL;
286}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:674
+ 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 595 of file alias.c.

596{
597 if (!addr)
598 {
599 mutt_debug(LL_DEBUG5, "no, NULL address\n");
600 return false;
601 }
602 if (!addr->mailbox)
603 {
604 mutt_debug(LL_DEBUG5, "no, no mailbox\n");
605 return false;
606 }
607
609 {
610 mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", buf_string(addr->mailbox),
612 return true;
613 }
615 {
616 mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
618 return true;
619 }
620 const char *fqdn = mutt_fqdn(false, NeoMutt->sub);
622 {
623 mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
624 NeoMutt->username, NONULL(fqdn));
625 return true;
626 }
627 fqdn = mutt_fqdn(true, NeoMutt->sub);
629 {
630 mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
631 NeoMutt->username, NONULL(fqdn));
632 return true;
633 }
634
635 const struct Address *c_from = cs_subset_address(NeoMutt->sub, "from");
636 if (c_from && mutt_istr_equal(buf_string(c_from->mailbox), buf_string(addr->mailbox)))
637 {
638 mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", buf_string(addr->mailbox),
639 buf_string(c_from->mailbox));
640 return true;
641 }
642
644 return true;
645
646 mutt_debug(LL_DEBUG5, "no, all failed\n");
647 return false;
648}
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
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:255
bool mutt_alternates_match(const char *addr)
Compare an Address to the Un/Alternates lists.
Definition alternates.c:180
char * ShortHostname
Short version of the hostname.
Definition globals.c:37
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG5
Log at debug level 5.
Definition logging2.h:49
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition sendlib.c:706
#define NONULL(x)
Definition string2.h:44
Container for Accounts, Notifications.
Definition neomutt.h:128
char * username
User's login name.
Definition neomutt.h:142
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:134
+ 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 308 of file alias.c.

309{
311 mutt_expand_aliases(&env->to);
312 mutt_expand_aliases(&env->cc);
316}
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition alias.c:294
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_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 294 of file alias.c.

295{
296 // previously expanded aliases to avoid loops
297 struct ListHead expn = STAILQ_HEAD_INITIALIZER(expn);
298
299 expand_aliases_r(al, &expn);
300 mutt_list_free(&expn);
302}
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition address.c:1397
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition alias.c:103
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition list.c:123
#define STAILQ_HEAD_INITIALIZER(head)
Definition queue.h:324
+ 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 326 of file alias.c.

327{
328 struct AddressList *al = NULL;
329 const char *pfx = NULL;
330
332 {
333 if (!TAILQ_EMPTY(&env->to) && !mutt_is_mail_list(TAILQ_FIRST(&env->to)))
334 {
335 pfx = "To";
336 al = &env->to;
337 }
338 else
339 {
340 pfx = "Cc";
341 al = &env->cc;
342 }
343 }
344 else if (!TAILQ_EMPTY(&env->reply_to) && !mutt_is_mail_list(TAILQ_FIRST(&env->reply_to)))
345 {
346 pfx = "Reply-To";
347 al = &env->reply_to;
348 }
349 else
350 {
351 al = &env->from;
352 pfx = "From";
353 }
354
355 if (prefix)
356 *prefix = pfx;
357
358 return al;
359}
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition alias.c:595
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_tags_to_buffer()

void alias_tags_to_buffer ( struct TagList * tl,
struct Buffer * buf )

Write a comma-separated list of tags to a Buffer.

Parameters
tlTags
bufBuffer for the result

Definition at line 48 of file commands.c.

49{
50 struct Tag *tag = NULL;
51 STAILQ_FOREACH(tag, tl, entries)
52 {
53 buf_addstr(buf, tag->name);
54 if (STAILQ_NEXT(tag, entries))
55 buf_addch(buf, ',');
56 }
57}
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_alias_comments()

void parse_alias_comments ( struct Alias * alias,
const char * com )

Parse the alias/query comment field.

Parameters
aliasAlias for the result
comComment string

If the comment contains a 'tags:' field, the result will be put in alias.tags

Definition at line 94 of file commands.c.

95{
96 if (!com || (com[0] == '\0'))
97 return;
98
99 const regmatch_t *match = mutt_prex_capture(PREX_ALIAS_TAGS, com);
100 if (match)
101 {
102 const regmatch_t *pre = &match[PREX_ALIAS_TAGS_MATCH_PRE];
103 const regmatch_t *tags = &match[PREX_ALIAS_TAGS_MATCH_TAGS];
104 const regmatch_t *post = &match[PREX_ALIAS_TAGS_MATCH_POST];
105
106 struct Buffer *tmp = buf_pool_get();
107
108 // Extract the tags
109 buf_addstr_n(tmp, com + mutt_regmatch_start(tags),
111 parse_alias_tags(buf_string(tmp), &alias->tags);
112 buf_reset(tmp);
113
114 // Collect all the other text as "comments"
115 buf_addstr_n(tmp, com + mutt_regmatch_start(pre),
117 buf_addstr_n(tmp, com + mutt_regmatch_start(post),
119 alias->comment = buf_strdup(tmp);
120
121 buf_pool_release(&tmp);
122 }
123 else
124 {
125 alias->comment = mutt_str_dup(com);
126 }
127}
size_t buf_addstr_n(struct Buffer *buf, const char *s, size_t len)
Add a string to a Buffer, expanding it if necessary.
Definition buffer.c:96
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
regmatch_t * mutt_prex_capture(enum Prex which, const char *str)
Match a precompiled regex against a string.
Definition prex.c:297
@ PREX_ALIAS_TAGS
tags:a,b,c
Definition prex.h:43
@ PREX_ALIAS_TAGS_MATCH_POST
... tags:a,b,c[ ...]
Definition prex.h:240
@ PREX_ALIAS_TAGS_MATCH_PRE
[... ]tags:a,b,c ...
Definition prex.h:237
@ PREX_ALIAS_TAGS_MATCH_TAGS
... tags:[a,b,c] ...
Definition prex.h:239
static regoff_t mutt_regmatch_end(const regmatch_t *match)
Return the end of a match.
Definition regex3.h:67
static regoff_t mutt_regmatch_start(const regmatch_t *match)
Return the start of a match.
Definition regex3.h:57
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_alias_tags()

void parse_alias_tags ( const char * tags,
struct TagList * tl )

Parse a comma-separated list of tags.

Parameters
tagsComma-separated string
tlTagList for the results

Definition at line 64 of file commands.c.

65{
66 if (!tags || !tl)
67 return;
68
69 struct Slist *sl = slist_parse(tags, D_SLIST_SEP_COMMA);
70 if (slist_is_empty(sl))
71 {
72 slist_free(&sl);
73 return;
74 }
75
76 struct ListNode *np = NULL;
77 STAILQ_FOREACH(np, &sl->head, entries)
78 {
79 struct Tag *tag = tag_new();
80 tag->name = np->data; // Transfer string
81 np->data = NULL;
82 STAILQ_INSERT_TAIL(tl, tag, entries);
83 }
84 slist_free(&sl);
85}
struct Tag * tag_new(void)
Create a new Tag.
Definition tags.c:64
struct Slist * slist_parse(const char *str, uint32_t flags)
Parse a list of strings into a list.
Definition slist.c:177
bool slist_is_empty(const struct Slist *list)
Is the slist empty?
Definition slist.c:140
void slist_free(struct Slist **ptr)
Free an Slist object.
Definition slist.c:124
#define STAILQ_INSERT_TAIL(head, elm, field)
Definition queue.h:427
A List node for strings.
Definition list.h:37
char * data
String.
Definition list.h:38
String list.
Definition slist.h:37
struct ListHead head
List containing values.
Definition slist.h:38
#define D_SLIST_SEP_COMMA
Slist items are comma-separated.
Definition types.h:110
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_complete()

int alias_complete ( struct Buffer * buf,
struct ConfigSubset * sub )

Alias completion routine.

Parameters
bufPartial Alias to complete
subConfig items
Return values
1Success
0Error

Given a partial alias, this routine attempts to fill in the alias from the alias list as much as possible. if given empty search string or found nothing, present all aliases

Definition at line 337 of file dlg_alias.c.

338{
339 char bestname[8192] = { 0 };
340 struct Alias *a_best = NULL;
341 int count = 0;
342
343 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
344 mdata.limit = buf_strdup(buf);
345 mdata.search_state = search_state_new();
346
347 if (buf_at(buf, 0) != '\0')
348 {
349 struct Alias **ap = NULL;
351 {
352 struct Alias *a = *ap;
353 if (a->name && mutt_strn_equal(a->name, buf_string(buf), buf_len(buf)))
354 {
355 a_best = a;
356 count++;
357
358 if (bestname[0] == '\0') /* init */
359 {
360 mutt_str_copy(bestname, a->name, MIN(mutt_str_len(a->name) + 1, sizeof(bestname)));
361 }
362 else
363 {
364 int i;
365 for (i = 0; a->name[i] && (a->name[i] == bestname[i]); i++)
366 ; // do nothing
367
368 bestname[i] = '\0';
369 }
370 }
371 }
372
373 // Exactly one match, so expand the Alias and return
374 if (count == 1)
375 {
376 buf_reset(buf);
377 mutt_addrlist_write(&a_best->addr, buf, true);
378 buf_addstr(buf, ", ");
379 FREE(&mdata.limit);
381 return 1;
382 }
383
384 if (bestname[0] == '\0')
385 {
386 // Create a View Array of all the Aliases
387 FREE(&mdata.limit);
389 {
390 alias_array_alias_add(&mdata.ava, *ap);
391 }
392 }
393 else
394 {
395 /* fake the pattern for menu title */
396 char *mtitle = NULL;
397 mutt_str_asprintf(&mtitle, "~f ^%s", buf_string(buf));
398 FREE(&mdata.limit);
399 mdata.limit = mtitle;
400
401 if (!mutt_str_equal(bestname, buf_string(buf)))
402 {
403 /* we are adding something to the completion */
404 buf_strcpy_n(buf, bestname, mutt_str_len(bestname) + 1);
405 FREE(&mdata.limit);
407 return 1;
408 }
409
410 /* build alias list and show it */
412 {
413 struct Alias *a = *ap;
414 int aasize = alias_array_alias_add(&mdata.ava, a);
415
416 struct AliasView *av = ARRAY_GET(&mdata.ava, aasize - 1);
417
418 if (a->name && !mutt_strn_equal(a->name, buf_string(buf), buf_len(buf)))
419 {
420 av->is_visible = false;
421 }
422 }
423 }
424 }
425
426 if (ARRAY_EMPTY(&mdata.ava))
427 {
428 struct Alias **ap = NULL;
430 {
431 alias_array_alias_add(&mdata.ava, *ap);
432 }
433
434 mutt_pattern_alias_func(NULL, &mdata, PAA_VISIBLE, NULL);
435 }
436
437 if (!dlg_alias(&mdata))
438 goto done;
439
440 buf_reset(buf);
441
442 // Extract the selected aliases
443 struct Buffer *tmpbuf = buf_pool_get();
444 struct AliasView *avp = NULL;
445 ARRAY_FOREACH(avp, &mdata.ava)
446 {
447 if (!avp->is_tagged)
448 continue;
449
450 mutt_addrlist_write(&avp->alias->addr, tmpbuf, true);
451 buf_addstr(tmpbuf, ", ");
452 }
453 buf_copy(buf, tmpbuf);
454 buf_pool_release(&tmpbuf);
455
456done:
457 // Process any deleted aliases
458 ARRAY_FOREACH(avp, &mdata.ava)
459 {
460 if (!avp->is_deleted)
461 continue;
462
463 // Find and remove the alias from the Aliases array
464 struct Alias **ap = NULL;
466 {
467 if (*ap == avp->alias)
468 {
469 ARRAY_REMOVE(&Aliases, ap);
470 break;
471 }
472 }
473 alias_free(&avp->alias);
474 }
475
476 ARRAY_FREE(&mdata.ava);
477 FREE(&mdata.limit);
478 FREE(&mdata.title);
480
481 return 0;
482}
int alias_array_alias_add(struct AliasViewArray *ava, struct Alias *alias)
Add an Alias to the AliasViewArray.
Definition array.c:47
#define ARRAY_REMOVE(head, elem)
Remove an entry from the array, shifting down the subsequent entries.
Definition array.h:355
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_GET(head, idx)
Return the element at index.
Definition array.h:109
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:491
size_t buf_strcpy_n(struct Buffer *buf, const char *s, size_t len)
Copy a string into a Buffer.
Definition buffer.c:416
static bool dlg_alias(struct AliasMenuData *mdata)
Display a menu of Aliases -.
Definition dlg_alias.c:266
#define MIN(a, b)
Definition memory.h:38
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition string.c:805
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:662
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition string.c:429
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:500
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:583
@ PAA_VISIBLE
Set AliasView.is_visible and hide the rest.
Definition lib.h:191
int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, enum PatternAlias action, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition pattern.c:186
void search_state_free(struct SearchState **ptr)
Free a SearchState.
struct SearchState * search_state_new(void)
Create a new SearchState.
AliasView array wrapper with Pattern information -.
Definition gui.h:54
char * limit
Limit being used.
Definition gui.h:60
struct AliasViewArray ava
All Aliases/Queries.
Definition gui.h:55
struct SearchState * search_state
State of the current search.
Definition gui.h:63
char * title
Title for the status bar.
Definition gui.h:62
struct ConfigSubset * sub
Config items.
Definition gui.h:57
GUI data wrapping an Alias.
Definition gui.h:38
bool is_visible
Is visible?
Definition gui.h:45
struct Alias * alias
Alias.
Definition gui.h:46
bool is_deleted
Is it deleted?
Definition gui.h:44
bool is_tagged
Is it tagged?
Definition gui.h:43
void * mdata
Private data.
Definition lib.h:149
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_dialog()

void alias_dialog ( struct Mailbox * m,
struct ConfigSubset * sub )

Open the aliases dialog.

Parameters
mMailbox
subConfig item

Definition at line 489 of file dlg_alias.c.

490{
491 struct Alias **ap = NULL;
492
493 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
495
496 // Create a View Array of all the Aliases
498 {
499 alias_array_alias_add(&mdata.ava, *ap);
500 }
501
502 if (!dlg_alias(&mdata))
503 goto done;
504
505 // Prepare the "To:" field of a new email
506 struct Email *e = email_new();
507 e->env = mutt_env_new();
508
509 struct AliasView *avp = NULL;
510 ARRAY_FOREACH(avp, &mdata.ava)
511 {
512 if (!avp->is_tagged)
513 continue;
514
515 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
516 if (alias_to_addrlist(&al_copy, avp->alias))
517 {
518 mutt_addrlist_copy(&e->env->to, &al_copy, false);
519 mutt_addrlist_clear(&al_copy);
520 }
521 }
522
523 mutt_send_message(SEND_REVIEW_TO, e, NULL, m, NULL, sub);
524
525done:
526 // Process any deleted aliases
527 ARRAY_FOREACH(avp, &mdata.ava)
528 {
529 if (avp->is_deleted)
530 {
531 // Find and remove the alias from the Aliases array
533 {
534 if (*ap == avp->alias)
535 {
536 ARRAY_REMOVE(&Aliases, ap);
537 break;
538 }
539 }
540 alias_free(&avp->alias);
541 }
542 }
543
544 ARRAY_FREE(&mdata.ava);
545 FREE(&mdata.limit);
546 FREE(&mdata.title);
548}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition address.c:765
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1460
bool alias_to_addrlist(struct AddressList *al, struct Alias *alias)
Turn an Alias into an AddressList.
Definition dlg_query.c:118
struct Email * email_new(void)
Create a new Email.
Definition email.c:77
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition envelope.c:45
#define TAILQ_HEAD_INITIALIZER(head)
Definition queue.h:694
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Mailbox *m, struct EmailArray *ea, struct ConfigSubset *sub)
Send an email.
Definition send.c:2027
#define SEND_REVIEW_TO
Allow the user to edit the To field.
Definition send.h:56
The envelope/body of an email.
Definition email.h:39
struct Envelope * env
Envelope information.
Definition email.h:68
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_complete()

int query_complete ( struct Buffer * buf,
struct ConfigSubset * sub )

Perform auto-complete using an Address Query.

Parameters
bufBuffer for completion
subConfig item
Return values
0Always

Definition at line 406 of file dlg_query.c.

407{
408 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
410
411 struct AliasArray aa = ARRAY_HEAD_INITIALIZER;
412 const char *const c_query_command = cs_subset_string(sub, "query_command");
413 if (!c_query_command)
414 {
415 mutt_warning(_("Query command not defined"));
416 goto done;
417 }
418
419 query_run(buf_string(buf), true, &aa, sub);
420 if (ARRAY_EMPTY(&aa))
421 goto done;
422
423 mdata.aa = &aa;
424
425 struct Alias **a_first = ARRAY_FIRST(&aa);
426 if (ARRAY_SIZE(&aa) == 1) // only one response?
427 {
428 struct AddressList addr = TAILQ_HEAD_INITIALIZER(addr);
429 if (alias_to_addrlist(&addr, *a_first))
430 {
432 buf_reset(buf);
433 mutt_addrlist_write(&addr, buf, false);
434 mutt_addrlist_clear(&addr);
436 buf_addstr(buf, ", ");
437 }
438 goto done;
439 }
440
441 struct Alias **ap = NULL;
442 ARRAY_FOREACH(ap, mdata.aa)
443 {
444 alias_array_alias_add(&mdata.ava, *ap);
445 }
446
447 /* multiple results, choose from query menu */
448 if (!dlg_query(buf, &mdata))
449 goto done;
450
451 buf_reset(buf);
452 buf_alloc(buf, 8192);
453 struct AliasView *avp = NULL;
454 ARRAY_FOREACH(avp, &mdata.ava)
455 {
456 if (!avp->is_tagged)
457 continue;
458
459 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
460 if (alias_to_addrlist(&al_copy, avp->alias))
461 {
462 mutt_addrlist_to_local(&al_copy);
463 mutt_addrlist_write(&al_copy, buf, false);
464 mutt_addrlist_clear(&al_copy);
465 }
466 buf_addstr(buf, ", ");
467 }
468
469done:
470 ARRAY_FREE(&mdata.ava);
471 FREE(&mdata.title);
472 FREE(&mdata.limit);
474 aliaslist_clear(&aa);
475 return 0;
476}
#define ARRAY_FIRST(head)
Convenience method to get the first element.
Definition array.h:136
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition buffer.c:337
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
int query_run(const char *s, bool verbose, struct AliasArray *aa, const struct ConfigSubset *sub)
Run an external program to find Addresses.
Definition dlg_query.c:187
static bool dlg_query(struct Buffer *buf, struct AliasMenuData *mdata)
Get the user to enter an Address Query -.
Definition dlg_query.c:347
#define mutt_warning(...)
Definition logging2.h:92
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
struct AliasArray * aa
Alias data.
Definition gui.h:56
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_index()

void query_index ( struct Mailbox * m,
struct ConfigSubset * sub )

Perform an Alias Query and display the results.

Parameters
mMailbox
subConfig item

Definition at line 483 of file dlg_query.c.

484{
485 const char *const c_query_command = cs_subset_string(sub, "query_command");
486 if (!c_query_command)
487 {
488 mutt_warning(_("Query command not defined"));
489 return;
490 }
491
492 struct AliasArray aa = ARRAY_HEAD_INITIALIZER;
493 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
494 mdata.aa = &aa;
495 mdata.search_state = search_state_new();
496
497 struct Buffer *buf = buf_pool_get();
498 if ((mw_get_field(_("Query: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
499 buf_is_empty(buf))
500 {
501 goto done;
502 }
503
504 query_run(buf_string(buf), false, &aa, sub);
505 if (ARRAY_EMPTY(&aa))
506 goto done;
507
508 struct Alias **ap = NULL;
509 ARRAY_FOREACH(ap, mdata.aa)
510 {
511 alias_array_alias_add(&mdata.ava, *ap);
512 }
513
514 if (!dlg_query(buf, &mdata))
515 goto done;
516
517 // Prepare the "To:" field of a new email
518 struct Email *e = email_new();
519 e->env = mutt_env_new();
520
521 struct AliasView *avp = NULL;
522 ARRAY_FOREACH(avp, &mdata.ava)
523 {
524 if (!avp->is_tagged)
525 continue;
526
527 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
528 if (alias_to_addrlist(&al_copy, avp->alias))
529 {
530 mutt_addrlist_copy(&e->env->to, &al_copy, false);
531 mutt_addrlist_clear(&al_copy);
532 }
533 }
534
535 mutt_send_message(SEND_REVIEW_TO, e, NULL, m, NULL, sub);
536
537done:
538 ARRAY_FREE(&mdata.ava);
539 FREE(&mdata.title);
540 FREE(&mdata.limit);
542 aliaslist_clear(&aa);
543 buf_pool_release(&buf);
544}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_reverse_lookup()

struct Address * alias_reverse_lookup ( const struct Address * addr)

Does the user have an alias for the given address.

Parameters
addrAddress to lookup
Return values
ptrMatching Address

Definition at line 105 of file reverse.c.

106{
107 if (!addr || !addr->mailbox)
108 return NULL;
109
111}
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition hash.c:363
static struct HashTable * ReverseAliases
Hash Table of aliases (email address -> alias)
Definition reverse.c:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ CompleteAliasOps

const struct CompleteOps CompleteAliasOps
extern

Auto-Completion of Aliases.

Definition at line 108 of file complete.c.

108 {
109 .complete = complete_alias,
110};
enum FunctionRetval complete_alias(struct EnterWindowData *wdata, int op)
Alias completion wrapper - Implements CompleteOps::complete() -.
Definition complete.c:95