NeoMutt  2025-12-11-1039-g550ac6
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 "alternates.h"
#include "expando.h"
#include "group.h"
#include "module_data.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)
void alias_init_keys (struct NeoMutt *n, struct SubMenu *sm_generic)
 Initialise the Alias Keybindings - Implements ::init_keys_api.
void alias_cleanup (void)
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, const struct ParseContext *pc, struct ParseError *pe)
 Parse the 'alias' command - Implements Command::parse() -.
enum CommandResult parse_unalias (const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
 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.
void mutt_auto_subscribe (const char *mailto)
 Check if user is subscribed to mailing list.

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 )

◆ alias_init_keys()

void alias_init_keys ( struct NeoMutt * n,
struct SubMenu * sm_generic )

Initialise the Alias Keybindings - Implements ::init_keys_api.

Definition at line 120 of file functions.c.

121{
123 ASSERT(mod_data);
124
125 struct MenuDefinition *md = NULL;
126 struct SubMenu *sm = NULL;
127
129 md = km_register_menu(MENU_ALIAS, "alias");
130 km_menu_add_submenu(md, sm);
131 km_menu_add_submenu(md, sm_generic);
133
134 mod_data->menu_alias = md;
135
137 md = km_register_menu(MENU_QUERY, "query");
138 km_menu_add_submenu(md, sm);
139 km_menu_add_submenu(md, sm_generic);
141
142 mod_data->menu_query = md;
143}
const struct MenuFuncOp OpQuery[]
Functions for the external Query Menu.
Definition functions.c:70
static const struct MenuOpSeq QueryDefaultBindings[]
Key bindings for the external Query Menu.
Definition functions.c:102
static const struct MenuOpSeq AliasDefaultBindings[]
Key bindings for the Alias Menu.
Definition functions.c:86
static const struct MenuFuncOp OpAlias[]
Functions for the Alias Menu.
Definition functions.c:55
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:88
struct MenuDefinition * km_register_menu(int menu, const char *name)
Register a menu.
Definition init.c:105
void km_menu_add_bindings(struct MenuDefinition *md, const struct MenuOpSeq bindings[])
Add Keybindings to a Menu.
Definition init.c:136
@ MODULE_ID_ALIAS
ModuleAlias, Alias
Definition module_api.h:48
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
#define ASSERT(COND)
Definition signal2.h:59
Alias private Module data.
Definition module_data.h:33
struct MenuDefinition * menu_query
Query menu definition.
Definition module_data.h:43
struct MenuDefinition * menu_alias
Alias menu definition.
Definition module_data.h:42
Functions for a Dialog or Window.
Definition menudef.h:44
Collection of related functions.
Definition menudef.h:33
@ MENU_QUERY
Select from results of external query.
Definition type.h:49
@ 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 )

◆ 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 369 of file alias.c.

