NeoMutt  2025-12-11-694-ga89709
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 713 of file address.c.

714{
715 if (!buf || !value || !specials)
716 return;
717
718 if (strpbrk(value, specials))
719 {
720 if (buflen < 4)
721 {
722 mutt_str_copy(buf, value, buflen);
723 return;
724 }
725
726 char *pc = buf;
727 size_t remaining = buflen - 3; // Reserve for opening quote, closing quote, NUL
728
729 *pc++ = '"';
730 for (; *value && (remaining > 1); value++)
731 {
732 if ((*value == '\\') || (*value == '"'))
733 {
734 *pc++ = '\\';
735 remaining--;
736 }
737 *pc++ = *value;
738 remaining--;
739 }
740 *pc++ = '"';
741 *pc = '\0';
742 }
743 else
744 {
745 mutt_str_copy(buf, value, buflen);
746 }
747}
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:586
+ 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 801 of file address.c.

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

902{
903 if (!a || !b)
904 return false;
905 if (!a->mailbox || !b->mailbox)
906 return false;
907 if (!buf_istr_equal(a->mailbox, b->mailbox))
908 return false;
909 return true;
910}
bool buf_istr_equal(const struct Buffer *a, const struct Buffer *b)
Return if two buffers are equal, case insensitive.
Definition buffer.c:695
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 754 of file address.c.

755{
756 if (!addr)
757 return NULL;
758
759 struct Address *p = mutt_addr_new();
760 p->personal = buf_dup(addr->personal);
761 p->mailbox = buf_dup(addr->mailbox);
762 p->group = addr->group;
763 p->is_intl = addr->is_intl;
764 p->intl_checked = addr->intl_checked;
765 return p;
766}
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:586
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:304
+ 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 1021 of file address.c.

1022{
1023 if (!a)
1024 return NULL;
1025
1026 char *user = NULL, *domain = NULL;
1027 static char *buf = NULL;
1028
1029 if (!a->mailbox || addr_is_local(a))
1030 return buf_string(a->mailbox);
1031
1032 if (addr_mbox_to_udomain(buf_string(a->mailbox), &user, &domain) == -1)
1033 return buf_string(a->mailbox);
1034
1035 char *local_mailbox = mutt_idna_intl_to_local(user, domain, MI_MAY_BE_IRREVERSIBLE);
1036
1037 FREE(&user);
1038 FREE(&domain);
1039
1040 if (!local_mailbox)
1041 return buf_string(a->mailbox);
1042
1043 mutt_str_replace(&buf, local_mailbox);
1044 FREE(&local_mailbox);
1045
1046 return buf;
1047}
static int addr_mbox_to_udomain(const char *mbox, char **user, char **domain)
Split a mailbox name into user and domain.
Definition address.c:966
static bool addr_is_local(const struct Address *a)
Does the Address have NO IDN components.
Definition address.c:949
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 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:319
+ 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 1272 of file address.c.

1273{
1274 if (!a || !a->mailbox || addr_is_intl(a))
1275 return true;
1276
1277 char *user = NULL;
1278 char *domain = NULL;
1279 if (addr_mbox_to_udomain(buf_string(a->mailbox), &user, &domain) == -1)
1280 return true;
1281
1282 char *intl_mailbox = mutt_idna_local_to_intl(user, domain);
1283
1284 FREE(&user);
1285 FREE(&domain);
1286
1287 if (!intl_mailbox)
1288 return false;
1289
1290 addr_set_intl(a, intl_mailbox);
1291 FREE(&intl_mailbox);
1292 return true;
1293}
static bool addr_is_intl(const struct Address *a)
Does the Address have IDN components.
Definition address.c:937
static void addr_set_intl(struct Address *a, char *intl_mailbox)
Mark an Address as having IDN components.
Definition address.c:988
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 1349 of file address.c.

1350{
1351 if (!a || !a->mailbox)
1352 {
1353 return false;
1354 }
1355
1356 if (addr_is_local(a))
1357 {
1358 return true;
1359 }
1360
1361 char *user = NULL;
1362 char *domain = NULL;
1363 if (addr_mbox_to_udomain(buf_string(a->mailbox), &user, &domain) == -1)
1364 {
1365 return false;
1366 }
1367
1368 char *local_mailbox = mutt_idna_intl_to_local(user, domain, MI_NO_FLAGS);
1369 FREE(&user);
1370 FREE(&domain);
1371
1372 if (!local_mailbox)
1373 {
1374 return false;
1375 }
1376
1377 addr_set_local(a, local_mailbox);
1378 FREE(&local_mailbox);
1379 return true;
1380}
static void addr_set_local(struct Address *a, char *local_mailbox)
Mark an Address as having NO IDN components.
Definition address.c:1003
#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 1511 of file address.c.

1512{
1513 if (!str)
1514 return false;
1515
1516 while (*str)
1517 {
1518 if ((unsigned char) *str & (1 << 7))
1519 return true;
1520 str++;
1521 }
1522
1523 return false;
1524}
+ 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 1059 of file address.c.

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

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

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

