NeoMutt  2022-04-29-178-g3b62e6
Teaching an old dog new tricks
DOXYGEN
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...
 

Macros

#define address_error(num)   AddressErrors[num]
 

Typedefs

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

Enumerations

enum  AddressError {
  ADDR_ERR_MEMORY = 1 , ADDR_ERR_MISMATCH_PAREN , ADDR_ERR_MISMATCH_QUOTE , ADDR_ERR_BAD_ROUTE ,
  ADDR_ERR_BAD_ROUTE_ADDR , ADDR_ERR_BAD_ADDR_SPEC
}
 Possible values for AddressError. More...
 

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

Variables

int AddressError
 An out-of-band error code. More...
 
const char *const AddressErrors []
 Messages for the error codes in AddressError. More...
 
const char AddressSpecials []
 Characters with special meaning for email addresses. More...
 

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.

Macro Definition Documentation

◆ address_error

#define address_error (   num)    AddressErrors[num]

Definition at line 63 of file address.h.

Typedef Documentation

◆ addr_predicate_t

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

Definition at line 73 of file address.h.

Enumeration Type Documentation

◆ AddressError

Possible values for AddressError.

Enumerator
ADDR_ERR_MEMORY 

Out of memory.

ADDR_ERR_MISMATCH_PAREN 

Mismatched parentheses.

ADDR_ERR_MISMATCH_QUOTE 

Mismatches quotes.

ADDR_ERR_BAD_ROUTE 

Bad route.

ADDR_ERR_BAD_ROUTE_ADDR 

Bad route address.

ADDR_ERR_BAD_ADDR_SPEC 

Bad address specifier.

Definition at line 49 of file address.h.

50{
51 ADDR_ERR_MEMORY = 1,
57};
@ ADDR_ERR_BAD_ROUTE
Bad route.
Definition: address.h:54
@ ADDR_ERR_BAD_ROUTE_ADDR
Bad route address.
Definition: address.h:55
@ ADDR_ERR_BAD_ADDR_SPEC
Bad address specifier.
Definition: address.h:56
@ ADDR_ERR_MEMORY
Out of memory.
Definition: address.h:51
@ ADDR_ERR_MISMATCH_PAREN
Mismatched parentheses.
Definition: address.h:52
@ ADDR_ERR_MISMATCH_QUOTE
Mismatches quotes.
Definition: address.h:53

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 681 of file address.c.

682{
683 if (!buf || !value || !specials)
684 return;
685
686 if (strpbrk(value, specials))
687 {
688 char tmp[256] = { 0 };
689 char *pc = tmp;
690 size_t tmplen = sizeof(tmp) - 3;
691
692 *pc++ = '"';
693 for (; *value && (tmplen > 1); value++)
694 {
695 if ((*value == '\\') || (*value == '"'))
696 {
697 *pc++ = '\\';
698 tmplen--;
699 }
700 *pc++ = *value;
701 tmplen--;
702 }
703 *pc++ = '"';
704 *pc = '\0';
705 mutt_str_copy(buf, tmp, buflen);
706 }
707 else
708 mutt_str_copy(buf, value, buflen);
709}
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:629
+ 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 764 of file address.c.

765{
766 /* msg-id = "<" addr-spec ">"
767 * addr-spec = local-part "@" domain
768 * local-part = word *("." word)
769 * word = atom / quoted-string
770 * atom = 1*<any CHAR except specials, SPACE and CTLs>
771 * CHAR = ( 0.-127. )
772 * specials = "(" / ")" / "<" / ">" / "@"
773 * / "," / ";" / ":" / "\" / <">
774 * / "." / "[" / "]"
775 * SPACE = ( 32. )
776 * CTLS = ( 0.-31., 127.)
777 * quoted-string = <"> *(qtext/quoted-pair) <">
778 * qtext = <any CHAR except <">, "\" and CR>
779 * CR = ( 13. )
780 * quoted-pair = "\" CHAR
781 * domain = sub-domain *("." sub-domain)
782 * sub-domain = domain-ref / domain-literal
783 * domain-ref = atom
784 * domain-literal = "[" *(dtext / quoted-pair) "]"
785 */
786
787 if (!msgid || (*msgid == '\0'))
788 return false;
789
790 size_t l = mutt_str_len(msgid);
791 if (l < 5) /* <atom@atom> */
792 return false;
793 if ((msgid[0] != '<') || (msgid[l - 1] != '>'))
794 return false;
795 if (!(strrchr(msgid, '@')))
796 return false;
797
798 /* TODO: complete parser */
799 for (size_t i = 0; i < l; i++)
800 if ((unsigned char) msgid[i] > 127)
801 return false;
802
803 return true;
804}
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:544
+ 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 864 of file address.c.

