NeoMutt  2024-04-25-1-g3de005
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
address.h File Reference

Representation of an email address. More...

#include <stddef.h>
#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 56 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 708 of file address.c.

709{
710 if (!buf || !value || !specials)
711 return;
712
713 if (strpbrk(value, specials))
714 {
715 char tmp[256] = { 0 };
716 char *pc = tmp;
717 size_t tmplen = sizeof(tmp) - 3;
718
719 *pc++ = '"';
720 for (; *value && (tmplen > 1); value++)
721 {
722 if ((*value == '\\') || (*value == '"'))
723 {
724 *pc++ = '\\';
725 tmplen--;
726 }
727 *pc++ = *value;
728 tmplen--;
729 }
730 *pc++ = '"';
731 *pc = '\0';
732 mutt_str_copy(buf, tmp, buflen);
733 }
734 else
735 {
736 mutt_str_copy(buf, value, buflen);
737 }
738}
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:575
+ 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 792 of file address.c.

793{
794 /* msg-id = "<" addr-spec ">"
795 * addr-spec = local-part "@" domain
796 * local-part = word *("." word)
797 * word = atom / quoted-string
798 * atom = 1*<any CHAR except specials, SPACE and CTLs>
799 * CHAR = ( 0.-127. )
800 * specials = "(" / ")" / "<" / ">" / "@"
801 * / "," / ";" / ":" / "\" / <">
802 * / "." / "[" / "]"
803 * SPACE = ( 32. )
804 * CTLS = ( 0.-31., 127.)
805 * quoted-string = <"> *(qtext/quoted-pair) <">
806 * qtext = <any CHAR except <">, "\" and CR>
807 * CR = ( 13. )
808 * quoted-pair = "\" CHAR
809 * domain = sub-domain *("." sub-domain)
810 * sub-domain = domain-ref / domain-literal
811 * domain-ref = atom
812 * domain-literal = "[" *(dtext / quoted-pair) "]"
813 */
814
815 if (!msgid || (*msgid == '\0'))
816 return false;
817
818 size_t l = mutt_str_len(msgid);
819 if (l < 5) /* <atom@atom> */
820 return false;
821 if ((msgid[0] != '<') || (msgid[l - 1] != '>'))
822 return false;
823 if (!(strrchr(msgid, '@')))
824 return false;
825
826 /* TODO: complete parser */
827 for (size_t i = 0; i < l; i++)
828 if ((unsigned char) msgid[i] > 127)
829 return false;
830
831 return true;
832}
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:490
+ 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 892 of file address.c.

893{
894 if (!a || !b)
895 return false;
896 if (!a->mailbox || !b->mailbox)
897 return false;
898 if (!buf_istr_equal(a->mailbox, b->mailbox))
899 return false;
900 return true;
901}
bool buf_istr_equal(const struct Buffer *a, const struct Buffer *b)
Return if two buffers are equal, case insensitive.
Definition: buffer.c:696
struct Buffer * mailbox
Mailbox and host address.
Definition: address.h:38
+ 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 745 of file address.c.

746{
747 if (!addr)
748 return NULL;
749
750 struct Address *p = mutt_addr_new();
751 p->personal = buf_dup(addr->personal);
752 p->mailbox = buf_dup(addr->mailbox);
753 p->group = addr->group;
754 p->is_intl = addr->is_intl;
755 p->intl_checked = addr->intl_checked;
756 return p;
757}
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:585
An email address.
Definition: address.h:36
struct Buffer * personal
Real name of address.
Definition: address.h:37
bool group
Group mailbox?
Definition: address.h:39
bool intl_checked
Checked for IDN?
Definition: address.h:41
bool is_intl
International Domain Name.
Definition: address.h:40
+ 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:303
+ 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 1012 of file address.c.

1013{
1014 if (!a)
1015 return NULL;
1016
1017 char *user = NULL, *domain = NULL;
1018 static char *buf = NULL;
1019
1020 if (!a->mailbox || addr_is_local(a))
1021 return buf_string(a->mailbox);
1022
1023 if (addr_mbox_to_udomain(buf_string(a->mailbox), &user, &domain) == -1)
1024 return buf_string(a->mailbox);
1025
1026 char *local_mailbox = mutt_idna_intl_to_local(user, domain, MI_MAY_BE_IRREVERSIBLE);
1027
1028 FREE(&user);
1029 FREE(&domain);
1030
1031 if (!local_mailbox)
1032 return buf_string(a->mailbox);
1033
1034 mutt_str_replace(&buf, local_mailbox);
1035 FREE(&local_mailbox);
1036
1037 return buf;
1038}
static int addr_mbox_to_udomain(const char *mbox, char **user, char **domain)
Split a mailbox name into user and domain.
Definition: address.c:957
static bool addr_is_local(const struct Address *a)
Does the Address have NO IDN components.
Definition: address.c:940
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)
Definition: memory.h:45
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:274
+ 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 462 of file address.c.