775{
776 if (!dst || !src)
777 return;
778
779 struct Address *a = NULL;
780 TAILQ_FOREACH(a, src, entries)
781 {
782 struct Address *next = TAILQ_NEXT(a, entries);
783 if (prune && a->group && (!next || !next->mailbox))
784 {
785 /* ignore this element of the list */
786 }
787 else
788 {
790 }
791 }
792}
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition address.c:1489
struct Address * mutt_addr_copy(const struct Address *addr)
Copy the real address.
Definition address.c:754
#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 881 of file address.c.

882{
883 if (!al)
884 return 0;
885
886 int c = 0;
887 struct Address *a = NULL;
888 TAILQ_FOREACH(a, al, entries)
889 {
890 c += (a->mailbox && !a->group);
891 }
892 return c;
893}
+ 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 1406 of file address.c.

1407{
1408 if (!al)
1409 return;
1410
1411 struct Address *a = NULL;
1412 TAILQ_FOREACH(a, al, entries)
1413 {
1414 if (a->mailbox)
1415 {
1416 struct Address *a2 = TAILQ_NEXT(a, entries);
1417 struct Address *tmp = NULL;
1418
1419 if (a2)
1420 {
1421 TAILQ_FOREACH_FROM_SAFE(a2, al, entries, tmp)
1422 {
1423 if (a2->mailbox && buf_istr_equal(a->mailbox, a2->mailbox))
1424 {
1425 mutt_debug(LL_DEBUG2, "Removing %s\n", buf_string(a2->mailbox));
1426 TAILQ_REMOVE(al, a2, entries);
1427 mutt_addr_free(&a2);
1428 }
1429 }
1430 }
1431 }
1432 }
1433}
#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 849 of file address.c.

850{
851 if (!ala || !alb)
852 {
853 return !(ala || alb);
854 }
855
856 struct Address *ana = TAILQ_FIRST(ala);
857 struct Address *anb = TAILQ_FIRST(alb);
858
859 while (ana && anb)
860 {
861 if (!buf_str_equal(ana->mailbox, anb->mailbox) ||
862 !buf_str_equal(ana->personal, anb->personal))
863 {
864 break;
865 }
866
867 ana = TAILQ_NEXT(ana, entries);
868 anb = TAILQ_NEXT(anb, entries);
869 }
870
871 return !(ana || anb);
872}
bool buf_str_equal(const struct Buffer *a, const struct Buffer *b)
Return if two buffers are equal.
Definition buffer.c:683
+ 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
492 /* Parse the address string character by character, handling RFC 2822
493 * constructs: quoted strings, comments, route-addr, group syntax */
495 while (*s)
496 {
497 switch (*s)
498 {
499 case ';':
500 case ',':
501 /* Address separator: convert accumulated phrase into an address */
502 if (phraselen != 0)
503 {
504 terminate_buffer(phrase, phraselen);
505 if (add_addrspec(al, phrase, comment, &commentlen, sizeof(comment) - 1))
506 {
507 parsed++;
508 }
509 }
510 else if (commentlen != 0)
511 {
512 struct Address *last = TAILQ_LAST(al, AddressList);
513 if (last && !last->personal && !buf_is_empty(last->mailbox))
514 {
515 terminate_buffer(comment, commentlen);
516 last->personal = buf_new(comment);
517 }
518 }
519
520 if (*s == ';')
521 {
522 /* add group terminator */
524 }
525
526 phraselen = 0;
527 commentlen = 0;
528 s++;
529 break;
530
531 case '(':
532 /* RFC 822 comment in parentheses */
533 if ((commentlen != 0) && (commentlen < (sizeof(comment) - 1)))
534 comment[commentlen++] = ' ';
535 s = next_token(s, comment, &commentlen, sizeof(comment) - 1);
536 if (!s)
537 {
539 return 0;
540 }
541 break;
542
543 case '"':
544 if ((phraselen != 0) && (phraselen < (sizeof(phrase) - 1)))
545 phrase[phraselen++] = ' ';
546 s = parse_quote(s + 1, phrase, &phraselen, sizeof(phrase) - 1);
547 if (!s)
548 {
550 return 0;
551 }
552 break;
553
554 case ':':
555 {
556 struct Address *a = mutt_addr_new();
557 terminate_buffer(phrase, phraselen);
558 if (phraselen != 0)
559 {
560 a->mailbox = buf_new(phrase);
561 }
562 a->group = true;
564 phraselen = 0;
565 commentlen = 0;
566 s++;
567 break;
568 }
569
570 case '<':
571 {
572 /* Route-addr: phrase before '<' becomes personal name */
573 struct Address *a = mutt_addr_new();
574 terminate_buffer(phrase, phraselen);
575 if (phraselen != 0)
576 {
577 a->personal = buf_new(phrase);
578 }
579 s = parse_route_addr(s + 1, comment, &commentlen, sizeof(comment) - 1, a);
580 if (!s)
581 {
583 mutt_addr_free(&a);
584 return 0;
585 }
587 phraselen = 0;
588 commentlen = 0;
589 parsed++;
590 break;
591 }
592
593 default:
594 if ((phraselen != 0) && (phraselen < (sizeof(phrase) - 1)) && ws_pending)
595 phrase[phraselen++] = ' ';
596 if (*s == '\\')
597 {
598 s++;
599 if (*s && (phraselen < (sizeof(phrase) - 1)))
600 {
601 phrase[phraselen++] = *s;
602 s++;
603 }
604 }
605 s = next_token(s, phrase, &phraselen, sizeof(phrase) - 1);
606 if (!s)
607 {
609 return 0;
610 }
611 break;
612 } // switch (*s)
613
614 ws_pending = mutt_str_is_email_wsp(*s);
616 } // while (*s)
617
618 if (phraselen != 0)
619 {
620 terminate_buffer(phrase, phraselen);
621 terminate_buffer(comment, commentlen);
622 if (add_addrspec(al, phrase, comment, &commentlen, sizeof(comment) - 1))
623 {
624 parsed++;
625 }
626 }
627 else if (commentlen != 0)
628 {
629 struct Address *last = TAILQ_LAST(al, AddressList);
630 if (last && !last->personal && !buf_is_empty(last->mailbox))
631 {
632 terminate_buffer(comment, commentlen);
633 last->personal = buf_new(comment);
634 }
635 }
636
637 return parsed;
638}
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:1469
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:291
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition string.c:613
#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 649 of file address.c.