865{
866 if (!a || !b)
867 return false;
868 if (!a->mailbox || !b->mailbox)
869 return false;
870 if (!mutt_istr_equal(a->mailbox, b->mailbox))
871 return false;
872 return true;
873}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:796
char * 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 716 of file address.c.

717{
718 if (!addr)
719 return NULL;
720
721 struct Address *p = mutt_addr_new();
722
723 p->personal = mutt_str_dup(addr->personal);
724 p->mailbox = mutt_str_dup(addr->mailbox);
725 p->group = addr->group;
726 p->is_intl = addr->is_intl;
727 p->intl_checked = addr->intl_checked;
728 return p;
729}
struct Address * mutt_addr_new(void)
Create a new Address.
Definition: address.c:385
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
An email address.
Definition: address.h:36
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
char * personal
Real name of address.
Definition: address.h:37
+ 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 398 of file address.c.

399{
400 struct Address *a = mutt_addr_new();
403 return a;
404}
+ 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 986 of file address.c.

987{
988 if (!a)
989 return NULL;
990
991 char *user = NULL, *domain = NULL;
992 static char *buf = NULL;
993
994 if (!a->mailbox || addr_is_local(a))
995 return a->mailbox;
996
997 if (addr_mbox_to_udomain(a->mailbox, &user, &domain) == -1)
998 return a->mailbox;
999
1000 char *local_mailbox = mutt_idna_intl_to_local(user, domain, MI_MAY_BE_IRREVERSIBLE);
1001
1002 FREE(&user);
1003 FREE(&domain);
1004
1005 if (!local_mailbox)
1006 return a->mailbox;
1007
1008 mutt_str_replace(&buf, local_mailbox);
1009 FREE(&local_mailbox);
1010
1011 return buf;
1012}
static int addr_mbox_to_udomain(const char *mbox, char **user, char **domain)
Split a mailbox name into user and domain.
Definition: address.c:929
static bool addr_is_local(const struct Address *a)
Does the Address have NO IDN components.
Definition: address.c:912
#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:144
#define FREE(x)
Definition: memory.h:43
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
+ 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 440 of file address.c.

441{
442 if (!ptr || !*ptr)
443 return;
444
445 struct Address *a = *ptr;
446
447 FREE(&a->personal);
448 FREE(&a->mailbox);
449 FREE(ptr);
450}
+ 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 385 of file address.c.

386{
387 return mutt_mem_calloc(1, sizeof(struct Address));
388}
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 1276 of file address.c.

1277{
1278 if (!a || !a->mailbox || addr_is_intl(a))
1279 return true;
1280
1281 char *user = NULL;
1282 char *domain = NULL;
1283 if (addr_mbox_to_udomain(a->mailbox, &user, &domain) == -1)
1284 return true;
1285
1286 char *intl_mailbox = mutt_idna_local_to_intl(user, domain);
1287
1288 FREE(&user);
1289 FREE(&domain);
1290
1291 if (!intl_mailbox)
1292 return false;
1293
1294 addr_set_intl(a, intl_mailbox);
1295 return true;
1296}
static bool addr_is_intl(const struct Address *a)
Does the Address have IDN components.
Definition: address.c:900
static void addr_set_intl(struct Address *a, char *intl_mailbox)
Mark an Address as having IDN components.
Definition: address.c:951
char * mutt_idna_local_to_intl(const char *user, const char *domain)
Convert an email's domain to Punycode.
Definition: idna.c:264
+ 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->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(a->mailbox, &user, &domain) == -1)
1366 {
1367 return false;
1368 }
1369
1370 char *local_mailbox = mutt_idna_intl_to_local(user, domain, MI_NO_FLAGS);
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 return true;
1381}
static void addr_set_local(struct Address *a, char *local_mailbox)
Mark an Address as having NO IDN components.
Definition: address.c:967
#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 1512 of file address.c.

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