463{
464 if (!ptr || !*ptr)
465 return;
466
467 struct Address *a = *ptr;
468
469 buf_free(&a->personal);
470 buf_free(&a->mailbox);
471 FREE(ptr);
472}
void buf_free(struct Buffer **ptr)
Deallocates a buffer.
Definition: buffer.c:318
+ 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, sizeof(struct Address));
404}
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
+ Here is the call graph for this function:
+ 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 1263 of file address.c.

1264{
1265 if (!a || !a->mailbox || addr_is_intl(a))
1266 return true;
1267
1268 char *user = NULL;
1269 char *domain = NULL;
1270 if (addr_mbox_to_udomain(buf_string(a->mailbox), &user, &domain) == -1)
1271 return true;
1272
1273 char *intl_mailbox = mutt_idna_local_to_intl(user, domain);
1274
1275 FREE(&user);
1276 FREE(&domain);
1277
1278 if (!intl_mailbox)
1279 return false;
1280
1281 addr_set_intl(a, intl_mailbox);
1282 FREE(&intl_mailbox);
1283 return true;
1284}
static bool addr_is_intl(const struct Address *a)
Does the Address have IDN components.
Definition: address.c:928
static void addr_set_intl(struct Address *a, char *intl_mailbox)
Mark an Address as having IDN components.
Definition: address.c:979
char * mutt_idna_local_to_intl(const char *user, const char *domain)
Convert an email's domain to Punycode.
Definition: idna.c:227
+ 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 1340 of file address.c.

1341{
1342 if (!a->mailbox)
1343 {
1344 return false;
1345 }
1346
1347 if (addr_is_local(a))
1348 {
1349 return true;
1350 }
1351
1352 char *user = NULL;
1353 char *domain = NULL;
1354 if (addr_mbox_to_udomain(buf_string(a->mailbox), &user, &domain) == -1)
1355 {
1356 return false;
1357 }
1358
1359 char *local_mailbox = mutt_idna_intl_to_local(user, domain, MI_NO_FLAGS);
1360 FREE(&user);
1361 FREE(&domain);
1362
1363 if (!local_mailbox)
1364 {
1365 return false;
1366 }
1367
1368 addr_set_local(a, local_mailbox);
1369 FREE(&local_mailbox);
1370 return true;
1371}
static void addr_set_local(struct Address *a, char *local_mailbox)
Mark an Address as having NO IDN components.
Definition: address.c:994
#define MI_NO_FLAGS
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 1502 of file address.c.

1503{
1504 if (!str)
1505 return false;
1506
1507 while (*str)
1508 {
1509 if ((unsigned char) *str & (1 << 7))
1510 return true;
1511 str++;
1512 }
1513
1514 return false;
1515}
+ 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 1050 of file address.c.

1051{
1052 if (!buf || !addr || (!addr->personal && !addr->mailbox))
1053 {
1054 return 0;
1055 }
1056
1057 const size_t initial_len = buf_len(buf);
1058
1059 if (addr->personal)
1060 {
1061 if (strpbrk(buf_string(addr->personal), AddressSpecials))
1062 {
1063 buf_addch(buf, '"');
1064 for (const char *pc = buf_string(addr->personal); *pc; pc++)
1065 {
1066 if ((*pc == '"') || (*pc == '\\'))
1067 {
1068 buf_addch(buf, '\\');
1069 }
1070 buf_addch(buf, *pc);
1071 }
1072 buf_addch(buf, '"');
1073 }
1074 else
1075 {
1076 buf_addstr(buf, buf_string(addr->personal));
1077 }
1078
1079 buf_addch(buf, ' ');
1080 }
1081
1082 if (addr->personal || (addr->mailbox && (buf_at(addr->mailbox, 0) == '@')))
1083 {
1084 buf_addch(buf, '<');
1085 }
1086
1087 if (addr->mailbox)
1088 {
1089 if (!mutt_str_equal(buf_string(addr->mailbox), "@"))
1090 {
1091 const char *a = display ? mutt_addr_for_display(addr) : buf_string(addr->mailbox);
1092 buf_addstr(buf, a);
1093 }
1094
1095 if (addr->personal || (addr->mailbox && (buf_at(addr->mailbox, 0) == '@')))
1096 {
1097 buf_addch(buf, '>');
1098 }
1099
1100 if (addr->group)
1101 {
1102 buf_addstr(buf, ": ");
1103 }
1104 }
1105 else
1106 {
1107 buf_addch(buf, ';');
1108 }
1109
1110 return buf_len(buf) - initial_len;
1111}
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:1012
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:490
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition: buffer.c:669
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:654
+ 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 1480 of file address.c.

