[ < ] [ > ]   [ << ] [ 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, char *progname, int flags)

Function: int filter_prog_stream_create (stream_t *stream, 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, fd;
  stream_t stream;
  size_t nb;
  fd_set fds;

  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)
        {
          ret = stream_get_fd (stream, &fd);
          if (ret != 0)
            {
              mu_error ("stream_get_fd: %s", mu_strerror (ret));
              exit (EXIT_FAILURE);
            }
          FD_ZERO (&fds);
          FD_SET (fd, &fds);
          select (fd + 1, NULL, &fds, NULL, NULL);
          goto connect_again;
        }
      mu_error ("stream_open: %s", mu_strerror (ret));
      exit (EXIT_FAILURE);
    }

  ret = stream_get_fd (stream, &fd);
  if (ret != 0)
    {
      mu_error ("stream_get_fd: %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)
        {
          FD_ZERO (&fds);
          FD_SET (fd, &fds);
          select (fd + 1, NULL, &fds, NULL, 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)
            {
              FD_ZERO (&fds);
              FD_SET (fd, &fds);
              select (fd + 1, &fds, NULL, NULL, NULL);
            }
          else
            {
              mu_error ("stream_read: %s", mu_strerror (ret));
              exit (EXIT_FAILURE);
            }
        }
      write (2, 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 ENOENT

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++)
	{
	  int j;
	  mu_mailcap_entry_t entry = NULL;
	  int 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++)
	    {
	      mu_mailcap_entry_get_field (entry, j, buffer, 
					  sizeof (buffer), NULL);
	      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)
The function returns the number of fields found in the entry. The return value is 0 on success and a code number on error conditions:
EINVAL
entry or count is NULL.

Function: int mu_mailcap_entry_get_typefield (mu_mailcap_entry_t entry, char *buffer, size_t buflen, size_t *n)

Function: int mu_mailcap_entry_get_viewcommand (mu_mailcap_entry_t entry, char *buffer, size_t buflen, size_t *n)

Function: int mu_mailcap_entry_get_field (mu_mailcap_entry_t entry, size_t no, char *buffer, size_t buflen, size_t *n)

Function: int mu_mailcap_entry_get_value (mu_mailcap_entry_t entry, const char *key, char *buffer, size_t buflen, size_t *n)

Function: int mu_mailcap_entry_get_compose (mu_mailcap_entry_t entry, char *buffer, size_t buflen, size_t *n)
Helper function saving in buffer, the argument of "compose" field.

Function: int mu_mailcap_entry_get_composetyped (mu_mailcap_entry_t entry, char *buffer, size_t buflen, size_t *n)
Helper function saving in buffer, the argument of "composetyped" field.

Function: int mu_mailcap_entry_get_edit (mu_mailcap_entry_t entry, char *buffer, size_t buflen, size_t *n)
Helper function saving in buffer, the argument of "edit" field.

Function: int mu_mailcap_entry_get_textualnewlines (mu_mailcap_entry_t entry, char *buffer, size_t buflen, size_t *n)
Helper function saving in buffer, the argument of "textualnewlines" field.

Function: int mu_mailcap_entry_get_test (mu_mailcap_entry_t entry, char *buffer, size_t buflen, size_t *n)
Helper function saving in buffer, the argument of "test" field.

Function: int mu_mailcap_entry_get_x11bitmap (mu_mailcap_entry_t entry, char *buffer, size_t buflen, size_t *n)
Helper function saving in buffer, the argument of "x11-bitmap" field.

Function: int mu_mailcap_entry_get_description (mu_mailcap_entry_t entry, char *buffer, size_t buflen, size_t *n)
Helper function saving in buffer, the argument of "description" field.

Function: int mu_mailcap_entry_get_nametemplate (mu_mailcap_entry_t entry, char *buffer, size_t buflen, size_t *n)
Helper function saving in buffer, the argument of "nametemplate" field.

Function: int mu_mailcap_entry_get_notes (mu_mailcap_entry_t entry, char *buffer, size_t buflen, size_t *n)
Helper function saving in buffer, the argument of "notes" field.

Function: int mu_mailcap_entry_needsterminal (mu_mailcap_entry_t entry, int *on)
Helper function. Returns *on != 0 if the flag "needsterminal" is in the record.

Function: int mu_mailcap_entry_copiousoutput (mu_mailcap_entry_t entry, int *on)
Helper function. Returns *on != 0 if the flag "copiousoutput" is in the record.


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

4.2 Authentication Library

The functions from `libmailbox' library get user information from the system user database. The library `libmuauth' extends this functionality, allowing `libmailbox' functions to obtain information about a user from several places, like SQL database, etc. The method used is described in detail in 3.2 Authorization and Authentication Principles. This chapter contains a very succinct description of the underlying library mechanism.

4.2.1 Data Types  
4.2.2 Initializing `libmuauth'  
4.2.3 Module Creation and Destruction  
4.2.4 Obtaining Authorization Information  
4.2.5 Existing Modules  
4.2.6 Using `libmuauth' in Your Programs  


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

4.2.1 Data Types

Data Type: mu_auth_fp

This is a pointer to authentication or authorization data. It is defined as follows:

 
typedef int (*mu_auth_fp) (struct mu_auth_data **return_data,
                           void *key,
                           void *func_data,
                           void *call_data);

Its arguments are:

return_data
Upon successful return authorization handler leaves in this memory location a pointer to the filled mu_auth_data structure with the user's information.

For authentication handlers this argument is always NULL and should be ignored.

key
The search key value. Its actual type depends upon type of the handler.

For authorization handlers it is const char* if the handler is called by mu_get_auth_by_name() and uid_t * if it is called by mu_get_auth_by_uid().

For authentication handlers it is always struct mu_auth_data* representing the user's data obtained by a previous call to a mu_get_auth_by_... function.

func_data
Any data associated with this handler.

call_data
Any call specific data. This argument is not used at the moment.

Data Type: mu_auth_data

The mu_auth_data is used to return the information about the user. It is similar to system struct passwd, except that it is more mailutils-specific. Its definition is:

 
struct mu_auth_data {
  /* These are from struct passwd */
  char    *name;       /* user name */
  char    *passwd;     /* user password */
  uid_t   uid;         /* user id */
  gid_t   gid;         /* group id */
  char    *gecos;      /* real name */
  char    *dir;        /* home directory */
  char    *shell;      /* shell program */
  /* */
  char    *mailbox;    /* Path to the user's system mailbox */
  int     change_uid;  /* Should the uid be changed? */
};

Data Type: mu_auth_module

The mu_auth_module structure contains full information about a libmuauth module. It is declared as follows:

 
struct mu_auth_module {
  char           *name;              /* Module name */
  struct argp    *argp;              /* Corresponding argp structure */
  mu_auth_fp     authenticate;       /* Authentication function ... */
  void           *authenticate_data; /* ... and its specific data */
  mu_auth_fp     auth_by_name;       /* Get user info by user name */ 
  void           *auth_by_name_data; /* ... and its specific data */
  mu_auth_fp     auth_by_uid;        /* Get user info by user id */  
  void           *auth_by_uid_data;  /* ... and its specific data */
};


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

4.2.2 Initializing `libmuauth'

Function: void mu_auth_init (void)
This function registers the command line capability "auth". It must be called after registering `libmuauth' modules and before calling mu_agrp_parse(). If an error occurs, this function prints diagnostic message and aborts the program.

Function: void MU_AUTH_REGISTER_ALL_MODULES (void)
This macro registers all default modules and calls mu_auth_init().


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

4.2.3 Module Creation and Destruction

Function: int mu_auth_data_alloc (struct mu_auth_data **ptr, const char *name, const char *passwd, uid_t uid, gid_t gid, const char *gecos, const char *dir, const char *shell, const char *mailbox, int change_uid)

Create a mu_auth_data structure and initialize it with the given values. Returns 0 on success and 1 otherwise.

Function: void mu_auth_data_free (struct mu_auth_data *ptr)
Free the mu_auth_data structure allocated by a call to mu_auth_data_alloc().

Function: void mu_auth_register_module (struct mu_auth_module *mod)
Register the module defined by the mod argument.


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

4.2.4 Obtaining Authorization Information

Function: int mu_auth_runlist (list_t flist, struct mu_auth_data **return_data, void *key, void *call_data);
The list is expected to contain mu_auth_fp pointers. Each of them is dereferenced and executed until either the list is exhausted or any of the functions returns non-zero, whichever occurs first. The return_data and key arguments are passed as the first two parameters to the function (see the definition of mu_auth_fp, notice the footnote), the call_data is passed as its last parameter.

The function returns 0 if none of the functions from list succeeded, i.e. returned non-zero value. Otherwise it returns the return code from the succeeded function.

Function: struct mu_auth_data * mu_get_auth_by_name (const char *username)
Search the information about given user by its username. Similar to system's getpwnam call).

Function: struct mu_auth_data * mu_get_auth_by_uid (uid_t uid)
Search the information about given user by its uid. Similar to system's getpwuid call).

Function: int mu_authenticate (struct mu_auth_data *auth_data, char *pass)
Authenticate the user whose data are in auth_data using password pass. Return 0 if the user is authenticated.


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

4.2.5 Existing Modules

Function: int mu_auth_nosupport (struct mu_auth_data **return_data, void *key, void *func_data, void *call_data);
The "not-supported" module. Always returns ENOSYS.

Variable: mu_auth_system_module
This module is always registered even if `libmuauth' is not linked. It performs usual authentication using system user database (`/etc/password' et al.)

Variable: mu_auth_generic_module
This module is always registered even if `libmuauth' is not linked. Both its authorization handlers are mu_auth_nosupport. Its authentication handler computes the MD5 or DES hash over the supplied password with the seed taken from passwd member of its key argument. Then it compares the obtained hash with the passwd member itself and returns 1 if both strings match.

Variable: mu_auth_pam_module
Implements PAM authentication. Both authorization handlers are mu_auth_nosupport().

Variable: mu_auth_sql_module
Implements authentication and authorization via MySQL database. The credentials for accessing the database are taken from global variables sql_host, sql_port, sql_user, sql_passwd and sql_db. The SQL queries for retrieving user information from global variables sql_getpwnam_query and sql_getpwuid_query. The variable sql_getpass_query keeps the query used for retrieving user's password. See section 3.1.6 Auth, for information on command line options used to set these variables.

Variable: mu_auth_virtual_module
Implements mu_get_auth_by_name method using virtual mail domains. Neither mu_get_auth_by_uid nor mu_authenticate is implemented. This module must be used together with generic module.


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

4.2.6 Using `libmuauth' in Your Programs

To link your program against `libmuauth', obtain loader arguments by running mailutils-config as follows:

 
mailutils-config --link auth

See section 3.16 mailutils-config -- Get the Information about the Mailutils Build, for more information about this utility.

Here is a sample Makefile fragment:

 
MU_LDFLAGS=`mailutils-config --link auth`
MU_INCLUDES=`mailutils-config --include`

myprog: myprog.c
        $(CC) -omyprog $(CFLAGS) $(MU_INCLUDES) myprog.c $(MU_LDFLAGS)

If your program will be using only default modules provided by the library, then it will suffice to call MU_AUTH_REGISTER_ALL_MODULES() somewhere near the start of your program. As an example, consider the following code fragment (it is taken from the imap4d daemon):

 
int
main (int argc, char **argv)
{
  struct group *gr;
  int status = EXIT_SUCCESS;
 
  state = STATE_NONAUTH; /* Starting state in non-auth.  */

  MU_AUTH_REGISTER_ALL_MODULES ();
  mu_argp_parse (&argp, &argc, &argv, 0, imap4d_capa,
                 NULL, &daemon_param);
  ...       

Otherwise, if your program will use it's own modules, first register them with mu_auth_register_module and then call mu_auth_init(), e.g.:

 
struct mu_auth_module radius_module = {
  ...
};

struct mu_auth_module ext_module = {
  ...
};

int
main (int argc, char **argv)
{
  mu_auth_register_module (&radius_module);
  mu_auth_register_module (&ext_module);
  mu_auth_init ();

  ...

These two approaches may be combined, allowing you to use both your modules and the ones provided by Mailutils. Consider the example below:

 
int
main (int argc, char **argv)
{
  mu_auth_register_module (&radius_module);
  mu_auth_register_module (&ext_module);
  MU_AUTH_REGISTER_ALL_MODULES ();

  ...
}


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

4.3 Mailutils to Scheme Interface

The library `libmu_scm' provides an interface between Mailutils and Guile, allowing to access the Mailutils functionality from a Scheme program. For more information about Guile, refer to section `Overview' in The Guile Reference Manual. For information about Scheme programming language, See section `Top' in Revised(4) Report on the Algorithmic Language Scheme.

Functions Provided by `libmu_scm'
4.3.1 Address Functions  
4.3.2 Mailbox Functions  
4.3.3 Message Functions  
4.3.4 MIME Functions  
4.3.5 Logging Functions  
Using `libmu_scm'
4.3.6 Direct Linking  
4.3.7 Dynamic Linking  


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

4.3.1 Address Functions

Scheme Function: mu-address-get-personal ADDRESS NUM
Return personal part of an email address.

Scheme Function: mu-address-get-comments ADDRESS NUM

Scheme Function: mu-address-get-email ADDRESS NUM
Return email part of an email address.

Scheme Function: mu-address-get-domain ADDRESS NUM
Return domain part of an email address

Scheme Function: mu-address-get-local ADDRESS NUM
Return local part of an email address.

Scheme Function: mu-address-get-count ADDRESS
Return number of parts in email address.


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

4.3.2 Mailbox Functions

Scheme Function: mu-mailbox-open URL MODE
Opens a mailbox specified by URL.

Scheme Function: mu-mailbox-close MBOX
Closes mailbox MBOX.

Scheme Function: mu-mailbox-get-url MBOX
Returns the URL of the mailbox.

Scheme Function: mu-mailbox-get-port MBOX MODE
Returns a port associated with the contents of the MBOX. MODE is a string defining operation mode of the stream. It may contain any of the two characters: `r' for reading, `w' for writing.

Scheme Function: mu-mailbox-get-message MBOX MSGNO
Retrieve from MBOX message # MSGNO.

Scheme Function: mu-mailbox-messages-count MBOX
Returns number of messages in the mailbox.

Scheme Function: mu-mailbox-expunge MBOX
Expunges deleted messages from the mailbox.

Scheme Function: mu-mailbox-url MBOX
Returns the URL of the mailbox

Scheme Function: mu-mailbox-append-message MBOX MESG
Appends the message to the mailbox


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

4.3.3 Message Functions

Scheme Function: mu-message-copy MESG
Creates the copy of the given message.

Scheme Function: mu-message-set-header MESG HEADER VALUE REPLACE
Sets new VALUE to the header HEADER of the message MESG. If the HEADER is already present in the message its value is replaced with the supplied one if the optional REPLACE is #t. Otherwise new header is created and appended.

Scheme Function: mu-message-get-size MESG
Returns the size of the given message.

Scheme Function: mu-message-get-lines MESG
Returns number of lines in the given message.

Scheme Function: mu-message-get-sender MESG
Returns the sender email address for the message MESG.

Scheme Function: mu-message-get-header MESG HEADER
Returns the header value of the HEADER in the MESG.

Scheme Function: mu-message-get-header-fields MESG HEADERS
Returns the list of headers in the MESG. If optional HEADERS is specified it should be a list of header names to restrict return value to.

Scheme Function: mu-message-set-header-fields MESG LIST REPLACE
Set the headers in the message MESG from LIST. LIST is a list of (cons HEADER VALUE). Optional parameter REPLACE specifies whether the new header values should replace the headers already present in the message.

Scheme Function: mu-message-delete MESG FLAG
Mark given message as deleted. Optional FLAG allows to toggle deleted mark. The message is deleted if it is #t and undeleted if it is #f.

Scheme Function: mu-message-get-flag MESG FLAG
Return value of the attribute FLAG.

Scheme Function: mu-message-set-flag MESG FLAG VALUE
Set the given attribute of the message. If optional VALUE is #f, the attribute is unset.

Scheme Function: mu-message-get-user-flag MESG FLAG
Returns value of the user attribute FLAG.

Scheme Function: mu-message-set-user-flag MESG FLAG VALUE
Set the given user attribute of the message. If optional VALUE is #f, the attribute is unset.

Scheme Function: mu-message-get-port MESG MODE FULL
Returns a port associated with the given MESG. MODE is a string defining operation mode of the stream. It may contain any of the two characters: `r' for reading, `w' for writing. If optional FULL argument specified, it should be a boolean value. If it is #t then the returned port will allow access to any part of the message (including headers). If it is #f then the port accesses only the message body (the default).

Scheme Function: mu-message-get-body MESG
Returns the message body for the message MESG.

Scheme Function: mu-message-send MESG MAILER
Sends the message MESG. Optional MAILER overrides default mailer settings in mu-mailer.


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

4.3.4 MIME Functions

Scheme Function: mu-mime-create FLAGS MESG
Creates a new MIME object.

Scheme Function: mu-mime-multipart? MIME
Returns #t if MIME is a multipart object.

Scheme Function: mu-mime-get-num-parts MIME
Returns number of parts in a MIME object.

Scheme Function: mu-mime-get-part MIME PART
Returns part number PART from a MIME object.

Scheme Function: mu-mime-add-part MIME MESG
Adds MESG to the MIME object.

Scheme Function: mu-mime-get-message MIME
Converts MIME object to a message.


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

4.3.5 Logging Functions

Scheme Function: mu-openlog IDENT OPTION FACILITY
Opens a connection to the system logger for Guile program.

Scheme Function: mu-logger PRIO TEXT
Generates a log message to be distributed via syslogd.

Scheme Function: mu-closelog
Closes the channel to the system logger open by mu-openlog.


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

4.3.6 Direct Linking

If you plan to link your program directly to `libguile', it will probably make sense to link `libmu_scm' directly as well. The arguments to the program loader may be obtained by running

 
mailutils-config --link guile

See section 3.16 mailutils-config -- Get the Information about the Mailutils Build, for more information about this utility.

Here is a sample Makefile fragment:

 
MU_LDFLAGS=`mailutils-config --link guile`
MU_INCLUDES=`mailutils-config --include`

myprog: myprog.c
        $(CC) -omyprog $(CFLAGS) $(MU_INCLUDES) myprog.c $(MU_LDFLAGS)


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

4.3.7 Dynamic Linking

Dynamic linking is the preferred method of using `libmu_scm'. It uses Guile "use-modules" mechanism. An interface module `mailutils.scm' is provided in order to facilitate using this method. This module is installed in the package data directory (by default it is `prefix/share/mailutils'). A sample use of this module is:

 
(set! %load-path (list "/usr/local/share/mailutils"))
(use-modules (mailutils))

# Now you may use mailutils functions:

(let ((mb (mu-mailbox-open "/var/spool/mail/gray" "r")))
...

Note, that you should explicitly modify the %load-path before calling use-modules, otherwise Guile will not be able to find `mailutils.scm'.


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

4.4 Sieve Library

Libsieve is GNU implementation of the mail filtering language Sieve. The library is built around a Sieve Machine -- an abstract computer constructed specially to handle mail filtering tasks. This computer has two registers: program counter and numeric accumulator; a runtime stack of unlimited depth and the code segment. A set of functions is provided for creating and destroying instances of Sieve Machine, manipulating its internal data, compiling and executing a sieve program.

The following is a typical scenario of using libsieve:

  1. Application program creates the instance of sieve machine.

  2. Then sieve_compile function is called to translate the Sieve source into an equivalent program executable by the Machine

  3. A mailbox is opened and associated with the Machine

  4. The Machine executes the program over the mailbox

  5. When the execution of the program is finished, all messages upon which an action was executed other than keep are marked with the delete flag. Thus, running mailbox_expunge upon the mailbox finishes the job, leaving in the mailbox only those messages that were preserved by the filter.

  6. Finally, the instance of Sieve Machine is destroyed and the resources allocated for it are reclaimed.

The following sections describe in detail the functions from the Sieve Library.

4.4.1 Sieve Data Types  
4.4.2 Manipulating the Sieve Machine  
4.4.3 Logging and Diagnostic Functions  
4.4.4 Symbol Space Functions  
4.4.5 Memory Allocation  
4.4.6 Compiling and Executing the Script  
4.4.7 Writing Loadable Commands  


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

4.4.1 Sieve Data Types

Data Type: sieve_machine_t
This is an opaque data type representing a pointer to an instance of sieve machine. The sieve_machine_t keeps all information necessary for compiling and executing the script.

It is created by sieve_machine_create() and destroyed by sieve_machine_destroy(). The functions for manipulating this data type are described in 4.4.2 Manipulating the Sieve Machine.

Data Type: sieve_data_type
This enumeration keeps the possible types of sieve data. These are:

SVT_VOID
No datatype.

SVT_NUMBER
Numeric type.

SVT_STRING
Character string.

SVT_STRING_LIST
A list_t. Each item in this list represents a character string.

SVT_TAG
A sieve tag. See sieve_runtime_tag_t below.

SVT_IDENT
A character string representing an identifier.

SVT_VALUE_LIST
A list_t. Each item in this list is of sieve_value_t.

SVT_POINTER
An opaque pointer.

Data Type: sieve_value_t
The sieve_value_t keeps an instance of sieve data. It is defined as follows:

 
typedef struct {
  sieve_data_type type;        /* Type of the data */
  union {
    char *string;              /* String value or identifier */
    size_t number;             /* Numeric value */
    list_t list;               /* List value */
    sieve_runtime_tag_t *tag;  /* Tag value */
    void *ptr;                 /* Pointer value */ 
  } v;
} sieve_value_t;

Depending on the value of type member, following members of the union v keep the actual value:

SVT_VOID
Never appears.

SVT_NUMBER
The numeric value is kept in number member.

SVT_STRING
The string is kept in string member.

SVT_STRING_LIST
SVT_VALUE_LIST
The list itself is pointed to by list member

SVT_TAG
The tag value is pointed to by tag member.

SVT_IDENT
The string member points to the identifier name.

SVT_POINTER
The data are pointed to by ptr member.

Data Type: sieve_tag_def_t
This structure represents a definition of a tagged (optional) argument to a sieve action or test. It is defined as follows:

 
typedef struct {
  char *name;              /* Tag name */
  sieve_data_type argtype; /* Type of tag argument. */
} sieve_tag_def_t;

The name member points to the tag's name without leading colon. The argtype is set to SVT_VOID if the tag does not take argument, or to the type of the argument otherwise.

Data Type: sieve_runtime_tag_t
This structure represents the tagged (optional) argument at a runtime. It is defined as:

 
struct sieve_runtime_tag {
  char *tag;                /* Tag name */
  sieve_value_t *arg;       /* Tag argument (if any) */
};

The arg member is NULL if the tag does not take an argument.

Data Type: sieve_handler_t

This is a pointer to function handler for a sieve action or test. It is defined as follows:

 
typedef int (*sieve_handler_t) (sieve_machine_t mach,
                                list_t args, list_t tags);

The arguments to the handler have the following meaning:

mach
Sieve machine being processed.
args
A list of required arguments to the handler
tags
A list of optional arguments (tags).

Data Type: sieve_printf_t
A pointer to a diagnostic output function. It is defined as follows:
 
typedef int (*sieve_printf_t) (void *data, const char *fmt, va_list ap);

data
A pointer to application specific data. These data are passed as second argument to sieve_machine_init().
fmt
Printf-like format string.
ap
Other arguments.

Data Type: sieve_parse_error_t
This data type is declared as follows:
 
typedef int (*sieve_parse_error_t) (void *data,
                                    const char *filename, int lineno,
                                    const char *fmt, va_list ap);

It is used to declare error handlers for parsing errors. The application-specific data are passed in the data argument. Arguments filename and line indicate the location of the error in the source text, while fmt and ap give verbose description of the error.

Data Type: sieve_action_log_t
A pointer to the application-specific logging function:

 
typedef void (*sieve_action_log_t) (void *data,
                                    const char *script,
                                    size_t msgno, message_t msg,
                                    const char *action,
                                    const char *fmt, va_list ap);

data
Application-specific data.

script
Name of the sieve script being executed.

msgno
Ordinal number of the message in mailbox, if appropriate. When execution is started using sieve_message(), this argument is zero.

msg
The message this action is executed upon.

action
The name of the action.

fmt
var
These two arguments give the detailed description of the action.

Data Type: sieve_relcmp_t
Data Type: sieve_relcmpn_t
 
typedef int (*sieve_relcmp_t) (int, int);  
typedef int (*sieve_relcmpn_t) (size_t, size_t);  

Data Type: sieve_comparator_t
 
typedef int (*sieve_comparator_t) (const char *, const char *);

A pointer to the comparator handler function. The function compares its two operands and returns 1 if they are equal, and 0 otherwise. Notice, that the sense of the return value is inverted in comparison with most standard libc functions like stcmp(), etc.

Data Type: sieve_retrieve_t
 
typedef int (*sieve_retrieve_t) (void *item, void *data, int idx,
                                 char **pval);

A pointer to generic retriever function. See description of sieve_vlist_compare() for details of its usage.

Data Type: sieve_destructor_t
 
typedef void (*sieve_destructor_t) (void *data);

A pointer to destructor function. The function frees any resources associated with data. See the description of sieve_machine_add_destructor() for more information.

Data Type: sieve_tag_checker_t
 
typedef int (*sieve_tag_checker_t) (const char *name, 
                                    list_t tags, 
                                    list_t args)

A pointer to tag checker function. The purpose of the function is to perform compilation-time consistency test on tags. Its arguments are:

name
Name of the test or action whose tags are being checked.

tags
A list of sieve_runtime_tag_t representing tags.

args
A list of sieve_value_t representing required arguments to name.

The function is allowed to make any changes in tags and args. It should return 0 if the syntax is correct and non-zero otherwise. It is responsible for issuing the diagnostics in the latter case. [FIXME: describe how to do that]


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

4.4.2 Manipulating the Sieve Machine

This subsection describes functions used to create an instance of the sieve machine, read or alter its internal fields and destroy it.

Function: int sieve_machine_init (sieve_machine_t *mach, void *data)

The sieve_machine_init() function creates an instance of a sieve machine. A pointer to the instance itself is returned in the argument mach. The user-specific data to be associated with the new machine are passed in data argument. The function returns 0 on success, non-zero error code otherwise,

Function: void sieve_machine_destroy (sieve_machine_t *pmach)

This function destroys the instance of sieve machine pointed to by mach parameter. After execution of sieve_machine_destroy() pmach contains NULL. The destructors registered with sieve_machine_add_destructor() are executed in LIFO order.

Function: int sieve_machine_add_destructor (sieve_machine_t mach, sieve_destructor_t destr, void *ptr);

This function registers a destructor function dest. The purpose of the destructor is to free any resources associated with the item ptr. The destructor function takes a single argument -- a pointer to the data being destroyed. All registered destructors are called in reverse order upon execution of sieve_machine_destroy(). Here's a short example of the use of this function:

 
static void
free_regex (void *data)
{
  regfree ((regex_t*)data);        
}

int
match_part_checker (const char *name, list_t tags, list_t args)
{
  regex_t *regex;

  /* Initialise the regex: */
  regex = sieve_malloc (mach, sizeof (*regex));
  /* Make sure it will be freed when necessary */
  sieve_machine_add_destructor (sieve_machine, free_regex, regex);
  .
  .
  .
}

Function: void* sieve_get_data (sieve_machine_t mach)
This function returns the application-specific data associated with the instance of sieve machine. See sieve_machine_init().

Function: message_t sieve_get_message (sieve_machine_t mach)
This function returns the current message.

Function: size_t sieve_get_message_num (sieve_machine_t mach)
This function returns the current message number in the mailbox. If there are no mailbox, i.e. the execution of the sieve code is started with sieve_message, this function returns 1.

Function: int sieve_get_debug_level (sieve_machine_t mach)
Returns the debug level set for this instance of sieve machine.

Function: ticket_t sieve_get_ticket (sieve_machine_t mach)
Returns the authentication ticket for this machine.

Function: mailer_t sieve_get_mailer (sieve_machine_t mach)
Returns the mailer.

Function: char * sieve_get_daemon_email (sieve_machine_t mach)
This function returns the daemon email associated with this instance of sieve machine. The daemon email is an email address used in envelope from addresses of automatic reply messages. By default its local part is `<MAILER-DAEMON>' and the domain part is the machine name.

Function: void sieve_set_error (sieve_machine_t mach, sieve_printf_t error_printer)
This function sets the error printer function for the machine. If it is not set, the default error printer will be used. It is defined as follows:

 
int
_sieve_default_error_printer (void *unused, const char *fmt, 
                              va_list ap)
{
  return mu_verror (fmt, ap);
}

Function: void sieve_set_parse_error (sieve_machine_t mach, sieve_parse_error_t p)
This function sets the parse error printer function for the machine. If it is not set, the default parse error printer will be used. It is defined as follows:

 
int
_sieve_default_parse_error (void *unused,
                            const char *filename, int lineno,
			    const char *fmt, va_list ap)
{
  if (filename)
    fprintf (stderr, "%s:%d: ", filename, lineno);
  vfprintf (stderr, fmt, ap);
  fprintf (stderr, "\n");
  return 0;
}

Function: void sieve_set_debug (sieve_machine_t mach, sieve_printf_t debug);
This function sets the debug printer function for the machine. If it is not set, the default debug printer is NULL which means no debugging information will be displayed.

Function: void sieve_set_debug_level (sieve_machine_t mach, mu_debug_t dbg, int level)
This function sets the debug level for the given instance of sieve machine. The dbg argument is the mu_debug_t object to be used with mailutils library, the level argument specifies the debugging level for the sieve library itself. It is a bitwise or of the following values:

MU_SIEVE_DEBUG_TRACE
Trace the execution of the sieve script.

MU_SIEVE_DEBUG_INSTR
Print the sieve machine instructions as they are executed.

MU_SIEVE_DEBUG_DISAS
Dump the disassembled code of the sieve machine. Do not run it.

MU_SIEVE_DRY_RUN
Do not executed the actions, only show what would have been done.

Function: void sieve_set_logger (sieve_machine_t mach, sieve_action_log_t logger)
This function sets the logger function. By default the logger function is NULL, which means that the executed actions are not logged.

Function: void sieve_set_ticket (sieve_machine_t mach, ticket_t ticket)
This function sets the authentication ticket to be used with this machine.

Function: void sieve_set_mailer (sieve_machine_t mach, mailer_t mailer)
This function sets the mailer. The default mailer is "sendmail:".

Function: void sieve_set_daemon_email (sieve_machine_t mach, const char *email)
This functions sets the daemon email for reject and redirect actions.

Function: int sieve_is_dry_run (sieve_machine_t mach)
The sieve_is_dry_run() returns 1 if the machine is in dry run state, i.e. it will only log the actions that would have been executed without actually executing them. The dry run state is set by calling sieve_set_debug_level() if its last argument has the MU_SIEVE_DRY_RUN bit set.

Function: const char * sieve_type_str (sieve_data_type type)
Returns the string representation for the given sieve data type. The return value is a pointer to a static constant string.


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

4.4.3 Logging and Diagnostic Functions

Function: void sieve_error (sieve_machine_t mach, const char *fmt, ...)
Format and output an error message using error printer of the machine mach.

Function: void sieve_debug (sieve_machine_t mach, const char *fmt, ...)
Format and output a debug message using debug printer of the machine mach.

Function: void sieve_log_action (sieve_machine_t mach, const char *action, const char *fmt, ...)
Log a sieve action using logger function associated with the machine mach.

Function: void sieve_abort (sieve_machine_t mach)
Immediately abort the execution of the script.


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

4.4.4 Symbol Space Functions

Function: sieve_register_t * sieve_test_lookup (sieve_machine_t mach, const char *name)
Find a register object describing the test name. Returns NULL if no such test exists.

Function: sieve_register_t * sieve_action_lookup (sieve_machine_t mach, const char *name)
Find a register object describing the action name. Returns NULL if no such action exists.
Function: int sieve_register_test (sieve_machine_t mach, const char *name, sieve_handler_t handler, sieve_data_type *arg_types, sieve_tag_group_t *tags, int required)
Function: int sieve_register_action (sieve_machine_t mach, const char *name, sieve_handler_t handler, sieve_data_type *arg_types, sieve_tag_group_t *tags, int required)
Function: int sieve_register_comparator (sieve_machine_t mach, const char *name, int required, sieve_comparator_t is, sieve_comparator_t contains, sieve_comparator_t matches, sieve_comparator_t regex, sieve_comparator_t eq)
Function: int sieve_tag_lookup (list_t taglist, char *name, sieve_value_t **arg)

Function: int sieve_load_ext (sieve_machine_t mach, const char *name)


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

4.4.5 Memory Allocation

The following functions act as their libc counterparts. The allocated memory is associated with the mach argument and is automatically freed upon the call to sieve_machine_destroy (mach).

Function: void * sieve_malloc (sieve_machine_t mach, size_t size)
Allocates size bytes and returns a pointer to the allocated memory.

Function: char * sieve_mstrdup (sieve_machine_t mach, const char *str)
This function returns a pointer to a new string which is a duplicate of the string str.

Function: void * sieve_mrealloc (sieve_machine_t mach, void *ptr, size_t size)
Changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated memory will be uninitialized. If ptr is NULL, the call is equivalent to sieve_malloc(mach, size); if size is equal to zero, the call is equivalent to sieve_mfree(ptr). Unless ptr is NULL, it must have been returned by an earlier call to sieve_malloc() or sieve_mrealloc().

Function: void sieve_mfree (sieve_machine_t mach, void *ptr)
sieve_mfree() frees the memory space pointed to by ptr and detaches it from the destructor list of mach. The ptr must have been returned by a previous call to sieve_malloc() or sieve_mrealloc(). Otherwise, or if sieve_mfree(ptr) has already been called before, undefined behaviour occurs.

If ptr is NULL, no operation is performed.


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

4.4.6 Compiling and Executing the Script

Function: int sieve_compile (sieve_machine_t mach, const char *name)
Compile the sieve script from the file name.

Function: int sieve_mailbox (sieve_machine_t mach, mailbox_t mbox)
Execute the code from the given instance of sieve machine mach over each message in the mailbox mbox.

Function: int sieve_message (sieve_machine_t mach, message_t message)
Execute the code from the given instance of sieve machine mach over the message.

Function: int sieve_disass (sieve_machine_t mach)
Dump the disassembled code of the sieve machine mach.


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

4.4.7 Writing Loadable Commands

This section contains an example of how to write external loadable commands for GNU libsieve.

 

/*  This is an example on how to write extension tests for GNU sieve.
    It provides test "numaddr".

    Syntax:   numaddr [":over" / ":under"] <header-names: string-list>
              <limit: number>

    The "numaddr" test counts Internet addresses in structured headers
    that contain addresses.  It returns true if the total number of
    addresses satisfies the requested relation:

    If the argument is ":over" and the number of addresses is greater than
    the number provided, the test is true; otherwise, it is false.

    If the argument is ":under" and the number of addresses is less than
    the number provided, the test is true; otherwise, it is false.

    If the argument is empty, ":over" is assumed. */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif  

#include <stdlib.h>
#include <mailutils/libsieve.h>

struct val_ctr {  /* Data passed to the counter function */
  header_t hdr;   /* Headers of the current message */
  size_t limit;   /* Limit for the number of addresses */
  size_t count;   /* Number of addresses counted so far */
};

/* Count addresses in a single header value.

   Input:
     ITEM is the name of the header to scan.
     DATA is a pointer to the val_ctr structure 
   Return value:
     non-zero if the limit on the number of addresses has been reached. */
     
static int
_count_items (void *item, void *data)
{
  char *name = item;
  struct val_ctr *vp = data;
  char *val;
  address_t addr;
  size_t count = 0;
  
  if (header_aget_value (vp->hdr, name, &val))
    return 0;
  if (address_create (&addr, val) == 0)
    {
      address_get_count (addr, &count);
      address_destroy (&addr);
      vp->count += count;
    }
  free (val);
  return vp->count >= vp->limit;
}

/* Handler for the numaddr test */
static int
numaddr_test (sieve_machine_t mach, list_t args, list_t tags)
{
  sieve_value_t *h, *v;
  struct val_ctr vc;
  int rc;
  
  if (sieve_get_debug_level (mach) & MU_SIEVE_DEBUG_TRACE)
    {
      sieve_locus_t locus;
      sieve_get_locus (mach, &locus);
      sieve_debug (mach, "%s:%lu: NUMADDR\n",
		   locus.source_file,
		   (unsigned long) locus.source_line);
    }

  /* Retrieve required arguments: */
  /* First argument: list of header names */
  h = sieve_value_get (args, 0);
  if (!h)
    {
      sieve_error (mach, "numaddr: can't get argument 1");
      sieve_abort (mach);
    }
  /* Second argument: Limit on the number of addresses */
  v = sieve_value_get (args, 1);
  if (!v)
    {
      sieve_error (mach, "numaddr: can't get argument 2");
      sieve_abort (mach);
    }

  /* Fill in the val_ctr structure */
  message_get_header (sieve_get_message (mach), &vc.hdr);
  vc.count = 0;
  vc.limit = v->v.number;

  /* Count the addresses */
  rc = sieve_vlist_do (h, _count_items, &vc);

  /* Here rc >= 1 iff the counted number of addresses is greater or equal
     to vc.limit. If `:under' tag was given we reverse the return value */
  if (sieve_tag_lookup (tags, "under", NULL))
    rc = !rc;
  return rc;
}

/* Syntactic definitions for the numaddr test */

/* Required arguments: */
static sieve_data_type numaddr_req_args[] = {
  SVT_STRING_LIST,
  SVT_NUMBER,
  SVT_VOID
};

/* Tagged arguments: */
static sieve_tag_def_t numaddr_tags[] = {
  { "over", SVT_VOID },
  { "under", SVT_VOID },
  { NULL }
};

static sieve_tag_group_t numaddr_tag_groups[] = {
  { numaddr_tags, NULL },
  { NULL }
};

/* Initialization function. It is the only function exported from this
   module. */
int
SIEVE_EXPORT(numaddr,init) (sieve_machine_t mach)
{
  return sieve_register_test (mach, "numaddr", numaddr_test,
                              numaddr_req_args, numaddr_tag_groups, 1);
}


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

This document was generated by Jordi Mallach on April, 16 2004 using texi2html