NeoMutt  2025-12-11-1039-g550ac6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
address.h File Reference

Representation of an email address. More...

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

Go to the source code of this file.

Data Structures

struct  Address
 An email address. More...

Typedefs

typedef bool(* addr_predicate_t) (const struct Address *a)

Functions

 TAILQ_HEAD (AddressList, Address)
void mutt_addr_cat (char *buf, size_t buflen, const char *value, const char *specials)
 Copy a string and wrap it in quotes if it contains special characters.
bool mutt_addr_valid_msgid (const char *msgid)
 Is this a valid Message ID?
bool mutt_addr_cmp (const struct Address *a, const struct Address *b)
 Compare two e-mail addresses.
struct Addressmutt_addr_copy (const struct Address *addr)
 Copy the real address.
struct Addressmutt_addr_create (const char *personal, const char *mailbox)
 Create and populate a new Address.
const char * mutt_addr_for_display (const struct Address *a)
 Convert an Address for display purposes.
void mutt_addr_free (struct Address **ptr)
 Free a single Address.
struct Addressmutt_addr_new (void)
 Create a new Address.
bool mutt_addr_to_intl (struct Address *a)
 Convert an Address to Punycode.
bool mutt_addr_to_local (struct Address *a)
 Convert an Address from Punycode.
bool mutt_addr_uses_unicode (const char *str)
 Does this address use Unicode character.
size_t mutt_addr_write (struct Buffer *buf, struct Address *addr, bool display)
 Write a single Address to a buffer.
void mutt_addrlist_append (struct AddressList *al, struct Address *a)
 Append an Address to an AddressList.
void mutt_addrlist_clear (struct AddressList *al)
 Unlink and free all Address in an AddressList.
void mutt_addrlist_copy (struct AddressList *dst, const struct AddressList *src, bool prune)
 Copy a list of addresses into another list.
int mutt_addrlist_count_recips (const struct AddressList *al)
 Count the number of Addresses with valid recipients.
void mutt_addrlist_dedupe (struct AddressList *al)
 Remove duplicate addresses.
bool mutt_addrlist_equal (const struct AddressList *ala, const struct AddressList *alb)
 Compare two Address lists for equality.
int mutt_addrlist_parse (struct AddressList *al, const char *s)
 Parse a list of email addresses.
int mutt_addrlist_parse2 (struct AddressList *al, const char *s)
 Parse a list of email addresses.
void mutt_addrlist_prepend (struct AddressList *al, struct Address *a)
 Prepend an Address to an AddressList.
void mutt_addrlist_qualify (struct AddressList *al, const char *host)
 Expand local names in an Address list using a hostname.
int mutt_addrlist_remove (struct AddressList *al, const char *mailbox)
 Remove an Address from a list.
void mutt_addrlist_remove_xrefs (const struct AddressList *a, struct AddressList *b)
 Remove cross-references.
bool mutt_addrlist_search (const struct AddressList *haystack, const struct Address *needle)
 Search for an e-mail address in a list.
int mutt_addrlist_to_intl (struct AddressList *al, char **err)
 Convert an Address list to Punycode.
int mutt_addrlist_to_local (struct AddressList *al)
 Convert an Address list from Punycode.
bool mutt_addrlist_uses_unicode (const struct AddressList *al)
 Do any of a list of addresses use Unicode characters.
size_t mutt_addrlist_write (const struct AddressList *al, struct Buffer *buf, bool display)
 Write an Address to a buffer.
size_t mutt_addrlist_write_wrap (const struct AddressList *al, struct Buffer *buf, const char *header)
 Write an AddressList to a buffer, perform line wrapping.
void mutt_addrlist_write_file (const struct AddressList *al, FILE *fp, const char *header)
 Wrapper for mutt_write_address().
size_t mutt_addrlist_write_list (const struct AddressList *al, struct ListHead *list)
 Write Addresses to a List.

Variables

const char AddressSpecials []
 Characters with special meaning for email addresses.

Detailed Description

Representation of an email address.

Authors
  • Richard Russon
  • Pietro Cerutti

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 address.h.

Typedef Documentation

◆ addr_predicate_t

typedef bool(* addr_predicate_t) (const struct Address *a)

Definition at line 55 of file address.h.

Function Documentation

◆ TAILQ_HEAD()

TAILQ_HEAD ( AddressList ,
Address  )

◆ mutt_addr_cat()

void mutt_addr_cat ( char * buf,
size_t buflen,
const char * value,
const char * specials )

Copy a string and wrap it in quotes if it contains special characters.

Parameters
bufBuffer for the result
buflenLength of the result buffer
valueString to copy
specialsCharacters to lookup

This function copies the string in the "value" parameter in the buffer pointed to by "buf" parameter. If the input string contains any of the characters specified in the "specials" parameters, the output string is wrapped in double quoted. Additionally, any backslashes or quotes inside the input string are backslash-escaped.