1481{
1482 if (al && a)
1483 TAILQ_INSERT_TAIL(al, a, entries);
1484}
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:809
+ 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 1460 of file address.c.

1461{
1462 if (!al)
1463 return;
1464
1465 struct Address *a = TAILQ_FIRST(al), *next = NULL;
1466 while (a)
1467 {
1468 next = TAILQ_NEXT(a, entries);
1469 mutt_addr_free(&a);
1470 a = next;
1471 }
1472 TAILQ_INIT(al);
1473}
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:462
#define TAILQ_INIT(head)
Definition: queue.h:765
#define TAILQ_FIRST(head)
Definition: queue.h:723
#define TAILQ_NEXT(elm, field)
Definition: queue.h:832
+ 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 765 of file address.c.

766{
767 if (!dst || !src)
768 return;
769
770 struct Address *a = NULL;
771 TAILQ_FOREACH(a, src, entries)
772 {
773 struct Address *next = TAILQ_NEXT(a, entries);
774 if (prune && a->group && (!next || !next->mailbox))
775 {
776 /* ignore this element of the list */
777 }
778 else
779 {
781 }
782 }
783}
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1480
struct Address * mutt_addr_copy(const struct Address *addr)
Copy the real address.
Definition: address.c:745
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
+ 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 872 of file address.c.

873{
874 if (!al)
875 return 0;
876
877 int c = 0;
878 struct Address *a = NULL;
879 TAILQ_FOREACH(a, al, entries)
880 {
881 c += (a->mailbox && !a->group);
882 }
883 return c;
884}
+ 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 1397 of file address.c.

1398{
1399 if (!al)
1400 return;
1401
1402 struct Address *a = NULL;
1403 TAILQ_FOREACH(a, al, entries)
1404 {
1405 if (a->mailbox)
1406 {
1407 struct Address *a2 = TAILQ_NEXT(a, entries);
1408 struct Address *tmp = NULL;
1409
1410 if (a2)
1411 {
1412 TAILQ_FOREACH_FROM_SAFE(a2, al, entries, tmp)
1413 {
1414 if (a2->mailbox && buf_istr_equal(a->mailbox, a2->mailbox))
1415 {
1416 mutt_debug(LL_DEBUG2, "Removing %s\n", buf_string(a2->mailbox));
1417 TAILQ_REMOVE(al, a2, entries);
1418 mutt_addr_free(&a2);
1419 }
1420 }
1421 }
1422 }
1423 }
1424}
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar)
Definition: queue.h:740
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:841
+ 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 840 of file address.c.

841{
842 if (!ala || !alb)
843 {
844 return !(ala || alb);
845 }
846
847 struct Address *ana = TAILQ_FIRST(ala);
848 struct Address *anb = TAILQ_FIRST(alb);
849
850 while (ana && anb)
851 {
852 if (!buf_str_equal(ana->mailbox, anb->mailbox) ||
853 !buf_str_equal(ana->personal, anb->personal))
854 {
855 break;
856 }
857
858 ana = TAILQ_NEXT(ana, entries);
859 anb = TAILQ_NEXT(anb, entries);
860 }
861
862 return !(ana || anb);
863}
bool buf_str_equal(const struct Buffer *a, const struct Buffer *b)
Return if two buffers are equal.
Definition: buffer.c:684
+ 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 480 of file address.c.

