NeoMutt  2024-02-01-25-ga71e95
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
lib.h File Reference

Email Aliases. More...

#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "core/lib.h"
#include "complete/lib.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_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 (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'alias' command - Implements Command::parse() -.
 
enum CommandResult parse_unalias (struct Buffer *buf, struct Buffer *s, intptr_t data, 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.
 
int complete_alias (struct EnterWindowData *wdata, int op)
 Alias completion wrapper - Implements complete_function_t -.
 
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 719 of file alias.c.

720{
722}
void alias_reverse_init(void)
Set up the Reverse Alias Hash Table.
Definition: reverse.c:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_cleanup()

void alias_cleanup ( void  )

Clean up the Alias globals.

Definition at line 727 of file alias.c.

728{
729 struct Alias *np = NULL;
730 TAILQ_FOREACH(np, &Aliases, entries)
731 {
733 }
736}
struct AliasList Aliases
List of all the user's email aliases.
Definition: alias.c:62
void aliaslist_clear(struct AliasList *al)
Empty a List of Aliases.
Definition: alias.c:702
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
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 372 of file alias.c.

373{
374 struct Buffer *buf = buf_pool_get();
375 struct Buffer *fixed = buf_pool_get();
376 struct Buffer *prompt = NULL;
377 struct Buffer *tmp = buf_pool_get();
378
379 struct Address *addr = NULL;
380 char *pc = NULL;
381 char *err = NULL;
382 FILE *fp_alias = NULL;
383
384 if (al)
385 {
386 addr = TAILQ_FIRST(al);
387 if (addr && addr->mailbox)
388 {
389 buf_copy(tmp, addr->mailbox);
390 pc = strchr(buf_string(tmp), '@');
391 if (pc)
392 *pc = '\0';
393 }
394 }
395
396 /* Don't suggest a bad alias name in the event of a strange local part. */
397 check_alias_name(buf_string(tmp), buf->data, buf->dsize);
398
399retry_name:
400 /* L10N: prompt to add a new alias */
401 if ((mw_get_field(_("Alias as: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
402 buf_is_empty(buf))
403 {
404 goto done;
405 }
406
407 /* check to see if the user already has an alias defined */
408 if (alias_lookup(buf_string(buf)))
409 {
410 mutt_error(_("You already have an alias defined with that name"));
411 goto done;
412 }
413
414 if (check_alias_name(buf_string(buf), fixed->data, fixed->dsize))
415 {
416 switch (query_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
417 {
418 case MUTT_YES:
419 buf_copy(buf, fixed);
420 goto retry_name;
421 case MUTT_ABORT:
422 goto done;
423 default:; // do nothing
424 }
425 }
426
427 struct Alias *alias = alias_new();
428 alias->name = buf_strdup(buf);
429
431
432 if (addr && addr->mailbox)
433 buf_copy(buf, addr->mailbox);
434 else
435 buf_reset(buf);
436
437 mutt_addrlist_to_intl(al, NULL);
438
439 do
440 {
441 if ((mw_get_field(_("Address: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
442 buf_is_empty(buf))
443 {
444 alias_free(&alias);
445 goto done;
446 }
447
448 mutt_addrlist_parse(&alias->addr, buf_string(buf));
449 if (TAILQ_EMPTY(&alias->addr))
450 mutt_beep(false);
451 if (mutt_addrlist_to_intl(&alias->addr, &err))
452 {
453 mutt_error(_("Bad IDN: '%s'"), err);
454 FREE(&err);
455 continue;
456 }
457 } while (TAILQ_EMPTY(&alias->addr));
458
459 if (addr && addr->personal && !mutt_is_mail_list(addr))
460 buf_copy(buf, addr->personal);
461 else
462 buf_reset(buf);
463
464 if (mw_get_field(_("Personal name: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
465 {
466 alias_free(&alias);
467 goto done;
468 }
469
470 TAILQ_FIRST(&alias->addr)->personal = buf_new(buf_string(buf));
471
472 buf_reset(buf);
473 if (mw_get_field(_("Comment: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) == 0)
474 {
475 mutt_str_replace(&alias->comment, buf_string(buf));
476 }
477
478 buf_reset(buf);
479 if (mw_get_field(_("Tags (comma-separated): "), buf, MUTT_COMP_NO_FLAGS,
480 HC_OTHER, NULL, NULL) == 0)
481 {
482 parse_alias_tags(buf_string(buf), &alias->tags);
483 }
484
485 buf_reset(buf);
486 mutt_addrlist_write(&alias->addr, buf, true);
487 prompt = buf_pool_get();
488
489 buf_printf(prompt, "alias %s %s", alias->name, buf_string(buf));
490
491 bool has_tags = STAILQ_FIRST(&alias->tags);
492
493 if (alias->comment || has_tags)
494 buf_addstr(prompt, " #");
495
496 if (alias->comment)
497 buf_add_printf(prompt, " %s", alias->comment);
498
499 if (has_tags)
500 {
501 if (STAILQ_FIRST(&alias->tags))
502 {
503 buf_addstr(prompt, " tags:");
504 alias_tags_to_buffer(&alias->tags, prompt);
505 }
506 }
507
508 buf_add_printf(prompt, "\n%s", _("Accept?"));
509
510 if (query_yesorno(buf_string(prompt), MUTT_YES) != MUTT_YES)
511 {
512 alias_free(&alias);
513 goto done;
514 }
515
516 alias_reverse_add(alias);
517 TAILQ_INSERT_TAIL(&Aliases, alias, entries);
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 };
523 if (mw_get_field(_("Save to file: "), buf, MUTT_COMP_CLEAR, HC_FILE,
524 &CompleteFileOps, &cdata) != 0)
525 {
526 goto done;
527 }
528 mutt_expand_path(buf->data, buf->dsize);
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 (!mutt_file_seek(fp_alias, 0, SEEK_END))
538 {
539 goto done;
540 }
541 if (ftell(fp_alias) > 0)
542 {
543 if (!mutt_file_seek(fp_alias, -1, SEEK_CUR))
544 {
545 goto done;
546 }
547 if (fread(buf->data, 1, 1, fp_alias) != 1)
548 {
549 mutt_perror(_("Error reading alias file"));
550 goto done;
551 }
552 if (!mutt_file_seek(fp_alias, 0, SEEK_END))
553 {
554 goto done;
555 }
556 if (buf->data[0] != '\n')
557 fputc('\n', fp_alias);
558 }
559
560 if (check_alias_name(alias->name, NULL, 0))
561 mutt_file_quote_filename(alias->name, buf->data, buf->dsize);
562 else
563 buf_strcpy(buf, alias->name);
564
565 recode_buf(buf);
566 fprintf(fp_alias, "alias %s ", buf_string(buf));
567 buf_reset(buf);
568
569 mutt_addrlist_write(&alias->addr, buf, false);
570 recode_buf(buf);
571 write_safe_address(fp_alias, buf_string(buf));
572 if (alias->comment)
573 fprintf(fp_alias, " # %s", alias->comment);
574 if (STAILQ_FIRST(&alias->tags))
575 {
576 fprintf(fp_alias, " tags:");
577
578 struct Tag *tag = NULL;
579 STAILQ_FOREACH(tag, &alias->tags, entries)
580 {
581 fprintf(fp_alias, "%s", tag->name);
582 if (STAILQ_NEXT(tag, entries))
583 fprintf(fp_alias, ",");
584 }
585 }
586 fputc('\n', fp_alias);
587 if (mutt_file_fsync_close(&fp_alias) != 0)
588 mutt_perror(_("Trouble adding alias"));
589 else
590 mutt_message(_("Alias added"));
591
592done:
593 mutt_file_fclose(&fp_alias);
594 buf_pool_release(&buf);
595 buf_pool_release(&fixed);
596 buf_pool_release(&prompt);
597 buf_pool_release(&tmp);
598}
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1382
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1210
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:1297
void parse_alias_tags(const char *tags, struct TagList *tl)
Parse a comma-separated list of tags.
Definition: commands.c:65
void alias_tags_to_buffer(struct TagList *tl, struct Buffer *buf)
Write a comma-separated list of tags to a Buffer.
Definition: commands.c:49
void alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:677
static int check_alias_name(const char *s, char *dest, size_t destlen)
Sanity-check an alias name.
Definition: alias.c:217
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:282
static void recode_buf(struct Buffer *buf)
Convert some text between two character sets.
Definition: alias.c:192
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:665
static void write_safe_address(FILE *fp, const char *s)
Defang malicious email addresses.
Definition: alias.c:88
const struct CompleteOps CompleteFileOps
Auto-Completion of Files.
Definition: complete.c:153
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:178
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:221
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:93
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:308
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition: buffer.c:321
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:243
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:412
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:618
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:588
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:97
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:169
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:68
size_t mutt_file_quote_filename(const char *filename, char *buf, size_t buflen)
Quote a filename to survive the shell's quoting rules.
Definition: file.c:929
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:771
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:188
#define mutt_file_fclose(FP)
Definition: file.h:148
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:147
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list? - Implements addr_predicate_t -.
Definition: maillist.c:45
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:274
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_perror(...)
Definition: logging2.h:93
@ HC_FILE
Files.
Definition: lib.h:54
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:56
#define FREE(x)
Definition: memory.h:45
#define _(a)
Definition: message.h:28
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:329
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:57
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:126
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition: quad.h:37
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:334
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:809
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define TAILQ_FIRST(head)
Definition: queue.h:723
#define TAILQ_EMPTY(head)
Definition: queue.h:721
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
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:36
struct Buffer * mailbox
Mailbox and host address.
Definition: address.h:38
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
size_t dsize
Length of data.
Definition: buffer.h:39
char * data
Pointer to data.
Definition: buffer.h:37
Input for the file completion function.
Definition: curs_lib.h:40
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 282 of file alias.c.

283{
284 struct Alias *a = NULL;
285
286 TAILQ_FOREACH(a, &Aliases, entries)
287 {
288 if (mutt_istr_equal(name, a->name))
289 return &a->addr;
290 }
291 return NULL;
292}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:721
+ 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 605 of file alias.c.

606{
607 if (!addr)
608 {
609 mutt_debug(LL_DEBUG5, "no, NULL address\n");
610 return false;
611 }
612 if (!addr->mailbox)
613 {
614 mutt_debug(LL_DEBUG5, "no, no mailbox\n");
615 return false;
616 }
617
619 {
620 mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", buf_string(addr->mailbox), Username);
621 return true;
622 }
624 {
625 mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
627 return true;
628 }
629 const char *fqdn = mutt_fqdn(false, NeoMutt->sub);
630 if (string_is_address(buf_string(addr->mailbox), Username, fqdn))
631 {
632 mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
633 Username, NONULL(fqdn));
634 return true;
635 }
636 fqdn = mutt_fqdn(true, NeoMutt->sub);
637 if (string_is_address(buf_string(addr->mailbox), Username, fqdn))
638 {
639 mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
640 Username, NONULL(fqdn));
641 return true;
642 }
643
644 const struct Address *c_from = cs_subset_address(NeoMutt->sub, "from");
645 if (c_from && mutt_istr_equal(buf_string(c_from->mailbox), buf_string(addr->mailbox)))
646 {
647 mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", buf_string(addr->mailbox),
648 buf_string(c_from->mailbox));
649 return true;
650 }
651
653 return true;
654
655 mutt_debug(LL_DEBUG5, "no, all failed\n");
656 return false;
657}
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:263
bool mutt_alternates_match(const char *addr)
Compare an Address to the Un/Alternates lists.
Definition: alternates.c:155
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
Definition: config_type.c:264
char * ShortHostname
Short version of the hostname.
Definition: globals.c:39
char * Username
User's login name.
Definition: globals.c:41
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG5
Log at debug level 5.
Definition: logging2.h:47
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:37
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

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

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

301{
302 // previously expanded aliases to avoid loops
303 struct ListHead expn = STAILQ_HEAD_INITIALIZER(expn);
304
305 expand_aliases_r(al, &expn);
306 mutt_list_free(&expn);
308}
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1401
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:106
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
#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 332 of file alias.c.

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

50{
51 struct Tag *tag = NULL;
52 STAILQ_FOREACH(tag, tl, entries)
53 {
54 buf_addstr(buf, tag->name);
55 if (STAILQ_NEXT(tag, entries))
56 buf_addch(buf, ',');
57 }
58}
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:258
+ 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 95 of file commands.c.

96{
97 if (!com || (com[0] == '\0'))
98 return;
99
100 const regmatch_t *match = mutt_prex_capture(PREX_ALIAS_TAGS, com);
101 if (match)
102 {
103 const regmatch_t *pre = &match[PREX_ALIAS_TAGS_MATCH_PRE];
104 const regmatch_t *tags = &match[PREX_ALIAS_TAGS_MATCH_TAGS];
105 const regmatch_t *post = &match[PREX_ALIAS_TAGS_MATCH_POST];
106
107 struct Buffer *tmp = buf_pool_get();
108
109 // Extract the tags
110 buf_addstr_n(tmp, com + mutt_regmatch_start(tags),
112 parse_alias_tags(buf_string(tmp), &alias->tags);
113 buf_reset(tmp);
114
115 // Collect all the other text as "comments"
116 buf_addstr_n(tmp, com + mutt_regmatch_start(pre),
118 buf_addstr_n(tmp, com + mutt_regmatch_start(post),
120 alias->comment = buf_strdup(tmp);
121
122 buf_pool_release(&tmp);
123 }
124 else
125 {
126 alias->comment = mutt_str_dup(com);
127 }
128}
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:113
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
regmatch_t * mutt_prex_capture(enum Prex which, const char *str)
Match a precompiled regex against a string.
Definition: prex.c:295
@ 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 65 of file commands.c.

66{
67 if (!tags || !tl)
68 return;
69
70 struct Slist *sl = slist_parse(tags, D_SLIST_SEP_COMMA);
71 if (slist_is_empty(sl))
72 {
73 slist_free(&sl);
74 return;
75 }
76
77 struct ListNode *np = NULL;
78 STAILQ_FOREACH(np, &sl->head, entries)
79 {
80 struct Tag *tag = tag_new();
81 tag->name = np->data; // Transfer string
82 np->data = NULL;
83 STAILQ_INSERT_TAIL(tl, tag, entries);
84 }
85 slist_free(&sl);
86}
struct Slist * slist_parse(const char *str, uint32_t flags)
Parse a list of strings into a list.
Definition: slist.c:179
bool slist_is_empty(const struct Slist *list)
Is the slist empty?
Definition: slist.c:142
void slist_free(struct Slist **ptr)
Free an Slist object.
Definition: slist.c:126
#define STAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:389
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
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:64
#define D_SLIST_SEP_COMMA
Slist items are comma-separated.
Definition: types.h:108
+ 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 396 of file dlg_alias.c.

397{
398 struct Alias *np = NULL;
399 char bestname[8192] = { 0 };
400
401 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
402 mdata.limit = buf_strdup(buf);
403 mdata.search_state = search_state_new();
404
405 if (buf_at(buf, 0) != '\0')
406 {
407 TAILQ_FOREACH(np, &Aliases, entries)
408 {
409 if (np->name && mutt_strn_equal(np->name, buf_string(buf), buf_len(buf)))
410 {
411 if (bestname[0] == '\0') /* init */
412 {
413 mutt_str_copy(bestname, np->name,
414 MIN(mutt_str_len(np->name) + 1, sizeof(bestname)));
415 }
416 else
417 {
418 int i;
419 for (i = 0; np->name[i] && (np->name[i] == bestname[i]); i++)
420 ; // do nothing
421
422 bestname[i] = '\0';
423 }
424 }
425 }
426
427 if (bestname[0] == '\0')
428 {
429 // Create a View Array of all the Aliases
430 FREE(&mdata.limit);
431 TAILQ_FOREACH(np, &Aliases, entries)
432 {
434 }
435 }
436 else
437 {
438 /* fake the pattern for menu title */
439 char *mtitle = NULL;
440 mutt_str_asprintf(&mtitle, "~f ^%s", buf_string(buf));
441 FREE(&mdata.limit);
442 mdata.limit = mtitle;
443
444 if (!mutt_str_equal(bestname, buf_string(buf)))
445 {
446 /* we are adding something to the completion */
447 buf_strcpy_n(buf, bestname, mutt_str_len(bestname) + 1);
448 FREE(&mdata.limit);
449 search_state_free(&mdata.search_state);
450 return 1;
451 }
452
453 /* build alias list and show it */
454 TAILQ_FOREACH(np, &Aliases, entries)
455 {
456 int aasize = alias_array_alias_add(&mdata.ava, np);
457
458 struct AliasView *av = ARRAY_GET(&mdata.ava, aasize - 1);
459
460 if (np->name && !mutt_strn_equal(np->name, buf_string(buf), buf_len(buf)))
461 {
462 av->is_visible = false;
463 }
464 }
465 }
466 }
467
468 if (ARRAY_EMPTY(&mdata.ava))
469 {
470 TAILQ_FOREACH(np, &Aliases, entries)
471 {
472 alias_array_alias_add(&mdata.ava, np);
473 }
474
475 mutt_pattern_alias_func(NULL, &mdata, NULL);
476 }
477
478 if (!dlg_alias(NULL, &mdata))
479 goto done;
480
481 buf_reset(buf);
482
483 // Extract the selected aliases
484 struct Buffer *tmpbuf = buf_pool_get();
485 struct AliasView *avp = NULL;
486 ARRAY_FOREACH(avp, &mdata.ava)
487 {
488 if (!avp->is_tagged)
489 continue;
490
491 mutt_addrlist_write(&avp->alias->addr, tmpbuf, true);
492 buf_addstr(tmpbuf, ", ");
493 }
494 buf_copy(buf, tmpbuf);
495 buf_pool_release(&tmpbuf);
496
497done:
498 // Process any deleted aliases
499 ARRAY_FOREACH(avp, &mdata.ava)
500 {
501 if (!avp->is_deleted)
502 continue;
503
504 TAILQ_REMOVE(&Aliases, avp->alias, entries);
505 alias_free(&avp->alias);
506 }
507
508 ARRAY_FREE(&mdata.ava);
509 FREE(&mdata.limit);
510 FREE(&mdata.title);
512
513 return 0;
514}
int alias_array_alias_add(struct AliasViewArray *ava, struct Alias *alias)
Add an Alias to the AliasViewArray.
Definition: array.c:47
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:212
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:74
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:204
#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:508
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition: buffer.c:687
size_t buf_strcpy_n(struct Buffer *buf, const char *s, size_t len)
Copy a string into a Buffer.
Definition: buffer.c:433
static bool dlg_alias(struct Buffer *buf, struct AliasMenuData *mdata)
Display a menu of Aliases -.
Definition: dlg_alias.c:325
#define MIN(a, b)
Definition: memory.h:32
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:852
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:709
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:474
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:545
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:630
int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition: pattern.c:190
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:841
void search_state_free(struct SearchState **ptr)
Free a SearchState.
Definition: search_state.c:51
struct SearchState * search_state_new(void)
Create a new SearchState.
Definition: search_state.c:39
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:135
+ 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 521 of file dlg_alias.c.

522{
523 struct Alias *np = NULL;
524
525 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
526 mdata.search_state = search_state_new();
527
528 // Create a View Array of all the Aliases
529 TAILQ_FOREACH(np, &Aliases, entries)
530 {
532 }
533
534 if (!dlg_alias(NULL, &mdata))
535 goto done;
536
537 // Prepare the "To:" field of a new email
538 struct Email *e = email_new();
539 e->env = mutt_env_new();
540
541 struct AliasView *avp = NULL;
542 ARRAY_FOREACH(avp, &mdata.ava)
543 {
544 if (!avp->is_tagged)
545 continue;
546
547 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
548 if (alias_to_addrlist(&al_copy, avp->alias))
549 {
550 mutt_addrlist_copy(&e->env->to, &al_copy, false);
551 mutt_addrlist_clear(&al_copy);
552 }
553 }
554
555 mutt_send_message(SEND_REVIEW_TO, e, NULL, m, NULL, sub);
556
557done:
558 // Process any deleted aliases
559 ARRAY_FOREACH(avp, &mdata.ava)
560 {
561 if (avp->is_deleted)
562 {
563 TAILQ_REMOVE(&Aliases, avp->alias, entries);
564 alias_free(&avp->alias);
565 }
566 }
567
568 ARRAY_FREE(&mdata.ava);
569 FREE(&mdata.limit);
570 FREE(&mdata.title);
572}
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:1464
bool alias_to_addrlist(struct AddressList *al, struct Alias *alias)
Turn an Alias into an AddressList.
Definition: dlg_query.c:120
struct Email * email_new(void)
Create a new Email.
Definition: email.c:80
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:46
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
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:2115
#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 465 of file dlg_query.c.

466{
467 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
468 mdata.search_state = search_state_new();
469
470 struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
471 const char *const c_query_command = cs_subset_string(sub, "query_command");
472 if (!c_query_command)
473 {
474 mutt_warning(_("Query command not defined"));
475 goto done;
476 }
477
478 query_run(buf_string(buf), true, &al, sub);
479 if (TAILQ_EMPTY(&al))
480 goto done;
481
482 mdata.al = &al;
483
484 struct Alias *a_first = TAILQ_FIRST(&al);
485 if (!TAILQ_NEXT(a_first, entries)) // only one response?
486 {
487 struct AddressList addr = TAILQ_HEAD_INITIALIZER(addr);
488 if (alias_to_addrlist(&addr, a_first))
489 {
491 buf_reset(buf);
492 mutt_addrlist_write(&addr, buf, false);
493 mutt_addrlist_clear(&addr);
495 }
496 goto done;
497 }
498
499 struct Alias *np = NULL;
500 TAILQ_FOREACH(np, mdata.al, entries)
501 {
502 alias_array_alias_add(&mdata.ava, np);
503 }
504
505 /* multiple results, choose from query menu */
506 if (!dlg_query(buf, &mdata))
507 goto done;
508
509 buf_reset(buf);
510 buf_alloc(buf, 8192);
511 bool first = true;
512 struct AliasView *avp = NULL;
513 ARRAY_FOREACH(avp, &mdata.ava)
514 {
515 if (!avp->is_tagged)
516 continue;
517
518 if (!first)
519 {
520 buf_addstr(buf, ", ");
521 }
522
523 first = false;
524 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
525 if (alias_to_addrlist(&al_copy, avp->alias))
526 {
527 mutt_addrlist_to_local(&al_copy);
528 mutt_addrlist_write(&al_copy, buf, false);
529 mutt_addrlist_clear(&al_copy);
530 }
531 }
532
533done:
534 ARRAY_FREE(&mdata.ava);
535 FREE(&mdata.title);
536 FREE(&mdata.limit);
538 aliaslist_clear(&al);
539 return 0;
540}
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:354
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
int query_run(const char *s, bool verbose, struct AliasList *al, const struct ConfigSubset *sub)
Run an external program to find Addresses.
Definition: dlg_query.c:269
static bool dlg_query(struct Buffer *buf, struct AliasMenuData *mdata)
Get the user to enter an Address Query -.
Definition: dlg_query.c:406
#define mutt_warning(...)
Definition: logging2.h:90
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
#define TAILQ_NEXT(elm, field)
Definition: queue.h:832
struct AliasList * al
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 547 of file dlg_query.c.

548{
549 const char *const c_query_command = cs_subset_string(sub, "query_command");
550 if (!c_query_command)
551 {
552 mutt_warning(_("Query command not defined"));
553 return;
554 }
555
556 struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
557 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
558 mdata.al = &al;
559 mdata.search_state = search_state_new();
560
561 struct Buffer *buf = buf_pool_get();
562 if ((mw_get_field(_("Query: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
563 buf_is_empty(buf))
564 {
565 goto done;
566 }
567
568 query_run(buf_string(buf), false, &al, sub);
569 if (TAILQ_EMPTY(&al))
570 goto done;
571
572 struct Alias *np = NULL;
573 TAILQ_FOREACH(np, mdata.al, entries)
574 {
575 alias_array_alias_add(&mdata.ava, np);
576 }
577
578 if (!dlg_query(buf, &mdata))
579 goto done;
580
581 // Prepare the "To:" field of a new email
582 struct Email *e = email_new();
583 e->env = mutt_env_new();
584
585 struct AliasView *avp = NULL;
586 ARRAY_FOREACH(avp, &mdata.ava)
587 {
588 if (!avp->is_tagged)
589 continue;
590
591 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
592 if (alias_to_addrlist(&al_copy, avp->alias))
593 {
594 mutt_addrlist_copy(&e->env->to, &al_copy, false);
595 mutt_addrlist_clear(&al_copy);
596 }
597 }
598
599 mutt_send_message(SEND_REVIEW_TO, e, NULL, m, NULL, sub);
600
601done:
602 ARRAY_FREE(&mdata.ava);
603 FREE(&mdata.title);
604 FREE(&mdata.limit);
606 aliaslist_clear(&al);
607 buf_pool_release(&buf);
608}
+ 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:362
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.