Definition at line 715 of file address.c.

716{
717 if (!buf || !value || !specials)
718 return;
719
720 if (strpbrk(value, specials))
721 {
722 if (buflen < 4)
723 {
724 mutt_str_copy(buf, value, buflen);
725 return;
726 }
727
728 char *pc = buf;
729 size_t remaining = buflen - 3; // Reserve for opening quote, closing quote, NUL
730
731 *pc++ = '"';
732 for (; *value && (remaining > 1); value++)
733 {
734 if ((*value == '\\') || (*value == '"'))
735 {
736 *pc++ = '\\';
737 remaining--;
738 }
739 *pc++ = *value;
740 remaining--;
741 }
742 *pc++ = '"';
743 *pc = '\0';
744 }
745 else
746 {
747 mutt_str_copy(buf, value, buflen);
748 }
749}
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination).
Definition string.c:587
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addr_valid_msgid()

bool mutt_addr_valid_msgid ( const char * msgid)

Is this a valid Message ID?

Parameters
msgidMessage ID
Return values
trueIt is a valid message ID

Incomplete. Only used to thwart the APOP MD5 attack

Definition at line 803 of file address.c.

804{
805 /* msg-id = "<" addr-spec ">"
806 * addr-spec = local-part "@" domain
807 * local-part = word *("." word)
808 * word = atom / quoted-string
809 * atom = 1*<any CHAR except specials, SPACE and CTLs>
810 * CHAR = ( 0.-127. )
811 * specials = "(" / ")" / "<" / ">" / "@"
812 * / "," / ";" / ":" / "\" / <">
813 * / "." / "[" / "]"
814 * SPACE = ( 32. )
815 * CTLS = ( 0.-31., 127.)
816 * quoted-string = <"> *(qtext/quoted-pair) <">
817 * qtext = <any CHAR except <">, "\" and CR>
818 * CR = ( 13. )
819 * quoted-pair = "\" CHAR
820 * domain = sub-domain *("." sub-domain)
821 * sub-domain = domain-ref / domain-literal
822 * domain-ref = atom
823 * domain-literal = "[" *(dtext / quoted-pair) "]"
824 */
825
826 if (!msgid || (*msgid == '\0'))
827 return false;
828
829 size_t l = mutt_str_len(msgid);
830 if (l < 5) /* <atom@atom> */
831 return false;
832 if ((msgid[0] != '<') || (msgid[l - 1] != '>'))
833 return false;
834 if (!(strrchr(msgid, '@')))
835 return false;
836
837 /* TODO: complete parser */
838 for (size_t i = 0; i < l; i++)
839 if ((unsigned char) msgid[i] > 127)
840 return false;
841
842 return true;
843}
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addr_cmp()

bool mutt_addr_cmp ( const struct Address * a,
const struct Address * b )

Compare two e-mail addresses.

Parameters
aAddress 1
bAddress 2
Return values
trueThey are equivalent

Definition at line 903 of file address.c.

904{
905 if (!a || !b)
906 return false;
907 if (!a->mailbox || !b->mailbox)
908 return false;
909 if (!buf_istr_equal(a->mailbox, b->mailbox))
910 return false;
911 return true;
912}
bool buf_istr_equal(const struct Buffer *a, const struct Buffer *b)
Return if two buffers are equal, case insensitive.
Definition buffer.c:701
struct Buffer * mailbox
Mailbox and host address.
Definition address.h:37
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addr_copy()

struct Address * mutt_addr_copy ( const struct Address * addr)

Copy the real address.

Parameters
addrAddress to copy
Return values
ptrNew Address

Definition at line 756 of file address.c.

757{
758 if (!addr)
759 return NULL;
760
761 struct Address *p = mutt_addr_new();
762 p->personal = buf_dup(addr->personal);
763 p->mailbox = buf_dup(addr->mailbox);
764 p->group = addr->group;
765 p->is_intl = addr->is_intl;
766 p->intl_checked = addr->intl_checked;
767 return p;
768}
struct Address * mutt_addr_new(void)
Create a new Address.
Definition address.c:401
struct Buffer * buf_dup(const struct Buffer *buf)
Copy a Buffer into a new allocated buffer.
Definition buffer.c:592
An email address.
Definition address.h:35
struct Buffer * personal
Real name of address.
Definition address.h:36
bool group
Group mailbox?
Definition address.h:38
bool intl_checked
Checked for IDN?
Definition address.h:40
bool is_intl
International Domain Name.
Definition address.h:39
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addr_create()

struct Address * mutt_addr_create ( const char * personal,
const char * mailbox )

Create and populate a new Address.

Parameters
[in]personalThe personal name for the Address (can be NULL)
[in]mailboxThe mailbox for the Address (can be NULL)
Return values
ptrNewly allocated Address
Note
The personal and mailbox values, if not NULL, are going to be copied into the newly allocated Address.