◆ mutt_addr_write()

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

Write a single Address to a buffer.

Parameters
bufBuffer for the Address
buflenLength of the buffer
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 1025 of file address.c.

1026{
1027 if (!buf || (buflen == 0) || !addr)
1028 return 0;
1029
1030 if (!addr->personal && !addr->mailbox)
1031 return 0;
1032
1033 size_t len;
1034 char *pbuf = buf;
1035 char *pc = NULL;
1036
1037 buflen--; /* save room for the terminal nul */
1038
1039 if (addr->personal)
1040 {
1041 if (strpbrk(addr->personal, AddressSpecials))
1042 {
1043 if (buflen == 0)
1044 goto done;
1045 *pbuf++ = '"';
1046 buflen--;
1047 for (pc = addr->personal; *pc && (buflen > 0); pc++)
1048 {
1049 if ((*pc == '"') || (*pc == '\\'))
1050 {
1051 *pbuf++ = '\\';
1052 buflen--;
1053 }
1054 if (buflen == 0)
1055 goto done;
1056 *pbuf++ = *pc;
1057 buflen--;
1058 }
1059 if (buflen == 0)
1060 goto done;
1061 *pbuf++ = '"';
1062 buflen--;
1063 }
1064 else
1065 {
1066 if (buflen == 0)
1067 goto done;
1068 len = mutt_str_copy(pbuf, addr->personal, buflen + 1);
1069 pbuf += len;
1070 buflen -= len;
1071 }
1072
1073 if (buflen == 0)
1074 goto done;
1075 *pbuf++ = ' ';
1076 buflen--;
1077 }
1078
1079 if (addr->personal || (addr->mailbox && (*addr->mailbox == '@')))
1080 {
1081 if (buflen == 0)
1082 goto done;
1083 *pbuf++ = '<';
1084 buflen--;
1085 }
1086
1087 if (addr->mailbox)
1088 {
1089 if (buflen == 0)
1090 goto done;
1091 if (mutt_str_equal(addr->mailbox, "@"))
1092 {
1093 *pbuf = '\0';
1094 }
1095 else
1096 {
1097 const char *a = display ? mutt_addr_for_display(addr) : addr->mailbox;
1098 len = mutt_str_copy(pbuf, a, buflen + 1);
1099 pbuf += len;
1100 buflen -= len;
1101 }
1102
1103 if (addr->personal || (addr->mailbox && (*addr->mailbox == '@')))
1104 {
1105 if (buflen == 0)
1106 goto done;
1107 *pbuf++ = '>';
1108 buflen--;
1109 }
1110
1111 if (addr->group)
1112 {
1113 if (buflen == 0)
1114 goto done;
1115 *pbuf++ = ':';
1116 buflen--;
1117 if (buflen == 0)
1118 goto done;
1119 *pbuf++ = ' ';
1120 buflen--;
1121 }
1122 }
1123 else
1124 {
1125 if (buflen == 0)
1126 goto done;
1127 *pbuf++ = ';';
1128 }
1129done:
1130 /* no need to check for length here since we already save space at the
1131 * beginning of this routine */
1132 *pbuf = '\0';
1133
1134 return pbuf - buf;
1135}
const char AddressSpecials[]
Characters with special meaning for email addresses.
Definition: address.c:42
const char * mutt_addr_for_display(const struct Address *a)
Convert an Address for display purposes.
Definition: address.c:986
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:784
static unsigned char * pbuf
Cached PGP data packet.
Definition: pgppacket.c:38
+ 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 1490 of file address.c.

