NeoMutt
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() -.
 
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 679 of file alias.c.

680{
682}
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 687 of file alias.c.

688{
689 struct Alias *np = NULL;
690 TAILQ_FOREACH(np, &Aliases, entries)
691 {
693 }
696}
struct AliasList Aliases
List of all the user's email aliases.
Definition: alias.c:60
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:662
#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:34
+ 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 370 of file alias.c.

371{
372 struct Buffer *buf = buf_pool_get();
373 struct Buffer *fixed = buf_pool_get();
374 struct Buffer *prompt = NULL;
375 struct Buffer *tmp = buf_pool_get();
376
377 struct Address *addr = NULL;
378 char *pc = NULL;
379 char *err = NULL;
380 FILE *fp_alias = NULL;
381
382 if (al)
383 {
384 addr = TAILQ_FIRST(al);
385 if (addr && addr->mailbox)
386 {
387 buf_copy(tmp, addr->mailbox);
388 pc = strchr(buf_string(tmp), '@');
389 if (pc)
390 *pc = '\0';
391 }
392 }
393
394 /* Don't suggest a bad alias name in the event of a strange local part. */
395 check_alias_name(buf_string(tmp), buf->data, buf->dsize);
396
397retry_name:
398 /* L10N: prompt to add a new alias */
399 if ((mw_get_field(_("Alias as: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
400 buf_is_empty(buf))
401 {
402 goto done;
403 }
404
405 /* check to see if the user already has an alias defined */
406 if (alias_lookup(buf_string(buf)))
407 {
408 mutt_error(_("You already have an alias defined with that name"));
409 goto done;
410 }
411
412 if (check_alias_name(buf_string(buf), fixed->data, fixed->dsize))
413 {
414 switch (query_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
415 {
416 case MUTT_YES:
417 buf_copy(buf, fixed);
418 goto retry_name;
419 case MUTT_ABORT:
420 goto done;
421 default:; // do nothing
422 }
423 }
424
425 struct Alias *alias = alias_new();
426 alias->name = buf_strdup(buf);
427
429
430 if (addr && addr->mailbox)
431 buf_copy(buf, addr->mailbox);
432 else
433 buf_reset(buf);
434
435 mutt_addrlist_to_intl(al, NULL);
436
437 do
438 {
439 if ((mw_get_field(_("Address: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
440 buf_is_empty(buf))
441 {
442 alias_free(&alias);
443 goto done;
444 }
445
446 mutt_addrlist_parse(&alias->addr, buf_string(buf));
447 if (TAILQ_EMPTY(&alias->addr))
448 mutt_beep(false);
449 if (mutt_addrlist_to_intl(&alias->addr, &err))
450 {
451 mutt_error(_("Bad IDN: '%s'"), err);
452 FREE(&err);
453 continue;
454 }
455 } while (TAILQ_EMPTY(&alias->addr));
456
457 if (addr && addr->personal && !mutt_is_mail_list(addr))
458 buf_copy(buf, addr->personal);
459 else
460 buf_reset(buf);
461
462 if (mw_get_field(_("Personal name: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
463 {
464 alias_free(&alias);
465 goto done;
466 }
467 buf_copy(TAILQ_FIRST(&alias->addr)->personal, buf);
468
469 buf_reset(buf);
470 if (mw_get_field(_("Comment: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) == 0)
471 {
472 mutt_str_replace(&alias->comment, buf_string(buf));
473 }
474
475 buf_reset(buf);
476 mutt_addrlist_write(&alias->addr, buf, true);
477 prompt = buf_pool_get();
478 if (alias->comment)
479 {
480 buf_printf(prompt, "[%s = %s # %s] %s", alias->name, buf_string(buf),
481 alias->comment, _("Accept?"));
482 }
483 else
484 {
485 buf_printf(prompt, "[%s = %s] %s", alias->name, buf_string(buf), _("Accept?"));
486 }
487 if (query_yesorno(buf_string(prompt), MUTT_YES) != MUTT_YES)
488 {
489 alias_free(&alias);
490 goto done;
491 }
492
493 alias_reverse_add(alias);
494 TAILQ_INSERT_TAIL(&Aliases, alias, entries);
495
496 const char *const c_alias_file = cs_subset_path(sub, "alias_file");
497 buf_strcpy(buf, c_alias_file);
498
499 struct FileCompletionData cdata = { false, NULL, NULL, NULL };
500 if (mw_get_field(_("Save to file: "), buf, MUTT_COMP_CLEAR, HC_FILE,
501 &CompleteMailboxOps, &cdata) != 0)
502 {
503 goto done;
504 }
505 mutt_expand_path(buf->data, buf->dsize);
506 fp_alias = fopen(buf_string(buf), "a+");
507 if (!fp_alias)
508 {
509 mutt_perror("%s", buf_string(buf));
510 goto done;
511 }
512
513 /* terminate existing file with \n if necessary */
514 if (!mutt_file_seek(fp_alias, 0, SEEK_END))
515 {
516 goto done;
517 }
518 if (ftell(fp_alias) > 0)
519 {
520 if (!mutt_file_seek(fp_alias, -1, SEEK_CUR))
521 {
522 goto done;
523 }
524 if (fread(buf->data, 1, 1, fp_alias) != 1)
525 {
526 mutt_perror(_("Error reading alias file"));
527 goto done;
528 }
529 if (!mutt_file_seek(fp_alias, 0, SEEK_END))
530 {
531 goto done;
532 }
533 if (buf->data[0] != '\n')
534 fputc('\n', fp_alias);
535 }
536
537 if (check_alias_name(alias->name, NULL, 0))
538 mutt_file_quote_filename(alias->name, buf->data, buf->dsize);
539 else
540 buf_strcpy(buf, alias->name);
541
542 recode_buf(buf);
543 fprintf(fp_alias, "alias %s ", buf_string(buf));
544 buf_reset(buf);
545
546 mutt_addrlist_write(&alias->addr, buf, false);
547 recode_buf(buf);
548 write_safe_address(fp_alias, buf_string(buf));
549 if (alias->comment)
550 fprintf(fp_alias, " # %s", alias->comment);
551 fputc('\n', fp_alias);
552 if (mutt_file_fsync_close(&fp_alias) != 0)
553 mutt_perror(_("Trouble adding alias"));
554 else
555 mutt_message(_("Alias added"));
556
557done:
558 mutt_file_fclose(&fp_alias);
559 buf_pool_release(&buf);
560 buf_pool_release(&fixed);
561 buf_pool_release(&prompt);
562 buf_pool_release(&tmp);
563}
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1379
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1207
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:478
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1294
void alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:641
static int check_alias_name(const char *s, char *dest, size_t destlen)
Sanity-check an alias name.
Definition: alias.c:215
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:280
static void recode_buf(struct Buffer *buf)
Convert some text between two character sets.
Definition: alias.c:190
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:630
static void write_safe_address(FILE *fp, const char *s)
Defang malicious email addresses.
Definition: alias.c:86
const struct CompleteOps CompleteMailboxOps
Auto-Completion of Files / Mailboxes.
Definition: complete.c:160
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:173
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:407
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:572
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:542
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
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:69
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
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:891
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:733
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:168
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list? - Implements addr_predicate_t -.
Definition: maillist.c:44
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:275
#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:52
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:54
#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:327
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:55
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:56
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:330
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:809
#define TAILQ_FIRST(head)
Definition: queue.h:723
#define TAILQ_EMPTY(head)
Definition: queue.h:721
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
char * comment
Free-form comment string.
Definition: alias.h:37
char * name
Short name.
Definition: alias.h:35
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
String manipulation buffer.
Definition: buffer.h:34
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
Input for the file completion function.
Definition: curs_lib.h:49
+ 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 280 of file alias.c.

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

571{
572 if (!addr)
573 {
574 mutt_debug(LL_DEBUG5, "no, NULL address\n");
575 return false;
576 }
577 if (!addr->mailbox)
578 {
579 mutt_debug(LL_DEBUG5, "no, no mailbox\n");
580 return false;
581 }
582
584 {
585 mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", buf_string(addr->mailbox), Username);
586 return true;
587 }
589 {
590 mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
592 return true;
593 }
594 const char *fqdn = mutt_fqdn(false, NeoMutt->sub);
595 if (string_is_address(buf_string(addr->mailbox), Username, fqdn))
596 {
597 mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
598 Username, NONULL(fqdn));
599 return true;
600 }
601 fqdn = mutt_fqdn(true, NeoMutt->sub);
602 if (string_is_address(buf_string(addr->mailbox), Username, fqdn))
603 {
604 mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
605 Username, NONULL(fqdn));
606 return true;
607 }
608
609 const struct Address *c_from = cs_subset_address(NeoMutt->sub, "from");
610 if (c_from && mutt_istr_equal(buf_string(c_from->mailbox), buf_string(addr->mailbox)))
611 {
612 mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", buf_string(addr->mailbox),
613 buf_string(c_from->mailbox));
614 return true;
615 }
616
618 return true;
619
620 mutt_debug(LL_DEBUG5, "no, all failed\n");
621 return false;
622}
static bool string_is_address(const char *str, const char *user, const char *domain)
Does an email address match a user and domain?
Definition: alias.c:261
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:262
char * ShortHostname
Short version of the hostname.
Definition: globals.c:40
char * Username
User's login name.
Definition: globals.c:42
#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:705
#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 312 of file alias.c.

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

299{
300 struct ListHead expn; /* previously expanded aliases to avoid loops */
301
302 STAILQ_INIT(&expn);
303 expand_aliases_r(al, &expn);
304 mutt_list_free(&expn);
306}
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1398
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:104
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
#define STAILQ_INIT(head)
Definition: queue.h:372
+ 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 330 of file alias.c.

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

386{
387 struct Alias *np = NULL;
388 char bestname[8192] = { 0 };
389
390 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
391 mdata.limit = buf_strdup(buf);
392 mdata.search_state = search_state_new();
393
394 if (buf_at(buf, 0) != '\0')
395 {
396 TAILQ_FOREACH(np, &Aliases, entries)
397 {
398 if (np->name && mutt_strn_equal(np->name, buf_string(buf), buf_len(buf)))
399 {
400 if (bestname[0] == '\0') /* init */
401 {
402 mutt_str_copy(bestname, np->name,
403 MIN(mutt_str_len(np->name) + 1, sizeof(bestname)));
404 }
405 else
406 {
407 int i;
408 for (i = 0; np->name[i] && (np->name[i] == bestname[i]); i++)
409 ; // do nothing
410
411 bestname[i] = '\0';
412 }
413 }
414 }
415
416 if (bestname[0] == '\0')
417 {
418 // Create a View Array of all the Aliases
419 FREE(&mdata.limit);
420 TAILQ_FOREACH(np, &Aliases, entries)
421 {
423 }
424 }
425 else
426 {
427 /* fake the pattern for menu title */
428 char *mtitle = NULL;
429 mutt_str_asprintf(&mtitle, "~f ^%s", buf_string(buf));
430 FREE(&mdata.limit);
431 mdata.limit = mtitle;
432
433 if (!mutt_str_equal(bestname, buf_string(buf)))
434 {
435 /* we are adding something to the completion */
436 buf_strcpy_n(buf, bestname, mutt_str_len(bestname) + 1);
437 FREE(&mdata.limit);
438 return 1;
439 }
440
441 /* build alias list and show it */
442 TAILQ_FOREACH(np, &Aliases, entries)
443 {
444 int aasize = alias_array_alias_add(&mdata.ava, np);
445
446 struct AliasView *av = ARRAY_GET(&mdata.ava, aasize - 1);
447
448 if (np->name && !mutt_strn_equal(np->name, buf_string(buf), buf_len(buf)))
449 {
450 av->is_visible = false;
451 }
452 }
453 }
454 }
455
456 if (ARRAY_EMPTY(&mdata.ava))
457 {
458 TAILQ_FOREACH(np, &Aliases, entries)
459 {
460 alias_array_alias_add(&mdata.ava, np);
461 }
462
463 mutt_pattern_alias_func(NULL, &mdata, NULL);
464 }
465
466 if (!dlg_alias(NULL, &mdata))
467 goto done;
468
469 buf_reset(buf);
470
471 // Extract the selected aliases
472 struct Buffer *tmpbuf = buf_pool_get();
473 struct AliasView *avp = NULL;
474 ARRAY_FOREACH(avp, &mdata.ava)
475 {
476 if (!avp->is_tagged)
477 continue;
478
479 mutt_addrlist_write(&avp->alias->addr, tmpbuf, true);
480 buf_addstr(tmpbuf, ", ");
481 }
482 buf_copy(buf, tmpbuf);
483 buf_pool_release(&tmpbuf);
484
485done:
486 // Process any deleted aliases
487 ARRAY_FOREACH(avp, &mdata.ava)
488 {
489 if (!avp->is_deleted)
490 continue;
491
492 TAILQ_REMOVE(&Aliases, avp->alias, entries);
493 alias_free(&avp->alias);
494 }
495
496 ARRAY_FREE(&mdata.ava);
497 FREE(&mdata.limit);
498 FREE(&mdata.title);
500
501 return 0;
502}
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:211
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:73
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:203
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:108
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:57
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:466
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition: buffer.c:638
size_t buf_strcpy_n(struct Buffer *buf, const char *s, size_t len)
Copy a string into a Buffer.
Definition: buffer.c:422
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:238
static bool dlg_alias(struct Buffer *buf, struct AliasMenuData *mdata)
Display a menu of Aliases -.
Definition: dlg_alias.c:314
#define MIN(a, b)
Definition: memory.h:32
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1022
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
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:497
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:568
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:653
int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition: pattern.c:191
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:841
void search_state_free(struct SearchState **ptr)
Free a SearchState.
Definition: search_state.c:50
struct SearchState * search_state_new(void)
Create a new SearchState.
Definition: search_state.c:38
AliasView array wrapper with Pattern information -.
Definition: gui.h:52
char * limit
Limit being used.
Definition: gui.h:58
struct AliasViewArray ava
All Aliases/Queries.
Definition: gui.h:53
struct SearchState * search_state
State of the current search.
Definition: gui.h:61
char * title
Title for the status bar.
Definition: gui.h:60
struct ConfigSubset * sub
Config items.
Definition: gui.h:55
GUI data wrapping an Alias.
Definition: gui.h:36
bool is_visible
Is visible?
Definition: gui.h:43
struct Alias * alias
Alias.
Definition: gui.h:44
bool is_deleted
Is it deleted?
Definition: gui.h:42
bool is_tagged
Is it tagged?
Definition: gui.h:41
void * mdata
Private data.
Definition: lib.h:137
+ 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 509 of file dlg_alias.c.

510{
511 struct Alias *np = NULL;
512
513 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
514 mdata.search_state = search_state_new();
515
516 // Create a View Array of all the Aliases
517 TAILQ_FOREACH(np, &Aliases, entries)
518 {
520 }
521
522 if (!dlg_alias(NULL, &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 // Process any deleted aliases
547 ARRAY_FOREACH(avp, &mdata.ava)
548 {
549 if (avp->is_deleted)
550 {
551 TAILQ_REMOVE(&Aliases, avp->alias, entries);
552 alias_free(&avp->alias);
553 }
554 }
555
556 ARRAY_FREE(&mdata.ava);
557 FREE(&mdata.limit);
558 FREE(&mdata.title);
560}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:762
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1461
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:78
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:43
#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:2127
#define SEND_REVIEW_TO
Allow the user to edit the To field.
Definition: send.h:54
The envelope/body of an email.
Definition: email.h:37
struct Envelope * env
Envelope information.
Definition: email.h:66
+ 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 456 of file dlg_query.c.

457{
458 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
459 mdata.search_state = search_state_new();
460
461 struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
462 const char *const c_query_command = cs_subset_string(sub, "query_command");
463 if (!c_query_command)
464 {
465 mutt_warning(_("Query command not defined"));
466 goto done;
467 }
468
469 query_run(buf_string(buf), true, &al, sub);
470 if (TAILQ_EMPTY(&al))
471 goto done;
472
473 mdata.al = &al;
474
475 struct Alias *a_first = TAILQ_FIRST(&al);
476 if (!TAILQ_NEXT(a_first, entries)) // only one response?
477 {
478 struct AddressList addr = TAILQ_HEAD_INITIALIZER(addr);
479 if (alias_to_addrlist(&addr, a_first))
480 {
482 buf_reset(buf);
483 mutt_addrlist_write(&addr, buf, false);
484 mutt_addrlist_clear(&addr);
486 }
487 goto done;
488 }
489
490 struct Alias *np = NULL;
491 TAILQ_FOREACH(np, mdata.al, entries)
492 {
493 alias_array_alias_add(&mdata.ava, np);
494 }
495
496 /* multiple results, choose from query menu */
497 if (!dlg_query(buf, &mdata))
498 goto done;
499
500 buf_reset(buf);
501 buf_alloc(buf, 8192);
502 bool first = true;
503 struct AliasView *avp = NULL;
504 ARRAY_FOREACH(avp, &mdata.ava)
505 {
506 if (!avp->is_tagged)
507 continue;
508
509 if (!first)
510 {
511 buf_addstr(buf, ", ");
512 }
513
514 first = false;
515 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
516 if (alias_to_addrlist(&al_copy, avp->alias))
517 {
518 mutt_addrlist_to_local(&al_copy);
519 mutt_addrlist_write(&al_copy, buf, false);
520 mutt_addrlist_clear(&al_copy);
521 }
522 }
523
524done:
525 ARRAY_FREE(&mdata.ava);
526 FREE(&mdata.title);
527 FREE(&mdata.limit);
529 aliaslist_free(&al);
530 return 0;
531}
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:349
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:260
static bool dlg_query(struct Buffer *buf, struct AliasMenuData *mdata)
Get the user to enter an Address Query -.
Definition: dlg_query.c:397
#define mutt_warning(...)
Definition: logging2.h:90
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
#define TAILQ_NEXT(elm, field)
Definition: queue.h:832
struct AliasList * al
Alias data.
Definition: gui.h:54
+ 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 538 of file dlg_query.c.

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