Definition at line 414 of file address.c.

415{
416 struct Address *a = mutt_addr_new();
417 if (personal)
418 {
420 }
421 if (mailbox)
422 {
423 a->mailbox = buf_new(mailbox);
424 }
425 return a;
426}
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition buffer.c:311
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addr_for_display()

const char * mutt_addr_for_display ( const struct Address * a)

Convert an Address for display purposes.

Parameters
aAddress to convert
Return values
ptrAddress to display
Warning
This function may return a static pointer. It must not be freed by the caller. Later calls may overwrite the returned pointer.

Definition at line 1023 of file address.c.

1024{
1025 if (!a)
1026 return NULL;
1027
1028 char *user = NULL;
1029 char *domain = NULL;
1030 static char *buf = NULL;
1031
1032 if (!a->mailbox || addr_is_local(a))
1033 return buf_string(a->mailbox);
1034
1035 if (addr_mbox_to_udomain(buf_string(a->mailbox), &user, &domain) == -1)
1036 return buf_string(a->mailbox);
1037
1038 char *local_mailbox = mutt_idna_intl_to_local(user, domain, MI_MAY_BE_IRREVERSIBLE);
1039
1040 FREE(&user);
1041 FREE(&domain);
1042
1043 if (!local_mailbox)
1044 return buf_string(a->mailbox);
1045
1046 mutt_str_replace(&buf, local_mailbox);
1047 FREE(&local_mailbox);
1048
1049 return buf;
1050}
static int addr_mbox_to_udomain(const char *mbox, char **user, char **domain)
Split a mailbox name into user and domain.
Definition address.c:968
static bool addr_is_local(const struct Address *a)
Does the Address have NO IDN components.
Definition address.c:951
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
#define MI_MAY_BE_IRREVERSIBLE
Definition idna2.h:30
char * mutt_idna_intl_to_local(const char *user, const char *domain, uint8_t flags)
Convert an email's domain from Punycode.
Definition idna.c:117
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addr_free()

void mutt_addr_free ( struct Address ** ptr)

Free a single Address.

Parameters
[out]ptrAddress to free

Definition at line 463 of file address.c.

464{
465 if (!ptr || !*ptr)
466 return;
467
468 struct Address *a = *ptr;
469
470 buf_free(&a->personal);
471 buf_free(&a->mailbox);
472 FREE(ptr);
473}
void buf_free(struct Buffer **ptr)
Deallocates a buffer.
Definition buffer.c:326
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addr_new()

struct Address * mutt_addr_new ( void )

Create a new Address.

Return values
ptrNewly allocated Address

Free the result with mutt_addr_free()

Definition at line 401 of file address.c.

402{
403 return MUTT_MEM_CALLOC(1, struct Address);
404}
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
Here is the caller graph for this function:

◆ mutt_addr_to_intl()

bool mutt_addr_to_intl ( struct Address * a)

Convert an Address to Punycode.

Parameters
aAddress to convert
Return values
trueSuccess
falseOtherwise

Definition at line 1274 of file address.c.

1275{
1276 if (!a || !a->mailbox || addr_is_intl(a))
1277 return true;
1278
1279 char *user = NULL;
1280 char *domain = NULL;
1281 if (addr_mbox_to_udomain(buf_string(a->mailbox), &user, &domain) == -1)
1282 return true;
1283
1284 char *intl_mailbox = mutt_idna_local_to_intl(user, domain);
1285
1286 FREE(&user);
1287 FREE(&domain);
1288
1289 if (!intl_mailbox)
1290 return false;
1291
1292 addr_set_intl(a, intl_mailbox);
1293 FREE(&intl_mailbox);
1294 return true;
1295}
static bool addr_is_intl(const struct Address *a)
Does the Address have IDN components.
Definition address.c:939
static void addr_set_intl(struct Address *a, char *intl_mailbox)
Mark an Address as having IDN components.
Definition address.c:990
char * mutt_idna_local_to_intl(const char *user, const char *domain)
Convert an email's domain to Punycode.
Definition idna.c:228
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addr_to_local()

bool mutt_addr_to_local ( struct Address * a)

Convert an Address from Punycode.

Parameters
aAddress to convert
Return values
trueSuccess
falseOtherwise

Definition at line 1351 of file address.c.

1352{
1353 if (!a || !a->mailbox)
1354 {
1355 return false;
1356 }
1357
1358 if (addr_is_local(a))
1359 {
1360 return true;
1361 }
1362
1363 char *user = NULL;
1364 char *domain = NULL;
1365 if (addr_mbox_to_udomain(buf_string(a->mailbox), &user, &domain) == -1)
1366 {
1367 return false;
1368 }
1369
1370 char *local_mailbox = mutt_idna_intl_to_local(user, domain, MI_NONE);
1371 FREE(&user);
1372 FREE(&domain);
1373
1374 if (!local_mailbox)
1375 {
1376 return false;
1377 }
1378
1379 addr_set_local(a, local_mailbox);
1380 FREE(&local_mailbox);
1381 return true;
1382}
static void addr_set_local(struct Address *a, char *local_mailbox)
Mark an Address as having NO IDN components.
Definition address.c:1005
#define MI_NONE
Definition idna2.h:29
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addr_uses_unicode()