1491{
1492 if (al && a)
1493 TAILQ_INSERT_TAIL(al, a, entries);
1494}
#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 1470 of file address.c.

1471{
1472 if (!al)
1473 return;
1474
1475 struct Address *a = TAILQ_FIRST(al), *next = NULL;
1476 while (a)
1477 {
1478 next = TAILQ_NEXT(a, entries);
1479 mutt_addr_free(&a);
1480 a = next;
1481 }
1482 TAILQ_INIT(al);
1483}
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:440
#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 737 of file address.c.

738{
739 if (!dst || !src)
740 return;
741
742 struct Address *a = NULL;
743 TAILQ_FOREACH(a, src, entries)
744 {
745 struct Address *next = TAILQ_NEXT(a, entries);
746 if (prune && a->group && (!next || !next->mailbox))
747 {
748 /* ignore this element of the list */
749 }
750 else
751 {
753 }
754 }
755}
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1490
struct Address * mutt_addr_copy(const struct Address *addr)
Copy the real address.
Definition: address.c:716
#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 844 of file address.c.

845{
846 if (!al)
847 return 0;
848
849 int c = 0;
850 struct Address *a = NULL;
851 TAILQ_FOREACH(a, al, entries)
852 {
853 c += (a->mailbox && !a->group);
854 }
855 return c;
856}
+ 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 1407 of file address.c.

1408{
1409 if (!al)
1410 return;
1411
1412 struct Address *a = NULL;
1413 TAILQ_FOREACH(a, al, entries)
1414 {
1415 if (a->mailbox)
1416 {
1417 struct Address *a2 = TAILQ_NEXT(a, entries);
1418 struct Address *tmp = NULL;
1419
1420 if (a2)
1421 {
1422 TAILQ_FOREACH_FROM_SAFE(a2, al, entries, tmp)
1423 {
1424 if (a2->mailbox && mutt_istr_equal(a->mailbox, a2->mailbox))
1425 {
1426 mutt_debug(LL_DEBUG2, "Removing %s\n", a2->mailbox);
1427 TAILQ_REMOVE(al, a2, entries);
1428 mutt_addr_free(&a2);
1429 }
1430 }
1431 }
1432 }
1433 }
1434}
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
#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 812 of file address.c.

813{
814 if (!ala || !alb)
815 {
816 return !(ala || alb);
817 }
818
819 struct Address *ana = TAILQ_FIRST(ala);
820 struct Address *anb = TAILQ_FIRST(alb);
821
822 while (ana && anb)
823 {
824 if (!mutt_str_equal(ana->mailbox, anb->mailbox) ||
825 !mutt_str_equal(ana->personal, anb->personal))
826 {
827 break;
828 }
829
830 ana = TAILQ_NEXT(ana, entries);
831 anb = TAILQ_NEXT(anb, entries);
832 }
833
834 return !(ana || anb);
835}
+ 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 458 of file address.c.

