Next: , Previous: Authenticator, Up: libmailbox


3.1.12 Address

     /* Prefix address_ is reserved. */
     #include <mailutils/address.h>

The Internet address format is defined in RFC 822. RFC 822 has been updated, and is now superceeded by RFC 2822, which makes some corrections and clarifications. References to RFC 822 here apply equally to RFC 2822.

The RFC 822 format is more flexible than many people realize, here is a quick summary of the syntax this parser implements, see RFC 822 for the details. ‘[]’ pairs mean "optional", ‘/’ means "one or the other", and double-quoted characters are literals.

     addr-spec    = local-part "@" domain
     mailbox      = addr-spec ["(" display-name ")"] /
                    [display-name] "<" [route] addr-spec ">"
     mailbox-list = mailbox ["," mailbox-list]
     group        = display-name ":" [mailbox-list] ";"
     address      = mailbox / group / unix-mbox
     address-list = address ["," address-list]

Unix-mbox is a non-standard extension meant to deal with the common practice of using user names as addresses in mail utilities. It allows addresses such as "root" to be parsed correctly. These are not valid internet email addresses, they must be qualified before use.

Several address functions have a set of common arguments with consistent semantics, these are described here to avoid repetition.

Since an address-list may contain multiple addresses, they are accessed by a one-based index number, no. The index is one-based because pop, imap, and other message stores commonly use one-based counts to access messages and attributes of messages.

If len is greater than 0 it is the length of the buffer buf, and as much of the component as possible will be copied into the buffer. The buffer will be NULL terminated.

The size of a particular component may be queried by providing 0 for the len of the buffer, in which case the buffer is optional. In this case, if n is provided *n is assigned the length of the component string.

— Data Type: mu_address_t

The mu_address_t object is used to hold information about a parsed RFC822 address list, and is an opaque data structure to the user. Functions are provided to retrieve information about an address in the address list.

— Function: int mu_address_create (mu_address_t *addr, const char *string)

This function allocates and initializes addr by parsing the RFC822 address-list string.

The return value is 0 on success and a code number on error conditions:

EINVAL
Invalid usage, usually a required argument was NULL.
ENOMEM
Not enough memory to allocate resources.
ENOENT
Invalid RFC822 syntax, parsing failed.

— Function: int mu_address_createv (mu_address_t *addr, const char *sv, size_t len)

This function allocates and initializes addr by parsing the array of pointers to RFC822 address-lists in sv. If len is -1, then sv must be NULL terminated in the fashion of argv, otherwise len is the length of the array.

The return value is 0 on success and a code number on error conditions:

EINVAL
Invalid usage, usually a required argument was NULL.
ENOMEM
Not enough memory to allocate resources.
ENOENT
Invalid RFC822 syntax, parsing failed.

— Function: void mu_address_destroy (mu_address_t *addr)

The addr is destroyed.

— Function: int mu_address_get_nth (mu_address_t addr, size_t no, mu_address_t *ret)
— Function: int mu_address_get_email (mu_address_t addr, size_t no, char* buf, size_t len, size_t *n)

Accesses the noth email address component of the address list. This address is the plain email address, correctly quoted, suitable for using in an smtp dialog, for example, or as the address part of a contact book entry.

Note that the entry may be valid, but be a group name. In this case success is returned, but the length of the address is 0.

The return value is 0 on success and a code number on error conditions:

EINVAL
Invalid usage, usually a required argument was NULL.
ENOENT
The index no is outside of the range of available addresses.

— Function: int mu_address_get_local_part (mu_address_t addr, size_t no, char *buf, size_t len, size_t *n)

Accesses the local-part of an email addr-spec extracted while parsing the noth email address.

The return value is 0 on success and a code number on error conditions:

EINVAL
Invalid usage, usually a required argument was NULL.
ENOENT
The index no is outside of the range of available addresses.

— Function: int mu_address_get_domain (mu_address_t addr, size_t no, char *buf, size_t len, size_t *n)

Accesses the domain of an email addr-spec extracted while parsing the noth email address. This will be 0 length for a unix-mbox.

The return value is 0 on success and a code number on error conditions:

EINVAL
Invalid usage, usually a required argument was NULL.
ENOENT
The index no is outside of the range of available addresses.

— Function: int mu_address_get_personal (mu_address_t addr, size_t no, char *buf, size_t len, size_t *n)

Accesses the display-name describing the noth email address. This display-name is optional, so may not be present. If it is not present, but there is an RFC822 comment after the address, that comment will be returned as the personal phrase, as this is a common usage of the comment even though it is not defined in the internet mail standard.

A group is a kind of a special case. It has a display-name, followed by an optional mailbox-list. The display-name will be allocated an address all it's own, but all the other elements (local-part, domain, etc.) will be zero-length. So "a group: ;" is valid, will have a count of 1, but mu_address_get_email(), and all the rest, will return zero-length output.

The return value is 0 on success and a code number on error conditions:

EINVAL
Invalid usage, usually a required argument was NULL.
ENOENT
The index no is outside of the range of available addresses.

— Function: int mu_address_get_comments (mu_address_t addr, size_t no, char *buf, size_t len, size_t *n)

Accesses the comments extracted while parsing the noth email address. These comments have no defined meaning, and are not currently collected.

The return value is 0 on success and a code number on error conditions:

EINVAL
Invalid usage, usually a required argument was NULL.
ENOENT
The index no is outside of the range of available addresses.