bool mutt_addr_uses_unicode ( const char * str)

Does this address use Unicode character.

Parameters
strAddress string to check
Return values
trueThe string uses 8-bit characters

Definition at line 1516 of file address.c.

1517{
1518 if (!str)
1519 return false;
1520
1521 while (*str)
1522 {
1523 if ((unsigned char) *str & (1 << 7))
1524 return true;
1525 str++;
1526 }
1527
1528 return false;
1529}
Here is the caller graph for this function:

◆ mutt_addr_write()

size_t mutt_addr_write ( struct Buffer * buf,
struct Address * addr,
bool display )

Write a single Address to a buffer.

Parameters
bufBuffer for the Address
addrAddress to display
displayThis address will be displayed to the user
Return values
numLength of the string written to buf

If 'display' is set, then it doesn't matter if the transformation isn't reversible.

Definition at line 1062 of file address.c.

1063{
1064 if (!buf || !addr || (!addr->personal && !addr->mailbox))
1065 {
1066 return 0;
1067 }
1068
1069 const size_t initial_len = buf_len(buf);
1070
1071 if (addr->personal)
1072 {
1073 if (strpbrk(buf_string(addr->personal), AddressSpecials) ||
1075 {
1076 buf_addch(buf, '"');
1077 for (const char *pc = buf_string(addr->personal); *pc; pc++)
1078 {
1079 if ((*pc == '"') || (*pc == '\\'))
1080 {
1081 buf_addch(buf, '\\');
1082 }
1083 buf_addch(buf, *pc);
1084 }
1085 buf_addch(buf, '"');
1086 }
1087 else
1088 {
1089 buf_addstr(buf, buf_string(addr->personal));
1090 }
1091
1092 buf_addch(buf, ' ');
1093 }
1094
1095 if (addr->personal || (addr->mailbox && (buf_at(addr->mailbox, 0) == '@')))
1096 {
1097 buf_addch(buf, '<');
1098 }
1099
1100 if (addr->mailbox)
1101 {
1102 if (!mutt_str_equal(buf_string(addr->mailbox), "@"))
1103 {
1104 const char *a = display ? mutt_addr_for_display(addr) : buf_string(addr->mailbox);
1105 buf_addstr(buf, a);
1106 }
1107
1108 if (addr->personal || (addr->mailbox && (buf_at(addr->mailbox, 0) == '@')))
1109 {
1110 buf_addch(buf, '>');
1111 }
1112
1113 if (addr->group)
1114 {
1115 buf_addstr(buf, ": ");
1116 }
1117 }
1118 else
1119 {
1120 buf_addch(buf, ';');
1121 }
1122
1123 return buf_len(buf) - initial_len;
1124}
bool mutt_addr_uses_unicode(const char *str)
Does this address use Unicode character.
Definition address.c:1516
const char AddressSpecials[]
Characters with special meaning for email addresses.
Definition address.c:45
const char * mutt_addr_for_display(const struct Address *a)
Convert an Address for display purposes.
Definition address.c:1023
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:497
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition buffer.c:674
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:248
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:233
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_append()

void mutt_addrlist_append ( struct AddressList * al,
struct Address * a )

Append an Address to an AddressList.

Parameters
alAddressList
aAddress

Definition at line 1494 of file address.c.

1495{
1496 if (al && a)
1497 TAILQ_INSERT_TAIL(al, a, entries);
1498}
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition queue.h:866
Here is the caller graph for this function:

◆ mutt_addrlist_clear()

void mutt_addrlist_clear ( struct AddressList * al)

Unlink and free all Address in an AddressList.

Parameters
alAddressList
Note
After this call, the AddressList is reinitialized and ready for reuse.

Definition at line 1473 of file address.c.

1474{
1475 if (!al)
1476 return;
1477
1478 struct Address *a = TAILQ_FIRST(al);
1479 struct Address *next = NULL;
1480 while (a)
1481 {
1482 next = TAILQ_NEXT(a, entries);
1483 mutt_addr_free(&a);
1484 a = next;
1485 }
1486 TAILQ_INIT(al);
1487}
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition address.c:463
#define TAILQ_INIT(head)
Definition queue.h:822
#define TAILQ_FIRST(head)
Definition queue.h:780
#define TAILQ_NEXT(elm, field)
Definition queue.h:889
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_copy()

void mutt_addrlist_copy ( struct AddressList * dst,
const struct AddressList * src,
bool prune )

Copy a list of addresses into another list.

Parameters
dstDestination Address list
srcSource Address list
pruneSkip groups if there are more addresses

Definition at line 776 of file address.c.

777{
778 if (!dst || !src)
779 return;
780
781 struct Address *a = NULL;
782 TAILQ_FOREACH(a, src, entries)
783 {
784 struct Address *next = TAILQ_NEXT(a, entries);
785 if (prune && a->group && (!next || !next->mailbox))
786 {
787 /* ignore this element of the list */
788 }
789 else
790 {
792 }
793 }
794}
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition address.c:1494
struct Address * mutt_addr_copy(const struct Address *addr)
Copy the real address.
Definition address.c:756
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:782
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_count_recips()

int mutt_addrlist_count_recips ( const struct AddressList * al)

Count the number of Addresses with valid recipients.

Parameters
alAddress list
Return values
numNumber of valid Addresses

An Address has a recipient if the mailbox is set and is not a group

Definition at line 883 of file address.c.

884{
885 if (!al)
886 return 0;
887
888 int c = 0;
889 struct Address *a = NULL;
890 TAILQ_FOREACH(a, al, entries)
891 {
892 c += (a->mailbox && !a->group);
893 }
894 return c;
895}
Here is the caller graph for this function:

◆ mutt_addrlist_dedupe()

void mutt_addrlist_dedupe ( struct AddressList * al)

Remove duplicate addresses.

Parameters
alAddress list to de-dupe

Given a list of addresses, return a list of unique addresses

Definition at line 1408 of file address.c.

1409{
1410 if (!al)
1411 return;
1412
1413 struct Address *a = NULL;
1414 TAILQ_FOREACH(a, al, entries)
1415 {
1416 if (a->mailbox)
1417 {
1418 struct Address *a2 = TAILQ_NEXT(a, entries);
1419 struct Address *tmp = NULL;
1420
1421 if (a2)
1422 {
1423 TAILQ_FOREACH_FROM_SAFE(a2, al, entries, tmp)
1424 {
1425 if (a2->mailbox && buf_istr_equal(a->mailbox, a2->mailbox))
1426 {
1427 mutt_debug(LL_DEBUG2, "Removing %s\n", buf_string(a2->mailbox));
1428 TAILQ_REMOVE(al, a2, entries);
1429 mutt_addr_free(&a2);
1430 }
1431 }
1432 }
1433 }
1434 }
1435}
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:46
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar)
Definition queue.h:797
#define TAILQ_REMOVE(head, elm, field)
Definition queue.h:901
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_equal()

