NeoMutt  2025-12-11-769-g906513
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 124 of file functions.c.

125{
127 ASSERT(mod_data);
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
138 mod_data->menu_alias = md;
139
141 md = km_register_menu(MENU_QUERY, "query");
142 km_menu_add_submenu(md, sm);
143 km_menu_add_submenu(md, sm_generic);
145
146 mod_data->menu_query = md;
147}
const struct MenuFuncOp OpQuery[]
Functions for the external Query Menu.
Definition functions.c:71
static const struct MenuOpSeq QueryDefaultBindings[]
Key bindings for the external Query Menu.
Definition functions.c:105
static const struct MenuOpSeq AliasDefaultBindings[]
Key bindings for the Alias Menu.
Definition functions.c:88
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:121
struct SubMenu * km_register_submenu(const struct MenuFuncOp functions[])
Register a submenu.
Definition init.c:87
struct MenuDefinition * km_register_menu(int menu, const char *name)
Register a menu.
Definition init.c:104
void km_menu_add_bindings(struct MenuDefinition *md, const struct MenuOpSeq bindings[])
Add Keybindings to a Menu.
Definition init.c:134
@ 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:665
#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 menu.h:80
Collection of related functions.
Definition menu.h:68
@ 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 )

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

369{
370 struct Buffer *buf = buf_pool_get();
371 struct Buffer *fixed = buf_pool_get();
372 struct Buffer *prompt = NULL;
373 struct Buffer *tmp = buf_pool_get();
374
375 struct Address *addr = NULL;
376 char *pc = NULL;
377 char *err = NULL;
378 FILE *fp_alias = NULL;
379
380 if (al)
381 {
382 addr = TAILQ_FIRST(al);
383 if (addr && addr->mailbox)
384 {
385 buf_copy(tmp, addr->mailbox);
386 pc = strchr(buf_string(tmp), '@');
387 if (pc)
388 *pc = '\0';
389 }
390 }
391
392 /* Don't suggest a bad alias name in the event of a strange local part. */
393 check_alias_name(buf_string(tmp), buf);
394
395retry_name:
396 /* L10N: prompt to add a new alias */
397 if ((mw_get_field(_("Alias as: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
398 buf_is_empty(buf))
399 {
400 goto done;
401 }
402
403 /* check to see if the user already has an alias defined */
404 if (alias_lookup(buf_string(buf)))
405 {
406 mutt_error(_("You already have an alias defined with that name"));
407 goto done;
408 }
409
410 if (check_alias_name(buf_string(buf), fixed))
411 {
412 switch (query_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
413 {
414 case MUTT_YES:
415 buf_copy(buf, fixed);
416 goto retry_name;
417 case MUTT_ABORT:
418 goto done;
419 default:; // do nothing
420 }
421 }
422
423 struct Alias *alias = alias_new();
424 alias->name = buf_strdup(buf);
425
427
428 if (addr && addr->mailbox)
429 buf_copy(buf, addr->mailbox);
430 else
431 buf_reset(buf);
432
433 mutt_addrlist_to_intl(al, NULL);
434
435 do
436 {
437 if ((mw_get_field(_("Address: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
438 buf_is_empty(buf))
439 {
440 alias_free(&alias);
441 goto done;
442 }
443
444 mutt_addrlist_parse(&alias->addr, buf_string(buf));
445 if (TAILQ_EMPTY(&alias->addr))
446 mutt_beep(false);
447 if (mutt_addrlist_to_intl(&alias->addr, &err))
448 {
449 mutt_error(_("Bad IDN: '%s'"), err);
450 FREE(&err);
451 continue;
452 }
453 } while (TAILQ_EMPTY(&alias->addr));
454
455 if (addr && addr->personal && !mutt_is_mail_list(addr))
456 buf_copy(buf, addr->personal);
457 else
458 buf_reset(buf);
459
460 if (mw_get_field(_("Personal name: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
461 {
462 alias_free(&alias);
463 goto done;
464 }
465
466 TAILQ_FIRST(&alias->addr)->personal = buf_new(buf_string(buf));
467
468 buf_reset(buf);
469 if (mw_get_field(_("Comment: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) == 0)
470 {
471 mutt_str_replace(&alias->comment, buf_string(buf));
472 }
473
474 buf_reset(buf);
475 if (mw_get_field(_("Tags (comma-separated): "), buf, MUTT_COMP_NO_FLAGS,
476 HC_OTHER, NULL, NULL) == 0)
477 {
478 parse_alias_tags(buf_string(buf), &alias->tags);
479 }
480
481 buf_reset(buf);
482 mutt_addrlist_write(&alias->addr, buf, true);
483 prompt = buf_pool_get();
484
485 buf_printf(prompt, "alias %s %s", alias->name, buf_string(buf));
486
487 bool has_tags = STAILQ_FIRST(&alias->tags);
488
489 if (alias->comment || has_tags)
490 buf_addstr(prompt, " #");
491
492 if (alias->comment)
493 buf_add_printf(prompt, " %s", alias->comment);
494
495 if (has_tags)
496 {
497 if (STAILQ_FIRST(&alias->tags))
498 {
499 buf_addstr(prompt, " tags:");
500 alias_tags_to_buffer(&alias->tags, prompt);
501 }
502 }
503
504 buf_add_printf(prompt, "\n%s", _("Accept?"));
505
506 if (query_yesorno(buf_string(prompt), MUTT_YES) != MUTT_YES)
507 {
508 alias_free(&alias);
509 goto done;
510 }
511
513 ASSERT(mod_data);
514
515 alias_reverse_add(alias);
516 ARRAY_ADD(&mod_data->aliases, alias);
517
518 const char *const c_alias_file = cs_subset_path(sub, "alias_file");
519 buf_strcpy(buf, c_alias_file);
520
521 struct FileCompletionData cdata = { false, NULL, NULL, NULL, NULL };
522 if (mw_get_field(_("Save to file: "), buf, MUTT_COMP_CLEAR, HC_FILE,
523 &CompleteFileOps, &cdata) != 0)
524 {
525 goto done;
526 }
527 expand_path(buf, false);
528 fp_alias = mutt_file_fopen(buf_string(buf), "a+");
529 if (!fp_alias)
530 {
531 mutt_perror("%s", buf_string(buf));
532 goto done;
533 }
534
535 /* terminate existing file with \n if necessary */
536 if (ftell(fp_alias) > 0)
537 {
538 if (!mutt_file_seek(fp_alias, -1, SEEK_CUR))
539 {
540 goto done;
541 }
542 if (fread(buf->data, 1, 1, fp_alias) != 1)
543 {
544 mutt_perror(_("Error reading alias file"));
545 goto done;
546 }
547 if (!mutt_file_seek(fp_alias, 0, SEEK_END))
548 {
549 goto done;
550 }
551 if (buf_at(buf, 0) != '\n')
552 fputc('\n', fp_alias);
553 }
554
555 if (check_alias_name(alias->name, NULL))
556 buf_quote_filename(buf, alias->name, true);
557 else
558 buf_strcpy(buf, alias->name);
559
560 recode_buf(buf);
561 fprintf(fp_alias, "alias %s ", buf_string(buf));
562 buf_reset(buf);
563
564 mutt_addrlist_write(&alias->addr, buf, false);
565 recode_buf(buf);
566 write_safe_address(fp_alias, buf_string(buf));
567 if (alias->comment)
568 fprintf(fp_alias, " # %s", alias->comment);
569 if (STAILQ_FIRST(&alias->tags))
570 {
571 fprintf(fp_alias, " tags:");
572
573 struct Tag *tag = NULL;
574 STAILQ_FOREACH(tag, &alias->tags, entries)
575 {
576 fprintf(fp_alias, "%s", tag->name);
577 if (STAILQ_NEXT(tag, entries))
578 fprintf(fp_alias, ",");
579 }
580 }
581 fputc('\n', fp_alias);
582 if (mutt_file_fsync_close(&fp_alias) != 0)
583 mutt_perror(_("Trouble adding alias"));
584 else
585 mutt_message(_("Alias added"));
586
587done:
588 mutt_file_fclose(&fp_alias);
589 buf_pool_release(&buf);
590 buf_pool_release(&fixed);
591 buf_pool_release(&prompt);
592 buf_pool_release(&tmp);
593}
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition address.c:1387
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition address.c:1215
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:1302
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:673
static int check_alias_name(const char *s, struct Buffer *dest)
Sanity-check an alias name.
Definition alias.c:212
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition alias.c:273
static void recode_buf(struct Buffer *buf)
Convert some text between two character sets.
Definition alias.c:188
struct Alias * alias_new(void)
Create a new Alias.
Definition alias.c:661
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: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:69
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition wdata.h:42
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition wdata.h:43
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: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: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:467
#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)
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 273 of file alias.c.

274{
275 struct Alias **ap = NULL;
276
278 ASSERT(mod_data);
279
280 ARRAY_FOREACH(ap, &mod_data->aliases)
281 {
282 struct Alias *a = *ap;
283
284 if (mutt_istr_equal(name, a->name))
285 return &a->addr;
286 }
287 return NULL;
288}
#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:677
+ 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 600 of file alias.c.

601{
602 if (!addr)
603 {
604 mutt_debug(LL_DEBUG5, "no, NULL address\n");
605 return false;
606 }
607 if (!addr->mailbox)
608 {
609 mutt_debug(LL_DEBUG5, "no, no mailbox\n");
610 return false;
611 }
612
614 {
615 mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", buf_string(addr->mailbox),
617 return true;
618 }
620 {
621 mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
623 return true;
624 }
625 const char *fqdn = mutt_fqdn(false, NeoMutt->sub);
627 {
628 mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
629 NeoMutt->username, NONULL(fqdn));
630 return true;
631 }
632 fqdn = mutt_fqdn(true, NeoMutt->sub);
634 {
635 mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
636 NeoMutt->username, NONULL(fqdn));
637 return true;
638 }
639
640 const struct Address *c_from = cs_subset_address(NeoMutt->sub, "from");
641 if (c_from && mutt_istr_equal(buf_string(c_from->mailbox), buf_string(addr->mailbox)))
642 {
643 mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", buf_string(addr->mailbox),
644 buf_string(c_from->mailbox));
645 return true;
646 }
647
649 return true;
650
651 mutt_debug(LL_DEBUG5, "no, all failed\n");
652 return false;
653}
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:254
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:713
#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 310 of file alias.c.

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

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

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

346{
347 char bestname[8192] = { 0 };
348 struct Alias *a_best = NULL;
349 int count = 0;
350
351 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
352 mdata.limit = buf_strdup(buf);
353 mdata.search_state = search_state_new();
354
356 ASSERT(mod_data);
357
358 if (buf_at(buf, 0) != '\0')
359 {
360 struct Alias **ap = NULL;
361 ARRAY_FOREACH(ap, &mod_data->aliases)
362 {
363 struct Alias *a = *ap;
364 if (a->name && mutt_strn_equal(a->name, buf_string(buf), buf_len(buf)))
365 {
366 a_best = a;
367 count++;
368
369 if (bestname[0] == '\0') /* init */
370 {
371 mutt_str_copy(bestname, a->name, MIN(mutt_str_len(a->name) + 1, sizeof(bestname)));
372 }
373 else
374 {
375 int i;
376 for (i = 0; a->name[i] && (a->name[i] == bestname[i]); i++)
377 ; // do nothing
378
379 bestname[i] = '\0';
380 }
381 }
382 }
383
384 // Exactly one match, so expand the Alias and return
385 if (count == 1)
386 {
387 buf_reset(buf);
388 mutt_addrlist_write(&a_best->addr, buf, true);
389 buf_addstr(buf, ", ");
390 FREE(&mdata.limit);
392 return 1;
393 }
394
395 if (bestname[0] == '\0')
396 {
397 // Create a View Array of all the Aliases
398 FREE(&mdata.limit);
399 ARRAY_FOREACH(ap, &mod_data->aliases)
400 {
401 alias_array_alias_add(&mdata.ava, *ap);
402 }
403 }
404 else
405 {
406 /* fake the pattern for menu title */
407 char *mtitle = NULL;
408 mutt_str_asprintf(&mtitle, "~f ^%s", buf_string(buf));
409 FREE(&mdata.limit);
410 mdata.limit = mtitle;
411
412 if (!mutt_str_equal(bestname, buf_string(buf)))
413 {
414 /* we are adding something to the completion */
415 buf_strcpy_n(buf, bestname, mutt_str_len(bestname) + 1);
416 FREE(&mdata.limit);
418 return 1;
419 }
420
421 /* build alias list and show it */
422 ARRAY_FOREACH(ap, &mod_data->aliases)
423 {
424 struct Alias *a = *ap;
425 int aasize = alias_array_alias_add(&mdata.ava, a);
426
427 struct AliasView *av = ARRAY_GET(&mdata.ava, aasize - 1);
428
429 if (a->name && !mutt_strn_equal(a->name, buf_string(buf), buf_len(buf)))
430 {
431 av->is_visible = false;
432 }
433 }
434 }
435 }
436
437 if (ARRAY_EMPTY(&mdata.ava))
438 {
439 struct Alias **ap = NULL;
440 ARRAY_FOREACH(ap, &mod_data->aliases)
441 {
442 alias_array_alias_add(&mdata.ava, *ap);
443 }
444
445 mutt_pattern_alias_func(NULL, &mdata, PAA_VISIBLE, NULL);
446 }
447
448 if (!dlg_alias(&mdata))
449 goto done;
450
451 buf_reset(buf);
452
453 // Extract the selected aliases
454 struct Buffer *tmpbuf = buf_pool_get();
455 struct AliasView *avp = NULL;
456 ARRAY_FOREACH(avp, &mdata.ava)
457 {
458 if (!avp->is_tagged)
459 continue;
460
461 mutt_addrlist_write(&avp->alias->addr, tmpbuf, true);
462 buf_addstr(tmpbuf, ", ");
463 }
464 buf_copy(buf, tmpbuf);
465 buf_pool_release(&tmpbuf);
466
467done:
468 // Process any deleted aliases
469 ARRAY_FOREACH(avp, &mdata.ava)
470 {
471 if (!avp->is_deleted)
472 continue;
473
474 // Find and remove the alias from the Aliases array
475 struct Alias **ap = NULL;
476 ARRAY_FOREACH(ap, &mod_data->aliases)
477 {
478 if (*ap == avp->alias)
479 {
480 ARRAY_REMOVE(&mod_data->aliases, ap);
481 break;
482 }
483 }
484 alias_free(&avp->alias);
485 }
486
487 ARRAY_FREE(&mdata.ava);
488 FREE(&mdata.limit);
489 FREE(&mdata.title);
491
492 return 0;
493}
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: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:808
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:665
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:586
@ 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: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: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 500 of file dlg_alias.c.

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

113{
114 if (!addr || !addr->mailbox)
115 return NULL;
116
118 ASSERT(mod_data);
119
120 return mutt_hash_find(mod_data->reverse_aliases, buf_string(addr->mailbox));
121}
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:364
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:1723
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:337
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition hash.c:261
#define MUTT_HASH_STRDUP_KEYS
make a copy of the keys
Definition hash.h:113
#define MUTT_HASH_STRCASECMP
use strcasecmp() to compare keys
Definition hash.h:112
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:200
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