370{
371 struct Buffer *buf = buf_pool_get();
372 struct Buffer *fixed = buf_pool_get();
373 struct Buffer *prompt = NULL;
374 struct Buffer *tmp = buf_pool_get();
375
376 struct Address *addr = NULL;
377 char *pc = NULL;
378 char *err = NULL;
379 FILE *fp_alias = NULL;
380
381 if (al)
382 {
383 addr = TAILQ_FIRST(al);
384 if (addr && addr->mailbox)
385 {
386 buf_copy(tmp, addr->mailbox);
387 pc = strchr(buf_string(tmp), '@');
388 if (pc)
389 *pc = '\0';
390 }
391 }
392
393 /* Don't suggest a bad alias name in the event of a strange local part. */
394 check_alias_name(buf_string(tmp), buf);
395
396retry_name:
397 /* L10N: prompt to add a new alias */
398 if ((mw_get_field(_("Alias as: "), buf, MUTT_COMP_NONE, HC_OTHER, NULL, NULL) != 0) ||
399 buf_is_empty(buf))
400 {
401 goto done;
402 }
403
404 /* check to see if the user already has an alias defined */
405 if (alias_lookup(buf_string(buf)))
406 {
407 mutt_error(_("You already have an alias defined with that name"));
408 goto done;
409 }
410
411 if (check_alias_name(buf_string(buf), fixed))
412 {
413 switch (query_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
414 {
415 case MUTT_YES:
416 buf_copy(buf, fixed);
417 goto retry_name;
418 case MUTT_ABORT:
419 goto done;
420 default:; // do nothing
421 }
422 }
423
424 struct Alias *alias = alias_new();
425 alias->name = buf_strdup(buf);
426
428
429 if (addr && addr->mailbox)
430 buf_copy(buf, addr->mailbox);
431 else
432 buf_reset(buf);
433
434 mutt_addrlist_to_intl(al, NULL);
435
436 do
437 {
438 if ((mw_get_field(_("Address: "), buf, MUTT_COMP_NONE, HC_OTHER, NULL, NULL) != 0) ||
439 buf_is_empty(buf))
440 {
441 alias_free(&alias);
442 goto done;
443 }
444
445 mutt_addrlist_parse(&alias->addr, buf_string(buf));
446 if (TAILQ_EMPTY(&alias->addr))
447 mutt_beep(false);
448 if (mutt_addrlist_to_intl(&alias->addr, &err))
449 {
450 mutt_error(_("Bad IDN: '%s'"), err);
451 FREE(&err);
452 continue;
453 }
454 } while (TAILQ_EMPTY(&alias->addr));
455
456 if (addr && addr->personal && !mutt_is_mail_list(addr))
457 buf_copy(buf, addr->personal);
458 else
459 buf_reset(buf);
460
461 if (mw_get_field(_("Personal name: "), buf, MUTT_COMP_NONE, HC_OTHER, NULL, NULL) != 0)
462 {
463 alias_free(&alias);
464 goto done;
465 }
466
467 TAILQ_FIRST(&alias->addr)->personal = buf_new(buf_string(buf));
468
469 buf_reset(buf);
470 if (mw_get_field(_("Comment: "), buf, MUTT_COMP_NONE, HC_OTHER, NULL, NULL) == 0)
471 {
472 mutt_str_replace(&alias->comment, buf_string(buf));
473 }
474
475 buf_reset(buf);
476 if (mw_get_field(_("Tags (comma-separated): "), buf, MUTT_COMP_NONE, HC_OTHER,
477 NULL, NULL) == 0)
478 {
479 parse_alias_tags(buf_string(buf), &alias->tags);
480 }
481
482 buf_reset(buf);
483 mutt_addrlist_write(&alias->addr, buf, true);
484 prompt = buf_pool_get();
485
486 buf_printf(prompt, "alias %s %s", alias->name, buf_string(buf));
487
488 bool has_tags = STAILQ_FIRST(&alias->tags);
489
490 if (alias->comment || has_tags)
491 buf_addstr(prompt, " #");
492
493 if (alias->comment)
494 buf_add_printf(prompt, " %s", alias->comment);
495
496 if (has_tags)
497 {
498 if (STAILQ_FIRST(&alias->tags))
499 {
500 buf_addstr(prompt, " tags:");
501 alias_tags_to_buffer(&alias->tags, prompt);
502 }
503 }
504
505 buf_add_printf(prompt, "\n%s", _("Accept?"));
506
507 if (query_yesorno(buf_string(prompt), MUTT_YES) != MUTT_YES)
508 {
509 alias_free(&alias);
510 goto done;
511 }
512
514 ASSERT(mod_data);
515
516 alias_reverse_add(alias);
517 ARRAY_ADD(&mod_data->aliases, alias);
518
519 const char *const c_alias_file = cs_subset_path(sub, "alias_file");
520 buf_strcpy(buf, c_alias_file);
521
522 struct FileCompletionData cdata = { false, NULL, NULL, NULL, NULL };
523 if (mw_get_field(_("Save to file: "), buf, MUTT_COMP_CLEAR, HC_FILE,
524 &CompleteFileOps, &cdata) != 0)
525 {
526 goto done;
527 }
528 expand_path(buf, false);
529 fp_alias = mutt_file_fopen(buf_string(buf), "a+");
530 if (!fp_alias)
531 {
532 mutt_perror("%s", buf_string(buf));
533 goto done;
534 }
535
536 /* terminate existing file with \n if necessary */
537 if (ftell(fp_alias) > 0)
538 {
539 if (!mutt_file_seek(fp_alias, -1, SEEK_CUR))
540 {
541 goto done;
542 }
543 if (fread(buf->data, 1, 1, fp_alias) != 1)
544 {
545 mutt_perror(_("Error reading alias file"));
546 goto done;
547 }
548 if (!mutt_file_seek(fp_alias, 0, SEEK_END))
549 {
550 goto done;
551 }
552 if (buf_at(buf, 0) != '\n')
553 fputc('\n', fp_alias);
554 }
555
556 if (check_alias_name(alias->name, NULL))
557 buf_quote_filename(buf, alias->name, true);
558 else
559 buf_strcpy(buf, alias->name);
560
561 recode_buf(buf);
562 fprintf(fp_alias, "alias %s ", buf_string(buf));
563 buf_reset(buf);
564
565 mutt_addrlist_write(&alias->addr, buf, false);
566 recode_buf(buf);
567 write_safe_address(fp_alias, buf_string(buf));
568 if (alias->comment)
569 fprintf(fp_alias, " # %s", alias->comment);
570 if (STAILQ_FIRST(&alias->tags))
571 {
572 fprintf(fp_alias, " tags:");
573
574 struct Tag *tag = NULL;
575 STAILQ_FOREACH(tag, &alias->tags, entries)
576 {
577 fprintf(fp_alias, "%s", tag->name);
578 if (STAILQ_NEXT(tag, entries))
579 fprintf(fp_alias, ",");
580 }
581 }
582 fputc('\n', fp_alias);
583 if (mutt_file_fsync_close(&fp_alias) != 0)
584 mutt_perror(_("Trouble adding alias"));
585 else
586 mutt_message(_("Alias added"));
587
588done:
589 mutt_file_fclose(&fp_alias);
590 buf_pool_release(&buf);
591 buf_pool_release(&fixed);
592 buf_pool_release(&prompt);
593 buf_pool_release(&tmp);
594}
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition address.c:1389
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition address.c:1217
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition address.c:481
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition address.c:1304
void parse_alias_tags(const char *tags, struct TagList *tl)
Parse a comma-separated list of tags.
Definition commands.c:105
void alias_tags_to_buffer(struct TagList *tl, struct Buffer *buf)
Write a comma-separated list of tags to a Buffer.
Definition commands.c:89
void alias_free(struct Alias **ptr)
Free an Alias.
Definition alias.c:674
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:662
static void write_safe_address(FILE *fp, const char *s)
Defang malicious email addresses.
Definition alias.c:84
#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:168
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition buffer.c:211
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:89
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:298
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition buffer.c:674
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition buffer.c:311
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:233
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:401
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition buffer.c:607
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:577
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
@ MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition wdata.h:47
@ MUTT_COMP_NONE
No flags are set.
Definition wdata.h:46
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:803
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition file.c:648
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer).
Definition file.c:128
#define mutt_file_fclose(FP)
Definition file.h:144
#define mutt_file_fopen(PATH, MODE)
Definition file.h:143
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list?
Definition maillist.c:46
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:502
#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:59
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:61
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#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:122
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
@ 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:329
#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:62
An email address.
Definition address.h:35
struct Buffer * mailbox
Mailbox and host address.
Definition address.h:37
struct AliasArray aliases
User's email aliases.
Definition module_data.h:35
A shortcut for an email address or addresses.
Definition alias.h:35
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
Container for Accounts, Notifications.
Definition neomutt.h:41
LinkedList Tag Element.
Definition tags.h:41
char * name
Tag name.
Definition tags.h:42
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 ASSERT(mod_data);
280
281 ARRAY_FOREACH(ap, &mod_data->aliases)
282 {
283 struct Alias *a = *ap;
284
285 if (mutt_istr_equal(name, a->name))
286 return &a->addr;
287 }
288 return NULL;
289}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:678
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 601 of file alias.c.