bool mutt_addrlist_equal ( const struct AddressList * ala,
const struct AddressList * alb )

Compare two Address lists for equality.

Parameters
alaFirst Address
albSecond Address
Return values
trueAddress lists are strictly identical

Definition at line 851 of file address.c.

852{
853 if (!ala || !alb)
854 {
855 return !(ala || alb);
856 }
857
858 struct Address *ana = TAILQ_FIRST(ala);
859 struct Address *anb = TAILQ_FIRST(alb);
860
861 while (ana && anb)
862 {
863 if (!buf_str_equal(ana->mailbox, anb->mailbox) ||
864 !buf_str_equal(ana->personal, anb->personal))
865 {
866 break;
867 }
868
869 ana = TAILQ_NEXT(ana, entries);
870 anb = TAILQ_NEXT(anb, entries);
871 }
872
873 return !(ana || anb);
874}
bool buf_str_equal(const struct Buffer *a, const struct Buffer *b)
Return if two buffers are equal.
Definition buffer.c:689
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_parse()

int mutt_addrlist_parse ( struct AddressList * al,
const char * s )

Parse a list of email addresses.

Parameters
alAddressList to append addresses
sString to parse
Return values
numNumber of parsed addresses

Definition at line 481 of file address.c.

482{
483 if (!s)
484 return 0;
485
486 int parsed = 0;
487 char comment[1024] = { 0 };
488 char phrase[1024] = { 0 };
489 size_t phraselen = 0;
490 size_t commentlen = 0;
491
492 bool ws_pending = mutt_str_is_email_wsp(*s);
493
494 /* Parse the address string character by character, handling RFC 2822
495 * constructs: quoted strings, comments, route-addr, group syntax */
497 while (*s)
498 {
499 switch (*s)
500 {
501 case ';':
502 case ',':
503 /* Address separator: convert accumulated phrase into an address */
504 if (phraselen != 0)
505 {
506 terminate_buffer(phrase, phraselen);
507 if (add_addrspec(al, phrase, comment, &commentlen, sizeof(comment) - 1))
508 {
509 parsed++;
510 }
511 }
512 else if (commentlen != 0)
513 {
514 struct Address *last = TAILQ_LAST(al, AddressList);
515 if (last && !last->personal && !buf_is_empty(last->mailbox))
516 {
517 terminate_buffer(comment, commentlen);
518 last->personal = buf_new(comment);
519 }
520 }
521
522 if (*s == ';')
523 {
524 /* add group terminator */
526 }
527
528 phraselen = 0;
529 commentlen = 0;
530 s++;
531 break;
532
533 case '(':
534 /* RFC 822 comment in parentheses */
535 if ((commentlen != 0) && (commentlen < (sizeof(comment) - 1)))
536 comment[commentlen++] = ' ';
537 s = next_token(s, comment, &commentlen, sizeof(comment) - 1);
538 if (!s)
539 {
541 return 0;
542 }
543 break;
544
545 case '"':
546 if ((phraselen != 0) && (phraselen < (sizeof(phrase) - 1)))
547 phrase[phraselen++] = ' ';
548 s = parse_quote(s + 1, phrase, &phraselen, sizeof(phrase) - 1);
549 if (!s)
550 {
552 return 0;
553 }
554 break;
555
556 case ':':
557 {
558 struct Address *a = mutt_addr_new();
559 terminate_buffer(phrase, phraselen);
560 if (phraselen != 0)
561 {
562 a->mailbox = buf_new(phrase);
563 }
564 a->group = true;
566 phraselen = 0;
567 commentlen = 0;
568 s++;
569 break;
570 }
571
572 case '<':
573 {
574 /* Route-addr: phrase before '<' becomes personal name */
575 struct Address *a = mutt_addr_new();
576 terminate_buffer(phrase, phraselen);
577 if (phraselen != 0)
578 {
579 a->personal = buf_new(phrase);
580 }
581 s = parse_route_addr(s + 1, comment, &commentlen, sizeof(comment) - 1, a);
582 if (!s)
583 {
585 mutt_addr_free(&a);
586 return 0;
587 }
589 phraselen = 0;
590 commentlen = 0;
591 parsed++;
592 break;
593 }
594
595 default:
596 if ((phraselen != 0) && (phraselen < (sizeof(phrase) - 1)) && ws_pending)
597 phrase[phraselen++] = ' ';
598 if (*s == '\\')
599 {
600 s++;
601 if (*s && (phraselen < (sizeof(phrase) - 1)))
602 {
603 phrase[phraselen++] = *s;
604 s++;
605 }
606 }
607 s = next_token(s, phrase, &phraselen, sizeof(phrase) - 1);
608 if (!s)
609 {
611 return 0;
612 }
613 break;
614 } // switch (*s)
615
616 ws_pending = mutt_str_is_email_wsp(*s);
618 } // while (*s)
619
620 if (phraselen != 0)
621 {
622 terminate_buffer(phrase, phraselen);
623 terminate_buffer(comment, commentlen);
624 if (add_addrspec(al, phrase, comment, &commentlen, sizeof(comment) - 1))
625 {
626 parsed++;
627 }
628 }
629 else if (commentlen != 0)
630 {
631 struct Address *last = TAILQ_LAST(al, AddressList);
632 if (last && !last->personal && !buf_is_empty(last->mailbox))
633 {
634 terminate_buffer(comment, commentlen);
635 last->personal = buf_new(comment);
636 }
637 }
638
639 return parsed;
640}
static bool add_addrspec(struct AddressList *al, const char *phrase, char *comment, size_t *commentlen, size_t commentmax)
Parse an email address and add an Address to a list.
Definition address.c:380
static const char * parse_route_addr(const char *s, char *comment, size_t *commentlen, size_t commentmax, struct Address *addr)
Parse an email addresses.
Definition address.c:300
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1473
static const char * next_token(const char *s, char *token, size_t *tokenlen, size_t tokenmax)
Find the next word, skipping quoted and parenthesised text.
Definition address.c:166
static const char * parse_quote(const char *s, char *token, size_t *tokenlen, size_t tokenmax)
Extract a quoted string.
Definition address.c:134
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:298
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition string.c:614
#define TAILQ_LAST(head, headname)
Definition queue.h:876
#define terminate_buffer(str, strlen)
Definition string2.h:59
static bool mutt_str_is_email_wsp(char c)
Is this a whitespace character (for an email header).
Definition string2.h:111
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_parse2()