459{
460 if (!s)
461 return 0;
462
463 int parsed = 0;
464 char comment[1024], phrase[1024];
465 size_t phraselen = 0, commentlen = 0;
466 AddressError = 0;
467
468 bool ws_pending = mutt_str_is_email_wsp(*s);
469
471 while (*s)
472 {
473 switch (*s)
474 {
475 case ';':
476 case ',':
477 if (phraselen != 0)
478 {
479 terminate_buffer(phrase, phraselen);
480 if (add_addrspec(al, phrase, comment, &commentlen, sizeof(comment) - 1))
481 {
482 parsed++;
483 }
484 }
485 else if (commentlen != 0)
486 {
487 struct Address *last = TAILQ_LAST(al, AddressList);
488 if (last && !last->personal && last->mailbox)
489 {
490 terminate_buffer(comment, commentlen);
491 last->personal = mutt_str_dup(comment);
492 }
493 }
494
495 if (*s == ';')
496 {
497 /* add group terminator */
499 }
500
501 phraselen = 0;
502 commentlen = 0;
503 s++;
504 break;
505
506 case '(':
507 if ((commentlen != 0) && (commentlen < (sizeof(comment) - 1)))
508 comment[commentlen++] = ' ';
509 s = next_token(s, comment, &commentlen, sizeof(comment) - 1);
510 if (!s)
511 {
513 return 0;
514 }
515 break;
516
517 case '"':
518 if ((phraselen != 0) && (phraselen < (sizeof(phrase) - 1)))
519 phrase[phraselen++] = ' ';
520 s = parse_quote(s + 1, phrase, &phraselen, sizeof(phrase) - 1);
521 if (!s)
522 {
524 return 0;
525 }
526 break;
527
528 case ':':
529 {
530 struct Address *a = mutt_addr_new();
531 terminate_buffer(phrase, phraselen);
532 a->mailbox = mutt_str_dup(phrase);
533 a->group = true;
535 phraselen = 0;
536 commentlen = 0;
537 s++;
538 break;
539 }
540
541 case '<':
542 {
543 struct Address *a = mutt_addr_new();
544 terminate_buffer(phrase, phraselen);
545 a->personal = mutt_str_dup(phrase);
546 s = parse_route_addr(s + 1, comment, &commentlen, sizeof(comment) - 1, a);
547 if (!s)
548 {
550 mutt_addr_free(&a);
551 return 0;
552 }
554 phraselen = 0;
555 commentlen = 0;
556 parsed++;
557 break;
558 }
559
560 default:
561 if ((phraselen != 0) && (phraselen < (sizeof(phrase) - 1)) && ws_pending)
562 phrase[phraselen++] = ' ';
563 if (*s == '\\')
564 {
565 s++;
566 if (*s && (phraselen < (sizeof(phrase) - 1)))
567 {
568 phrase[phraselen++] = *s;
569 s++;
570 }
571 }
572 s = next_token(s, phrase, &phraselen, sizeof(phrase) - 1);
573 if (!s)
574 {
576 return 0;
577 }
578 break;
579 } // switch (*s)
580
581 ws_pending = mutt_str_is_email_wsp(*s);
583 } // while (*s)
584
585 if (phraselen != 0)
586 {
587 terminate_buffer(phrase, phraselen);
588 terminate_buffer(comment, commentlen);
589 if (add_addrspec(al, phrase, comment, &commentlen, sizeof(comment) - 1))
590 {
591 parsed++;
592 }
593 }
594 else if (commentlen != 0)
595 {
596 struct Address *last = TAILQ_LAST(al, AddressList);
597 if (last && !last->personal && last->mailbox)
598 {
599 terminate_buffer(comment, commentlen);
600 last->personal = mutt_str_dup(comment);
601 }
602 }
603
604 return parsed;
605}
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:364
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:283
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
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:151
static const char * parse_quote(const char *s, char *token, size_t *tokenlen, size_t tokenmax)
Extract a quoted string.
Definition: address.c:120
AddressError
Possible values for AddressError.
Definition: address.h:50
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:656
bool mutt_str_is_email_wsp(char c)
Is this a whitespace character (for an email header)
Definition: string.c:672
#define TAILQ_LAST(head, headname)
Definition: queue.h:819
#define terminate_buffer(str, strlen)
Definition: string2.h:53
+ 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 616 of file address.c.

617{
618 if (!s || (*s == '\0'))
619 return 0;
620
621 int parsed = 0;
622
623 /* check for a simple whitespace separated list of addresses */
624 if (!strpbrk(s, "\"<>():;,\\"))
625 {
626 char *copy = mutt_str_dup(s);
627 char *r = copy;
628 while ((r = strtok(r, " \t")))
629 {
630 parsed += mutt_addrlist_parse(al, r);
631 r = NULL;
632 }
633 FREE(&copy);
634 }
635 else
636 parsed = mutt_addrlist_parse(al, s);
637
638 return parsed;
639}
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
+ 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 1501 of file address.c.