602{
603 if (!addr)
604 {
605 mutt_debug(LL_DEBUG5, "no, NULL address\n");
606 return false;
607 }
608 if (!addr->mailbox)
609 {
610 mutt_debug(LL_DEBUG5, "no, no mailbox\n");
611 return false;
612 }
613
615 {
616 mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", buf_string(addr->mailbox),
618 return true;
619 }
621 {
622 mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
624 return true;
625 }
626 const char *fqdn = mutt_fqdn(false, NeoMutt->sub);
628 {
629 mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
630 NeoMutt->username, NONULL(fqdn));
631 return true;
632 }
633 fqdn = mutt_fqdn(true, NeoMutt->sub);
635 {
636 mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
637 NeoMutt->username, NONULL(fqdn));
638 return true;
639 }
640
641 const struct Address *c_from = cs_subset_address(NeoMutt->sub, "from");
642 if (c_from && mutt_istr_equal(buf_string(c_from->mailbox), buf_string(addr->mailbox)))
643 {
644 mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", buf_string(addr->mailbox),
645 buf_string(c_from->mailbox));
646 return true;
647 }
648
650 return true;
651
652 mutt_debug(LL_DEBUG5, "no, all failed\n");
653 return false;
654}
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:164
char * ShortHostname
Short version of the hostname.
Definition globals.c:36
#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:718
#define NONULL(x)
Definition string2.h:44
char * username
User's login name.
Definition neomutt.h:56
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
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 311 of file alias.c.

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