int mutt_addrlist_parse2 ( struct AddressList * al,
const char * s )

Parse a list of email addresses.

Parameters
alAdd to this List of Addresses
sString to parse
Return values
numNumber of parsed addresses

Simple email addresses (without any personal name or grouping) can be separated by whitespace or commas.

Definition at line 651 of file address.c.

652{
653 if (!s || (*s == '\0'))
654 return 0;
655
656 int parsed = 0;
657
658 /* check for a simple whitespace separated list of addresses */
659 if (!strpbrk(s, "\"<>():;,\\"))
660 {
661 char *copy = mutt_str_dup(s);
662 char *r = copy;
663 while ((r = strtok(r, " \t")))
664 {
665 parsed += mutt_addrlist_parse(al, r);
666 r = NULL;
667 }
668 FREE(&copy);
669 }
670 else
671 {
672 parsed = mutt_addrlist_parse(al, s);
673 }
674
675 return parsed;
676}
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition address.c:481
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_prepend()

void mutt_addrlist_prepend ( struct AddressList * al,
struct Address * a )

Prepend an Address to an AddressList.

Parameters
alAddressList
aAddress

Definition at line 1505 of file address.c.

1506{
1507 if (al && a)
1508 TAILQ_INSERT_HEAD(al, a, entries);
1509}
#define TAILQ_INSERT_HEAD(head, elm, field)
Definition queue.h:853
Here is the caller graph for this function:

◆ mutt_addrlist_qualify()

void mutt_addrlist_qualify ( struct AddressList * al,
const char * host )

Expand local names in an Address list using a hostname.

Parameters
alAddress list
hostHostname

Any addresses containing a bare name will be expanded using the hostname. e.g. "john", "example.com" -> 'john@.nosp@m.exam.nosp@m.ple.c.nosp@m.om'. This function has no effect if host is NULL or the empty string.

Definition at line 687 of file address.c.

688{
689 if (!al || !host || (*host == '\0'))
690 return;
691
692 struct Address *a = NULL;
693 TAILQ_FOREACH(a, al, entries)
694 {
695 if (!a->group && a->mailbox && !buf_find_char(a->mailbox, '@'))
696 {
697 buf_add_printf(a->mailbox, "@%s", host);
698 }
699 }
700}
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition buffer.c:211
const char * buf_find_char(const struct Buffer *buf, const char c)
Return a pointer to a char found in the buffer.
Definition buffer.c:659
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_remove()

int mutt_addrlist_remove ( struct AddressList * al,
const char * mailbox )

Remove an Address from a list.

Parameters
[in,out]alAddressList
[in]mailboxEmail address to match
Return values
0Success
-1Error, or email not found

Definition at line 435 of file address.c.

436{
437 if (!al)
438 return -1;
439
440 if (!mailbox)
441 return 0;
442
443 int rc = -1;
444 struct Address *a = NULL;
445 struct Address *tmp = NULL;
446 TAILQ_FOREACH_SAFE(a, al, entries, tmp)
447 {
449 {
450 TAILQ_REMOVE(al, a, entries);
451 mutt_addr_free(&a);
452 rc = 0;
453 }
454 }
455
456 return rc;
457}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:678
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition queue.h:792
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_remove_xrefs()

void mutt_addrlist_remove_xrefs ( const struct AddressList * a,
struct AddressList * b )

Remove cross-references.

Parameters
aReference AddressList
bAddressLis to trim

Remove addresses from "b" which are contained in "a"

Definition at line 1444 of file address.c.

1445{
1446 if (!a || !b)
1447 return;
1448
1449 struct Address *aa = NULL;
1450 struct Address *ab = NULL;
1451 struct Address *tmp = NULL;
1452
1453 TAILQ_FOREACH_SAFE(ab, b, entries, tmp)
1454 {
1455 TAILQ_FOREACH(aa, a, entries)
1456 {
1457 if (mutt_addr_cmp(aa, ab))
1458 {
1459 TAILQ_REMOVE(b, ab, entries);
1460 mutt_addr_free(&ab);
1461 break;
1462 }
1463 }
1464 }
1465}
bool mutt_addr_cmp(const struct Address *a, const struct Address *b)
Compare two e-mail addresses.
Definition address.c:903
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_search()

bool mutt_addrlist_search ( const struct AddressList * haystack,
const struct Address * needle )

Search for an e-mail address in a list.

Parameters
haystackAddress List
needleAddress containing the search email
Return values
trueThe Address is in the list

Definition at line 920 of file address.c.

921{
922 if (!needle || !haystack)
923 return false;
924
925 struct Address *a = NULL;
926 TAILQ_FOREACH(a, haystack, entries)
927 {
928 if (mutt_addr_cmp(needle, a))
929 return true;
930 }
931 return false;
932}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_to_intl()

int mutt_addrlist_to_intl ( struct AddressList * al,
char ** err )

Convert an Address list to Punycode.

Parameters
[in]alAddress list to modify
[out]errPointer for failed addresses
Return values
0Success, all addresses converted
-1Error, err will be set to the failed address

Definition at line 1304 of file address.c.