1502{
1503 if (al && a)
1504 TAILQ_INSERT_HEAD(al, a, entries);
1505}
#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 650 of file address.c.

651{
652 if (!al || !host || (*host == '\0'))
653 return;
654
655 struct Address *a = NULL;
656 TAILQ_FOREACH(a, al, entries)
657 {
658 if (!a->group && a->mailbox && !strchr(a->mailbox, '@'))
659 {
660 char *p = mutt_mem_malloc(mutt_str_len(a->mailbox) + mutt_str_len(host) + 2);
661 sprintf(p, "%s@%s", a->mailbox, host);
662 FREE(&a->mailbox);
663 a->mailbox = p;
664 }
665 }
666}
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
+ 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 413 of file address.c.

414{
415 if (!al)
416 return -1;
417
418 if (!mailbox)
419 return 0;
420
421 int rc = -1;
422 struct Address *a = NULL, *tmp = NULL;
423 TAILQ_FOREACH_SAFE(a, al, entries, tmp)
424 {
426 {
427 TAILQ_REMOVE(al, a, entries);
428 mutt_addr_free(&a);
429 rc = 0;
430 }
431 }
432
433 return rc;
434}
#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 1443 of file address.c.

1444{
1445 if (!a || !b)
1446 return;
1447
1448 struct Address *aa = NULL, *ab = NULL, *tmp = NULL;
1449
1450 TAILQ_FOREACH_SAFE(ab, b, entries, tmp)
1451 {
1452 TAILQ_FOREACH(aa, a, entries)
1453 {
1454 if (mutt_addr_cmp(aa, ab))
1455 {
1456 TAILQ_REMOVE(b, ab, entries);
1457 mutt_addr_free(&ab);
1458 break;
1459 }
1460 }
1461 }
1462}
bool mutt_addr_cmp(const struct Address *a, const struct Address *b)
Compare two e-mail addresses.
Definition: address.c:864
+ 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 881 of file address.c.

882{
883 if (!needle || !haystack)
884 return false;
885
886 struct Address *a = NULL;
887 TAILQ_FOREACH(a, haystack, entries)
888 {
889 if (mutt_addr_cmp(needle, a))
890 return true;
891 }
892 return false;
893}
+ 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 1305 of file address.c.

1306{
1307 if (!al)
1308 return 0;
1309
1310 int rc = 0;
1311
1312 if (err)
1313 *err = NULL;
1314
1315 struct Address *a = NULL;
1316 TAILQ_FOREACH(a, al, entries)
1317 {
1318 if (!a->mailbox || addr_is_intl(a))
1319 continue;
1320
1321 char *user = NULL;
1322 char *domain = NULL;
1323 if (addr_mbox_to_udomain(a->mailbox, &user, &domain) == -1)
1324 continue;
1325
1326 char *intl_mailbox = mutt_idna_local_to_intl(user, domain);
1327
1328 FREE(&user);
1329 FREE(&domain);
1330
1331 if (!intl_mailbox)
1332 {
1333 rc = -1;
1334 if (err && !*err)
1335 *err = mutt_str_dup(a->mailbox);
1336 continue;
1337 }
1338
1339 addr_set_intl(a, intl_mailbox);
1340 }
1341
1342 return rc;
1343}
+ 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 1388 of file address.c.

1389{
1390 if (!al)
1391 return 0;
1392
1393 struct Address *a = NULL;
1394 TAILQ_FOREACH(a, al, entries)
1395 {
1397 }
1398 return 0;
1399}
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 1532 of file address.c.

1533{
1534 if (!al)
1535 {
1536 return false;
1537 }
1538
1539 struct Address *a = NULL;
1540 TAILQ_FOREACH(a, al, entries)
1541 {
1542 if (a->mailbox && !a->group && mutt_addr_uses_unicode(a->mailbox))
1543 return true;
1544 }
1545 return false;
1546}
bool mutt_addr_uses_unicode(const char *str)
Does this address use Unicode character.
Definition: address.c:1512
+ 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,
char *  buf,
size_t  buflen,
bool  display 
)