298{
299 // previously expanded aliases to avoid loops
300 struct ListHead expn = STAILQ_HEAD_INITIALIZER(expn);
301
302 expand_aliases_r(al, &expn);
303 mutt_list_free(&expn);
305}
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition address.c:1408
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition alias.c:102
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 329 of file alias.c.

330{
331 struct AddressList *al = NULL;
332 const char *pfx = NULL;
333
335 {
336 if (!TAILQ_EMPTY(&env->to) && !mutt_is_mail_list(TAILQ_FIRST(&env->to)))
337 {
338 pfx = "To";
339 al = &env->to;
340 }
341 else
342 {
343 pfx = "Cc";
344 al = &env->cc;
345 }
346 }
347 else if (!TAILQ_EMPTY(&env->reply_to) && !mutt_is_mail_list(TAILQ_FIRST(&env->reply_to)))
348 {
349 pfx = "Reply-To";
350 al = &env->reply_to;
351 }
352 else
353 {
354 al = &env->from;
355 pfx = "From";
356 }
357
358 if (prefix)
359 *prefix = pfx;
360
361 return al;
362}
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition alias.c:601
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 89 of file commands.c.

90{
91 struct Tag *tag = NULL;
92 STAILQ_FOREACH(tag, tl, entries)
93 {
94 buf_addstr(buf, tag->name);
95 if (STAILQ_NEXT(tag, entries))
96 buf_addch(buf, ',');
97 }
98}
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:248
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 135 of file commands.c.