650{
651 if (!s || (*s == '\0'))
652 return 0;
653
654 int parsed = 0;
655
656 /* check for a simple whitespace separated list of addresses */
657 if (!strpbrk(s, "\"<>():;,\\"))
658 {
659 char *copy = mutt_str_dup(s);
660 char *r = copy;
661 while ((r = strtok(r, " \t")))
662 {
663 parsed += mutt_addrlist_parse(al, r);
664 r = NULL;
665 }
666 FREE(&copy);
667 }
668 else
669 {
670 parsed = mutt_addrlist_parse(al, s);
671 }
672
673 return parsed;
674}
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: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 1500 of file address.c.

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

686{
687 if (!al || !host || (*host == '\0'))
688 return;
689
690 struct Address *a = NULL;
691 TAILQ_FOREACH(a, al, entries)
692 {
693 if (!a->group && a->mailbox && !buf_find_char(a->mailbox, '@'))
694 {
695 buf_add_printf(a->mailbox, "@%s", host);
696 }
697 }
698}
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition buffer.c:204
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:653
+ 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:677
#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 1442 of file address.c.

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

919{
920 if (!needle || !haystack)
921 return false;
922
923 struct Address *a = NULL;
924 TAILQ_FOREACH(a, haystack, entries)
925 {
926 if (mutt_addr_cmp(needle, a))
927 return true;
928 }
929 return false;
930}
+ 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 1302 of file address.c.

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

1388{
1389 if (!al)
1390 return 0;
1391
1392 struct Address *a = NULL;
1393 TAILQ_FOREACH(a, al, entries)
1394 {
1396 }
1397 return 0;
1398}
bool mutt_addr_to_local(struct Address *a)
Convert an Address from Punycode.
Definition address.c:1349
+ 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 1531 of file address.c.

1532{
1533 if (!al)
1534 {
1535 return false;
1536 }
1537
1538 struct Address *a = NULL;
1539 TAILQ_FOREACH(a, al, entries)
1540 {
1542 return true;
1543 }
1544 return false;
1545}
bool mutt_addr_uses_unicode(const char *str)
Does this address use Unicode character.
Definition address.c:1511
+ 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 1215 of file address.c.

1216{
1217 return addrlist_write(al, buf, display, NULL, -1);
1218}
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:1135
+ 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 1198 of file address.c.

1200{
1201 return addrlist_write(al, buf, false, header, 74);
1202}
+ 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 1257 of file address.c.

1258{
1259 struct Buffer *buf = buf_pool_get();
1260 mutt_addrlist_write_wrap(al, buf, header);
1261 fputs(buf_string(buf), fp);
1262 buf_pool_release(&buf);
1263 fputc('\n', fp);
1264}
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:1198
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 1226 of file address.c.

1227{
1228 if (!al || !list)
1229 return 0;
1230
1231 size_t count = 0;
1232 struct Address *a = NULL;
1233 TAILQ_FOREACH(a, al, entries)
1234 {
1235 struct Buffer buf = { 0 };
1236 mutt_addr_write(&buf, a, true);
1237 if (!buf_is_empty(&buf))
1238 {
1239 /* We're taking the ownership of the buffer string here */
1240 mutt_list_insert_tail(list, (char *) buf_string(&buf));
1241 count++;
1242 }
1243 }
1244
1245 return count;
1246}
size_t mutt_addr_write(struct Buffer *buf, struct Address *addr, bool display)
Write a single Address to a buffer.
Definition address.c:1059
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.