— Function: int mu_address_get_route (mu_address_t addr, size_t no, char *buf, size_t len, size_t *n)

Accesses the route of an email addr-spec extracted while parsing the noth email address. This is a rarely used RFC822 address syntax, but is legal in SMTP as well. The entire route is returned as a string, those wishing to parse it should look at mailutils/parse822.h.

The return value is 0 on success and a code number on error conditions:

EINVAL
Invalid usage, usually a required argument was NULL.
ENOENT
The index no is outside of the range of available addresses.

— Function: int mu_address_aget_email (mu_address_t addr, size_t no, char **bufp)

As above, but mallocs the email address, if present, and write a pointer to it into bufp. bufp will be NULL if there is no email address to return.

The return value is 0 on success and a code number on error conditions:

EINVAL
Invalid usage, usually a required argument was NULL.
ENOENT
The index no is outside of the range of available addresses.

— Function: int mu_address_aget_local_part (mu_address_t addr, size_t no, char **buf)
— Function: int mu_address_aget_domain (mu_address_t addr, size_t no, char **buf)
— Function: int mu_address_aget_personal (mu_address_t addr, size_t no, char **buf)
— Function: int mu_address_is_group (mu_address_t addr, size_t no, int *yes)

Sets *yes to 1 if this address is just the name of a group, 0 otherwise. This is faster than checking if the address has a non-zero length personal, and a zero-length local_part and domain.

yes can be NULL, though that doesn't serve much purpose other than determining that no refers to an address.

Currently, there is no way to determine the end of the group.

The return value is 0 on success and a code number on error conditions:

EINVAL
Invalid usage, usually a required argument was NULL.
ENOENT
The index no is outside of the range of available addresses.

— Function: int mu_address_to_string (mu_address_t *addr, char *buf, size_t len, size_t *n)

Returns the entire address list as a single RFC822 formatted address list.

The return value is 0 on success and a code number on error conditions:

EINVAL
Invalid usage, usually a required argument was NULL.
ENOMEM
Not enough memory to allocate resources.

— Function: int mu_address_get_count (mu_address_t addr, size_t *count)

Returns a count of the addresses in the address list.

If addr is NULL, the count is 0. If count is not NULL, the count will be written to *count.

The return value is 0.

— Function: int mu_address_get_group_count (mu_address_t addr, size_t *)
— Function: int mu_address_get_email_count (mu_address_t addr, size_t *)
— Function: int mu_address_get_unix_mailbox_count (mu_address_t addr, size_t *)
— Function: int mu_address_contains_email (mu_address_t addr, const char *email)
— Function: int mu_address_union (mu_address_t *a, mu_address_t b)
— Function: size_t mu_address_format_string (mu_address_t addr, char *buf, size_t buflen)

Example

     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     #include <stdio.h>
     #include <string.h>
     #include <errno.h>
     
     #include <mailutils/address.h>
     #include <mailutils/errno.h>
     #include <mailutils/mutil.h>
     
     #define EPARSE MU_ERR_NOENT
     
     static int
     parse (const char *str)
     {
       size_t no = 0;
       size_t pcount = 0;
       int status;
       char buf[BUFSIZ];
       mu_address_t address = NULL;
     
       mu_set_user_email_domain ("localhost");
       status = mu_address_create (&address, str);
       mu_address_get_count (address, &pcount);
     
       if (status)
         {
           printf ("%s=> error %s\n\n", str, mu_errname (status));
           return 0;
         }
       else
         {
           printf ("%s=> pcount %lu\n", str, (unsigned long) pcount);
         }
     
       for (no = 1; no <= pcount; no++)
         {
           size_t got = 0;
           int isgroup;
     
           mu_address_is_group (address, no, &isgroup);
           printf ("%lu ", (unsigned long) no);
     
           if (isgroup)
             {
               mu_address_get_personal (address, no, buf, sizeof (buf), &got);
               printf ("group <%s>\n", buf);
             }
           else
             {
               mu_address_get_email (address, no, buf, sizeof (buf), 0);
               printf ("email <%s>\n", buf);
             }
     
           mu_address_get_personal (address, no, buf, sizeof (buf), &got);
           if (got && !isgroup)
             printf ("   personal <%s>\n", buf);
     
           mu_address_get_comments (address, no, buf, sizeof (buf), &got);
           if (got)
             printf ("   comments <%s>\n", buf);
     
           mu_address_get_local_part (address, no, buf, sizeof (buf), &got);
           if (got)
             {
               printf ("   local-part <%s>", buf);
     
               mu_address_get_domain (address, no, buf, sizeof (buf), &got);
               if (got)
                 printf (" domain <%s>", buf);
     
               printf ("\n");
             }
     
           mu_address_get_route (address, no, buf, sizeof (buf), &got);
           if (got)
             printf ("   route <%s>\n", buf);
         }
       mu_address_destroy (&address);
     
       printf ("\n");
       return 0;
     }
     
     static int
     parseinput (void)
     {
       char buf[BUFSIZ];
     
       while (fgets (buf, sizeof (buf), stdin) != 0)
         {
           buf[strlen (buf) - 1] = 0;
           parse (buf);
         }
     
       return 0;
     }
     
     int
     main (int argc, const char *argv[])
     {
       argc = 1;
     
       if (!argv[argc])
         return parseinput ();
     
       for (; argv[argc]; argc++)
         {
           if (strcmp (argv[argc], "-") == 0)
     	parseinput ();
           else
     	parse (argv[argc]);
         }
     
       return 0;
     }