1305{
1306 if (!al)
1307 return 0;
1308
1309 int rc = 0;
1310
1311 if (err)
1312 *err = NULL;
1313
1314 struct Address *a = NULL;
1315 TAILQ_FOREACH(a, al, entries)
1316 {
1317 if (!a->mailbox || addr_is_intl(a))
1318 continue;
1319
1320 char *user = NULL;
1321 char *domain = NULL;
1322 if (addr_mbox_to_udomain(buf_string(a->mailbox), &user, &domain) == -1)
1323 continue;
1324
1325 char *intl_mailbox = mutt_idna_local_to_intl(user, domain);
1326
1327 FREE(&user);
1328 FREE(&domain);
1329
1330 if (!intl_mailbox)
1331 {
1332 rc = -1;
1333 if (err && !*err)
1334 *err = buf_strdup(a->mailbox);
1335 continue;
1336 }
1337
1338 addr_set_intl(a, intl_mailbox);
1339 FREE(&intl_mailbox);
1340 }
1341
1342 return rc;
1343}
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:577
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_to_local()

int mutt_addrlist_to_local ( struct AddressList * al)

Convert an Address list from Punycode.

Parameters
alAddress list to modify
Return values
0Always

Definition at line 1389 of file address.c.

1390{
1391 if (!al)
1392 return 0;
1393
1394 struct Address *a = NULL;
1395 TAILQ_FOREACH(a, al, entries)
1396 {
1398 }
1399 return 0;
1400}
bool mutt_addr_to_local(struct Address *a)
Convert an Address from Punycode.
Definition address.c:1351
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_uses_unicode()

bool mutt_addrlist_uses_unicode ( const struct AddressList * al)

Do any of a list of addresses use Unicode characters.

Parameters
alAddress list to check
Return values
trueAny use 8-bit characters

Definition at line 1536 of file address.c.

1537{
1538 if (!al)
1539 {
1540 return false;
1541 }
1542
1543 struct Address *a = NULL;
1544 TAILQ_FOREACH(a, al, entries)
1545 {
1547 return true;
1548 }
1549 return false;
1550}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_write()

size_t mutt_addrlist_write ( const struct AddressList * al,
struct Buffer * buf,
bool display )

Write an Address to a buffer.

Parameters
alAddressList to display
bufBuffer for the Address
displayThis address will be displayed to the user
Return values
numLength of the string written to buf

If 'display' is set, then it doesn't matter if the transformation isn't reversible.

Definition at line 1217 of file address.c.

1218{
1219 return addrlist_write(al, buf, display, NULL, -1);
1220}
static size_t addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display, const char *header, int cols)
Write an AddressList to a buffer, optionally perform line wrapping and display conversion.
Definition address.c:1138
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_write_wrap()

size_t mutt_addrlist_write_wrap ( const struct AddressList * al,
struct Buffer * buf,
const char * header )

Write an AddressList to a buffer, perform line wrapping.

Parameters
alAddressList to display
bufBuffer for the Address
headerHeader name; if present, addresses we be written after ": "
Return values
numLength of the string written to buf

Definition at line 1201 of file address.c.

1203{
1204 return addrlist_write(al, buf, false, header, 74);
1205}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_write_file()

void mutt_addrlist_write_file ( const struct AddressList * al,
FILE * fp,
const char * header )

Wrapper for mutt_write_address().

Parameters
alAddress list
fpFile to write to
headerHeader name; if present, addresses we be written after ": "

So we can handle very large recipient lists without needing a huge temporary buffer in memory

Definition at line 1259 of file address.c.

1260{
1261 struct Buffer *buf = buf_pool_get();
1262 mutt_addrlist_write_wrap(al, buf, header);
1263 fputs(buf_string(buf), fp);
1264 buf_pool_release(&buf);
1265 fputc('\n', fp);
1266}
size_t mutt_addrlist_write_wrap(const struct AddressList *al, struct Buffer *buf, const char *header)
Write an AddressList to a buffer, perform line wrapping.
Definition address.c:1201
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
String manipulation buffer.
Definition buffer.h:36
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_addrlist_write_list()

size_t mutt_addrlist_write_list ( const struct AddressList * al,
struct ListHead * list )

Write Addresses to a List.

Parameters
alAddressList to write
listList for the Addresses
Return values
numNumber of addresses written

Definition at line 1228 of file address.c.

1229{
1230 if (!al || !list)
1231 return 0;
1232
1233 size_t count = 0;
1234 struct Address *a = NULL;
1235 TAILQ_FOREACH(a, al, entries)
1236 {
1237 struct Buffer buf = { 0 };
1238 mutt_addr_write(&buf, a, true);
1239 if (!buf_is_empty(&buf))
1240 {
1241 /* We're taking the ownership of the buffer string here */
1242 mutt_list_insert_tail(list, (char *) buf_string(&buf));
1243 count++;
1244 }
1245 }
1246
1247 return count;
1248}
size_t mutt_addr_write(struct Buffer *buf, struct Address *addr, bool display)
Write a single Address to a buffer.
Definition address.c:1062
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition list.c:65
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ AddressSpecials

const char AddressSpecials[]
extern

Characters with special meaning for email addresses.

Definition at line 45 of file address.c.