[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4. Mailutils Libraries

4.1 Framework  The Core Library.
4.2 Authentication Library  Auxiliary Library for Authenticating Users.
4.3 Mailutils to Scheme Interface  
4.4 Sieve Library  GNU Implementation of Sieve Mail Filtering.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1 Framework

4.1.1 Folder  
4.1.2 Mailbox  
4.1.3 Mailer  Protocol Used to Send Mail.
4.1.4 Message  
4.1.5 Envelope  
4.1.6 Headers  
4.1.7 Body  
4.1.8 Attribute  
4.1.9 Stream  
4.1.10 Iterator  
4.1.11 Authenticator  
4.1.12 Address  
4.1.13 Locker  
4.1.14 URL  Uniform Resource Locators.
4.1.15 Parse822  Parsing RFC 822 headers.
4.1.16 Mailcap  Parsing RFC 1524 file.

Wherever the mail is and whatever format it is stored in, it is operated upon using the same set of functions. To unified the C API, GNU Mailutils offers a heteroclite set of objects that work in aggregation to do operations on emails. Each object does a specific task and delegates non-related tasks to others. The object comes alive by specifying a URL parameter when created, it will indicate the storage format or protocol (POP3, IMAP4, MH, MAILDIR, etc ..).

 
                          folder_t                  url_t
  -/var/mail-    +- .. ->+-----------------+   +-->+------------+
 (  alain *-)-+  |       |   url_t       *-|---+   |   port     |
  ----------  |  |       |-----------------|       |   hostname |
 (  jakob *-)-+--+       |   auth_t      *-|---+   |   file     |
  ----------  |          |-----------------|   |   |   ...      |
 (  jeff  *-)-+          |   stream_t      |   |   +------------+
  ----------  |          |-----------------|   |
 (  shaleh*-)-+          |   .....         |   |    auth_t
  ----------             |-----------------|   +-->+------------+
                     +---|-* mailbox_t[]   |       |   ticket_t |
  mailbox_t          |   +-----------------+       +------------+
 +----------------+<-+
 |   locker_t  *--|-------------+
 |----------------|             |
 |   url_t        |             |          locker_t
 |----------------|             +-------->+---------+
 |   stream_t     |                       | lock    |
 |----------------|                       | unlock  |
 |  message_t[] *-|-------+               +---------+
 +----------------+       |                     envelope_t
                          |          +-------->+-----------+
  message_t               |          |         | date      |
 +----------------+<------+          |         | from      |
 |   envelope_t *-|------------------+         | to        |
 |----------------|              header_t      +-----------+
 |   header_t   *-|------------>+--------------+
 |----------------|             |   stream_t   |
 |   body_t     *-|----+        +--------------+
 +----------------+    |    body_t
                       +-->+--------------+
                           |   stream_t   |
                           +--------------+

As an example, here is a simplified version of from command. It lists the `From' and `Subject' headers of every mail in a mailbox.

 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <mailutils/mailutils.h>

int
main (int argc, const char **argv)
{
  char *from;
  char *subject;
  mailbox_t mbox;
  size_t msgno, total = 0;
  int status;

  /* Register the formats. */
  mu_register_all_mbox_formats ();

  status = mailbox_create_default (&mbox, argv[1]);
  if (status != 0)
    {
      mu_error ("mailbox_create: %s", mu_strerror (status));
      exit (EXIT_FAILURE);
    }

  status = mailbox_open (mbox, MU_STREAM_READ);
  if (status != 0)
    {
      mu_error ("mailbox_open: %s", mu_strerror (status));
      exit (EXIT_FAILURE);
    }

  mailbox_messages_count (mbox, &total);

  for (msgno = 1; msgno <= total; msgno++)
    {
      message_t msg;
      header_t hdr;

      if ((status = mailbox_get_message (mbox, msgno, &msg)) != 0
          || (status = message_get_header (msg, &hdr)) != 0)
        {
          mu_error ("Error message: %s", mu_strerror (status));
          exit (EXIT_FAILURE);
        }

      if (header_aget_value (hdr, MU_HEADER_FROM, &from))
        from = strdup ("(NO FROM)");

      if (header_aget_value (hdr, MU_HEADER_SUBJECT, &subject))
        subject = strdup ("(NO SUBJECT)");

      printf ("%s\t%s\n", from, subject);
      free (from);
      free (subject);
    }

  status = mailbox_close (mbox);
  if (status != 0)
    {
      mu_error ("mailbox_close: %s", mu_strerror (status));
      exit (EXIT_FAILURE);
    }

  mailbox_destroy (&mbox);
  return 0;
}

Here is a sample output produced by this program:

 
% ./sfrom pop://alain@localhost
Passwd: xxxx
Jim Meyering <meyering@foo.org>      fetish(shellutils) beta
François Pinard <pinard@bar.org> recode new alpha
...


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.1 Folder

 
/* Prefix folder_ is reserved. */
#include <mailutils/folder.h>

 
                             folder_t                  url_t
  -/var/mail-    +---//--->/-----------------\   +-->/-----------\
 (  alain *-)-+  |         |  url_t        *-|---+   |  port     |
  ----------  |  |         |-----------------+       |  hostname |
 (  jakob *-)-+--+         |  observer_t   *-|       |  file     |
  ----------  |            |-----------------+       |  ...      |
 (  jeff  *-)-+            |  stream_t       |       \-----------/
  ----------  |            |-----------------|
 (  sean  *-)-+            |  auth_t         |
  ----------               |-----------------|
                           |  mailbox_t(1)   |
                           |-----------------|
                           |  mailbox_t(2)   |
                           |  ......         |
                           |  mailbox_t(n)   |
                           \-----------------/

Data structures:

 
struct list_response
{
  int type;
  int separator;
  char *name;
};

struct folder_list
{
  struct list_response **element;
  size_t num;
};

Function: int folder_create (folder_t *, const char *url)

Function: void folder_destroy (folder_t *)

Function: int folder_open (folder_t, int flag)

Function: int folder_close (folder_t)

Function: int folder_delete (folder_t, const char *mailbox)

Function: int folder_rename (folder_t, const char *, const char *mailbox)

Function: int folder_subscribe (folder_t, const char *mailbox)

Function: int folder_unsubscribe (folder_t, const char *mailbox)

Function: int folder_list (folder_t, const char *ref, const char *wcard, struct folder_list *)

Function: int folder_lsub (folder_t, const char *ref, const char *wcard, struct folder_list *)

Function: int folder_list_destroy (struct folder_list *)

Function: int folder_get_stream (folder_t, stream_t *)

Function: int folder_set_stream (folder_t, stream_t)

Function: int folder_get_observable (folder_t, observable_t *)

Function: int folder_has_debug (folder_t)

Function: int folder_get_debug (folder_t, mu_debug_t *)

Function: int folder_set_debug (folder_t, mu_debug_t)

Function: int folder_get_authority (folder_t, authority_t *)

Function: int folder_set_authority (folder_t, authority_t)

Function: int folder_get_url (folder_t, url_t *)

Function: int folder_set_url (folder_t, url_t)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.2 Mailbox

 
/* Prefix mailbox_ is reserved. */
#include <mailutils/mailbox.h>

Data Type: mailbox_t
The mailbox_t object is used to hold information and it is an opaque data structure to the user. Functions are provided to retrieve information from the data structure.

 
                             mailbox_t                  url_t
  -/var/mail-    +---//--->/-----------------\   +-->/-----------\
 (  alain   )    |         |  url_t        *-|---+   |  port     |
  ----------     |         |-----------------+       |  hostname |
 (  jakob *-)----+         |  observer_t   *-|       |  file     |
  ----------               |-----------------+       |  ...      |
 (  jeff    )              |  stream_t       |       \-----------/
  ----------               |-----------------|
 (  sean    )              |  locker_t       |
  ----------               |-----------------|
                           |  message_t(1)   |
                           |-----------------|
                           |  message_t(2)   |
                           |  ......         |
                           |  message_t(n)   |
                           \-----------------/

Function: int mailbox_create (mailbox_t *mbox, const char *name)
The function mailbox_create allocates and initializes mbox. The concrete mailbox type instantiate is based on the scheme of the url name.

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

MU_ERR_OUT_PTR_NULL
The pointer mbox supplied is NULL.
MU_ERR_NO_HANDLER
The url name supplied is invalid or not supported.
EINVAL
ENOMEM
Not enough memory to allocate resources.

Function: int mailbox_create_default (mailbox_t *mbox, const char *name)
Create a mailbox with mailbox_create() based on the environment variable MAIL or the string formed by _PATH_MAILDIR/user" or LOGNAME if user is null,

Function: void mailbox_destroy (mailbox_t *mbox)
Destroys and releases resources held by mbox.

Function: int mailbox_open (mailbox_t mbox, int flag)
A connection is open, if no stream was provided, a stream is created based on the mbox type. The flag can be OR'ed. See stream_create() for flag's description.

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

EAGAIN
EINPROGRESS
Operation in progress.
EBUSY
Resource busy.
MU_ERROR_INVALID_PARAMETER
mbox is NULL or flag is invalid.
ENOMEM
Not enough memory.

Function: int mailbox_close (mailbox_t mbox)
The stream attach to mbox is closed.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.

Function: int mailbox_flush (mailbox_t mbox, int expunge)

Function: int mailbox_get_folder (mailbox_t mbox, folder_t *folder)
Get the folder.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.

Function: int mailbox_set_folder (mailbox_t mbox, folder_t folder)

Function: int mailbox_uidvalidity (mailbox_t mbox, unsigned long *number);
Give the uid validity of mbox.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.

Function: int mailbox_uidnext (mailbox_t mbox, size_t *number);
Give the next predicted uid for mbox.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.

Function: int mailbox_get_message (mailbox_t mbox, size_t msgno, message_t *message)
Retrieve message number msgno, message is allocated and initialized.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL or msgno is invalid.
ENOMEM
Not enough memory.

Function: int mailbox_append_message (mailbox_t mbox, message_t message)
The message is appended to the mailbox mbox.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL or message is invalid.

Function: int mailbox_messages_count (mailbox_t mbox, size_t *number);
Give the number of messages in mbox.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.

Function: int mailbox_messages_recent (mailbox_t mbox, size_t *number);
Give the number of recent messages in mbox.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.

Function: int mailbox_message_unseen (mailbox_t mbox, size_t *number);
Give the number of first unseen message in mbox.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.

Function: int mailbox_expunge (mailbox_t mbox)
All messages marked for deletion are removed.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.

Function: int mailbox_save_attributes (mailbox_t mbox)

Function: int mailbox_get_size (mailbox_t mbox, off_t *size)
Gives the mbox size.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.

Function: int mailbox_is_updated (mailbox_t mbox)

Function: int mailbox_scan (mailbox_t mbox, size_t msgno, size_t *count);
Scan the mailbox for new messages starting at message msgno.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.
ENOMEM
Not enough memory.

Function: int mailbox_get_stream (mailbox_t mbox, stream_t *stream)
The mailbox stream is put in stream.

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

MU_ERROR_INVALID_PARAMETER
mbox is invalid or stream is NULL.

Function: int mailbox_set_stream (mailbox_t mbox, stream_t stream)
Set the stream connection to use for the mailbox.

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

MU_ERROR_INVALID_PARAMETER
mbox or stream is NULL.

Function: int mailbox_get_locker (mailbox_t mbox, locker_t *locker)
Get the locker_t object.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.

Function: int mailbox_set_locker (mailbox_t mbox, locker_t locker)
Set the type of locking done by the mbox.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.

Function: int mailbox_get_property (mailbox_t mbox, property_t *property)
Get the property object. The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
mbox is NULL.
ENOMEM

Function: int mailbox_get_url (mailbox_t mbox, url_t *url)
Gives the constructed url.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.

Function: int mailbox_has_debug (mailbox_t mbox)

Function: int mailbox_get_debug (mailbox_t mbox, mu_debug_t *debug)
Get a debug object. The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
mbox is NULL.
ENOMEM

Function: int mailbox_set_debug (mailbox_t mbox, mu_debug_t debug)

Function: int mailbox_get_observable (mailbox_t mbox mbox, observable_t *observable)
Get the observable object.

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

MU_ERROR_INVALID_PARAMETER
mbox is NULL.
ENOMEM
Not enough memory.

Function: int mailbox_lock (mailbox_t mbox)

Function: int mailbox_unlock (mailbox_t mbox)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.3 Mailer

 
/* Prefix mailer_ is reserved. */
#include <mailutils/mailer.h>

Function: int mailer_create (mailer_t *, const char *url)

Function: void mailer_destroy (mailer_t *)

Function: int mailer_open (mailer_t, int flags)

Function: int mailer_close (mailer_t)

Function: int mailer_send_message (mailer_t mailer, message_t msg, address_t from, address_t to);

If from is not NULL, it must contain a single fully qualified RFC2822 email address which will be used as the envelope from address. This is the address to which delivery status notifications are sent, so it never matters what it is set to until it really matters. This is equivalent to Sendmail's `-f' flag.

The default for from is provided by the specific mailer.

If to is not NULL, then the message will be sent to the list of addresses that it specifies.

The default for to is to use the contents of the standard "To:", "Cc:", and "Bcc:" fields, this is equivalent to Sendmail's `-t' flag.

Function: int mailer_get_property (mailer_t, property_t *)

Function: int mailer_get_stream (mailer_t, stream_t *)

Function: int mailer_set_stream (mailer_t, stream_t)

Function: int mailer_get_debug (mailer_t, mu_debug_t *)

Function: int mailer_set_debug (mailer_t, mu_debug_t)

Function: int mailer_get_observable (mailer_t, observable_t *)

Function: int mailer_get_url (mailer_t, url_t *)

Function: int mailer_check_from (address_t from)

Function: int mailer_check_to (address_t to)

Some Usage Notes

Some possible use cases the API must support are:

- original submission

1 - fill in header addresses

2 - mailer_send_message(mailer, msg, NULL, NULL)

- from will be filled in if missing,

- Bcc's will be deleted before delivery to a non-bcc address,

- message-id and date will be added, if missing,

- a To: or Apparently-To: will be added if non is present (for RFC compliance)

- MTA-style `.forward' (and Sieve-style redirect)

1 - get the envelope from of the message to be forwarded

2 - mailer_send_message(mailer, msg, from, to)

- MUA-style bounce

1 - add Resent-[To,From,...]

2 - mailer_send_message(mailer, msg, NULL, to)

- DSN "bounce"

1 - compose DSN

2 - mailer_deliver(mailer, msg, address_t("<>"), to)

Don't want mail loops, so the null but valid SMTP address of `<>' is the envelope From.

The Sendmail Mailer

`/sbin/sendmail' isn't always Sendmail... Sometimes it's a Sendmail-compatible wrapper, so assume `/sbin/sendmail' understands only a recipient list, `-f' and `-oi', these seem to be pretty basic. Cross fingers.

Pipe to "/sbin/sendmail -oi [-f from] [to...]", supplying `-f' if there was a from, and supplying the recipient list from the to (if there is no recipient list, assume it will read the message contents for the recipients).

Caution: since the stdout and stderr of Sendmail is closed, we have no way of ever giving feedback on failure. Also, what should the return code be from mailer_send_message() when Sendmail returns `1'? `1' maps to EPERM, which is less than descriptive!

The SMTP Mailer

This mailer does not canonicalize the message. This must be done before sending the message, or it may be assumed that the MTA will do so.

It does blind out the Bcc: header before sending, though.

Caution: Mutt always puts the recipient addresses on the command line, even Bcc: ones, do we strip the Bcc: before forwarding with SMTP?

Non-RFC822 Addresses

An address that has no domain is not and RFC822 email address. What do I do with them? Should the user of the API be responsible for determining what is mean by email to "John" means? Or should the be able to configure Sendmail to decide globally what this means. If so, we can pass the address to Sendmail, but we have to decide for SMTP! So, right now these addresses are rejected. This could be changed.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.4 Message

 
/* Prefix message_ is reserved. */
#include <mailutils/message.h>

The message_t object is a convenient way to manipulate messages. It encapsulates the envelope_t, the header_t and the body_t.

 
    mailbox_t
    ----------                   message_t
   (message[1])        +------>+--------------------+
    ----------         |       |  envelope_t        |
   (message[2])        |       |--------------------|
    ----------         |       |  header_t          |
   (message[3])--------+       |--------------------|
    ----------                 |  body_t            |
   (message[n])                |--------------------|
    ----------                 |  attribute_t       |
                               |--------------------|
                               |  stream_t          |
                               +--------------------+

Function: void message_create (message_t *msg, void *owner)

Function: void message_destroy (message_t *msg, void *owner)
The resources allocate for msg are freed.

Function: int message_create_copy (message_t *to, message_t *from)

Function: void* message_get_owner (message_t msg)

Function: int message_is_modified (message_t msg)

Function: int message_clear_modified (message_t msg)

Function: int message_get_mailbox (message_t msg, mailbox_t *mbox)

Function: int message_set_mailbox (message_t msg, mailbox_t mbox, void *owner)

Function: int message_ref (message_t msg)

Function: int message_get_envelope (message_t msg, envelope_t *envelope)

Function: int message_set_envelope (message_t msg, envelope_t envelope, void *owner)

Function: int message_get_header (message_t msg, header_t *header)
Retrieve msg header.

Function: int message_set_header (message_t msg, header_t header, void *owner)

Function: int message_get_body (message_t msg, body_t *body)

Function: int message_set_body (message_t msg, body_t body, void *owner)

Function: int message_get_stream (message_t msg, stream_t *stream)

Function: int message_set_stream (message_t msg, stream_t stream, void *owner)

Function: int message_get_attribute (message_t msg, attribute_t *attribute)

Function: int message_set_attribute (message_t msg, attribute_t attribute, void *owner)

Function: int message_get_observable (message_t msg, observable_t *observable)

Function: int message_is_multipart (message_t msg, int *multi)
Set *multi to non-zero value if msg is multi-part.

Function: int message_set_is_multipart (message_t msg, int (*_is_multipart) (message_t, int *), void *);

Function: int message_size (message_t msg, size_t *size)

Function: int message_set_size (message_t msg, int (*_size) (message_t, size_t *), void *owner)

Function: int message_lines (message_t msg, size_t *size)

Function: int message_set_lines (message_t msg, int (*_lines) (message_t, size_t *), void *owner)

Function: int message_get_num_parts (message_t msg, size_t *nparts)

Function: int message_set_get_num_parts (message_t msg, int (*_get_num_parts) (message_t, size_t *), void *owner)

Function: int message_get_part (message_t msg, size_t part, message_t *msg)

Function: int message_set_get_part (message_t msg, int (*_get_part) (message_t, size_t, message_t *), void *owner)

Function: int message_get_uidl (message_t msg, char *buffer, size_t buflen, size_t *writen)

Function: int message_set_uidl (message_t msg, int (*_get_uidl) (message_t, char *, size_t, size_t *), void *owner)

Function: int message_get_uid (message_t msg, size_t *uid)

Function: int message_set_uid (message_t msg, int (*_get_uid) (message_t, size_t *), void *owner)

Function: int message_create_attachment (const char *content_type, const char *encoding, const char *filename, message_t *newmsg)

Function: int message_save_attachment (message_t msg, const char *filename, void **data)

Function: int message_encapsulate (message_t msg, message_t *newmsg, void **data)

Function: int message_unencapsulate (message_t msg, message_t *newmsg, void **data);

Function: int message_get_attachment_name (message_t msg, char *name, size_t bufsize, size_t *size);

Function: int message_aget_attachment_name (message_t msg, char **name);

Function: int message_save_to_mailbox (message_t msg, ticket_t ticket, mu_debug_t debug, const char *toname);


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.5 Envelope

 
/* Prefix envelope_ is reserved. */
#include <mailutils/envelope.h>

Function: int envelope_create (envelope_t *, void *)
Primarily for internal use.

Function: void envelope_destroy (envelope_t *, void *)
Primarily for internal use.

Function: void* envelope_get_owner (envelope_t)

Function: int envelope_sender (envelope_t, char *, size_t, size_t *)
Get the address that this message was reportedly received from. This would be the "mail from" argument if the message was delivered or received via SMTP, for example.

Function: int envelope_set_sender (envelope_t, int (*_sender) (envelope_t, char *, size_t, size_t *), void *)
Primarily for internal use. The implementation of envelope_t depends on the mailbox type, this allows the function which actually gets the sender to be set by the creator of an envelope_t.

Function: int envelope_date (envelope_t, char *, size_t, size_t *)
Get the date that the message was delivered to the mailbox, in something close to ANSI ctime() format: Mon Jul 05 13:08:27 1999.

Function: int envelope_set_date (envelope_t, int (*_date) (envelope_t, char *, size_t, size_t *), void *)
Primarily for internal use. The implementation of envelope_t depends on the mailbox type, this allows the function which actually gets the date to be set by the creator of an envelope_t.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.6 Headers

 
/* Prefix header_ is reserved. */
#include <mailutils/header.h>

So far we plan support for RFC822 and plan for RFC1522. With RFC1522 non-ASCII characters will be encoded.

Function: int header_create (header_t *hdr, const char *blurb, size_t len, void *owner)
Initialize a hdr to a supported type. If blurb is not NULL, it is parsed.

Function: void header_destroy (header_t *hdr, void *owner)
The resources allocated for hdr are freed.

Function: void* header_get_owner (header_t *hdr)

Function: int header_is_modified (header_t hdr)

Function: int header_clear_modified (header_t hdr)

Function: int header_set_value (header_t hdr, const char *fn, const char *fv, int n)

Some basic macros are already provided for RFC822.

MU_HEADER_UNIX_FROM
From
MU_HEADER_RETURN_PATH
Return-Path
MU_HEADER_RECEIVED
Received
MU_HEADER_DATE
Date
MU_HEADER_FROM
From
MU_HEADER_SENDER
Sender
MU_HEADER_RESENT_FROM
Resent-From
MU_HEADER_SUBJECT
Subject
MU_HEADER_SENDER
Sender
MU_HEADER_RESENT_SENDER
Resent-SENDER
MU_HEADER_TO
To
MU_HEADER_RESENT_TO
Resent-To
MU_HEADER_CC
Cc
MU_HEADER_RESENT_CC
Resent-Cc
MU_HEADER_BCC
Bcc
MU_HEADER_RESENT_BCC
Resent-Bcc
MU_HEADER_REPLY_TO
Reply-To
MU_HEADER_RESENT_REPLY_TO
Resent-Reply-To
MU_HEADER_MESSAGE_ID
Message-ID
MU_HEADER_RESENT_MESSAGE_ID
Resent-Message-ID
MU_HEADER_IN_REPLY_TO
In-Reply-To
MU_HEADER_REFERENCE
Reference
MU_HEADER_REFERENCES
References
MU_HEADER_ENCRYPTED
Encrypted
MU_HEADER_PRECEDENCE
Precedence
MU_HEADER_STATUS
Status
MU_HEADER_CONTENT_LENGTH
Content-Length
MU_HEADER_CONTENT_LANGUAGE
Content-Language
MU_HEADER_CONTENT_TRANSFER_ENCODING
Content-transfer-encoding
MU_HEADER_CONTENT_ID
Content-ID
MU_HEADER_CONTENT_TYPE
Content-Type
MU_HEADER_CONTENT_DESCRIPTION
Content-Description
MU_HEADER_CONTENT_DISPOSITION
Content-Disposition
MU_HEADER_CONTENT_MD5
Content-MD5
MU_HEADER_MIME_VERSION
MIME-Version
MU_HEADER_X_UIDL
X-UIDL
MU_HEADER_X_UID
X-UID
MU_HEADER_X_IMAPBASE
X-IMAPbase
MU_HEADER_ENV_SENDER
X-Envelope-Sender
MU_HEADER_ENV_DATE
X-Envelope-Date
MU_HEADER_FCC
Fcc
MU_HEADER_DELIVERY_DATE
Delivery-date
MU_HEADER_ENVELOPE_TO
Envelope-to

Function: int header_get_value (header_t hdr, const char *fn, char *fv, size_t len, size_t *n)
Value of field-name fn is returned in buffer fv of size len. The number of bytes written is put in n.

Function: int header_aget_value (header_t hdr, const char *fn, char **fv)
The value is allocated.

Function: int header_get_address (header_t hdr, const char *buf, address_t *addr)

Function: int header_get_stream (header_t hdr, stream_t *stream)

Function: int header_set_stream (header_t hdr, stream_t stream, void *)

Function: int header_get_field_count (header_t hdr, size_t *count)

Function: int header_get_field_value (header_t hdr, size_t index, char *, size_t, size_t *)

Function: int header_get_field_name (header_t hdr, size_t index, char *, size_t, size_t *)

Function: int header_aget_field_value (header_t hdr, size_t index, char **)

Function: int header_aget_field_name (header_t hdr, size_t index, char **)

Function: int header_get_value_unfold (header_t hdr, const char *name, char *buffer, size_t buflen, size_t *n)

Function: int header_aget_value_unfold (header_t hdr, const char *name, char **value)

Function: int header_get_field_value_unfold (header_t hdr, size_t num, char *buf, size_t buflen, size_t *nwritten)

Function: int header_aget_field_value_unfold (header_t hdr, size_t num, char **value);

Function: int header_size (header_t hdr, size_t *);

Function: int header_lines (header_t hdr, size_t *);

Function: int header_set_set_value (header_t hdr, int (*_set_value) (header_t, const char *, const char *, int), void *);

Function: int header_set_get_value (header_t hdr, int (*_get_value) (header_t, const char *, char *, size_t, size_t *), void *);

Function: int header_set_get_fvalue (header_t hdr, int (*_get_value) (header_t, const char *, char *, size_t, size_t *), void *);

Function: int header_set_size (header_t hdr, int (*_size) (header_t, size_t *), void *);

Function: int header_set_lines (header_t hdr, int (*_lines) (header_t, size_t *), void *);

Function: int header_set_fill (header_t hdr, int (*_fill) (header_t, char *, size_t, off_t, size_t *), void *owner);


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.7 Body

 
/* Prefix body_ is reserved. */
#include <mailutils/body.h>

Function: int body_create (body_t *body, void *owner)
Initialize an object body.

Function: void body_destroy (body_t *body)
The resources allocated are release.

Function: void* body_get_owner (body_t body)

Function: int body_is_modified (body_t body)

Function: int body_clear_modified (body_t body)

Function: int body_get_stream (body_t body, stream_t *stream)

Function: int body_set_stream (body_t body, stream_t stream, void *owner)

Function: int body_get_filename (body_t body, char *buffer, size_t buflen, size_t *writen)

Function: int body_size (body_t body, size_t *size)

Function: int body_set_size (body_t body, int (*_size) (body_t, size_t *), void *owner)

Function: int body_lines (body_t body, size_t *lines)

Function: int body_set_lines (body_t body, int (*_lines) (body_t, size_t *), void *owner)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.8 Attribute

 
/* Prefix attribute_ is reserved. */
#include <mailutils/attribute.h>

Function: int attribute_create (attribute_t *attr, void *)

Function: void attribute_destroy (attribute_t *attr, void *)

Function: void* attribute_get_owner (attribute_t attr)

Function: int attribute_is_modified (attribute_t attr)

Function: int attribute_clear_modified (attribute_t attr)

Function: int attribute_set_modified (attribute_t attr)

Function: int attribute_is_userflag (attribute_t attr)

Function: int attribute_is_seen (attribute_t attr)

Function: int attribute_is_answered (attribute_t attr)

Function: int attribute_is_flagged (attribute_t attr)

Function: int attribute_is_deleted (attribute_t attr)

Function: int attribute_is_draft (attribute_t attr)

Function: int attribute_is_recent (attribute_t attr)

Function: int attribute_is_read (attribute_t attr)

Function: int attribute_set_userflag (attribute_t attr, int)

Function: int attribute_set_seen (attribute_t attr)

Function: int attribute_set_answered (attribute_t attr)

Function: int attribute_set_flagged (attribute_t attr)

Function: int attribute_set_deleted (attribute_t attr)

Function: int attribute_set_draft (attribute_t attr)

Function: int attribute_set_recent (attribute_t attr)

Function: int attribute_set_read (attribute_t attr)

Function: int attribute_unset_userflag (attribute_t attr, int)

Function: int attribute_unset_seen (attribute_t attr)

Function: int attribute_unset_answered (attribute_t attr)

Function: int attribute_unset_flagged (attribute_t attr)

Function: int attribute_unset_deleted (attribute_t attr)

Function: int attribute_unset_draft (attribute_t attr)

Function: int attribute_unset_recent (attribute_t attr)

Function: int attribute_unset_read (attribute_t attr)

Function: int attribute_get_flags (attribute_t attr, int *)

Function: int attribute_set_flags (attribute_t attr, int)

Function: int attribute_unset_flags (attribute_t attr, int)

Function: int attribute_set_set_flags (attribute_t attr, int (*_set_flags) (attribute_t, int), void *)

Function: int attribute_set_unset_flags (attribute_t attr, int (*_unset_flags) (attribute_t, int), void *)

Function: int attribute_set_get_flags (attribute_t attr, int (*_get_flags) (attribute_t, int *), void *)

Function: int attribute_is_equal (attribute_t attr1, attribute_t attr2)

Function: int attribute_copy (attribute_t dst, attribute_t src)

Function: int attribute_to_string (attribute_t attr, char *buf, size_t len, size_t *writen)

Function: int string_to_flags (const char *buf, int *)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.9 Stream

 
#include <mailutils/stream.h>

These generic flags are interpreted as appropriate to the specific streams.

MU_STREAM_READ
The stream is open read only.
MU_STREAM_WRITE
The stream is open write only.
MU_STREAM_RDWR
The stream is open read and write.
MU_STREAM_APPEND
The stream is open in append mode for writing.
MU_STREAM_CREAT
The stream open will create the underlying resource (such as a file) if it doesn't exist already.
MU_STREAM_NONBLOCK
The stream is set non blocking.
MU_STREAM_NO_CHECK
Stream is destroyed without checking for the owner.
MU_STREAM_SEEKABLE

MU_STREAM_NO_CLOSE
Stream doesn't close it's underlying resource when it is closed or destroyed.
MU_STREAM_ALLOW_LINKS

Function: int file_stream_create (stream_t *stream, const char *filename, int flags)

Function: int tcp_stream_create (stream_t *stream, const char *host, int port, int flags)

Function: int mapfile_stream_create (stream_t *stream, const char *filename, int flags)

Function: int memory_stream_create (stream_t *stream, const char *filename, int flags)

Function: int encoder_stream_create (stream_t *stream, stream_t iostream, const char *encoding)

Function: int decoder_stream_create (stream_t *stream, stream_t iostream, const char *encoding)

Function: int stdio_stream_create (stream_t *stream, FILE *stdio, int flags)
If MU_STREAM_NO_CLOSE is specified, fclose() will not be called on stdio when the stream is closed.

Function: int prog_stream_create (stream_t *stream, const char *progname, int flags)

Function: int filter_prog_stream_create (stream_t *stream, const char *progname, stream_t input)

Function: void stream_destroy (stream_t *stream, void *owner)

Function: int stream_open (stream_t stream)

Function: int stream_close (stream_t stream)

Function: int stream_is_seekable (stream_t stream)

Function: int stream_get_fd (stream_t stream, int *fd)

Function: int stream_get_fd2 (stream_t stream, int *fd1, int *fd2)

Function: int stream_read (stream_t stream, char *buffer, size_t buflen, off_t offset, size_t *writen)

Function: int stream_readline (stream_t stream, char *buffer, size_t buflen, off_t offset, size_t *writen)

Function: int stream_size (stream_t stream, off_t *size)

Function: n int stream_truncate (stream_t stream, off_t size)

Function: int stream_write (stream_t stream, const char *buffer, size_t buflen, off_t offset, size_t *writen)

Function: int stream_setbufsiz (stream_t stream, size_t size)

Function: int stream_flush (stream_t stream)

Function: int stream_create (stream_t *stream, int flags, void *owner)
Used to implement a new kind of stream.

Function: void* stream_get_owner (stream_t stream)

Function: void stream_set_owner (stream_t stream, void *owner)

Function: int stream_get_flags (stream_t stream, int *flags)

Function: int stream_set_flags (stream_t stream, int flags)

Function: int stream_get_property (stream_t stream, property_t *)

Function: int stream_set_property (stream_t stream, property_t, void *)

Function: int stream_get_state (stream_t stream, int *state)
MU_STREAM_STATE_OPEN
Last action was stream_open.
MU_STREAM_STATE_READ
Last action was stream_read or stream_readline.
MU_STREAM_STATE_WRITE
Last action was stream_write.
MU_STREAM_STATE_CLOSE
Last action was stream_close.

Function: int stream_set_destroy (stream_t stream, void (*_destroy) (stream_t), void *owner)

Function: int stream_set_open (stream_t stream, int (*_open) (stream_t), void *owner)

Function: int stream_set_close (stream_t stream, int (*_close) (stream_t), void *owner)

Function: int stream_set_fd (stream_t stream, int (*_get_fd) (stream_t, int *, int *), void *owner)

Function: int stream_set_read (stream_t stream, int (*_read) (stream_t, char *, size_t, off_t, size_t *), void *owner)

Function: int stream_set_readline (stream_t stream, int (*_readline) (stream_t, char *, size_t, off_t, size_t *), void *owner)

Function: int stream_set_size (stream_t stream, int (*_size) (stream_t, off_t *), void *owner)

Function: int stream_set_truncate (stream_t stream, int (*_truncate) (stream_t, off_t), void *owner)

Function: int stream_set_write (stream_t stream, int (*_write) (stream_t, const char *, size_t, off_t, size_t *), void *owner)

Function: int stream_set_flush (stream_t stream, int (*_flush) (stream_t), void *owner)

Function: int stream_set_strerror (stream_t stream, int (*_fp) (stream_t, char **), void *owner)

Function: int stream_sequential_readline (stream_ts stream, char *buf, size_t size, size_t *nbytes)

Function: int stream_sequential_write (stream_t stream, char *buf, size_t size)

Function: int stream_seek (stream_t stream, off_t off, int whence)

Function: int stream_strerror (stream_t stream, char **p)

An example using tcp_stream_create() to make a simple web client:

 
/* This is an example program to illustrate the use of stream functions.
   It connects to a remote HTTP server and prints the contents of its
   index page */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

#include <mailutils/mailutils.h>

const char *wbuf = "GET / HTTP/1.0\r\n\r\n";
char rbuf[1024];

int
main (void)
{
  int ret, off = 0;
  stream_t stream;
  size_t nb;
  
  ret = tcp_stream_create (&stream, "www.gnu.org", 80, MU_STREAM_NONBLOCK);
  if (ret != 0)
    {
      mu_error ("tcp_stream_create: %s", mu_strerror (ret));
      exit (EXIT_FAILURE);
    }

connect_again:
  ret = stream_open (stream);
  if (ret != 0)
    {
      if (ret == EAGAIN)
        {
	  int wflags = MU_STREAM_READY_WR;
	  stream_wait (stream, &wflags, NULL);
          goto connect_again;
        }
      mu_error ("stream_open: %s", mu_strerror (ret));
      exit (EXIT_FAILURE);
    }

write_again:
  ret = stream_write (stream, wbuf + off, strlen (wbuf), 0, &nb);
  if (ret != 0)
    {
      if (ret == EAGAIN)
        {
	  int wflags = MU_STREAM_READY_WR;
	  stream_wait (stream, &wflags, NULL);
          off += nb;
          goto write_again;
        }
      mu_error ("stream_write: %s", mu_strerror (ret));
      exit (EXIT_FAILURE);
    }

  if (nb != strlen (wbuf))
    {
      mu_error ("stream_write: %s", "nb != wbuf length");
      exit (EXIT_FAILURE);
    }

  do
    {
      ret = stream_read (stream, rbuf, sizeof (rbuf), 0, &nb);
      if (ret != 0)
        {
          if (ret == EAGAIN)
            {
	      int wflags = MU_STREAM_READY_RD;
	      stream_wait (stream, &wflags, NULL);
            }
          else
            {
              mu_error ("stream_read: %s", mu_strerror (ret));
              exit (EXIT_FAILURE);
            }
        }
      write (1, rbuf, nb);
    }
  while (nb || ret == EAGAIN);

  ret = stream_close (stream);
  if (ret != 0)
    {
      mu_error ("stream_close: %s", mu_strerror (ret));
      exit (EXIT_FAILURE);
    }

  stream_destroy (&stream, NULL);
  exit (EXIT_SUCCESS);
}


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.10 Iterator

 
/* Prefix iterator_ is reserved. */
#include <mailutils/iterator.h>

Function: int iterator_create (iterator_t *iterator, list_t)

Function: int iterator_dup (iterator_t *iterator, iterator_t orig)

Function: void iterator_destroy (iterator_t *)

Function: int iterator_first (iterator_t)

Function: int iterator_next (iterator_t)

Function: int iterator_current (iterator_t, void **item)

Function: int iterator_is_done (iterator_t)

Function: int iterator_get_list (iterator_t iterator, list_t *list)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.11 Authenticator

 
/* Prefixes authority_, ticket_, and wicket_ are reserved. */
#include <mailutils/auth.h>

There are many ways to authenticate to a server. To be flexible the authentication process is provided by three objects authority_t, ticket_t, and wicket_t. The authority_t can implement different protocol like APOP, MD5-AUTH, One Time Passwd, etc. By default if a mailbox does not understand or know how to authenticate it falls back to user/passwd authentication. The ticket_t is a way for Mailboxes and Mailers provide a way to authenticate when the URL does not contain enough information. The default action is to call the function authority_authenticate() which will get the user and passwd if not set, this function can be overridden by a custom method.

Function: int ticket_create (ticket_t *, void *owner)

Function: void ticket_destroy (ticket_t *, void *owner)

Function: int ticket_set_destroy (ticket_t, void (*) (ticket_t), void *owner)

Function: void* ticket_get_owner (ticket_t)

Function: int ticket_set_pop (ticket_t, int (*_pop) (ticket_t, url_t, const char *, char **), void *)

Function: int ticket_pop (ticket_t, url_t, const char *, char **)

Function: int ticket_set_data (ticket_t, void *, void *owner)

Function: int ticket_get_data (ticket_t, void **)

Function: int authority_create (authority_t *, ticket_t, void *)

Function: void authority_destroy (authority_t *, void *)

Function: void* authority_get_owner (authority_t)

Function: int authority_set_ticket (authority_t, ticket_t)

Function: int authority_get_ticket (authority_t, ticket_t *)

Function: int authority_authenticate (authority_t)

Function: int authority_set_authenticate (authority_t, int (*_authenticate) (authority_t), void *)

Function: int authority_create_null (authority_t *authority, void *owner)

Function: int wicket_create (wicket_t *, const char *)

Function: void wicket_destroy (wicket_t *)

Function: int wicket_set_filename (wicket_t, const char *)

Function: int wicket_get_filename (wicket_t, char *, size_t, size_t *)

Function: int wicket_set_ticket (wicket_t, int (*) (wicket_t, const char *, const char *, ticket_t *))

Function: int wicket_get_ticket (wicket_t, ticket_t *, const char *, const char *)

A simple example of an authenticate function:

 
#include <stdio.h>
#include <string.h>
#include <mailutils/auth.h>

int
my_authenticate (auth_t auth, char **user, char **passwd)
{
  char u[128] = "";
  char p[128] = "";

  /* prompt the user name */
  printf ("User: ");
  fflush (stdout);
  fgets (u, sizeof (u), stdin);
  u[strlen (u) - 1] = '\0'; /* nuke the trailing NL */

  /* prompt the passwd */
  printf ("Passwd: "); fflush (stdout);
  echo_off ();
  fgets (p, sizeof(p), stdin);
  echo_on ();
  p[strlen (p) - 1] = '\0';

  /* duplicate */
  *user = strdup (u);
  *passwd = strdup (p);
  return 0;
}


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.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: address_t
The 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 address_create (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 address_createv (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 address_destroy (address_t *addr)
The addr is destroyed.

Function: int address_get_nth (address_t addr, size_t no, address_t *ret)

Function: int address_get_email (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 address_get_local_part (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 address_get_domain (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 address_get_personal (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 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 address_get_comments (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 address_get_route (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 address_aget_email (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 address_aget_local_part (address_t addr, size_t no, char **buf)

Function: int address_aget_domain (address_t addr, size_t no, char **buf)

Function: int address_aget_personal (address_t addr, size_t no, char **buf)

Function: int address_is_group (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 address_to_string (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 address_get_count (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 address_get_group_count (address_t addr, size_t *)

Function: int address_get_email_count (address_t addr, size_t *)

Function: int address_get_unix_mailbox_count (address_t addr, size_t *)

Function: int address_contains_email (address_t addr, const char *email)

Function: int address_union (address_t *a, address_t b)

Function: size_t address_format_string (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];
  address_t address = NULL;

  mu_set_user_email_domain ("localhost");
  status = address_create (&address, str);
  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;

      address_is_group (address, no, &isgroup);
      printf ("%lu ", (unsigned long) no);

      if (isgroup)
        {
          address_get_personal (address, no, buf, sizeof (buf), &got);
          printf ("group <%s>\n", buf);
        }
      else
        {
          address_get_email (address, no, buf, sizeof (buf), 0);
          printf ("email <%s>\n", buf);
        }

      address_get_personal (address, no, buf, sizeof (buf), &got);
      if (got && !isgroup)
        printf ("   personal <%s>\n", buf);

      address_get_comments (address, no, buf, sizeof (buf), &got);
      if (got)
        printf ("   comments <%s>\n", buf);

      address_get_local_part (address, no, buf, sizeof (buf), &got);
      if (got)
        {
          printf ("   local-part <%s>", buf);

          address_get_domain (address, no, buf, sizeof (buf), &got);
          if (got)
            printf (" domain <%s>", buf);

          printf ("\n");
        }

      address_get_route (address, no, buf, sizeof (buf), &got);
      if (got)
        printf ("   route <%s>\n", buf);
    }
  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;
}


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.13 Locker

 
/* Prefix locker_ is reserved. */
#include <mailutils/locker.h>

Function: int locker_set_default_flags (int flags, enum mu_locker_set_mode mode)

Function: void locker_set_default_retry_timeout (time_t to)

Function: void locker_set_default_retry_count (size_t n)

Function: void locker_set_default_expire_timeout (time_t t)

Function: void locker_set_default_external_program (char *path)

A flags of 0 means that the default will be used.

Function: int locker_create (locker_t *, const char *filename, int flags)

Function: void locker_destroy (locker_t *)

Time is measured in seconds.

Function: int locker_set_flags (locker_t, int)

Function: int locker_set_expire_time (locker_t, int)

Function: int locker_set_retries (locker_t, int)

Function: int locker_set_retry_sleep (locker_t, int)

Function: int locker_set_external (locker_t, const char *program)

Function: int locker_get_flags (locker_t, int *)

Function: int locker_get_expire_time (locker_t, int*)

Function: int locker_get_retries (locker_t, int *)

Function: int locker_get_retry_sleep (locker_t, int *)

Function: int locker_get_external (locker_t, char **)

Function: int locker_lock (locker_t)

Function: int locker_touchlock (locker_t)

Function: int locker_unlock (locker_t)

Function: int locker_remove_lock (locker_t)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.14 URL

A mailbox or a mailer can be described in a URL, the string will contain the necessary information to initialize mailbox_t, or mailer_t properly.

POP3

The POP URL scheme contains a POP server, optional port number and the authentication mechanism. The general form is

 
pop://[<user>[;AUTH=<auth>]@]<host>[:<port>]
 or
pop://[<user>[:<passwd>]@]<host>[:<port>]

If :port is omitted the default value is 110. Different forms of authentication can be specified with ;AUTH=type. The special string ;AUTH=* indicates that the client will use a default scheme base on the capability of the server.

 
pop://obelix@gaulois.org
pop://asterix;AUTH=*@france.com
pop://falbala;AUTH=+APOP@france.com
pop://obelix;AUTH=+APOP@village.gaulois.org:2000
pop://obelix:menhir@village.gaulois.org:2000

For more complete information see RFC 2368.

IMAP

The IMAP URL scheme contains an IMAP server, optional port number and the authentication mechanism. The general form is

 
imap://[<user>[;AUTH=<type>]]@<host>[:port][/<mailbox>]
 or
imap://[<user>[:<passwd>]]@<host>[:port][/<mailbox>]

If :port is omitted the default value is 143. Different forms of authentication can be specified with ;AUTH=type. The special string ;AUTH=* indicates that the client will use a default scheme base on the capability of the server.

 
imap://obelix@imap.gaulois.org
imap://asterix;AUTH=*@imap.france.com
imap://asterix:potion@imap.france.com

For more complete information see RFC 2192.

File

Local folder should be handle by this URL. It is preferable to let the mailbox recognize the type of mailbox and take the appropriate action.

 
file://path
file://var/mail/user
file://home/obelix/Mail

For MMDF, MH local mailboxes URLs are provided, but it is preferable to use file://path and let the library figure out which one.

 
mmdf://path
mh://path

Mailto

After setting a mailer, mailto: is used to tell the mailer where and to whom the message is for.

 
mailto://hostname

Mailto can be used to generate short messages, for example to subscribe to mailing lists.

 
mailto://bug-mailutils@gnu.org?body=subscribe
mailto://bug-mailutils@gnu.org?Subject=hello&body=subscribe

For more complete information see RFC 2368.

URL Functions

Helper functions are provided to retrieve and set the URL fields.

Function: int url_create (url_t *url, const char *name)
Create the url data structure, but do not parse it.

Function: void url_destroy (url_t *url)
Destroy the url and free its resources.

Function: int url_parse (url_t)
Parses the url, after calling this the get functions can be called.

The syntax, condensed from RFC 1738, and extended with the ;auth= of RFC 2384 (for POP) and RFC 2192 (for IMAP) is:

 
url =
    scheme ":" [ "//"

    [ user [ ( ":" password ) | ( ";auth=" auth ) ] "@" ]

    host [ ":" port ]

    [ ( "/" urlpath ) | ( "?" query ) ] ]

This is a generalized URL syntax, and may not be exactly appropriate for any particular scheme.

Function: int url_get_scheme (const url_t, char *, size_t, size_t *)

Function: int url_get_user (const url_t, char *, size_t, size_t *)

Function: int url_get_passwd (const url_t, char *, size_t, size_t *)

Function: int url_get_auth (const url_t, char *, size_t, size_t *)

Function: int url_get_host (const url_t, char *, size_t, size_t *)

Function: int url_get_port (const url_t, long *)

Function: int url_get_path (const url_t, char *, size_t, size_t *)

Function: int url_get_query (const url_t, char *, size_t, size_t *)

Function: const char* url_to_string (const url_t)

Function: int url_is_scheme (url_t, const char *scheme)

Function: int url_is_same_scheme (url_t, url_t)

Function: int url_is_same_user (url_t, url_t)

Function: int url_is_same_path (url_t, url_t)

Function: int url_is_same_host (url_t, url_t)

Function: int url_is_same_port (url_t, url_t)

Function: char* url_decode (const char *string)
Decodes an RFC 1738 encoded string, returning the decoded string in allocated memory. If the string is not encoded, this degenerates to a strdup().

Function: int url_is_ticket (url_t ticket, url_t url)

Example

 
#include <stdio.h>
#include <string.h>
#include <mailutils/errno.h>
#include <mailutils/url.h>

int
main ()
{
  char str[1024];
  char buffer[1024];
  long port = 0;
  int len = sizeof (buffer);
  url_t u = NULL;

  while (fgets (str, sizeof (str), stdin) != NULL)
    {
      int rc;

      str[strlen (str) - 1] = '\0';     /* chop newline */
      if (strspn (str, " \t") == strlen (str))
        continue;               /* skip empty lines */
      if ((rc = url_create (&u, str)) != 0)
        {
          fprintf (stderr, "url_create %s ERROR: [%d] %s",
                   str, rc, mu_strerror (rc));
          exit (1);
        }
      if ((rc = url_parse (u)) != 0)
        {
          printf ("%s => FAILED: [%d] %s\n",
                  str, rc, mu_strerror (rc));
          continue;
        }
      printf ("%s => SUCCESS\n", str);

      url_get_scheme (u, buffer, len, NULL);
      printf ("\tscheme <%s>\n", buffer);

      url_get_user (u, buffer, len, NULL);
      printf ("\tuser <%s>\n", buffer);

      url_get_passwd (u, buffer, len, NULL);
      printf ("\tpasswd <%s>\n", buffer);

      url_get_auth (u, buffer, len, NULL);
      printf ("\tauth <%s>\n", buffer);

      url_get_host (u, buffer, len, NULL);
      printf ("\thost <%s>\n", buffer);

      url_get_port (u, &port);
      printf ("\tport %ld\n", port);

      url_get_path (u, buffer, len, NULL);
      printf ("\tpath <%s>\n", buffer);

      url_get_query (u, buffer, len, NULL);
      printf ("\tquery <%s>\n", buffer);

      url_destroy (&u);

    }
  return 0;
}


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.15 Parse822

 
/* Prefix parse822_ is reserved. */
#include <mailutils/parse822.h>

Function: int parse822_is_char (char c)

Function: int parse822_is_digit (char c)

Function: int parse822_is_ctl (char c)

Function: int parse822_is_space (char c)

Function: int parse822_is_htab (char c)

Function: int parse822_is_lwsp_char (char c)

Function: int parse822_is_special (char c)

Function: int parse822_is_atom_char (char c)

Function: int parse822_is_q_text (char c)

Function: int parse822_is_d_text (char c)

Function: int parse822_is_smtp_q (char c)

Function: int parse822_skip_crlf (const char **p, const char *e)

Function: int parse822_skip_lwsp_char (const char **p, const char *e)

Function: int parse822_skip_lwsp (const char **p, const char *e)

Function: int parse822_skip_comments (const char **p, const char *e)

Function: int parse822_skip_nl (const char **p, const char *e)

Function: int parse822_digits (const char **p, const char *e, int min, int max, int *digits)

Function: int parse822_special (const char **p, const char *e, char c)

Function: int parse822_comment (const char **p, const char *e, char **comment)

Function: int parse822_atom (const char **p, const char *e, char **atom)

Function: int parse822_quoted_pair (const char **p, const char *e, char **qpair)

Function: int parse822_quoted_string (const char **p, const char *e, char **qstr)

Function: int parse822_word (const char **p, const char *e, char **word)

Function: int parse822_phrase (const char **p, const char *e, char **phrase)

Function: int parse822_d_text (const char **p, const char *e, char **dtext)

Function: int parse822_address_list (address_t *a, const char *s)

Function: int parse822_mail_box (const char **p, const char *e, address_t *a)

Function: int parse822_group (const char **p, const char *e, address_t *a)

Function: int parse822_address (const char **p, const char *e, address_t *a)

Function: int parse822_route_addr (const char **p, const char *e, address_t *a)

Function: int parse822_route (const char **p, const char *e, char **route)

Function: int parse822_addr_spec (const char **p, const char *e, address_t *a)

Function: int parse822_unix_mbox (const char **p, const char *e, address_t *a)

Function: int parse822_local_part (const char **p, const char *e, char **local_part)

Function: int parse822_domain (const char **p, const char *e, char **domain)

Function: int parse822_sub_domain (const char **p, const char *e, char **sub_domain)

Function: int parse822_domain_ref (const char **p, const char *e, char **domain_ref)

Function: int parse822_domain_literal (const char **p, const char *e, char **domain_literal)

Function: int parse822_quote_string (char **quoted, const char *raw)

Function: int parse822_quote_local_part (char **quoted, const char *raw)

Function: int parse822_field_body (const char **p, const char *e, char **fieldbody)

Function: int parse822_field_name (const char **p, const char *e, char **fieldname)

Function: int parse822_day (const char **p, const char *e, int *day)

Function: int parse822_date (const char **p, const char *e, int *day, int *mon, int *year)

Function: int parse822_time (const char **p, const char *e, int *h, int *m, int *s, int *tz, const char **tz_name)

Function: int parse822_date_time (const char **p, const char *e, struct tm *tm, mu_timezone *tz)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.16 Mailcap

 
/* Prefix mu_mailcap_ is reserved. */
#include <mailutils/mailcap.h>

The standard RFC 1524 (A User Agent Configuration Mechanism) suggests a file format to be used to inform a mail user agent about facilities for handling mail in various format. The configuration file is known also as mailcap and it is tipically found in UNIX platforms, a example of `/etc/mailcap':

 
application/pgp; gpg < %s | metamail; needsterminal; \
       test=test %{encapsulation}=entity ; copiousoutput

A mailcap file consits of a set of mailcap entries per line, lines beginning with `#' are considered comments and ignored. Long mailcap entry may be continued on multiple lines if each line ends with a backslash character `\', the multiline will be considered a single mailcap entry. The overall format in BNF:

 
Mailcap-File = *mailcap-line
Mailcap-Line = comment | mailcap-entry
Comment = newline | "#" * char newline
Newline = <newline as defined by OS convention>

Each mailcap entry consists of a number of fields, separated by semi-colons. The first two filds are required and must occur in the secified order, the remaining fields are optional.

 
Mailcap-Entry = typefield ";" view-command ";" *[ ";" field ]

Data Type: mu_mailcap_t, mu_mailcap_entry_t
The mu_mailcap_t and mu_mailcap_entry_t objects are used to hold information and it is an opaque data structure to the user. Functions are provided to retrieve information from the data structure.

 
                        mu_mailcap_t                  mu_mailcap_entry_t
-/etc/mailcap-  +--->/------------------------\  +-->/------------------\
(  alain   )         |  mu_mailcap_entry[0]*--|--+   |  typefield       |
                     |  mu_mailcap_entry[1]   |      |  view-command    |
                     |  .....                 |      |  field[0]        |
                     |  mu_mailcap_entry[n]   |      |  .....           |
                     \------------------------/      |  field[n]        |
                                                     \------------------/

An Example of Parsing a Mailcap File:

 
#include <stdio.h>
#include <mailutils/mailcap.h>
#include <mailutils/stream.h>
#include <mailutils/error.h>

int
main (int argc, char **argv)
{
  stream_t stream = NULL;
  int status = 0;
  char *file = argc == 1 ? "/etc/mailcap" : argv[1];
  mu_mailcap_t mailcap = NULL;

  status = file_stream_create (&stream, file, MU_STREAM_READ);
  if (status)
    {
      mu_error ("cannot create file stream %s: %s",
		file, mu_strerror (status));
      exit (1);
    }

  status = stream_open (stream);
  if (status)
    {
      mu_error ("cannot open file stream %s: %s",
		file, mu_strerror (status));
      exit (1);
    }

  status = mu_mailcap_create (&mailcap, stream);
  if (status == 0)
    {
      int i;
      size_t count = 0;
      char buffer[256];

      mu_mailcap_entries_count (mailcap, &count);
      for (i = 1; i <= count; i++)
	{
	  size_t j;
	  mu_mailcap_entry_t entry = NULL;
	  size_t fields_count = 0;

	  printf ("entry[%d]\n", i);

	  mu_mailcap_get_entry (mailcap, i, &entry);

	  /* typefield.  */
	  mu_mailcap_entry_get_typefield (entry, buffer, 
					  sizeof (buffer), NULL);
	  printf ("\ttypefield: %s\n", buffer);
	  
	  /* view-command.  */
	  mu_mailcap_entry_get_viewcommand (entry, buffer, 
					    sizeof (buffer), NULL);
	  printf ("\tview-command: %s\n", buffer);

	  /* fields.  */
	  mu_mailcap_entry_fields_count (entry, &fields_count);
	  for (j = 1; j <= fields_count; j++)
	    {
	      int status = mu_mailcap_entry_get_field (entry, j, buffer, 
						       sizeof (buffer), NULL);
	      if (status)
		{
		  mu_error ("cannot retrieve field %lu: %s",
			    (unsigned long) j,
			    mu_strerror (status));
		  break;
		}
	      printf ("\tfields[%d]: %s\n", j, buffer);
	    }
	  printf ("\n");
	}
      mu_mailcap_destroy (&mailcap);
    }
  
  return 0;
}

Function: int mu_mailcap_create (mu_mailcap_t *mailcap, stream_t stream)
The function allocates, parses the buffer from the stream and initializes mailcap. The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
mailcap is NULL or stream is invalid.

Function: void mu_mailcap_destroy (mu_mailcap_t *mailcap)
Release any resources from the mailcap object.

Function: int mu_mailcap_entries_count (mu_mailcap_t mailcap, size_t *count)
The function returns the number of entries found in the mailcap. The return value is 0 on success and a code number on error conditions:
EINVAL
mailcap or count is NULL.

Function: int mu_mailcap_get_entry (mu_mailcap_t mailcap, size_t no, mu_mailcap_entry_t *entry)
Returns in entry the mailcap entry of no.

Function: int mu_mailcap_entry_fields_count (mu_mailcap_entry_t entry, size_t *count)