481{
482 if (!s)
483 return 0;
484
485 int parsed = 0;
486 char comment[1024] = { 0 };
487 char phrase[1024] = { 0 };
488 size_t phraselen = 0, commentlen = 0;
489
490 bool ws_pending = mutt_str_is_email_wsp(*s);
491
493 while (*s)
494 {
495 switch (*s)
496 {
497 case ';':
498 case ',':
499 if (phraselen != 0)
500 {
501 terminate_buffer(phrase, phraselen);
502 if (add_addrspec(al, phrase, comment, &commentlen, sizeof(comment) - 1))
503 {
504 parsed++;
505 }
506 }
507 else if (commentlen != 0)
508 {
509 struct Address *last = TAILQ_LAST(al, AddressList);
510 if (last && !last->personal && !buf_is_empty(last->mailbox))
511 {
512 terminate_buffer(comment, commentlen);
513 last->personal = buf_new(comment);
514 }
515 }
516
517 if (*s == ';')
518 {
519 /* add group terminator */
521 }
522
523 phraselen = 0;
524 commentlen = 0;
525 s++;
526 break;
527
528 case '(':
529 if ((commentlen != 0) && (commentlen < (sizeof(comment) - 1)))
530 comment[commentlen++] = ' ';
531 s = next_token(s, comment, &commentlen, sizeof(comment) - 1);
532 if (!s)
533 {
535 return 0;
536 }
537 break;
538
539 case '"':
540 if ((phraselen != 0) && (phraselen < (sizeof(phrase) - 1)))
541 phrase[phraselen++] = ' ';
542 s = parse_quote(s + 1, phrase, &phraselen, sizeof(phrase) - 1);
543 if (!s)
544 {
546 return 0;
547 }
548 break;
549
550 case ':':
551 {
552 struct Address *a = mutt_addr_new();
553 terminate_buffer(phrase, phraselen);
554 if (phraselen != 0)
555 {
556 a->mailbox = buf_new(phrase);
557 }
558 a->group = true;
560 phraselen = 0;
561 commentlen = 0;
562 s++;
563 break;
564 }
565
566 case '<':
567 {
568 struct Address *a = mutt_addr_new();
569 terminate_buffer(phrase, phraselen);
570 if (phraselen != 0)
571 {
572 a->personal = buf_new(phrase);
573 }
574 s = parse_route_addr(s + 1, comment, &commentlen, sizeof(comment) - 1, a);
575 if (!s)
576 {
578 mutt_addr_free(&a);
579 return 0;
580 }
582 phraselen = 0;
583 commentlen = 0;
584 parsed++;
585 break;
586 }
587
588 default:
589 if ((phraselen != 0) && (phraselen < (sizeof(phrase) - 1)) && ws_pending)
590 phrase[phraselen++] = ' ';
591 if (*s == '\\')
592 {
593 s++;
594 if (*s && (phraselen < (sizeof(phrase) - 1)))
595 {
596 phrase[phraselen++] = *s;
597 s++;
598 }
599 }
600 s = next_token(s, phrase, &phraselen, sizeof(phrase) - 1);
601 if (!s)
602 {
604 return 0;
605 }
606 break;
607 } // switch (*s)
608
609 ws_pending = mutt_str_is_email_wsp(*s);
611 } // while (*s)
612
613 if (phraselen != 0)
614 {
615 terminate_buffer(phrase, phraselen);
616 terminate_buffer(comment, commentlen);
617 if (add_addrspec(al, phrase, comment, &commentlen, sizeof(comment) - 1))
618 {
619 parsed++;
620 }
621 }
622 else if (commentlen != 0)
623 {
624 struct Address *last = TAILQ_LAST(al, AddressList);
625 if (last && buf_is_empty(last->personal) && !buf_is_empty(last->mailbox))
626 {
627 terminate_buffer(comment, commentlen);
628 buf_strcpy(last->personal, comment);
629 }
630 }
631
632 return parsed;
633}
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:1460
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:290
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:394
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:602
#define TAILQ_LAST(head, headname)
Definition: queue.h:819
#define terminate_buffer(str, strlen)
Definition: string2.h:52
static bool mutt_str_is_email_wsp(char c)
Is this a whitespace character (for an email header)
Definition: string2.h:103
+ 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 644 of file address.c.

645{
646 if (!s || (*s == '\0'))
647 return 0;
648
649 int parsed = 0;
650
651 /* check for a simple whitespace separated list of addresses */
652 if (!strpbrk(s, "\"<>():;,\\"))
653 {
654 char *copy = mutt_str_dup(s);
655 char *r = copy;
656 while ((r = strtok(r, " \t")))
657 {
658 parsed += mutt_addrlist_parse(al, r);
659 r = NULL;
660 }
661 FREE(&copy);
662 }
663 else
664 {
665 parsed = mutt_addrlist_parse(al, s);
666 }
667
668 return parsed;
669}
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:480
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
+ 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 1491 of file address.c.

1492{
1493 if (al && a)
1494 TAILQ_INSERT_HEAD(al, a, entries);
1495}
#define TAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:796
+ 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 680 of file address.c.