Write an Address to a buffer.

Parameters
alAddressList to display
bufBuffer for the Address
buflenLength of the buffer
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.

Note
It is assumed that buf is nul terminated!

Definition at line 1150 of file address.c.

1151{
1152 if (!buf || (buflen == 0) || !al)
1153 return 0;
1154
1155 size_t len = mutt_str_len(buf);
1156 if (len >= buflen)
1157 {
1158 return 0;
1159 }
1160
1161 char *pbuf = buf + len;
1162 buflen -= len;
1163
1164 struct Address *a = NULL;
1165 TAILQ_FOREACH(a, al, entries)
1166 {
1167 if (len > 0)
1168 {
1169 if (buflen > 1)
1170 {
1171 *pbuf++ = ',';
1172 buflen--;
1173 }
1174 if (buflen > 1)
1175 {
1176 *pbuf++ = ' ';
1177 buflen--;
1178 }
1179 }
1180
1181 if (buflen == 1)
1182 {
1183 break;
1184 }
1185
1186 len = mutt_addr_write(pbuf, buflen, a, display);
1187 pbuf += len;
1188 buflen -= len;
1189 }
1190
1191 *pbuf = '\0';
1192 return pbuf - buf;
1193}
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write a single Address to a buffer.
Definition: address.c:1025
+ 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,
int  start_col,
bool  display 
)

Wrapper for mutt_write_address()

Parameters
alAddress list
fpFile to write to
start_colStarting column in the output line
displayTrue if these addresses will be displayed to the user

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

Definition at line 1231 of file address.c.

1232{
1233 char buf[1024] = { 0 };
1234 int count = 0;
1235 int linelen = start_col;
1236
1237 struct Address *a = NULL;
1238 TAILQ_FOREACH(a, al, entries)
1239 {
1240 buf[0] = '\0';
1241 size_t len = mutt_addr_write(buf, sizeof(buf), a, display);
1242 if (len == 0)
1243 continue;
1244 if (count && (linelen + len > 74))
1245 {
1246 fputs("\n\t", fp);
1247 linelen = len + 8; /* tab is usually about 8 spaces... */
1248 }
1249 else
1250 {
1251 if (count && a->mailbox)
1252 {
1253 fputc(' ', fp);
1254 linelen++;
1255 }
1256 linelen += len;
1257 }
1258 fputs(buf, fp);
1259 struct Address *next = TAILQ_NEXT(a, entries);
1260 if (!a->group && next && next->mailbox)
1261 {
1262 linelen++;
1263 fputc(',', fp);
1264 }
1265 count++;
1266 }
1267 fputc('\n', fp);
1268}
+ 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 1201 of file address.c.

1202{
1203 if (!al || !list)
1204 return 0;
1205
1206 char addr[256] = { 0 };
1207 size_t count = 0;
1208 struct Address *a = NULL;
1209 TAILQ_FOREACH(a, al, entries)
1210 {
1211 if (mutt_addr_write(addr, sizeof(addr), a, true) != 0)
1212 {
1213 mutt_list_insert_tail(list, strdup(addr));
1214 count++;
1215 }
1216 }
1217
1218 return count;
1219}
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

◆ AddressError

int AddressError
extern

An out-of-band error code.

Many of the Address functions set this variable on error. Its values are defined in AddressError. Text for the errors can be looked up using AddressErrors.

Definition at line 57 of file address.c.

◆ AddressErrors

const char* const AddressErrors[]
extern

Messages for the error codes in AddressError.

These must defined in the same order as enum AddressError.

Definition at line 64 of file address.c.

◆ AddressSpecials

const char AddressSpecials[]
extern

Characters with special meaning for email addresses.

Definition at line 42 of file address.c.