136{
137 if (!com || (com[0] == '\0'))
138 return;
139
140 const regmatch_t *match = mutt_prex_capture(PREX_ALIAS_TAGS, com);
141 if (match)
142 {
143 const regmatch_t *pre = &match[PREX_ALIAS_TAGS_MATCH_PRE];
144 const regmatch_t *tags = &match[PREX_ALIAS_TAGS_MATCH_TAGS];
145 const regmatch_t *post = &match[PREX_ALIAS_TAGS_MATCH_POST];
146
147 struct Buffer *tmp = buf_pool_get();
148
149 // Extract the tags
150 buf_addstr_n(tmp, com + mutt_regmatch_start(tags),
152 parse_alias_tags(buf_string(tmp), &alias->tags);
153 buf_reset(tmp);
154
155 // Collect all the other text as "comments"
156 buf_addstr_n(tmp, com + mutt_regmatch_start(pre),
158 buf_addstr_n(tmp, com + mutt_regmatch_start(post),
160 alias->comment = buf_strdup(tmp);
161
162 buf_pool_release(&tmp);
163 }
164 else
165 {
166 alias->comment = mutt_str_dup(com);
167 }
168}
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:109
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:301
@ PREX_ALIAS_TAGS
tags:a,b,c
Definition prex.h:43
@ PREX_ALIAS_TAGS_MATCH_POST
... tags:a,b,c[ ...]
Definition prex.h:239
@ PREX_ALIAS_TAGS_MATCH_PRE
[... ]tags:a,b,c ...
Definition prex.h:236
@ PREX_ALIAS_TAGS_MATCH_TAGS
... tags:[a,b,c] ...
Definition prex.h:238
static regoff_t mutt_regmatch_end(const regmatch_t *match)
Return the end of a match.
Definition regex3.h:66
static regoff_t mutt_regmatch_start(const regmatch_t *match)
Return the start of a match.
Definition regex3.h:56
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 105 of file commands.c.

106{
107 if (!tags || !tl)
108 return;
109
110 struct Slist *sl = slist_parse(tags, D_SLIST_SEP_COMMA);
111 if (slist_is_empty(sl))
112 {
113 slist_free(&sl);
114 return;
115 }
116
117 struct ListNode *np = NULL;
118 STAILQ_FOREACH(np, &sl->head, entries)
119 {
120 struct Tag *tag = tag_new();
121 tag->name = np->data; // Transfer string
122 np->data = NULL;
123 STAILQ_INSERT_TAIL(tl, tag, entries);
124 }
125 slist_free(&sl);
126}
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
struct Tag * tag_new(void)
Create a new Tag.
Definition tags.c:62
#define D_SLIST_SEP_COMMA
Slist items are comma-separated.
Definition types.h:111
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 353 of file dlg_alias.c.

354{
355 char bestname[8192] = { 0 };
356 struct Alias *a_best = NULL;
357 int count = 0;
358
359 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
360 mdata.limit = buf_strdup(buf);
361 mdata.search_state = search_state_new();
362
364 ASSERT(mod_data);
365
366 if (buf_at(buf, 0) != '\0')
367 {
368 struct Alias **ap = NULL;
369 ARRAY_FOREACH(ap, &mod_data->aliases)
370 {
371 struct Alias *a = *ap;
372 if (a->name && mutt_strn_equal(a->name, buf_string(buf), buf_len(buf)))
373 {
374 a_best = a;
375 count++;
376
377 if (bestname[0] == '\0') /* init */
378 {
379 mutt_str_copy(bestname, a->name, MIN(mutt_str_len(a->name) + 1, sizeof(bestname)));
380 }
381 else
382 {
383 int i;
384 for (i = 0; a->name[i] && (a->name[i] == bestname[i]); i++)
385 ; // do nothing
386
387 bestname[i] = '\0';
388 }
389 }
390 }
391
392 // Exactly one match, so expand the Alias and return
393 if (count == 1)
394 {
395 buf_reset(buf);
396 mutt_addrlist_write(&a_best->addr, buf, true);
397 buf_addstr(buf, ", ");
398 FREE(&mdata.limit);
400 return 1;
401 }
402
403 if (bestname[0] == '\0')
404 {
405 // Create a View Array of all the Aliases
406 FREE(&mdata.limit);
407 ARRAY_FOREACH(ap, &mod_data->aliases)
408 {
409 alias_array_alias_add(&mdata.ava, *ap);
410 }
411 }
412 else
413 {
414 /* fake the pattern for menu title */
415 char *mtitle = NULL;
416 mutt_str_asprintf(&mtitle, "~f ^%s", buf_string(buf));
417 FREE(&mdata.limit);
418 mdata.limit = mtitle;
419
420 if (!mutt_str_equal(bestname, buf_string(buf)))
421 {
422 /* we are adding something to the completion */
423 buf_strcpy_n(buf, bestname, mutt_str_len(bestname) + 1);
424 FREE(&mdata.limit);
426 return 1;
427 }
428
429 /* build alias list and show it */
430 ARRAY_FOREACH(ap, &mod_data->aliases)
431 {
432 struct Alias *a = *ap;
433 int aasize = alias_array_alias_add(&mdata.ava, a);
434
435 struct AliasView *av = ARRAY_GET(&mdata.ava, aasize - 1);
436
437 if (a->name && !mutt_strn_equal(a->name, buf_string(buf), buf_len(buf)))
438 {
439 av->is_visible = false;
440 }
441 }
442 }
443 }
444
445 if (ARRAY_EMPTY(&mdata.ava))
446 {
447 struct Alias **ap = NULL;
448 ARRAY_FOREACH(ap, &mod_data->aliases)
449 {
450 alias_array_alias_add(&mdata.ava, *ap);
451 }
452
453 mutt_pattern_alias_func(NULL, &mdata, PAA_VISIBLE, NULL);
454 }
455
456 if (!dlg_alias(&mdata))
457 goto done;
458
459 buf_reset(buf);
460
461 // Extract the selected aliases
462 struct Buffer *tmpbuf = buf_pool_get();
463 struct AliasView *avp = NULL;
464 ARRAY_FOREACH(avp, &mdata.ava)
465 {
466 if (!avp->is_tagged)
467 continue;
468
469 mutt_addrlist_write(&avp->alias->addr, tmpbuf, true);
470 buf_addstr(tmpbuf, ", ");
471 }
472 buf_copy(buf, tmpbuf);
473 buf_pool_release(&tmpbuf);
474
475done:
476 // Process any deleted aliases
477 ARRAY_FOREACH(avp, &mdata.ava)
478 {
479 if (!avp->is_deleted)
480 continue;
481
482 // Find and remove the alias from the Aliases array
483 struct Alias **ap = NULL;
484 ARRAY_FOREACH(ap, &mod_data->aliases)
485 {
486 if (*ap == avp->alias)
487 {
488 ARRAY_REMOVE(&mod_data->aliases, ap);
489 break;
490 }
491 }
492 alias_free(&avp->alias);
493 }
494
495 ARRAY_FREE(&mdata.ava);
496 FREE(&mdata.limit);
497 FREE(&mdata.title);
499
500 return 0;
501}
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:497
size_t buf_strcpy_n(struct Buffer *buf, const char *s, size_t len)
Copy a string into a Buffer.
Definition buffer.c:422
static bool dlg_alias(struct AliasMenuData *mdata)
Display a menu of Aliases -.
Definition dlg_alias.c:271
#define MIN(a, b)
Return the minimum of two values.
Definition memory.h:40
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition string.c:809
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
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:503
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:587
@ PAA_VISIBLE
Set AliasView.is_visible and hide the rest.
Definition lib.h:203
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:170
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:55
char * limit
Limit being used.
Definition gui.h:61
struct AliasViewArray ava
All Aliases/Queries.
Definition gui.h:56
struct SearchState * search_state
State of the current search.
Definition gui.h:64
char * title
Title for the status bar.
Definition gui.h:63
struct ConfigSubset * sub
Config items.
Definition gui.h:58
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:155
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 508 of file dlg_alias.c.

509{
510 struct Alias **ap = NULL;
511
512 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
514
516 ASSERT(mod_data);
517
518 // Create a View Array of all the Aliases
519 ARRAY_FOREACH(ap, &mod_data->aliases)
520 {
521 alias_array_alias_add(&mdata.ava, *ap);
522 }
523
524 if (!dlg_alias(&mdata))
525 goto done;
526
527 // Prepare the "To:" field of a new email
528 struct Email *e = email_new();
529 e->env = mutt_env_new();
530
531 struct AliasView *avp = NULL;
532 ARRAY_FOREACH(avp, &mdata.ava)
533 {
534 if (!avp->is_tagged)
535 continue;
536
537 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
538 if (alias_to_addrlist(&al_copy, avp->alias))
539 {
540 mutt_addrlist_copy(&e->env->to, &al_copy, false);
541 mutt_addrlist_clear(&al_copy);
542 }
543 }
544
545 mutt_send_message(SEND_REVIEW_TO, e, NULL, m, NULL, sub);
546
547done:
548 // Process any deleted aliases
549 ARRAY_FOREACH(avp, &mdata.ava)
550 {
551 if (avp->is_deleted)
552 {
553 // Find and remove the alias from the Aliases array
554 ARRAY_FOREACH(ap, &mod_data->aliases)
555 {
556 if (*ap == avp->alias)
557 {
558 ARRAY_REMOVE(&mod_data->aliases, ap);
559 break;
560 }
561 }
562 alias_free(&avp->alias);
563 }
564 }
565
566 ARRAY_FREE(&mdata.ava);
567 FREE(&mdata.limit);
568 FREE(&mdata.title);
570}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition address.c:776
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1473
bool alias_to_addrlist(struct AddressList *al, struct Alias *alias)
Turn an Alias into an AddressList.
Definition dlg_query.c:119
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:2035
@ SEND_REVIEW_TO
Allow the user to edit the To field.
Definition send.h:60
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 414 of file dlg_query.c.

415{
416 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
418
419 struct AliasArray aa = ARRAY_HEAD_INITIALIZER;
420 const char *const c_query_command = cs_subset_string(sub, "query_command");
421 if (!c_query_command)
422 {
423 mutt_warning(_("Query command not defined"));
424 goto done;
425 }
426
427 query_run(buf_string(buf), true, &aa, sub);
428 if (ARRAY_EMPTY(&aa))
429 goto done;
430
431 mdata.aa = &aa;
432
433 struct Alias **a_first = ARRAY_FIRST(&aa);
434 if (ARRAY_SIZE(&aa) == 1) // only one response?
435 {
436 struct AddressList addr = TAILQ_HEAD_INITIALIZER(addr);
437 if (alias_to_addrlist(&addr, *a_first))
438 {
440 buf_reset(buf);
441 mutt_addrlist_write(&addr, buf, false);
442 mutt_addrlist_clear(&addr);
444 buf_addstr(buf, ", ");
445 }
446 goto done;
447 }
448
449 struct Alias **ap = NULL;
450 ARRAY_FOREACH(ap, mdata.aa)
451 {
452 alias_array_alias_add(&mdata.ava, *ap);
453 }
454
455 /* multiple results, choose from query menu */
456 if (!dlg_query(buf, &mdata))
457 goto done;
458
459 buf_reset(buf);
460 buf_alloc(buf, 8192);
461 struct AliasView *avp = NULL;
462 ARRAY_FOREACH(avp, &mdata.ava)
463 {
464 if (!avp->is_tagged)
465 continue;
466
467 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
468 if (alias_to_addrlist(&al_copy, avp->alias))
469 {
470 mutt_addrlist_to_local(&al_copy);
471 mutt_addrlist_write(&al_copy, buf, false);
472 mutt_addrlist_clear(&al_copy);
473 }
474 buf_addstr(buf, ", ");
475 }
476
477done:
478 ARRAY_FREE(&mdata.ava);
479 FREE(&mdata.title);
480 FREE(&mdata.limit);
482 aliaslist_clear(&aa);
483 return 0;
484}
void aliaslist_clear(struct AliasArray *aa)
Empty a List of Aliases.
Definition alias.c:699
#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:342
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:188
static bool dlg_query(struct Buffer *buf, struct AliasMenuData *mdata)
Get the user to enter an Address Query -.
Definition dlg_query.c:352
#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:57
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 491 of file dlg_query.c.

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

111{
112 if (!addr || !addr->mailbox)
113 return NULL;
114
116 ASSERT(mod_data);
117
118 return mutt_hash_find(mod_data->reverse_aliases, buf_string(addr->mailbox));
119}
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:365
struct HashTable * reverse_aliases
Hash Table of aliases (email address -> alias).
Definition module_data.h:36
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_auto_subscribe()

void mutt_auto_subscribe ( const char * mailto)

Check if user is subscribed to mailing list.

Parameters
mailtoURL of mailing list subscribe

Definition at line 49 of file commands.c.

50{
51 if (!mailto)
52 return;
53
55 ASSERT(mod_data);
56
57 if (!mod_data->auto_subscribe_cache)
59
60 if (mutt_hash_find(mod_data->auto_subscribe_cache, mailto))
61 return;
62
64
65 struct Envelope *lpenv = mutt_env_new(); /* parsed envelope from the List-Post mailto: URL */
66
67 if (mutt_parse_mailto(lpenv, NULL, mailto) && !TAILQ_EMPTY(&lpenv->to))
68 {
69 const char *mailbox = buf_string(TAILQ_FIRST(&lpenv->to)->mailbox);
70 if (mailbox && !mutt_regexlist_match(&mod_data->subscribed, mailbox) &&
71 !mutt_regexlist_match(&mod_data->unmail, mailbox) &&
72 !mutt_regexlist_match(&mod_data->unsubscribed, mailbox))
73 {
74 /* mutt_regexlist_add() detects duplicates, so it is safe to
75 * try to add here without any checks. */
76 mutt_regexlist_add(&mod_data->mail, mailbox, REG_ICASE, NULL);
77 mutt_regexlist_add(&mod_data->subscribed, mailbox, REG_ICASE, NULL);
78 }
79 }
80
81 mutt_env_free(&lpenv);
82}
bool mutt_parse_mailto(struct Envelope *env, char **body, const char *src)
Parse a mailto:// url.
Definition parse.c:1911
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition envelope.c:125
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys).
Definition hash.c:338
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys).
Definition hash.c:262
@ MUTT_HASH_STRCASECMP
use strcasecmp() to compare keys
Definition hash.h:116
@ MUTT_HASH_STRDUP_KEYS
make a copy of the keys
Definition hash.h:117
int mutt_regexlist_add(struct RegexList *rl, const char *str, uint16_t flags, struct Buffer *err)
Compile a regex string and add it to a list.
Definition regex.c:140
bool mutt_regexlist_match(struct RegexList *rl, const char *str)
Does a string match any Regex in the list?
Definition regex.c:201
struct RegexList subscribed
Regexes to match subscribed mailing lists.
Definition module_data.h:49
struct RegexList mail
Regexes to match mailing lists.
Definition module_data.h:48
struct HashTable * auto_subscribe_cache
Hash Table: "mailto:" (no value).
Definition module_data.h:47
struct RegexList unmail
Regexes to exclude false matches in mail.
Definition module_data.h:50
struct RegexList unsubscribed
Regexes to exclude false matches in subscribed.
Definition module_data.h:51
The header of an Email.
Definition envelope.h:57
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