681{
682 if (!al || !host || (*host == '\0'))
683 return;
684
685 struct Address *a = NULL;
686 TAILQ_FOREACH(a, al, entries)
687 {
688 if (!a->group && a->mailbox && !buf_find_char(a->mailbox, '@'))
689 {
690 buf_add_printf(a->mailbox, "@%s", host);
691 }
692 }
693}
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:203
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:654
+ 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, *tmp = NULL;
445 TAILQ_FOREACH_SAFE(a, al, entries, tmp)
446 {
448 {
449 TAILQ_REMOVE(al, a, entries);
450 mutt_addr_free(&a);
451 rc = 0;
452 }
453 }
454
455 return rc;
456}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:666
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:735
+ 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 1433 of file address.c.

1434{
1435 if (!a || !b)
1436 return;
1437
1438 struct Address *aa = NULL, *ab = NULL, *tmp = NULL;
1439
1440 TAILQ_FOREACH_SAFE(ab, b, entries, tmp)
1441 {
1442 TAILQ_FOREACH(aa, a, entries)
1443 {
1444 if (mutt_addr_cmp(aa, ab))
1445 {
1446 TAILQ_REMOVE(b, ab, entries);
1447 mutt_addr_free(&ab);
1448 break;
1449 }
1450 }
1451 }
1452}
bool mutt_addr_cmp(const struct Address *a, const struct Address *b)
Compare two e-mail addresses.
Definition: address.c:892
+ 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 909 of file address.c.

910{
911 if (!needle || !haystack)
912 return false;
913
914 struct Address *a = NULL;
915 TAILQ_FOREACH(a, haystack, entries)
916 {
917 if (mutt_addr_cmp(needle, a))
918 return true;
919 }
920 return false;
921}
+ 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 1293 of file address.c.

1294{
1295 if (!al)
1296 return 0;
1297
1298 int rc = 0;
1299
1300 if (err)
1301 *err = NULL;
1302
1303 struct Address *a = NULL;
1304 TAILQ_FOREACH(a, al, entries)
1305 {
1306 if (!a->mailbox || addr_is_intl(a))
1307 continue;
1308
1309 char *user = NULL;
1310 char *domain = NULL;
1311 if (addr_mbox_to_udomain(buf_string(a->mailbox), &user, &domain) == -1)
1312 continue;
1313
1314 char *intl_mailbox = mutt_idna_local_to_intl(user, domain);
1315
1316 FREE(&user);
1317 FREE(&domain);
1318
1319 if (!intl_mailbox)
1320 {
1321 rc = -1;
1322 if (err && !*err)
1323 *err = buf_strdup(a->mailbox);
1324 continue;
1325 }
1326
1327 addr_set_intl(a, intl_mailbox);
1328 FREE(&intl_mailbox);
1329 }
1330
1331 return rc;
1332}
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:570
+ 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 1378 of file address.c.

1379{
1380 if (!al)
1381 return 0;
1382
1383 struct Address *a = NULL;
1384 TAILQ_FOREACH(a, al, entries)
1385 {
1387 }
1388 return 0;
1389}
bool mutt_addr_to_local(struct Address *a)
Convert an Address from Punycode.
Definition: address.c:1340
+ 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 1522 of file address.c.

1523{
1524 if (!al)
1525 {
1526 return false;
1527 }
1528
1529 struct Address *a = NULL;
1530 TAILQ_FOREACH(a, al, entries)
1531 {
1533 return true;
1534 }
1535 return false;
1536}
bool mutt_addr_uses_unicode(const char *str)
Does this address use Unicode character.
Definition: address.c:1502
+ 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 1206 of file address.c.

1207{
1208 return addrlist_write(al, buf, display, NULL, -1);
1209}
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:1126
+ 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 1189 of file address.c.

1191{
1192 return addrlist_write(al, buf, false, header, 74);
1193}
+ 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 1248 of file address.c.

1249{
1250 struct Buffer *buf = buf_pool_get();
1251 mutt_addrlist_write_wrap(al, buf, header);
1252 fputs(buf_string(buf), fp);
1253 buf_pool_release(&buf);
1254 fputc('\n', fp);
1255}
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:1189
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
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 1217 of file address.c.

1218{
1219 if (!al || !list)
1220 return 0;
1221
1222 size_t count = 0;
1223 struct Address *a = NULL;
1224 TAILQ_FOREACH(a, al, entries)
1225 {
1226 struct Buffer buf = { 0 };
1227 mutt_addr_write(&buf, a, true);
1228 if (!buf_is_empty(&buf))
1229 {
1230 /* We're taking the ownership of the buffer string here */
1231 mutt_list_insert_tail(list, (char *) buf_string(&buf));
1232 count++;
1233 }
1234 }
1235
1236 return count;
1237}
size_t mutt_addr_write(struct Buffer *buf, struct Address *addr, bool display)
Write a single Address to a buffer.
Definition: address.c:1050
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
+ 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.