libEtPan! API

Viet Hoa DINH

   Copyright © 2003 DINH Viet Hoa
     __________________________________________________________________

   Table of Contents
   1. Introduction
   2. Tools and datatypes

        Array

              carray_new and carray_free
              carray_set_size
              carray_count, carray_add, carray_get and carray_set
              carray_delete
              carray_data

        List

              clist_new and clist_free
              clist_isempty and clist_count
              running through clist
              clist modification
              clist_foreach
              clist_concat

        Hash table

              chash_new and chash_free
              chash_set and chash_get
              chash_delete
              chash_resize
              running through the chash
              chash_size and chash_count

        Buffered I/O

              socket stream
              TLS stream

        non-buffered I/O
        strings

              constructor and destructor
              string value modification
              insertion in string, deletion in string
              referencing string

   3. Internet Message Format

        Quick start

              Parse message headers
              Render the message headers

        Data types

              mailimf_mailbox - mailbox
              mailimf_address - address
              mailimf_mailbox_list - list of mailboxes
              mailimf_address_list - list of addresses
              mailimf_group - named group of mailboxes
              mailimf_date_time - date of a message
              mailimf_orig_date - parsed content of date header
              mailimf_from - parsed content of From header
              mailimf_sender - parsed content of Sender header
              mailimf_reply_to - parsed content of Reply-To header
              mailimf_to - parsed content of To header
              mailimf_cc - parsed content of Cc
              mailimf_bcc - parsed content of Bcc field
              mailimf_message_id - parsed content of Message-ID header
              mailimf_in_reply_to - parsed content of In-Reply-To field
              mailimf_references - parsed content of References field
              mailimf_subject - parsed content of Subject field
              mailimf_comments - parsed content of Comments field
              mailimf_keywords - parsed content of Keywords field
              mailimf_return - parsed content of Return-Path field
              mailimf_path - address in Return-Path field
              mailimf_optional_field - non-standard header
              mailimf_field - header field
              mailimf_fields - list of header fields
              mailimf_body - message body without headers
              mailimf_message - parsed message
              mailimf_single_fields - simplified fields

        Parser functions

              mailimf_address_list_parse
              mailimf_address_parse
              mailimf_body_parse
              mailimf_envelope_and_optional_fields_parse
              mailimf_envelope_fields_parse
              mailimf_optional_fields_parse
              mailimf_fields_parse
              mailimf_ignore_field_parse
              mailimf_mailbox_list_parse
              mailimf_mailbox_parse
              mailimf_message_parse

        Creation functions

              mailimf_mailbox_list
              mailimf_address_list
              mailimf_fields

        Rendering of messages

              Header fields

   4. MIME

        Quick start

              Parse MIME message
              Render the MIME message

        Data types

              mailmime_composite_type - Composite MIME type
              mailmime_content - MIME content type (Content-Type)
              mailmime_discrete_type - MIME discrete type
              mailmime_field - MIME header field
              mailmime_mechanism - MIME transfer encoding mechanism
                      (Content-Transfer-Encoding)

              mailmime_fields - header fields
              mailmime_parameter - MIME type parameter
              mailmime_type - MIME main type
              mailmime_language - Language of MIME part
              mailmime_data - Content of MIME part
              mailmime - MIME part
              mailmime_disposition - MIME disposition information
                      (Content-Disposition)

              mailmime_disposition_type - Type of MIME disposition
              mailmime_disposition_parm - MIME disposition parameter
              mailmime_single_fields - MIME headers

        Parser functions

              mailmime_content_parse
              mailmime_description_parse
              mailmime_encoding_parse
              mailmime_field_parse
              mailmime_id_parse
              mailmime_fields_parse
              mailmime_version_parse
              mailmime_parameter_parse
              mailmime_language_parse
              mailmime_disposition_parse
              mailmime_disposition_type_parse
              mailmime_encoded_phrase_parse
              mailmime_parse
              mailmime_base64_body_parse
              mailmime_quoted_printable_body_parse
              mailmime_binary_body_parse
              mailmime_part_parse

        Rendering of MIME parts

              mailmime_fields_write, mailmime_content_write and
                      mailmime_content_type_write

              mailmime_write
              mailmime_quoted_printable_write and mailmime_base64_write
              mailmime_data_write

        Creation functions

              mailmime_disposition_new_filename and
                      mailmime_disposition_new_with_data

              mailmime_fields_new_empty and mailmime_fields_add
              mailmime_fields_new_with_data and
                      mailmime_fields_new_with_version

              mailmime_get_content_message
              mailmime_data_new_data and mailmime_data_new_file
              mailmime_new_message_data, mailmime_new_empty and
                      mailmime_new_with_content

              mailmime_set_preamble_file, mailmime_set_epilogue_file,
                      mailmime_set_preamble_text and
                      mailmime_set_epilogue_text

              mailmime_set_body_file and mailmime_set_body_text
              mailmime_add_part, mailmime_remove_part,
                      mailmime_smart_add_part and
                      mailmime_smart_remove_part

              mailmime_set_imf_fields
              mailmime_fields_new_encoding and
                      mailmime_fields_new_filename

        Helper functions

              mailmime_transfer_encoding_get
              mailmime_content_charset_get and mailmime_content_param_get

   5. Storages, folders, messages

        Introduction

              Message
              MIME part
              Mailbox
              Storage
              Folder
              Session

        Error codes
        Storage

              Storage driver
              Storage
              mailstorage_new and mailstorage_free
              mailstorage_connect and mailstorage_disconnect
              IMAP storage
              Example

        Folder

              Folder driver
              Folder
              mailfolder_new and mail_folder_free
              mailfolder_connect and mailfolder_disconnect
              mailfolder_noop
              mailfolder_check
              mailfolder_expunge
              mailfolder_status
              mailfolder_append_message
              mailfolder_get_messages_list
              mailfolder_get_envelopes_list
              mailfolder_get_message
              mailfolder_get_message_by_uid
              Example

        Message

              Message driver
              Message
              mailmessage_new
              mailmessage_init
              mailmessage_flush
              mailmessage_check
              mailmessage_fetch_result_free
              mailmessage_fetch
              mailmessage_fetch_header
              mailmessage_fetch_body
              mailmessage_fetch_size
              mailmessage_get_bodystructure
              mailmessage_fetch_section
              mailmessage_fetch_section_header
              mailmessage_fetch_section_mime
              mailmessage_fetch_section_body
              mailmessage_fetch_envelope
              mailmessage_get_flags
              mailmessage_resolve_single_fields
              Message list
              Message tree
              Message flags
              Example

        Session

              Session driver
              Session
              mailsession_parameters
              mailsession_connect_stream
              mailsession_connect_path
              mailsession_starttls
              mailsession_login
              mailsession_logout
              mailsession_noop
              mailsession_check_folder
              mailsession_select_folder
              mailsession_expunge_folder
              mailsession_status_folder
              mailsession_messages_number
              mailsession_recent_number
              mailsession_unseen_number
              mailsession_append_message
              mailsession_get_messages_list
              mailsession_get_envelopes_list
              mailsession_get_message
              mailsession_get_message_by_uid

   List of Examples
   2-1. carray creation
   2-2. preallocating carray
   2-3. carray access
   2-4. deletion in carray
   2-5. clist creation
   2-6. displaying content of clist
   2-7. deleting elements in a clist
   2-8. merging two clists
   2-9. chash insert and lookup
   2-10. key deletion in a chash
   2-11. running through a chash
   3-1. example of mailbox
   3-2. mailbox creation and display
   3-3. address creation and display
   3-4. Creation and display of mailimf_mailbox_list
   3-5. creation and display of list of addresses
   3-6. example of group
   3-7. creation and display of a group
   3-8. example of date
   3-9. creation and display of date
   3-10. creation and display of Date field
   3-11. creation and display of a From header
   3-12. creation and display of Sender field
   3-13. creation and display of Reply-To field
   3-14. creation and display of To field
   3-15. creation and display of Cc field
   3-16. creation and display of Bcc field
   3-17. example of Message-ID
   3-18. creation and display of Message-ID field
   3-19. creation and display of In-Reply-To field
   3-20. creation and display of References field
   3-21. creation and display of Subject field
   3-22. creation and display of Comment field
   3-23. creation and display of Keywords field
   3-24. creation and display of Return-Path field
   3-25. Creation and display of return path
   3-26. creation and display of non-standard fields
   3-27. creation and display of field
   3-28. creation and display of header fields
   3-29. creation and display of message body
   3-30. creation and display of message
   3-31. using mailimf_single_fields
   3-32. using mailimf_single_fields without memory allocation
   3-33. parsing a list of addresses
   3-34. parsing an address
   3-35. parsing a message body
   3-36. parsing commonly used fields and return other fields in a
          non-parsed form

   3-37. parsing commonly used fields
   3-38. parsing optional fields
   3-39. parsing header fields
   3-40. skipping fields
   3-41. parsing a list of mailboxes
   3-42. parsing a mailbox
   3-43. parsing a message
   3-44. creating a list of mailboxes
   3-45. creation of header fields
   3-46. rendering of fields
   4-1. create and display MIME composite type
   4-2. Creation and display of MIME content type
   4-3. Creation and display of MIME discrete type
   4-4. Creation and display of MIME header field
   4-5. Creation and display of MIME transfer encoding mechanism
   4-6. Creation and display of MIME fields
   4-7. Creation and display of MIME type parameter
   4-8. Creation and display of MIME main type
   4-9. Creation and display of language of MIME part
   4-10. Creation and display of MIME part content
   4-11. Creation and display of MIME part
   4-12. Creation and display of MIME disposition information
   4-13. Creation and display of MIME disposition type
   4-14. Creation and display of MIME disposition parameter
   4-15. Creation and display of single fields
   4-16. Parsing MIME content type
   4-17. Parsing MIME description
   4-18. parsing MIME encoding mechanism
   4-19. parsing MIME header field
   4-20. Parsing MIME content identifier
   4-21. parsing MIME header fields
   4-22. parsing MIME version
   4-23. parsing a MIME parameter
   4-24. Parsing the MIME content langage
   4-25. Parsing the MIME content disposition
   4-26. parsing a MIME content disposition type
   4-27. decoding a MIME encoded header string
   4-28. parsing a MIME message
   4-29. Parsing a base64 encoded part
   4-30. Parsing a quoted printable encoded part
   4-31. Parsing a binary encoded part
   4-32. Parsing a MIME encoded part
   4-33. rendering MIME header fields
   4-34. render base64 or quoted printable
   4-35. creating a MIME content disposition
   4-36. creating a MIME header fields list
   4-37. creating new fields
   4-38. Creating a MIME content type
   4-39. creating MIME content
   4-40. creating a MIME part
   4-41. setting preamble and epilogue
   4-42. creating a MIME part
   4-43. modifying MIME structure
   4-44. modifying MIME structure
   4-45. creating MIME fields with only Content-Transfer-Encoding
   4-46. extracting MIME encoding mechanism
   4-47. extracting information from MIME content type
   5-1. use of storage
   5-2. use of folder
   5-3. use of message
     __________________________________________________________________

Chapter 1. Introduction

   This document will describe the API of libEtPan!
     __________________________________________________________________

Chapter 2. Tools and datatypes

   libEtPan! include a collection of datatypes such as lists, arrays, hash
   tables and tools such as buffered I/O.
     __________________________________________________________________

Array

#include <libetpan/libetpan.h>

typedef struct carray_s carray;

   carray is an array of pointers that will resize automatically in case a
   new element is added.

   The carray is implemented with an array (void **) that can be resized.
   An array has a size: this is the number of elements that can be added
   before the table is resized. It also has a count of elements: this is
   the elements that exist in the array.
     __________________________________________________________________

carray_new and carray_free

carray * carray_new(unsigned int initsize);

void carray_free(carray * array);

   carray_new() creates a new array with an initial size. The array is not
   resized until the number of element reach the initial size. It returns
   NULL in case of failure.

   carray_free() releases memory used by the given array.

   Example 2-1. carray creation
#include <libetpan/libetpan.h>
#include <stdlib.h>

#define SIZE 50

int main(void)
{
  carray * a;

  a = carray_new(SIZE);
  if (a == NULL)
    exit(EXIT_FAILURE);

  /* do things here */

  carray_free(a);

  exit(EXIT_SUCESS);
}
     __________________________________________________________________

carray_set_size

int carray_set_size(carray * array, uint32_t new_size);

   carray_set_size() sets the size of the array. It returns 0 in case of
   success, -1 in case of failure.

   Example 2-2. preallocating carray
#include <libetpan/libetpan.h>
#include <stdlib.h>

#define SIZE 50
#define NEWSIZE 200

int main(void)
{
  carray * a;
  unsigned int i;
  char p[500];

  a = carray_new(SIZE);
  if (a == NULL)
    goto err;

  r = carray_set_size(NEWSIZE);
  if (r < 0)
    goto free;

  for(i = 0 ; i < NEWSIZE ; i ++)
    carray_set(a, i, &p[i]);

  /* do things here */

  carray_free(a);

  exit(EXIT_SUCESS);

 free:
  carray_free(a);
 err:
  exit(EXIT_FAILURE);
}
     __________________________________________________________________

carray_count, carray_add, carray_get and carray_set

int carray_count(carray);

int carray_add(carray * array, void * data, unsigned int * index);

void * carray_get(carray * array, unsigned int indx);

void carray_set(carray * array, unsigned int indx, void * value);

   carray_count() returns the number of elements in the carray. Complexity
   is O(1).

   carray_add()adds an element at the end of the array. The index of the
   element is returns in (* index) if index is not NULL. It returns 0 in
   case of success, -1 in case of failure. Complexity is O(1).

   carray_get() returns the elements contained at the given cell of the
   table. Complexity is O(1).

   carray_set() replace the element at the given index of table table with
   the given value. Complexity is O(1).

   Example 2-3. carray access
#include <libetpan/libetpan.h>
#include <string.h>

#define SIZE 50

int main(void)
{
  carray * a;
  int r;

  a = carray_new(SIZE);
  if (a == NULL)
    goto err;

  r = carray_add(a, "foo-bar-1", NULL);
  if (r < 0)
    goto free;

  carray_add(a, "foo-bar-2", NULL);
  if (r < 0)
    goto free;

  carray_add(a, "foo-bar-3", NULL);
  if (r < 0)
    goto free;

  for(i = 0 ; i < carray_count(a) ; i ++) {
    char * str;

    str = carray_get(a, i);
    if (strcmp("foo-bar-2", str) == 0)
      carray_set(a, i, "foo-bar-2-replacement");

    printf("%s\n", str);
  }

  carray_free(a);

  exit(EXIT_SUCESS);

 free:
  carray_free(a);
 err:
  exit(EXIT_FAILURE);
}
     __________________________________________________________________

carray_delete

int carray_delete(carray * array, uint32_t indx);

int carray_delete_slow(carray * array, uint32_t indx);

int carray_delete_fast(carray * array, uint32_t indx);

   carray_delete() removes an element of the table. Order will not be
   garanteed. The returned result can be ignored. Complexity is O(1).

   carray_delete_slow() removes an element of the table. Order will be
   garanteed. The returned result can be ignored. Complexity is O(n).

   carray_delete_fast() the element will just be replaced with NULL. Order
   will be kept but the number of elements will remains the same. The
   returned result can be ignored. Complexity is O(1).

   Example 2-4. deletion in carray
#include <libetpan/libetpan.h>

#define SIZE 50

carray * build_array(void)
{
  carray * a;

  a = carray_new(SIZE);
  if (a == NULL)
    goto err;

  r = carray_add(a, "foo-bar-1", NULL);
  if (r < 0)
    goto free;

  carray_add(a, "foo-bar-2", NULL);
  if (r < 0)
    goto free;

  carray_add(a, "foo-bar-3", NULL);
  if (r < 0)
    goto free;

  return a;

 free:
  carray_free(a);
 err:
  exit(EXIT_FAILURE);
}

void delete(carray * a)
{
  /* deleting foo-bar-1 */
  carray_delete(a, 0);
  /* resulting size is 2, order of elements is undefined */
}

void delete_slow(carray * a)
{
  /* deleting foo-bar-1 */
  carray_delete_slow(a, 0);
  /* resulting size is 2, order of elements is the same */
}

void delete_fast(carray * a)
{
  /* deleting foo-bar-1 */
  carray_delete_slow(a, 0);
  /*
     resulting size is 3,
     order of elements is { NULL, foo-bar-2, foo-bar-3 }
  */
}
     __________________________________________________________________

carray_data

void ** carray_data(carray);

   carray_datareturns the table used for implementation : (void **).
     __________________________________________________________________

List

#include <libetpan/libetpan.h>

typedef struct clist_s clist;

typedef clistcell clistiter;

   clist() is a list of cells. Each cell of the list contains one element.
   This element is a pointer. An iterator (clistiter) is a pointer to an
   element of the list. With an iterator, we can get the previous element
   of the list, the next element of the list and the content of the
   element.
     __________________________________________________________________

clist_new and clist_free

clist * clist_new(void);

void clist_free(clist *);

   clist_new() allocates a new empty list and returns it.

   clist_free() frees the entire list with its cells.

   Example 2-5. clist creation
#include <libetpan/libetpan.h>

int main(void)
{
  clist * list;

  list = clist_new();
  if (list == NULL)
    goto err;

  r = clist_append(list, "foo-bar");
  if (r < 0)

  clist_free(list);

  exit(EXIT_SUCCESS);

 free:
  clist_free(list);
 err:
  exit(EXIT_FAILURE);
}
     __________________________________________________________________

clist_isempty and clist_count

int clist_isempty(clist *);

int clist_count(clist *);

   clist_isempty() returns 1 if the list is empty, else it is 0.
   Complexity is O(1).

   clist_count() returns the number of elements in the list. Complexity is
   O(1).
     __________________________________________________________________

running through clist

clistiter * clist_begin(clist *);

clistiter * clist_end(clist *);

clistiter * clist_next(clistiter *);

clistiter * clist_previous(clistiter *);

void * clist_content(clistiter *);

void * clist_nth_data(clist * lst, int index);

clistiter * clist_nth(clist * lst, int index);

   clist_begin() returns an iterator to the first element of the list.
   Complexity is O(1).

   clist_end() returns an iterator to the last element of the list.
   Complexity is O(1).

   clist_next() returns an iterator to the next element of the list.
   Complexity is O(1).

   clist_previous() returns an iterator to the previous element of the
   list. Complexity is O(1).

   clist_content() returns the element contained in the cell pointed by
   the iterator in the list. Complexity is O(1).

   clist_nth() returns an iterator on the index-th element of the list.
   Complexity is O(n).

   clist_nth_data() returns the index-th element of the list. Complexity
   is O(n).

   Example 2-6. displaying content of clist
#include <libetpan/libetpan.h>

int main(void)
{
  clist * list;
  clistiter * iter;

  list = build_string_list();
  if (list == NULL)
    goto err;

  for(iter = clist_begin(list) ; iter != NULL ; iter =
     clist_next(iter)) {
    char * str;

    str = clist_content(iter);
    printf("%s\n", str);
  }

  clist_free(list);

  exit(EXIT_SUCCESS);

 free:
  clist_free(list);
 err:
  exit(EXIT_FAILURE);
}
     __________________________________________________________________

clist modification

int clist_prepend(clist *, void *);

int clist_append(clist *, void *);

int clist_insert_before(clist *, clistiter *, void *);

int clist_insert_after(clist *, clistiter *, void *);

clistiter * clist_delete(clist *, clistiter *);

   clist_prepend() adds an element at the beginning of the list. Returns 0
   on sucess, -1 on error. Complexity is O(1).

   clist_append() adds an element at the end of the list. Returns 0 on
   sucess, -1 on error. Complexity is O(1).

   clist_insert_before() adds an element before the element pointed by the
   given iterator in the list. Returns 0 on sucess, -1 on error.
   Complexity is O(1).

   clist_insert_after() adds an element after the element pointed by the
   given iterator in the list. Returns 0 on sucess, -1 on error.
   Complexity is O(1).

   clist_delete() the elements pointed by the given iterator in the list
   and returns an iterator to the next element of the list. Complexity is
   O(1).

   Example 2-7. deleting elements in a clist
#include <libetpan/libetpan.h>

voir print_content(void * content, void * user_data)
{
  char * str;

  str = content;

  printf("%s\n", str);
}

int main(void)
{
  clist * list;
  clistiter * iter;

  list = build_string_list();
  if (list == NULL)
    goto err;

  iter = = clist_begin(list);
  while (iter != NULL)
    char * str;

    str = clist_content(iter);
    if (strcmp(str, "foo-bar") == 0)
      iter = clist_delete(list, cur);
    else
      iter = clist_next(iter);
  }

  clist_foreach(list, print_content, NULL);
  printf("\n");

  clist_free(list);

  exit(EXIT_SUCCESS);

 free:
  clist_free(list);
 err:
  exit(EXIT_FAILURE);
}
     __________________________________________________________________

clist_foreach

typedef void (* clist_func)(void *, void *);

void clist_foreach(clist * lst, clist_func func, void * data);

   clist_foreach() apply a fonction to each element of the list.
   Complexity is O(n).
     __________________________________________________________________

clist_concat

void clist_concat(clist * dest, clist * src);

   clist_concat() adds all the elements of src at the end of dest.
   Elements are added in the same order. src is an empty list when the
   operation is finished. Complexity is O(1).

   Example 2-8. merging two clists
#include <libetpan/libetpan.h>

int main(void)
{
  clist * list;
  clist * list_2;
  clistiter * iter;

  list = build_string_list();
  if (list == NULL)
    goto err;

  list_2 = build_string_list_2();
  if (list == NULL)
    goto free_list;

  clist_concat(list, list_2);
  clist_free(list_2);

  for(iter = clist_begin(list) ; iter != NULL ; iter =
     clist_next(iter)) {
    char * str;

    str = clist_content(iter);
    printf("%s\n", str);
  }

  clist_free(list);

  exit(EXIT_SUCCESS);

 free_list:
  clist_free(list);
 err:
  exit(EXIT_FAILURE);
}
     __________________________________________________________________

Hash table

#include <libetpan/libetpan.h>

typedef struct chash chash;

typedef struct chashcell chashiter;

typedef struct {
  char * data;
  int len;
} chashdatum;

   chash is a hash table. chashiter is a pointer to an element of the hash
   table. chashdatum is an element to be placed in the hash table as a key
   or a value. It consists in data and a corresponding length.
     __________________________________________________________________

chash_new and chash_free

#define CHASH_COPYNONE    0
#define CHASH_COPYKEY     1
#define CHASH_COPYVALUE   2
#define CHASH_COPYALL     (CHASH_COPYKEY | CHASH_COPYVALUE)

chash * chash_new(int size, int flags);

void chash_free(chash * hash);

   chash_new() returns a new empty hash table or NULL if this failed. size
   is the initial size of the table used for implementation. flags can be
   a combinaison of CHASH_COPYKEY and CHASH_COPYVALUE. CHASH_COPYKEY
   enables copy of key, so that the initial value used for chash_set()

   chash_free() releases memory used by the hash table.
     __________________________________________________________________

chash_set and chash_get

int chash_set(chash * hash,
    chashdatum * key, chashdatum * value, chashdatum * oldvalue);

int chash_get(chash * hash,
    chashdatum * key, chashdatum * result);

   chash_set() adds a new element into the hash table. If a previous
   element had the same key, it is returns into oldvalue if oldvalue is
   different of NULL. Medium complexity is O(1).

   returns -1 if it fails, 0 on success.

   chash_get()returns the corresponding value of the given key. If there
   is no corresponding value, -1 is returned. 0 on success. Medium
   complexity is O(1).

   Example 2-9. chash insert and lookup
int main(void)
{
  chash * hash;
  int r;
  chashdatum key;
  chashdatum value;
  char * str1 = "my-data";
  char * str2 = "my-data";

  hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE);

  key.data = "foo";
  key.len = strlen("foo");
  value.data = str1;
  value.data = strlen(str1) + 1;
  /* + 1 is needed to get the terminal zero in the returned string */
  r = chash_set(hash, &key, &value, NULL);
  if (r < 0)
    goto free_hash;

  key.data = "bar";
  key.len = strlen("bar");
  value.data = str2;
  value.data = strlen(str2) + 1;
  if (r < 0)
    goto free_hash;

  key.data = "foo";
  key.len = strlen("foo");
  r = chash_get(hash, &key, &value);
  if (r < 0) {
    printf("element not found\n");
  }
  else {
    char * str;

    str = value.data;
    printf("found : %s", str);
  }

  chash_free(hash);

  exit(EXIT_SUCCESS);

 free_hash:
  chash_free(hash);
 err:
  exit(EXIT_FAILURE);
}
     __________________________________________________________________

chash_delete

int chash_delete(chash * hash,
    chashdatum * key, chashdatum * oldvalue);

   deletes the key/value pair given the corresponding key. The value is
   returned in old_value. If there is no corresponding value, -1 is
   returned. 0 on success. Medium complexity is O(1).

   Example 2-10. key deletion in a chash
int main(void)
{
  chash * hash;
  int r;
  chashdatum key;
  chashdatum value;
  char * str1 = "my-data";
  char * str2 = "my-data";

  hash = build_hash();

  key.data = "foo";
  key.len = strlen("foo");
  chash_delete(hash, &key, &value);

  /* it will never be possible to lookup "foo" */
  key.data = "foo";
  key.len = strlen("foo");
  r = chash_get(hash, &key, &value);
  if (r < 0) {
    printf("element not found\n");
  }
  else {
    char * str;

    str = value.data;
    printf("found : %s", str);
  }

  chash_free(hash);

  exit(EXIT_SUCCESS);

 free_hash:
  chash_free(hash);
 err:
  exit(EXIT_FAILURE);
}
     __________________________________________________________________

chash_resize

int chash_resize(chash * hash, int size);

   chash_resize() changes the size of the table used for implementation of
   the hash table. returns 0 on success, -1 on failure.
     __________________________________________________________________

running through the chash

chashiter * chash_begin(chash * hash);

chashiter * chash_next(chash * hash, chashiter * iter);

void chash_key(chashiter * iter, chashdatum * result);

void chash_value(chashiter iter, chashdatum * result);

   chash_begin() returns a pointer to the first element of the hash table.
   Returns NULL if there is no elements in the hash table. Complexity is
   O(n).

   chash_next() returns a pointer to the next element of the hash table.
   Returns NULL if there is no next element. Complexity is O(n) but n
   calls to chash_next() also has a complexity of O(n).

   chash_key() returns the key of the given element of the hash table.

   chash_value returns the value of the given element of the hash table.

   Example 2-11. running through a chash
int main(void)
{
  chash * hash;
  int r;
  chashiter * iter;

  hash = build_hash();

  /* this will display all the values stored in the hash */
  for(iter = chash_begin(hash) ; iter != NULL ; iter =
    chash_next(hash, iter)) {
    chashdatum key;
    chashdatum value;
    char * str;

    chash_value(iter, &value);
    str = value.data;
    printf("%s\n", str);
  }

  chash_free(hash);
}
     __________________________________________________________________

chash_size and chash_count

int chash_size(chash * hash);

int chash_count(chash * hash);

   chash_size() returns the size of the table used for implementation of
   the hash table. Complexity is O(1).

   chash_count() returns the number of elements in the hash table.
   Complexity is O(1).
     __________________________________________________________________

Buffered I/O


#include <libetpan/libetpan.h>

typedef struct _mailstream mailstream;

   streams are objects where we can read data from and write data to. They
   are not seekable. That can be for example a pipe or a network stream.
mailstream * mailstream_new(mailstream_low * low, size_t buffer_size);

int mailstream_close(mailstream * s);

   mailstream_new() creates a new stream stream with the low-level (see
   the Section called non-buffered I/O) stream and a given buffer size.

   mailstream_close() closes the stream. This function will be in charge
   to free the mailstream_low structure.

ssize_t mailstream_write(mailstream * s, void * buf, size_t count);

int mailstream_flush(mailstream * s);

ssize_t mailstream_read(mailstream * s, void * buf, size_t count);

ssize_t mailstream_feed_read_buffer(mailstream * s);

   mailstream_write() writes a buffer to the given stream. This write
   operation will be buffered.

   mailstream_flush() will force a write of all buffered data for a given
   stream.

   mailstream_read() reads data from the stream to the given buffer.

   mailstream_feed_read_buffer() this function will just fill the buffer
   for reading.

mailstream_low * mailstream_get_low(mailstream * s);

void mailstream_set_low(mailstream * s, mailstream_low * low);

   mailstream_get_low() returns the low-level stream of the given stream.

   mailstream_set_low() changes the low-level of the given stream. Useful,
   for example, when a stream change from clear stream to SSL stream.
char * mailstream_read_line(mailstream * stream, MMAPString * line);

char * mailstream_read_line_append(mailstream * stream, MMAPString * line);

char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line);

char * mailstream_read_multiline(mailstream * s, size_t size,
    MMAPString * stream_buffer,
    MMAPString * multiline_buffer,
    size_t progr_rate,
    progress_function * progr_fun);

   mailstream_read_line() reads an entire line from the buffer and store
   it into the given string. returns NULL on error, the corresponding
   array of char is returned otherwise.

   mailstream_read_line_append() reads an entire line from the buffer and
   appends it to the given string. returns NULL on error, the array of
   char corresponding to the entire buffer is returned otherwise.

   mailstream_read_line_remove_eol() reads an entire line from the buffer
   and store it into the given string. All CR LF are removed. returns NULL
   on error, the corresponding array of char is returned otherwise.

   mailstream_read_multiline() reads a multiline data (several lines, the
   data are ended with a single period '.') from the given stream and
   store it into the given multiline buffer (multiline_buffer). progr_rate
   should be 0 and progr_fun NULL (deprecated things). stream_buffer is a
   buffer used for internal work of the function. size should be 0
   (deprecated things).

int mailstream_is_end_multiline(char * line);

   returns 1 if the line is an end of multiline data (a single period '.',
   eventually with CR and/or LF). 0 is returned otherwise.

int mailstream_send_data(mailstream * s, char * message,
    size_t size,
    size_t progr_rate,
    progress_function * progr_fun);

   sends multiline data to the given stream. size is the size of the data.
   progr_rate and progr_fun are deprecated. progr_rate must be 0,
   progr_fun must be NULL.
     __________________________________________________________________

socket stream

mailstream * mailstream_socket_open(int fd);

   mailstream_socket_open() will open a clear-text socket.
     __________________________________________________________________

TLS stream

mailstream * mailstream_ssl_open(int fd);

   mailstream_ssl_open() will open a TLS/SSL socket.
     __________________________________________________________________

non-buffered I/O


#include <libetpan/libetpan.h>

struct mailstream_low_driver {
  ssize_t (* mailstream_read)(mailstream_low *, void *, size_t);
  ssize_t (* mailstream_write)(mailstream_low *, void *, size_t);
  int (* mailstream_close)(mailstream_low *);
  int (* mailstream_get_fd)(mailstream_low *);
  void (* mailstream_free)(mailstream_low *);
};

typedef struct mailstream_low_driver mailstream_low_driver;

struct _mailstream_low {
  void * data;
  mailstream_low_driver * driver;
};

   mailstream_low is a non-buffered stream.

   The mailstream_low_driver is a set of functions used to access the
   stream.

     * mailstream_read/write/close() is the same interface as
       read/write/close() system calls, except that the file descriptor is
       replaced with the mailstream_low structure.
     * mailstream_get_fd() returns the file descriptor used for this
       non-buffered stream.
     * mailstream_free() is in charge to free the internal structure of
       the mailstream_low and the mailstream_low itself.


mailstream_low * mailstream_low_new(void * data,
    mailstream_low_driver * driver);

   mailstream_low_new() creates a low-level mailstream with the given
   internal structure (data) and using the given set of functions
   (driver).

ssize_t mailstream_low_write(mailstream_low * s, void * buf, size_t count);

ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count);

int mailstream_low_close(mailstream_low * s);

int mailstream_low_get_fd(mailstream_low * s);

void mailstream_low_free(mailstream_low * s);

   Each of these calls will call the corresponding function defined in the
   driver.
     __________________________________________________________________

strings


#include <libetpan/libetpan.h>

struct _MMAPString
{
  char * str;
  size_t len;
  size_t allocated_len;
  int fd;
  size_t mmapped_size;
};

typedef struct _MMAPString MMAPString;

   MMAPString is a string which size that can increase automatically.
     __________________________________________________________________

constructor and destructor

MMAPString * mmap_string_new(const char * init);

MMAPString * mmap_string_new_len(const char * init, size_t len);

MMAPString * mmap_string_sized_new(size_t dfl_size);

void mmap_string_free(MMAPString * string);

   mmap_string_new() allocates a new string. init is the intial value of
   the string. NULL will be returned on error.

   mmap_string_new_len() allocates a new string. init is the intial value
   of the string, len is the length of the initial string. NULL will be
   returned on error.

   mmap_string_sized_new() allocates a new string. dfl_size is the initial
   allocation of the string. NULL will be returned on error.

   mmap_string_free() release the memory used by the string.
     __________________________________________________________________

string value modification

MMAPString * mmap_string_assign(MMAPString * string, const char * rval);

MMAPString * mmap_string_truncate(MMAPString *string, size_t len);

   mmap_string_assign() sets a new value for the given string. NULL will
   be returned on error.

   mmap_string_truncate() sets a length for the string. NULL will be
   returned on error.
MMAPString * mmap_string_set_size (MMAPString * string, size_t len);

   sets the allocation of the string. NULL will be returned on error.
     __________________________________________________________________

insertion in string, deletion in string

MMAPString * mmap_string_insert_len(MMAPString * string, size_t pos,
    const char * val, size_t len);

MMAPString * mmap_string_append(MMAPString * string, const char * val);

MMAPString * mmap_string_append_len(MMAPString * string,
  const char * val, size_t len);

MMAPString * mmap_string_append_c(MMAPString * string, char c);

MMAPString * mmap_string_prepend(MMAPString * string, const char * val);

MMAPString * mmap_string_prepend_c(MMAPString * string, char c);

MMAPString * mmap_string_prepend_len(MMAPString * string, const char * val,
  size_t len);

MMAPString * mmap_string_insert(MMAPString * string, size_t pos,
  const char * val);

MMAPString * mmap_string_insert_c(MMAPString *string, size_t pos,
  char c);

MMAPString * mmap_string_erase(MMAPString * string, size_t pos,
  size_t len);

   For complexity here, n is the size of the given MMAPString, and len is
   the size of the string to insert.

   mmap_string_insert_len() inserts the given string value of given length
   in the string at the given position. NULL will be returned on error.
   Complexity is O(n + len).

   mmap_string_append() appends the given string value at the end of the
   string. NULL will be returned on error. Complexity is O(len).

   mmap_string_append_len() appends the given string value of given length
   at the end of the string. NULL will be returned on error. Complexity is
   O(len).

   mmap_string_append_c() appends the given character at the end of the
   string. NULL will be returned on error. Complexity is O(1).

   mmap_string_prepend() insert the given string value at the beginning of
   the string. NULL will be returned on error. Complexity is O(n + len).

   mmap_string_prepend_c() insert the given character at the beginning of
   the string. NULL will be returned on error. Complexity is O(n).

   mmap_string_prepend_len() insert the given string value of given length
   at the beginning of the string. NULL will be returned on error.
   Complexity is O(n + len).

   mmap_string_insert() inserts the given string value in the string at
   the given position. NULL will be returned on error. Complexity is O(n +
   len).

   mmap_string_insert_c() inserts the given character in the string at the
   given position. NULL will be returned on error. Complexity is O(n).

   mmap_string_erase() removes the given count of characters (len) at the
   given position of the string. NULL will be returned on error.
   Complexity is O(n).
     __________________________________________________________________

referencing string

int mmap_string_ref(MMAPString * string);

int mmap_string_unref(char * str);

   MMAPString provides a mechanism that let you use MMAPString like normal
   strings. You have first to use mmap_string_ref(), so that you notify
   that the string will be used as a normal string, then, you use
   mmapstr->str to refer to the string. When you have finished and you
   want to free a string corresponding to a MMAPString, you will use
   mmap_string_unref.

   mmap_string_ref() references the string so that the array of characters
   can be used as a normal string then released with mmap_string_unref().
   The array of characters will be obtained with string->str. returns -1
   on error, 0 on success.
     __________________________________________________________________

Chapter 3. Internet Message Format

   libEtPan! implements Internet Message parser. Currently, format is RFC
   2822. This module also allows to generate messages.

   Warning

   All allocation functions will take as argument allocated data and will
   store these data in the structure they will allocate. Data should be
   persistant during all the use of the structure and will be freed by the
   free function of the structure

   allocation functions will return NULL on failure functions returning
   integer will be returning one of the following error code:
   MAILIMF_NO_ERROR, MAILIMF_ERROR_PARSE, MAILIMF_ERROR_MEMORY,
   MAILIMF_ERROR_INVAL, or MAILIMF_ERROR_FILE.
     __________________________________________________________________

Quick start

   You will need this module when you want to parse headers of messages or
   when you want to build message headers conformant to standards.
     __________________________________________________________________

Parse message headers

   You will use one of the four following functions, depending on your
   needs :

     * mailimf_envelope_and_optional_fields_parse (the Section called
       mailimf_envelope_and_optional_fields_parse),
     * mailimf_envelope_fields_parse (the Section called
       mailimf_envelope_fields_parse),
     * mailimf_optional_fields_parse (the Section called
       mailimf_optional_fields_parse),
     * mailimf_fields_parse (the Section called mailimf_fields_parse).
     __________________________________________________________________

Render the message headers

   Build your message headers, then use mailimf_fields_write (the Section
   called Header fields) to render the headers.
     __________________________________________________________________

Data types

mailimf_mailbox - mailbox

   #include <libetpan/libetpan.h> struct mailimf_mailbox { char *
   mb_display_name; /* can be NULL */ char * mb_addr_spec; /* != NULL */
   }; struct mailimf_mailbox * mailimf_mailbox_new(char * mb_display_name,
   char * mb_addr_spec); void mailimf_mailbox_free(struct mailimf_mailbox
   * mailbox);

   This is an email mailbox with a display name.

   Example 3-1. example of mailbox
DINH Viet Hoa <hoa@users.sourceforge.net>

   mailimf_mailbox_new creates and initializes a data structure with a
   value. Strings given as argument are referenced by the created object
   and will be freed if the object is released.

   mailimf_mailbox_free frees memory used by the structure and
   substructures will also be released.

   Example 3-2. mailbox creation and display
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_mailbox * mb;
  char * display_name;
  char * address;

  display_name = strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?=");
  address = strdup("dinh.viet.hoa@free.fr");
  mb = mailimf_mailbox_new(str, address);
  /* do the things */
  mailimf_mailbox_free(mb);

  return 0;
}

/* display mailbox information */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_mailbox(struct mailimf_mailbox * mb)
{
  if (mb->mb_display_name != NULL)
    printf("display name: %s\n", mb->mb_display_name);
  printf("address specifier : %s\n", mb->mb_addr_spec);
}
     __________________________________________________________________

mailimf_address - address

#include <libetpan/libetpan.h>

struct mailimf_address {
  int ad_type;
  union {
    struct mailimf_mailbox * ad_mailbox; /* can be NULL */
    struct mailimf_group * ad_group;     /* can be NULL */
  } ad_data;
};

struct mailimf_address *
mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox,
                    struct mailimf_group * ad_group);

void mailimf_address_free(struct mailimf_address * address);

   This is a mailbox or a group of mailbox.

     * ad_type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP.
     * ad_data.ad_mailbox is a mailbox if ad_type is
       MAILIMF_ADDRESS_MAILBOX see the Section called mailimf_mailbox -
       mailbox)
     * ad_data.group is a group if type is MAILIMF_ADDRESS_GROUP. see the
       Section called mailimf_group - named group of mailboxes)

   mailimf_address_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_address_free frees memory used by the structure and
   substructures will also be released.

   Example 3-3. address creation and display
/* creates an address of type mailbox */

#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_address * a_mb;
  struct mailimf_mailbox * mb;
  char * display_name;
  char * address;

  display_name = strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?=");
  address = strdup("dinh.viet.hoa@free.fr");
  mb = mailimf_mailbox_new(str, address);

  a_mb = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  /* do the things */
  mailimf_address_free(a_mb);
}

/* creates an address of type group */

#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_address * a_g;
  struct mailimf_group * g;
  char * display_name;

  display_name = strdup("undisclosed-recipient");
  g = mailimf_group_new(display_name, NULL);

  a_g = mailimf_address_new(MAILIMF_ADDRESS_GROUP, NULL, g);
  /* do the things */
  mailimf_address_free(a_g);

  return 0;
}

/* display the content of an address */

#include <libetpan/libetpan.h>

void display_address(struct mailimf_address * a)
{
  clistiter * cur;

  switch (a->ad_type) {
    case MAILIMF_ADDRESS_GROUP:
      display_mailimf_group(a->ad_data.ad_group);
      break;

    case MAILIMF_ADDRESS_MAILBOX:
      display_mailimf_mailbox(a->ad_data.ad_mailbox);
      break;
  }
}
     __________________________________________________________________

mailimf_mailbox_list - list of mailboxes

#include <libetpan/libetpan.h>

struct mailimf_mailbox_list {
  clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */
};

struct mailimf_mailbox_list *
mailimf_mailbox_list_new(clist * mb_list);

void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list);

   This is a list of mailboxes.

   mb_list is a list of mailboxes. This is a clist which elements are of
   type mailimf_mailbox (see the Section called mailimf_mailbox -
   mailbox).

   mailimf_mailbox_list_new() creates and initializes a data structure
   with a value. Structures given as argument are referenced by the
   created object and will be freed if the object is released.

   mailimf_mailbox_list_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-4. Creation and display of mailimf_mailbox_list
/* creates a list of mailboxes with two mailboxes */

#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_group * g;
  char * display_name;
  struct mailimf_mailbox_list * mb_list;
  clist * list;

  list = clist_new();
  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  list = clist_append(mb);
  mb = mailimf_mailbox_new(strdup("Christophe GIAUME"),
    strdup("christophe@giaume.com"));
  list = clist_append(mb);

  mb_list = mailimf_mailbox_list_new(list);
  /* do the things */
  mailimf_mailbox_list_free(mb_list);

  return 0;
}

/* display a list of mailboxes */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_mailbox_list(struct mailimf_mailbox_list * mb_list)
{
  clistiter * cur;

  for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ;
    cur = clist_next(cur)) {
    struct mailimf_mailbox * mb;

    mb = clist_content(cur);

    display_mailbox(mb);
    printf("\n");
  }
}
     __________________________________________________________________

mailimf_address_list - list of addresses

#include <libetpan/libetpan.h>

struct mailimf_address_list {
  clist * ad_list; /* list of (struct mailimf_address *), != NULL */
};

struct mailimf_address_list *
mailimf_address_list_new(clist * ad_list);

void mailimf_address_list_free(struct mailimf_address_list * addr_list);

   This is a list of addresses.

   ad_list is a list of addresses. This is a clist which elements are of
   type mailimf_address (see the Section called mailimf_address -
   address).

   mailimf_address_list_new() creates and initializes a data structure
   with a value. Structures given as argument are referenced by the
   created object and will be freed if the object is released.

   mailimf_address_list_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-5. creation and display of list of addresses
/* creates a list of addresses with two addresses */

#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_address_list * addr_list;
  clist * list;
  struct mailimf_mailbox * mb;
  struct mailimf_address * addr;

  list = clist_new();
  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  list = clist_append(addr);

  mb = mailimf_mailbox_new(strdup("Christophe GIAUME"),
    strdup("christophe@giaume.com"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  list = clist_append(addr);

  addr_list = mailimf_address_list_new(list);
  /* do the things */
  mailimf_address_list_free(mb_list);

  return 0;
}

/* display a list of addresses */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_address_list(struct mailimf_address_list * addr_list)
{
  clistiter * cur;

  for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ;
    cur = clist_next(cur)) {
    struct mailimf_address * addr;

    addr = clist_content(cur);

    display_address(addr);
    printf("\n");
  }
}
     __________________________________________________________________

mailimf_group - named group of mailboxes

#include <libetpan/libetpan.h>

struct mailimf_group {
  char * grp_display_name; /* != NULL */
  struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */
};

struct mailimf_group *
mailimf_group_new(char * grp_display_name,
    struct mailimf_mailbox_list * grp_mb_list);

void mailimf_group_free(struct mailimf_group * group);

   This is a list of mailboxes tagged with a name.

   Example 3-6. example of group
            they play music: <steve@morse.foo>, <neal@morse.foo>,
            <yngwie@malmsteen.bar>, <michael@romeo.bar>;

   grp_display_name is the name that will be displayed for this group, for
   example 'group_name' in 'group_name: address1@domain1,
   address2@domain2;'. This must be allocated with malloc(). grp_mb_list
   is a list of mailboxes (see the Section called mailimf_mailbox_list -
   list of mailboxes).

   mailimf_group_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_group_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-7. creation and display of a group
/* creates an empty group */

#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_group * g;
  char * display_name;

  display_name = strdup("undisclosed-recipient");
  g = mailimf_group_new(display_name, NULL);
  /* do the things */
  mailimf_group_free(g);
}

/* creates a group with two mailboxes */

#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_group * g;
  char * display_name;
  struct mailimf_mailbox_list * mb_list;
  struct mailimf_mailbox * mb;
  clist * list;

  list = clist_new();
  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  list = clist_append(mb);
  mb = mailimf_mailbox_new(strdup("Christophe GIAUME"),
    strdup("christophe@giaume.com"));
  list = clist_append(mb);

  mb_list = mailimf_mailbox_list_new(list);

  display_name = strdup("my_group");
  g = mailimf_group_new(display_name, mb_list);
  /* do the things */
  mailimf_group_free(g);

  return 0;
}

/* display content of group */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_group(struct mailimf_group * group)
{
  printf("name of the group: %s\n", a->group->display_name);
  for(cur = clist_begin(a->group->mb_list->list) ; cur != NULL ;
    cur = clist_next(cur)) {
    struct mailimf_mailbox * mb;

    mb = clist_content(cur);
    display_mailbox(mb);
    printf("\n");
  }
}
     __________________________________________________________________

mailimf_date_time - date of a message

   #include <libetpan/libetpan.h> struct mailimf_date_time { int dt_day;
   int dt_month; int dt_year; int dt_hour; int dt_min; int dt_sec; int
   dt_zone; }; struct mailimf_date_time * mailimf_date_time_new(int
   dt_day, int dt_month, int dt_year, int dt_hour, int dt_min, int dt_sec,
   int dt_zone); void mailimf_date_time_free(struct mailimf_date_time *
   date_time);

   This is the date and time of a message. For example :

   Example 3-8. example of date
Thu, 11 Dec 2003 00:15:02 +0100.

     * dt_day is the day of month (1 to 31)
     * dt_month (1 to 12)
     * dt_year (4 digits)
     * dt_hour (0 to 23)
     * dt_min (0 to 59)
     * dt_sec (0 to 59)
     * dt_zone (this is the decimal value that we can read, for example:
       for '-0200', the value is -200).

   mailimf_date_time_new() creates and initializes a date structure with a
   value.

   mailimf_date_time_free() frees memory used by the structure.

   Example 3-9. creation and display of date
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_date_time * d;

  d = mailimf_date_time_new(9, 5, 2003, 3, 01, 40, -0200);
  /* do the things */
  mailimf_date_time_free(d);

  return 0;
}

/* display the date */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_date(struct mailimf_date_time * d)
{
  printf("%02i/%02i/%i %02i:%02i:%02i %+04i\n",
    d->dt_day, d->dt_month, d->dt_year,
    d->dt_hour, d->dt_min, d->dt_sec, d->dt_zone);
}
     __________________________________________________________________

mailimf_orig_date - parsed content of date header

#include <libetpan/libetpan.h>

struct mailimf_orig_date {
  struct mailimf_date_time * dt_date_time; /* != NULL */
};

struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time *
    dt_date_time);

void mailimf_orig_date_free(struct mailimf_orig_date * orig_date);

   This is the content of a header Date or Resent-Date. It encapsulates a
   mailimf_date_time

   dt_date_time is the parsed date (see the Section called
   mailimf_date_time - date of a message).

   mailimf_orig_date_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_orig_date_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-10. creation and display of Date field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_date_time * d;
  struct mailimf_orig_date * date;

  d = mailimf_date_time_new(9, 5, 2003, 3, 01, 40, -0200);
  date = mailimf_orig_date_new(d);
  /* do the things */
  mailimf_orig_date_free(date);

  return 0;
}

/* display date header */

#include <libetpan/libetpan.h>

void display_orig_date(struct mailimf_orig_date * orig_date)
{
  display_date_time(d->dt_date_time);
}
     __________________________________________________________________

mailimf_from - parsed content of From header

#include <libetpan/libetpan.h>

struct mailimf_from {
  struct mailimf_mailbox_list * frm_mb_list; /* != NULL */
};

struct mailimf_from *
mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list);

void mailimf_from_free(struct mailimf_from * from);

   This is the content of a header From or Resent-From.

   frm_mb_list is the parsed mailbox list (see the Section called
   mailimf_mailbox_list - list of mailboxes).

   mailimf_from_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_from_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-11. creation and display of a From header
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  clist * list;
  struct mailimf_mailbox * mb;
  struct mailimf_mailbox_list * mb_list;
  struct mailimf_from * from;

  list = clist_new();
  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  clist_append(list, mb);
  mb_list = mailimf_mailbox_list_new(list);

  from = mailimf_from_new(mb_list);
  /* do the things */
  mailimf_from_free(from);

  return 0;
}

/* display content of from header */

#include <libetpan/libetpan.h>

void display_from(struct mailimf_from * from)
{
  display_mailbox_list(from->frm_mb_list);
}
     __________________________________________________________________

mailimf_sender - parsed content of Sender header

#include <libetpan/libetpan.h>

struct mailimf_sender {
  struct mailimf_mailbox * snd_mb; /* != NULL */
};

struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb);

void mailimf_sender_free(struct mailimf_sender * sender);

   This is the content of a header Sender or Resent-Sender.

   snd_mb is the parsed mailbox (see the Section called mailimf_mailbox -
   mailbox).

   mailimf_sender_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_sender_free() This function frees memory used by the structure
   and substructures will also be released.

   Example 3-12. creation and display of Sender field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_mailbox * mb;
  struct mailimf_sender * sender;

  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));

  sender = mailimf_sender_new(mb);
  /* do the things */
  mailimf_sender_free(sender);

  return 0;
}

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_sender(struct mailimf_sender * sender)
{
  display_mailbox(sender->snd_mb);
}
     __________________________________________________________________

mailimf_reply_to - parsed content of Reply-To header

#include <libetpan/libetpan.h>

struct mailimf_reply_to {
  struct mailimf_address_list * rt_addr_list; /* != NULL */
};

struct mailimf_reply_to *
mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list);

void mailimf_reply_to_free(struct mailimf_reply_to * reply_to);

   This is the content of a header Reply-To.

   addr_list is the parsed address list (see the Section called
   mailimf_address_list - list of addresses).

   mailimf_reply_to_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_reply_to_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-13. creation and display of Reply-To field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  clist * list;
  struct mailimf_mailbox * mb;
  struct mailimf_address * addr;
  struct mailimf_address_list * addr_list;
  struct mailimf_reply_to * reply_to;

  list = clist_new();

  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  clist_append(list, addr);

  mb = mailimf_mailbox_new(strdup("Christophe GIAUME"),
    strdup("christophe@giaume.com"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  clist_append(list, addr);

  addr_list = mailimf_address_list_new(list);

  reply_to = mailimf_reply_to_new(addr_list);
  /* do the things */
  mailimf_reply_to_free(reply_to);

  return 0;
}

/* display Reply-To header */

#include <libetpan/libetpan.h>

void display_reply_to(struct mailimf_reply_to * reply_to)
{
  display_address_list(reply_to->addr_list);
}
     __________________________________________________________________

mailimf_to - parsed content of To header

        struct mailimf_to {
  struct mailimf_address_list * to_addr_list; /* != NULL */
};

struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list);

void mailimf_to_free(struct mailimf_to * to);

   This is the content of a header To or Resent-To.

   to_addr_list is the parsed address list (see the Section called
   mailimf_address_list - list of addresses).

   mailimf_to_new() creates and initializes a data structure with a value.
   Structures given as argument are referenced by the created object and
   will be freed if the object is released.

   mailimf_to_free() frees memory used by the structure and substructures
   will also be released.

   Example 3-14. creation and display of To field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  clist * list;
  struct mailimf_mailbox * mb;
  struct mailimf_address * addr;
  struct mailimf_address_list * addr_list;
  struct mailimf_to * to;

  list = clist_new();

  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  clist_append(list, addr);

  mb = mailimf_mailbox_new(strdup("Christophe GIAUME"),
    strdup("christophe@giaume.com"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  clist_append(list, addr);

  addr_list = mailimf_address_list_new(list);

  to = mailimf_to_new(addr_list);
  /* do the things */
  mailimf_to_free(to);

  return 0;
}

/* display To header */

#include <libetpan/libetpan.h>

void display_to(struct mailimf_to * to)
{
  display_address_list(to->to_addr_list);
}
     __________________________________________________________________

mailimf_cc - parsed content of Cc

#include <libetpan/libetpan.h>

struct mailimf_cc {
  struct mailimf_address_list * cc_addr_list; /* != NULL */
};

struct mailimf_cc *
mailimf_cc_new(struct mailimf_address_list * cc_addr_list);

void mailimf_cc_free(struct mailimf_cc * cc);

   This is the content of a header Cc or Resent-Cc.

   cc_addr_list is the parsed address list (see the Section called
   mailimf_address_list - list of addresses).

   mailimf_cc_new() creates and initializes a data structure with a value.
   Structures given as argument are referenced by the created object and
   will be freed if the object is released.

   mailimf_cc_free() This function frees memory used by the structure and
   substructures will also be released.

   Example 3-15. creation and display of Cc field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  clist * list;
  struct mailimf_mailbox * mb;
  struct mailimf_address * addr;
  struct mailimf_address_list * addr_list;
  struct mailimf_cc * cc;

  list = clist_new();

  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  clist_append(list, addr);

  mb = mailimf_mailbox_new(strdup("Christophe GIAUME"),
    strdup("christophe@giaume.com"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  clist_append(list, addr);

  addr_list = mailimf_address_list_new(list);

  cc = mailimf_cc_new(addr_list);
  /* do the things */
  mailimf_cc_free(cc);

  return 0;
}

/* display content of Cc field */

#include <libetpan/libetpan.h>

void display_cc(struct mailimf_cc * cc)
{
  display_address_list(cc->cc_addr_list);
}

     __________________________________________________________________

mailimf_bcc - parsed content of Bcc field

#include <libetpan/libetpan.h>

struct mailimf_bcc {
  struct mailimf_address_list * bcc_addr_list; /* can be NULL */
};

struct mailimf_bcc *
mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list);

void mailimf_bcc_free(struct mailimf_bcc * bcc);

   This is the content of a header Bcc or Resent-Bcc.

   bcc_addr_list is the parsed address list (see the Section called
   mailimf_address_list - list of addresses).

   mailimf_bcc_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_bcc_free() frees memory used by the structure and substructures
   will also be released.

   Example 3-16. creation and display of Bcc field
/* create visible Bcc */

#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  clist * list;
  struct mailimf_mailbox * mb;
  struct mailimf_address * addr;
  struct mailimf_address_list * addr_list;
  struct mailimf_bcc * bcc;

  list = clist_new();

  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  clist_append(list, addr);

  mb = mailimf_mailbox_new(strdup("Christophe GIAUME"),
    strdup("christophe@giaume.com"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  clist_append(list, addr);

  addr_list = mailimf_address_list_new(list);

  bcc = mailimf_bcc_new(addr_list);
  /* do the things */
  mailimf_bcc_free(bcc);

  return 0;
}

/* create unvisible Bcc */

#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_bcc * bcc;

  bcc = mailimf_bcc_new(NULL);
  /* do the things */
  mailimf_bcc_free(bcc);

  return 0;
}

/* display content of Bcc field */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_bcc(struct mailimf_bcc * bcc)
{
  if (bcc->addr_list == NULL) {
    printf("hidden Bcc\n");
  }
  else {
    display_address_list(bcc->bcc_addr_list);
  }
}
     __________________________________________________________________

mailimf_message_id - parsed content of Message-ID header

#include <libetpan/libetpan.h>

struct mailimf_message_id {
  char * mid_value; /* != NULL */
};

struct mailimf_message_id * mailimf_message_id_new(char * mid_value);

void mailimf_message_id_free(struct mailimf_message_id * message_id);

   This is the content of a header Message-ID or Resent-Message-ID. For
   example :

   Example 3-17. example of Message-ID
Message-ID: <200312100009.43592@c01n-c01n.plop.P4N>>

   mid_value is the message identifier. It is not enclosed by angle
   bracket.

   mailimf_message_id_new() This function creates and initializes a data
   structure with a value. Structures given as argument are referenced by
   the created object and will be freed if the object is released.

   The given string is allocated with malloc() and is not enclosed by
   angle bracket.

   mailimf_message_id_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-18. creation and display of Message-ID field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_message_id * msg_id;
  char * id;

  id = strdup("1037197913.3dd26259752fa@imp.free.fr");
  msg_id = mailimf_message_id_new(id);
  /* do the things */
  mailimf_message_id_free(msg_id);

  return 0;
}

/* display message id */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_message_id(struct mailimf_message_id * msg_id)
{
  printf("%s\n", msg_id->mid_value);
}
     __________________________________________________________________

mailimf_in_reply_to - parsed content of In-Reply-To field

#include <libetpan/libetpan.h>

struct mailimf_in_reply_to {
  clist * mid_list; /* list of (char *), != NULL */
};

struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list);

void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to);

   content of a header In-Reply-To. For example :
In-Reply-To: <etPan.3fd5fa29.4c3901c1.6b39@homer>

   mid_list is a clist in which elements are message identifiers. their
   types are (char *) and they are allocated with malloc().

   mailimf_in_reply_to_new() creates and initializes a data structure with
   a value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_in_reply_to_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-19. creation and display of In-Reply-To field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_in_reply_to * in_reply_to;
  clist * msg_id_list;

  msg_id_list = clist_new();
  clist_append(msg_id_list,
    strdup("etPan.3ebbcc18.4014197f.bc1@homer.invalid"));

  in_reply_to = mailimf_in_reply_to_new(msg_id_list);
  /* do the things */
  mailimf_in_reply_to_free(in_reply_to);

  return 0;
}

/* display the content of mailimf_in_reply_to */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_in_reply_to(struct mailimf_in_reply_to * in_reply_to)
{
  clistiter * cur;

  for(cur = clist_begin(in_reply_to->mid_list) ; cur != NULL ;
    cur = clist_next(cur)) {
    char * str;

    str = clist_content(cur);

    printf("%s\n", str);
  }
}
     __________________________________________________________________

mailimf_references - parsed content of References field

#include <libetpan/libetpan.h>

struct mailimf_references {
  clist * mid_list; /* list of (char *) */
       /* != NULL */
};

struct mailimf_references * mailimf_references_new(clist * mid_list);

void mailimf_references_free(struct mailimf_references * references);

   This is the content of a header References. For example :
In-Reply-To: <etPan.3fd5fa29.4c3901c1.6b39@homer>
  <3FD5FA78.A1D98E7@oleane.net>
  <etPan.3fd5fc69.2b349482.730e@homer>

   mid_list is a clist in which elements are message identifiers. their
   types are (char *) and they are allocated with malloc().

   mailimf_references_new() creates and initializes a data structure with
   a value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_references_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-20. creation and display of References field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_references * ref;
  clist * msg_id_list;

  msg_id_list = clist_new();
  clist_append(msg_id_list,
    strdup("200304280144.23633.wim.delvaux@adaptiveplanet.com"));
  clist_append(msg_id_list,
    strdup("200304301153.19688.wim.delvaux@adaptiveplanet.com"));
  clist_append(msg_id_list,
    strdup("etPan.3eb29de4.5fc4d652.3f83@homer"));

  ref = mailimf_references_new(msg_id_list);
  /* do the things */
  mailimf_in_reply_to_free(ref);

  return 0;
}

/* display references */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_references(struct mailimf_references * ref)
{
  clistiter * cur;

  for(cur = clist_begin(ref->mid_list) ; cur != NULL ;
    cur = clist_next(cur)) {
    char * msg_id;

    msg_id = clist_content(cur);

    printf("%s\n", msg_id);
  }
}
     __________________________________________________________________

mailimf_subject - parsed content of Subject field

#include <libetpan/libetpan.h>

struct mailimf_subject {
  char * sbj_value; /* != NULL */
};

struct mailimf_subject * mailimf_subject_new(char * sbj_value);

void mailimf_subject_free(struct mailimf_subject * subject);

   This is the content of a header Subject.

   sbj_value is the value of the field.

   mailimf_subject_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_subject_free frees memory used by the structure and
   substructures will also be released.

   Example 3-21. creation and display of Subject field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_subject * subject;

  subject = mailimf_subject_new(strdup("example of subject"));
  /* do the things */
  mailimf_subject_free(subject);

  return 0;
}

/* display subject header */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_subject(struct mailimf_subject * subject)
{
  printf("%s\n", subject->value);
}
     __________________________________________________________________

mailimf_comments - parsed content of Comments field

#include <libetpan/libetpan.h>

struct mailimf_comments {
  char * cm_value; /* != NULL */
};

struct mailimf_comments * mailimf_comments_new(char * cm_value);

void mailimf_comments_free(struct mailimf_comments * comments);

   This is the content of a header Comments.

   cm_value is the value of the field.

   mailimf_comments_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_comments_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-22. creation and display of Comment field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_comments * comments;

  comments = mailimf_comments_new(strdup("example of comment"));
  /* do the things */
  mailimf_comments_free(comments);

  return 0;
}

/* display the content of a comments */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_comments(struct mailimf_comments * comments)
{
  printf("%s\n", comments->cm_value);
}
     __________________________________________________________________

mailimf_keywords - parsed content of Keywords field

#include <libetpan/libetpan.h>

struct mailimf_keywords {
  clist * kw_list; /* list of (char *), != NULL */
};

struct mailimf_keywords * mailimf_keywords_new(clist * kw_list);

void mailimf_keywords_free(struct mailimf_keywords * keywords);

   This is the content of a header Keywords.

   kw_list is the list of keywords. This is a list of (char *) allocated
   with malloc().

   mailimf_keywords_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_keywords_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-23. creation and display of Keywords field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_keywords * keywords;
  clist * list;

  list = clist_new();
  clist_append(list, strdup("sauerkraut"));
  clist_append(list, strdup("potatoes"));
  clist_append(list, strdup("cooking"));

  keywords = mailimf_keywords_new(list);
  /* do the things */
  mailimf_keywords_free(keywords);

  return 0;
}

/* display the content of mailimf_in_reply_to */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_keywords(struct mailimf_keywords * kw)
{
  clistiter * cur;

  for(cur = clist_begin(kw->kw_list) ; cur != NULL ;
    cur = clist_next(cur)) {
    char * str;

    str = clist_content(cur);

    printf("%s\n", str);
  }
}
     __________________________________________________________________

mailimf_return - parsed content of Return-Path field

#include <libetpan/libetpan.h>

struct mailimf_return {
  struct mailimf_path * ret_path; /* != NULL */
};

struct mailimf_return *
mailimf_return_new(struct mailimf_path * ret_path);

void mailimf_return_free(struct mailimf_return * return_path);

   This is the content of a header Return-Path.

   ret_path is the parsed value of Return-Path (see the Section called
   mailimf_path - address in Return-Path field).

   mailimf_return_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_return_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-24. creation and display of Return-Path field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_path * path;
  struct mailimf_return * r;

  path = mailimf_path_new(strdup("dinh.viet.hoa@free.fr"));
  r = mailimf_return_new(path);
  /* do the things */
  mailimf_return_free(r);

  return 0;
}

/* display return path */

#include <libetpan/libetpan.h>

void display_return(struct mailimf_return * r)
{
  display_path(r->ret_path);
}
     __________________________________________________________________

mailimf_path - address in Return-Path field

#include <libetpan/libetpan.h>

struct mailimf_path {
  char * pt_addr_spec; /* can be NULL */
};

struct mailimf_path * mailimf_path_new(char * pt_addr_spec);

void mailimf_path_free(struct mailimf_path * path);

   This is the encapsulation of address specifier for Return-Path content.

   pt_addr_spec is a mailbox destination.

   mailimf_path_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   The given string is allocated with malloc(). This is a address
   specifier.

   mailimf_path_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-25. Creation and display of return path

#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_path * path;

  path = mailimf_path_new(strdup("dinh.viet.hoa@free.fr"));
  /* do the things */
  mailimf_path_free(r);

  return 0;
}

/* display return path */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_path(struct mailimf_path * path)
{
  printf("%s\n", path->pt_addr_spec);
}
     __________________________________________________________________

mailimf_optional_field - non-standard header

#include <libetpan/libetpan.h>

struct mailimf_optional_field {
  char * fld_name;  /* != NULL */
  char * fld_value; /* != NULL */
};

struct mailimf_optional_field *
mailimf_optional_field_new(char * fld_name, char * fld_value);

void mailimf_optional_field_free(struct mailimf_optional_field * opt_field);

   This is a non-standard header or unparsed header.

     * fld_name is the name of the header field.
     * fld_value is the value of the header field.

   mailimf_optional_field_new() This function creates and initializes a
   data structure with a value. Structures given as argument are
   referenced by the created object and will be freed if the object is
   released.

   field name and field value have to be allocated with malloc().

   mailimf_optional_field_free() This function frees memory used by the
   structure and substructures will also be released.

   Example 3-26. creation and display of non-standard fields
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_optional_field * opt;

  opt = mailimf_optional_field_new(strdup("X-My-Field"), strdup("my value"));
  /* do the things */
  mailimf_optional_field_free(opt);

  return 0;
}

/* display the optional field */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_optional_field(struct mailimf_optional_field * opt)
{
  printf("%s: %s\n", opt->fld_name, opt->fld_value);
}
     __________________________________________________________________

mailimf_field - header field

#include <libetpan/libetpan.h>

enum {
  MAILIMF_FIELD_NONE,           /* on parse error */
  MAILIMF_FIELD_RETURN_PATH,    /* Return-Path */
  MAILIMF_FIELD_RESENT_DATE,    /* Resent-Date */
  MAILIMF_FIELD_RESENT_FROM,    /* Resent-From */
  MAILIMF_FIELD_RESENT_SENDER,  /* Resent-Sender */
  MAILIMF_FIELD_RESENT_TO,      /* Resent-To */
  MAILIMF_FIELD_RESENT_CC,      /* Resent-Cc */
  MAILIMF_FIELD_RESENT_BCC,     /* Resent-Bcc */
  MAILIMF_FIELD_RESENT_MSG_ID,  /* Resent-Message-ID */
  MAILIMF_FIELD_ORIG_DATE,      /* Date */
  MAILIMF_FIELD_FROM,           /* From */
  MAILIMF_FIELD_SENDER,         /* Sender */
  MAILIMF_FIELD_REPLY_TO,       /* Reply-To */
  MAILIMF_FIELD_TO,             /* To */
  MAILIMF_FIELD_CC,             /* Cc */
  MAILIMF_FIELD_BCC,            /* Bcc */
  MAILIMF_FIELD_MESSAGE_ID,     /* Message-ID */
  MAILIMF_FIELD_IN_REPLY_TO,    /* In-Reply-To */
  MAILIMF_FIELD_REFERENCES,     /* References */
  MAILIMF_FIELD_SUBJECT,        /* Subject */
  MAILIMF_FIELD_COMMENTS,       /* Comments */
  MAILIMF_FIELD_KEYWORDS,       /* Keywords */
  MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */
};

struct mailimf_field {
  int fld_type;
  union {
    struct mailimf_return * fld_return_path;              /* can be NULL */
    struct mailimf_orig_date * fld_resent_date;    /* can be NULL */
    struct mailimf_from * fld_resent_from;         /* can be NULL */
    struct mailimf_sender * fld_resent_sender;     /* can be NULL */
    struct mailimf_to * fld_resent_to;             /* can be NULL */
    struct mailimf_cc * fld_resent_cc;             /* can be NULL */
    struct mailimf_bcc * fld_resent_bcc;           /* can be NULL */
    struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */
    struct mailimf_orig_date * fld_orig_date;             /* can be NULL */
    struct mailimf_from * fld_from;                       /* can be NULL */
    struct mailimf_sender * fld_sender;                   /* can be NULL */
    struct mailimf_reply_to * fld_reply_to;               /* can be NULL */
    struct mailimf_to * fld_to;                           /* can be NULL */
    struct mailimf_cc * fld_cc;                           /* can be NULL */
    struct mailimf_bcc * fld_bcc;                         /* can be NULL */
    struct mailimf_message_id * fld_message_id;           /* can be NULL */
    struct mailimf_in_reply_to * fld_in_reply_to;         /* can be NULL */
    struct mailimf_references * fld_references;           /* can be NULL */
    struct mailimf_subject * fld_subject;                 /* can be NULL */
    struct mailimf_comments * fld_comments;               /* can be NULL */
    struct mailimf_keywords * fld_keywords;               /* can be NULL */
    struct mailimf_optional_field * fld_optional_field;   /* can be NULL */
  } fld_data;
};

struct mailimf_field *
mailimf_field_new(int fld_type,
    struct mailimf_return * fld_return_path,
    struct mailimf_orig_date * fld_resent_date,
    struct mailimf_from * fld_resent_from,
    struct mailimf_sender * fld_resent_sender,
    struct mailimf_to * fld_resent_to,
    struct mailimf_cc * fld_resent_cc,
    struct mailimf_bcc * fld_resent_bcc,
    struct mailimf_message_id * fld_resent_msg_id,
    struct mailimf_orig_date * fld_orig_date,
    struct mailimf_from * fld_from,
    struct mailimf_sender * fld_sender,
    struct mailimf_reply_to * fld_reply_to,
    struct mailimf_to * fld_to,
    struct mailimf_cc * fld_cc,
    struct mailimf_bcc * fld_bcc,
    struct mailimf_message_id * fld_message_id,
    struct mailimf_in_reply_to * fld_in_reply_to,
    struct mailimf_references * fld_references,
    struct mailimf_subject * fld_subject,
    struct mailimf_comments * fld_comments,
    struct mailimf_keywords * fld_keywords,
    struct mailimf_optional_field * fld_optional_field);

void mailimf_field_free(struct mailimf_field * field);

   This is one header field of a message.

     * type is the type of the field. This define the type of the field.
       Only the corresponding field should be, then, filled. The value of
       this field can be one of : MAILIMF_FIELD_RETURN_PATH,
       MAILIMF_FIELD_RESENT_DATE, MAILIMF_FIELD_RESENT_FROM,
       MAILIMF_FIELD_RESENT_SENDER, MAILIMF_FIELD_RESENT_TO,
       MAILIMF_FIELD_RESENT_CC, MAILIMF_FIELD_RESENT_BCC,
       MAILIMF_FIELD_RESENT_MSG_ID, MAILIMF_FIELD_ORIG_DATE,
       MAILIMF_FIELD_FROM, MAILIMF_FIELD_SENDER, MAILIMF_FIELD_REPLY_TO,
       MAILIMF_FIELD_TO, MAILIMF_FIELD_CC, MAILIMF_FIELD_BCC,
       MAILIMF_FIELD_MESSAGE_ID, MAILIMF_FIELD_IN_REPLY_TO,
       MAILIMF_FIELD_REFERENCES, MAILIMF_FIELD_SUBJECT,
       MAILIMF_FIELD_COMMENTS, MAILIMF_FIELD_KEYWORDS,
       MAILIMF_FIELD_OPTIONAL_FIELD.
     * fld_data.fld_return_path is the parsed content of the Return-Path
       field if type is MAILIMF_FIELD_RETURN_PATH (see the Section called
       mailimf_return - parsed content of Return-Path field).
     * fld_data.fld_resent_date is the parsed content of the Resent-Date
       field if type is MAILIMF_FIELD_RESENT_DATE (see the Section called
       mailimf_orig_date - parsed content of date header).
     * fld_data.fld_resent_from is the parsed content of the Resent-From
       field if type is MAILIMF_FIELD_RESENT_FROM (see the Section called
       mailimf_from - parsed content of From header).
     * fld_data.fld_resent_sender is the parsed content of the
       Resent-Sender field if type is MAILIMF_FIELD_RESENT_SENDER (see the
       Section called mailimf_sender - parsed content of Sender header).
     * fld_data.fld_resent_to is the parsed content of the Resent-To field
       if type is MAILIMF_FIELD_RESENT_TO (see the Section called
       mailimf_to - parsed content of To header).
     * fld_data.fld_resent_cc is the parsed content of the Resent-Cc field
       if type is MAILIMF_FIELD_CC (see the Section called mailimf_cc -
       parsed content of Cc).
     * fld_data.fld_resent_bcc is the parsed content of the Resent-Bcc
       field if type is MAILIMF_FIELD_BCC (see the Section called
       mailimf_bcc - parsed content of Bcc field).
     * fld_data.fld_resent_msg_id is the parsed content of the
       Resent-Message-ID field if type is MAILIMF_FIELD_RESENT_MSG_ID (see
       the Section called mailimf_message_id - parsed content of
       Message-ID header).
     * fld_data.fld_orig_date is the parsed content of the Date field if
       type is MAILIMF_FIELD_ORIG_DATE (see the Section called
       mailimf_orig_date - parsed content of date header).
     * fld_data.fld_from is the parsed content of the From field if type
       is MAILIMF_FIELD_FROM (see the Section called mailimf_from - parsed
       content of From header).
     * fld_data.fld_sender is the parsed content of the Sender field if
       type is MAILIMF_FIELD_SENDER (see the Section called mailimf_sender
       - parsed content of Sender header).
     * fld_data.fld_reply_to is the parsed content of the Reply-To field
       if type is MAILIMF_FIELD_REPLY_TO (see the Section called
       mailimf_reply_to - parsed content of Reply-To header).
     * fld_data.fld_to is the parsed content of the To field if type is
       MAILIMF_FIELD_TO (see the Section called mailimf_to - parsed
       content of To header).
     * fld_data.fld_cc is the parsed content of the Cc field if type is
       MAILIMF_FIELD_CC (see the Section called mailimf_cc - parsed
       content of Cc).
     * fld_data.fld_bcc is the parsed content of the Bcc field if type is
       MAILIMF_FIELD_BCC (see the Section called mailimf_bcc - parsed
       content of Bcc field).
     * fld_data.fld_message_id is the parsed content of the Message-ID
       field if type is MAILIMF_FIELD_MESSAGE_ID (see the Section called
       mailimf_message_id - parsed content of Message-ID header).
     * fld_data.fld_in_reply_to is the parsed content of the In-Reply-To
       field if type is MAILIMF_FIELD_IN_REPLY_TO (see the Section called
       mailimf_in_reply_to - parsed content of In-Reply-To field).
     * fld_data.fld_references is the parsed content of the References
       field if type is MAILIMF_FIELD_REFERENCES (see the Section called
       mailimf_references - parsed content of References field).
     * fld_data.fld_subject is the content of the Subject field if type is
       MAILIMF_FIELD_SUBJECT (see the Section called mailimf_subject -
       parsed content of Subject field).
     * fld_data.fld_comments is the content of the Comments field if type
       is MAILIMF_FIELD_COMMENTS (see the Section called mailimf_comments
       - parsed content of Comments field).
     * fld_data.fld_keywords is the parsed content of the Keywords field
       if type is MAILIMF_FIELD_KEYWORDS (see the Section called
       mailimf_keywords - parsed content of Keywords field).
     * fld_data.fld_optional_field is an other field and is not parsed if
       type is MAILIMF_FIELD_OPTIONAL_FIELD (see the Section called
       mailimf_optional_field - non-standard header).

   mailimf_field_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_field_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-27. creation and display of field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_field * f;
  struct mailimf_mailbox * mb;
  struct mailimf_mailbox_list * mb_list;
  struct mailimf_from * from;

  /* build header 'From' */

  list = clist_new();
  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  clist_append(list, mb);
  mb_list = mailimf_mailbox_list_new(list);

  from = mailimf_from_new(mb_list);

  f = mailimf_field_new(MAILIMF_FIELD_FROM,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL);
  /* do the things */
  mailimf_field_free(f);

  return 0;
}

/* display content of the header */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_field(struct mailimf_field * field)
{
  switch (field->type) {
  case MAILIMF_FIELD_RETURN_PATH:
    printf("Return-Path:\n");
    display_return(field->fld_data.fld_return_path);
    break;
  case MAILIMF_FIELD_RESENT_DATE:
    printf("Resent-Date:\n");
    display_orig_date(field->fld_data.fld_orig_date);
    break;
  case MAILIMF_FIELD_RESENT_FROM:
    printf("Resent-From:\n");
    display_from(field->fld_data.fld_orig_date);
    break;
  case MAILIMF_FIELD_RESENT_SENDER:
    printf("Resent-Sender:\n");
    display_sender(field->fld_data.fld_resent_sender);
    break;
  case MAILIMF_FIELD_RESENT_TO:
    printf("Resent-To:\n");
    display_to(field->fld_data.fld_resent_to);
    break;
  case MAILIMF_FIELD_RESENT_CC:
    printf("Resent-Cc:\n");
    display_from(field->fld_data.fld_resent_cc);
    break;
  case MAILIMF_FIELD_RESENT_BCC:
    printf("Resent-Bcc:\n");
    display_from(field->fld_data.fld_resent_bcc);
    break;
  case MAILIMF_FIELD_RESENT_MSG_ID:
    printf("Resent-Message-ID:\n");
    display_message_id(field->fld_data.fld_resent_msg_id);
    break;
  case MAILIMF_FIELD_ORIG_DATE:
    printf("Date:\n");
    display_orig_date(field->fld_data.fld_orig_date);
    break;
  case MAILIMF_FIELD_FROM:
    printf("From:\n");
    display_from(field->fld_data.fld_from);
    break;
  case MAILIMF_FIELD_SENDER:
    printf("Sender:\n");
     display_sender(field->fld_data.fld_sender);
    break;
  case MAILIMF_FIELD_REPLY_TO:
    printf("Reply-To:\n");
    display_reply_to(field->fld_data.fld_reply_to);
    break;
  case MAILIMF_FIELD_TO:
    printf("To:\n");
    display_to(field->fld_data.fld_to);
    break;
  case MAILIMF_FIELD_CC:
    printf("Cc:\n");
    display_cc(field->fld_data.fld_cc);
    break;
  case MAILIMF_FIELD_BCC:
    printf("Bcc:\n");
    display_bcc(field->fld_data.fld_bcc);
    break;
  case MAILIMF_FIELD_MESSAGE_ID:
    printf("Message-ID:\n");
    display_message_id(field->fld_data.fld_message_id);
    break;
  case MAILIMF_FIELD_IN_REPLY_TO:
    printf("In-Reply-To:\n");
    display_in_reply_to(field->fld_data.fld_in_reply_to);
    break;
  case MAILIMF_FIELD_REFERENCES:
    printf("References:\n");
    display_references(field->fld_data.fld_references_to);
    break;
  case MAILIMF_FIELD_SUBJECT:
    printf("Subject:\n");
    display_subject(field->fld_data.fld_subject);
    break;
  case MAILIMF_FIELD_COMMENTS:
    printf("Comments:\n");
    display_comments(field->fld_data.fld_comments);
    break;
  case MAILIMF_FIELD_KEYWORDS:
    printf("Keywords:\n");
    display_keywords(field->fld_data.fld_keywords);
    break;
  case MAILIMF_FIELD_OPTIONAL_FIELD:
    printf("[optional field]:\n");
    display_optional_field(field->fld_data.fld_optional_field);
    break;
  }
}
     __________________________________________________________________

mailimf_fields - list of header fields

#include <libetpan/libetpan.h>

struct mailimf_fields {
  clist * fld_list; /* list of (struct mailimf_field *), != NULL */
};

struct mailimf_fields * mailimf_fields_new(clist * fld_list);

void mailimf_fields_free(struct mailimf_fields * fields);

   This is the list of header fields of a message.

   fld_list is a list of header fields. This is a clist which elements are
   of type mailimf_field (see the Section called mailimf_field - header
   field).

   mailimf_fields_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_fields_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-28. creation and display of header fields
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_fields * fields;
  struct mailimf_field * f;
  clist * list;
  struct mailimf_from * from;
  struct mailimf_to * to
  struct mailimf_mailbox * mb;
  struct mailimf_address * addr;
  struct mailimf_mailbox_list * mb_list;
  struct mailimf_address_list * addr_list;
  clist * fields_list;

  /* build headers */

  fields_list = clist_new();

  /* build header 'From' */

  list = clist_new();
  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  clist_append(list, mb);
  mb_list = mailimf_mailbox_list_new(list);

  from = mailimf_from_new(mb_list);

  f = mailimf_field_new(MAILIMF_FIELD_FROM,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL);

  clist_append(fields_list, f);

  /* build header To */

  list = clist_new();
  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  clist_append(list, addr);
  addr_list = mailimf_address_list_new(list);

  to = mailimf_to_new(addr_list);

  f = mailimf_field_new(MAILIMF_FIELD_TO,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL);

  clist_append(fields_list, f);

  fields = mailimf_fields_new(fields_list);
  /* do the things */
  mailimf_fields_free(fields);

  return 0;
}

/* display list of headers */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_fields(struct mailimf_fields * fields)
{
  clistiter * cur;

  for(cur = clist_begin(field->fld_list) ; cur != NULL ;
    cur = clist_next(cur)) {
    struct mailimf_field * f;

    f = clist_content(cur);

    display_field(f);
    printf("\n");
  }
}
     __________________________________________________________________

mailimf_body - message body without headers

#include <libetpan/libetpan.h>

struct mailimf_body {
  const char * bd_text; /* != NULL */
  size_t bd_size;
};

struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size);

void mailimf_body_free(struct mailimf_body * body);

   This is the text content of a message (without headers).

     * bd_text is the beginning of the text part, it is a substring of an
       other string. It is not necessarily zero terminated.
     * bd_size is the size of the text part

   mailimf_body_new() creates and initializes a data structure with a
   value. Text given as argument will NOT be released.

   mailimf_body_free() frees memory used by the structure.

   Example 3-29. creation and display of message body
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_body * b;

  b = mailimf_body_new("this is the content of the message", 34);
  /* do the things */
  mailimf_body_free(b);

  return 0;
}

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_body(struct mailimf_body * b)
{
  char * text;

  text = malloc(b->size + 1);
  strncpy(text, b->bd_text, b->bd_size);
  text[b->size] = 0;

  puts(text);
  printf("\n");

  free(text);

  return 0;
}
     __________________________________________________________________

mailimf_message - parsed message

#include <libetpan/libetpan.h>

struct mailimf_message {
  struct mailimf_fields * msg_fields; /* != NULL */
  struct mailimf_body * msg_body;     /* != NULL */
};

struct mailimf_message *
mailimf_message_new(struct mailimf_fields * msg_fields,
    struct mailimf_body * msg_body);

void mailimf_message_free(struct mailimf_message * message);

   This is the message content (text and headers).

     * msg_fields is the header fields of the message (see the Section
       called mailimf_fields - list of header fields).
     * msg_body is the text part of the message (see the Section called
       mailimf_body - message body without headers).

   mailimf_message_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailimf_message_free() frees memory used by the structure and
   substructures will also be released.

   Example 3-30. creation and display of message
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_body * b;
  struct mailimf_message * m;
  struct mailimf_fields * fields;
  struct mailimf_fields * f;
  clist * list;
  struct mailimf_from * from;
  struct mailimf_to * to
  struct mailimf_mailbox * mb;
  struct mailimf_address * addr;
  struct mailimf_mailbox_list * mb_list;
  struct mailimf_address_list * addr_list;
  clist * fields_list;

  /* build text content */

  b = mailimf_body_new("this is the content of the message", 34);

  /* build headers */

  fields_list = clist_new();

  /* build header 'From' */

  list = clist_new();
  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  clist_append(list, mb);
  mb_list = mailimf_mailbox_list_new(list);

  from = mailimf_from_new(mb_list);

  f = mailimf_field_new(MAILIMF_FIELD_FROM,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL);

  clist_append(fields_list, f);

  /* build header To */

  list = clist_new();
  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  clist_append(list, addr);
  addr_list = mailimf_address_list_new(list);

  to = mailimf_to_new(addr_list);

  f = mailimf_field_new(MAILIMF_FIELD_TO,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL);

  clist_append(fields_list, f);

  fields = mailimf_fields_new(fields_list);

  /* build message */

  m = mailimf_message_new(fields, b);
  /* do the things */
  mailimf_message_free(m);

  return 0;
}

/* display the message */

#include <libetpan/libetpan.h>
#include <stdio.h>

void display_message(struct mailimf_message * msg)
{
  display_fields(msg->msg_fields);
  printf("\n");
  display_body(msg->msg_body);
  printf("\n");
}
     __________________________________________________________________

mailimf_single_fields - simplified fields

#include <libetpan/libetpan.h>

struct mailimf_single_fields {
  struct mailimf_orig_date * fld_orig_date;      /* can be NULL */
  struct mailimf_from * fld_from;                /* can be NULL */
  struct mailimf_sender * fld_sender;            /* can be NULL */
  struct mailimf_reply_to * fld_reply_to;        /* can be NULL */
  struct mailimf_to * fld_to;                    /* can be NULL */
  struct mailimf_cc * fld_cc;                    /* can be NULL */
  struct mailimf_bcc * fld_bcc;                  /* can be NULL */
  struct mailimf_message_id * fld_message_id;    /* can be NULL */
  struct mailimf_in_reply_to * fld_in_reply_to;  /* can be NULL */
  struct mailimf_references * fld_references;    /* can be NULL */
  struct mailimf_subject * fld_subject;          /* can be NULL */
  struct mailimf_comments * fld_comments;        /* can be NULL */
  struct mailimf_keywords * fld_keywords;        /* can be NULL */
};

struct mailimf_single_fields *
mailimf_single_fields_new(struct mailimf_fields * fields);

void mailimf_single_fields_free(struct mailimf_single_fields *
                                single_fields);

void mailimf_single_fields_init(struct mailimf_single_fields * single_fields,
                                struct mailimf_fields * fields);

   Structure that contains some standard fields and allows access to a
   given header without running through the list.

   mailimf_fields is the native structure that IMF module will use, this
   module will provide an easier structure to use when parsing fields.
   mailimf_single_fields is an easier structure to get parsed fields,
   rather than iteration over the list of fields

     * fld_orig_date is the parsed "Date" field (see the Section called
       mailimf_orig_date - parsed content of date header).
     * fld_from is the parsed "From" field (see the Section called
       mailimf_from - parsed content of From header).
     * fld_sender is the parsed "Sender "field (see the Section called
       mailimf_sender - parsed content of Sender header).
     * reply_to is the parsed "Reply-To" field (see the Section called
       mailimf_reply_to - parsed content of Reply-To header).
     * fld_to is the parsed "To" field (see the Section called mailimf_to
       - parsed content of To header).
     * fld_cc is the parsed "Cc" field (see the Section called mailimf_cc
       - parsed content of Cc).
     * fld_bcc is the parsed "Bcc" field (see the Section called
       mailimf_bcc - parsed content of Bcc field).
     * fld_message_id is the parsed "Message-ID" field. (see the Section
       called mailimf_message_id - parsed content of Message-ID header).
     * fld_in_reply_to is the parsed "In-Reply-To" field. (see the Section
       called mailimf_in_reply_to - parsed content of In-Reply-To field).
     * fld_references is the parsed "References" field. (see the Section
       called mailimf_references - parsed content of References field).
     * fld_subject is the parsed "Subject" field (see the Section called
       mailimf_subject - parsed content of Subject field).
     * fld_comments is the parsed "Comments" field (see the Section called
       mailimf_comments - parsed content of Comments field).
     * fld_keywords is the parsed "Keywords" field (see the Section called
       mailimf_keywords - parsed content of Keywords field).

   mailimf_single_fields_new() creates and initializes a data structure
   with a value. Structures given as argument are referenced by the
   created object and will NOT be freed if the object is released.

   mailimf_single_fields_free() frees memory used by the structure and
   substructures will NOT be released. They should be released by the
   application.

   mailimf_single_fields_init() will initialize fill the data structure,
   using the given argument (fields). The interesting fields will be
   filled into single_fields.

   Example 3-31. using mailimf_single_fields
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_single_fields * single_fields;
  struct mailimf_fields * fields;
  struct mailimf_field * f;
  clist * list;
  struct mailimf_from * from;
  struct mailimf_to * to
  struct mailimf_mailbox * mb;
  struct mailimf_address * addr;
  struct mailimf_mailbox_list * mb_list;
  struct mailimf_address_list * addr_list;
  clist * fields_list;

  /* build headers */

  fields_list = clist_new();

  /* build header 'From' */

  list = clist_new();
  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  clist_append(list, mb);
  mb_list = mailimf_mailbox_list_new(list);

  from = mailimf_from_new(mb_list);

  f = mailimf_field_new(MAILIMF_FIELD_FROM,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL);

  clist_append(fields_list, f);

  /* build header To */

  list = clist_new();
  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  clist_append(list, addr);
  addr_list = mailimf_address_list_new(list);

  to = mailimf_to_new(addr_list);

  f = mailimf_field_new(MAILIMF_FIELD_TO,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL);

  clist_append(fields_list, f);

  fields = mailimf_fields_new(fields_list);

  /* create the single fields */
  single_fields = mailimf_single_fields_new(fields);
  /* do the things */
  mailimf_single_fields_free(single_fields);
  mailimf_fields_free(fields);

  return 0;
}

   Example 3-32. using mailimf_single_fields without memory allocation
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_single_fields single_fields;
  struct mailimf_fields * fields;
  struct mailimf_field * f;
  clist * list;
  struct mailimf_from * from;
  struct mailimf_to * to
  struct mailimf_mailbox * mb;
  struct mailimf_address * addr;
  struct mailimf_mailbox_list * mb_list;
  struct mailimf_address_list * addr_list;
  clist * fields_list;

  /* build headers */

  fields_list = clist_new();

  /* build header 'From' */

  list = clist_new();
  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  clist_append(list, mb);
  mb_list = mailimf_mailbox_list_new(list);

  from = mailimf_from_new(mb_list);

  f = mailimf_field_new(MAILIMF_FIELD_FROM,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL);

  clist_append(fields_list, f);

  /* build header To */

  list = clist_new();
  mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="),
    strdup("dinh.viet.hoa@free.fr"));
  addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  clist_append(list, addr);
  addr_list = mailimf_address_list_new(list);

  to = mailimf_to_new(addr_list);

  f = mailimf_field_new(MAILIMF_FIELD_TO,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL);

  clist_append(fields_list, f);

  fields = mailimf_fields_new(fields_list);

  /* fill the single fields */
  mailimf_fields_fields_init(&single_fields, fields);
  /* do the things */
  mailimf_fields_free(fields);

  return 0;
}
     __________________________________________________________________

Parser functions

mailimf_address_list_parse

int
mailimf_address_list_parse(char * message, size_t length,
    size_t * index,
    struct mailimf_address_list ** result);

   mailimf_address_list_parse() parse a list of addresses in RFC 2822
   form.

     * message this is a string containing the list of addresses.
     * length this is the size of the given string
     * index this is a pointer to the start of the list of addresses in
       the given string, (* index) is modified to point at the end of the
       parsed data.
     * result the result of the parse operation is stored in (* result)
       (see the Section called mailimf_address_list - list of addresses).

   return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error.

   Example 3-33. parsing a list of addresses
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_address_list * addr_list;
        size_t current_index;

        current_index = 0;
        r = mailimf_address_list_parse(mem, stat_info.st_size,
          &current_index, &addr_list);
        if (r == MAILIMF_NO_ERROR) {
            display_address_list(addr_list);
          /* do the things */
          status = EXIT_SUCCESS;
          mailimf_address_list_free(addr_list);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailimf_address_parse

#include <libetpan/libetpan.h>

int
mailimf_address_parse(char * message, size_t length,
    size_t * index,
    struct mailimf_address ** result);

   mailimf_address_parse() parse an address in RFC 2822 form.

     * message this is a string containing the address.
     * length this is the size of the given string.
     * index index this is a pointer to the start of the address in the
       given string, (* index) is modified to point at the end of the
       parsed data.
     * result the result of the parse operation is stored in (* result)
       (see the Section called mailimf_address - address).

   return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error.

   Example 3-34. parsing an address
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_address * addr;
        size_t current_index;

        current_index = 0;
        r = mailimf_address_parse(mem, stat_info.st_size,
          &current_index, &addr);
        if (r == MAILIMF_NO_ERROR) {
            display_address(addr);
          /* do the things */
          status = EXIT_SUCCESS;
          mailimf_address_free(addr);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailimf_body_parse

#include <libetpan/libetpan.h>

int mailimf_body_parse(char * message, size_t length,
                       size_t * index,
                       struct mailimf_body ** result);

   mailimf_body_parse() parse text body of a message.

     * message this is a string containing the message body part.
     * length this is the size of the given string.
     * index this is a pointer to the start of the message text part in
       the given string, (* index) is modified to point at the end of the
       parsed data.
     * result the result of the parse operation is stored in (* result)
       (see the Section called mailimf_body - message body without
       headers).

   return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error.

   Example 3-35. parsing a message body
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_body * b;
        struct mailimf_fields * f;
        size_t current_index;
        size_t size;

        size = stat_info.st_size;
        current_index = 0;
        r = mailimf_fields_parse(mem, size, &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
          r = mailimf_crlf_parse(mem, size, &current_index);
          /* ignore parse error of crlf */

          r = mailimf_body_parse(mem, size, &current_index, &b);
          if (r == MAILIMF_NO_ERROR) {

            display_body(b);
            /* do the things */
            status = EXIT_SUCCESS;
            mailimf_body_free(b);
          }
          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailimf_envelope_and_optional_fields_parse

#include <libetpan/libetpan.h>

int
mailimf_envelope_and_optional_fields_parse(char * message, size_t length,
    size_t * index,
    struct mailimf_fields ** result);

   mailimf_envelope_and_optional_fields_parse() returns a list of most
   useful headers (parsed). The other headers will be placed in the list
   in a non-parsed form.

     * message this is a string containing the header.
     * length this is the size of the given string
     * index index this is a pointer to the start of the header in the
       given string, (* index) is modified to point at the end of the
       parsed data
     * result the result of the parse operation is stored in (* result)
       (see the Section called mailimf_fields - list of header fields).

   return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error.

   Example 3-36. parsing commonly used fields and return other fields in a
   non-parsed form
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_envelope_and_optional_fields_parse(mem, stat_info.st_size,
            &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
            display_fields(m);
          /* do the things */
          status = EXIT_SUCCESS;
          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailimf_envelope_fields_parse

#include <libetpan/libetpan.h>

int mailimf_envelope_fields_parse(char * message, size_t length,
    size_t * index,
    struct mailimf_fields ** result);

   mailimf_envelope_fields_parse() return a list of most useful headers
   (parsed).

     * message this is a string containing the header
     * length this is the size of the given string
     * index index this is a pointer to the start of the header in the
       given string, (* index) is modified to point at the end of the
       parsed data
     * result the result of the parse operation is stored in (* result)
       (see the Section called mailimf_fields - list of header fields).

   return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error.

   Example 3-37. parsing commonly used fields
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_envelope_fields_parse(mem, stat_info.st_size,
            &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
            display_fields(m);
          /* do the things */
          status = EXIT_SUCCESS;
          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailimf_optional_fields_parse

#include <libetpan/libetpan.h>

int
mailimf_optional_fields_parse(char * message, size_t length,
    size_t * index,
    struct mailimf_fields ** result);

   mailimf_optional_fields_parse return a list of non-parsed headers.

     * message this is a string containing the header
     * length this is the size of the given string
     * index index this is a pointer to the start of the header in the
       given string, (* index) is modified to point at the end of the
       parsed data
     * result the result of the parse operation is stored in (* result)
       (see the Section called mailimf_fields - list of header fields).

   return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error.

   Example 3-38. parsing optional fields
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_optional_fields_parse(mem, stat_info.st_size,
            &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
            display_fields(m);
          /* do the things */
          status = EXIT_SUCCESS;
          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailimf_fields_parse

#include <libetpan/libetpan.h>

int mailimf_fields_parse(char * message, size_t length,
    size_t * index,
    struct mailimf_fields ** result);

   mailimf_fields_parse() parse headers of a message.

     * message this is a string containing the header
     * length this is the size of the given string
     * index index this is a pointer to the start of the header in the
       given string, (* index) is modified to point at the end of the
       parsed data
     * result the result of the parse operation is stored in (* result)
       (see the Section called mailimf_fields - list of header fields).

   return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error.

   Example 3-39. parsing header fields
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_fields_parse(mem, stat_info.st_size,
          &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
            display_fields(f);
          /* do the things */
          status = EXIT_SUCCESS;
          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailimf_ignore_field_parse

#include <libetpan/libetpan.h>

int mailimf_ignore_field_parse(char * message, size_t length,
    size_t * index);

   mailimf_ignore_field_parse() skip the next header.

     * message this is a string containing the header
     * length this is the size of the given string
     * index index this is a pointer to the start of the field to skip in
       the given string, (* index) is modified to point at the end of the
       parsed data

   return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error.

   Example 3-40. skipping fields
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        size_t current_index;

        current_index = 0;
        r = mailimf_ignore_field_parse(mem, stat_info.st_size,
            &current_index);
        if (r == MAILIMF_NO_ERROR) {
          /* do the things */
          status = EXIT_SUCCESS;
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailimf_mailbox_list_parse

#include <libetpan/libetpan.h>

int
mailimf_mailbox_list_parse(char * message, size_t length,
    size_t * index,
    struct mailimf_mailbox_list ** result);

   mailimf_mailbox_list_parse() parse a list of mailboxes in RFC 2822
   form.

     * message this is a string containing the list of mailboxes.
     * length this is the size of the given string.
     * index index this is a pointer to the start of the list of mailboxes
       in the given string, (* index) is modified to point at the end of
       the parsed data.
     * result the result of the parse operation is stored in (* result).
       (see the Section called mailimf_mailbox_list - list of mailboxes)

   return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error.

   Example 3-41. parsing a list of mailboxes
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_mailbox_list * mb_list;
        size_t current_index;

        current_index = 0;
        r = mailimf_mailbox_list_parse(mem, stat_info.st_size,
          &current_index, &mb_list);
        if (r == MAILIMF_NO_ERROR) {
            display_mailbox_list(mb_list);
          /* do the things */
          status = EXIT_SUCCESS;
          mailimf_mailbox_list_free(mb_list);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailimf_mailbox_parse


#include <libetpan/libetpan.h>

int mailimf_mailbox_parse(char * message, size_t length,
    size_t * index,
    struct mailimf_mailbox ** result);

   mailimf_mailbox_parse parse a mailbox in RFC 2822 form.

     * message this is a string containing the mailbox.
     * length this is the size of the given string.
     * index index this is a pointer to the start of the mailbox in the
       given string, (* index) is modified to point at the end of the
       parsed data.
     * result the result of the parse operation is stored in (* result).
       (see the Section called mailimf_mailbox - mailbox)

   return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error.

   Example 3-42. parsing a mailbox
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_mailbox_list * mb_list;
        size_t current_index;

        current_index = 0;
        r = mailimf_mailbox_parse(mem, stat_info.st_size,
          &current_index, &mb_list);
        if (r == MAILIMF_NO_ERROR) {
            display_mailbox_list(mb_list);
          /* do the things */
          status = EXIT_SUCCESS;
          mailimf_mailbox_free(mb_list);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailimf_message_parse

#include <libetpan/libetpan.h>

int mailimf_message_parse(char * message, size_t length,
                          size_t * index,
                          struct mailimf_message ** result);

   mailimf_message_parse parse message (headers and body).

     * message this is a string containing the message content.
     * param length this is the size of the given string.
     * param index this is a pointer to the start of the message in the
       given string, (* index) is modified to point at the end of the
       parsed data.
     * param result the result of the parse operation is stored in (*
       result) (see the Section called mailimf_message - parsed message).

   Example 3-43. parsing a message
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_message * m;
        size_t current_index;

        current_index = 0;
        r = mailimf_message_parse(mem, stat_info.st_size,
          &current_index, &m);
        if (r == MAILIMF_NO_ERROR) {
            display_message(m);
          /* do the things */
          status = EXIT_SUCCESS;
          mailimf_message_free(m);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

Creation functions

mailimf_mailbox_list

#include <libetpan/libetpan.h>

struct mailimf_mailbox_list *
mailimf_mailbox_list_new_empty();

int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list,
                             struct mailimf_mailbox * mb);

int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list,
                                   char * mb_str);

int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list,
                                char * display_name, char * address);

   mailimf_mailbox_list_new_empty() creates a new empty list of mailboxes.

   mailimf_mailbox_list_add adds a mailbox to the list of mailboxes.

   mailimf_mailbox_list_add_parse adds a mailbox given in form of a string
   to the list of mailboxes.

   mailimf_mailbox_list_add_mb adds a mailbox given in form of a couple :
   display name, mailbox address.

     * mailbox_list is the list of mailboxes.
     * mb is a mailbox (see the Section called mailimf_mailbox - mailbox).
     * mb_str is a mailbox given in the form of a string.
     * display_name is the display name.
     * address is the mailbox address.

   Example 3-44. creating a list of mailboxes
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_mailbox_list * mb_list;
  struct mailimf_mailbox * mb;

  mb_list = mailimf_mailbox_list_new_empty();

  mb = mailimf_mailbox_new(strdup("DINH Viet Hoa"),
    strdup("dinh.viet.hoa@free.fr"));
  mailimf_mailbox_list_add(mb_list, mb);

  mailimf_mailbox_list_add_parse(mb_list, "foo bar <foo@bar.org>");

  mailimf_mailbox_list_add_mb(mb_list, strdup("bar foo"), strdup("bar@foo.com"))
;

  mailimf_mailbox_list_free(mb_list);
}
     __________________________________________________________________

mailimf_address_list

#include <libetpan/libetpan.h>

struct mailimf_address_list * mailimf_address_list_new_empty();

int mailimf_address_list_add(struct mailimf_address_list * address_list,
                             struct mailimf_address * addr);

int mailimf_address_list_add_parse(struct mailimf_address_list * address_list,
                                   char * addr_str);

int mailimf_address_list_add_mb(struct mailimf_address_list * address_list,
                                char * display_name, char * address);

   mailimf_address_list_new_empty() creates a new empty list of addresses.

   mailimf_address_list_add adds an address to the list of addresses.

   mailimf_address_list_add_parse adds an address given in form of a
   string to the list of addresses.

   mailimf_address_list_add_mb adds a mailbox given in form of a couple :
   display name, mailbox address.

     * address_list is the list of mailboxes.
     * addr is an address. (see the Section called mailimf_address -
       address).
     * addr_str is an address given in the form of a string.
     * display_name is the display name.
     * address is the mailbox address.
     __________________________________________________________________

mailimf_fields

#include <libetpan/libetpan.h>

struct mailimf_fields *
mailimf_fields_new_empty(void);

struct mailimf_field * mailimf_field_new_custom(char * name, char * value);

int mailimf_fields_add(struct mailimf_fields * fields,
                       struct mailimf_field * field);

int mailimf_fields_add_data(struct mailimf_fields * fields,
                            struct mailimf_date_time * date,
                            struct mailimf_mailbox_list * from,
                            struct mailimf_mailbox * sender,
                            struct mailimf_address_list * reply_to,
                            struct mailimf_address_list * to,
                            struct mailimf_address_list * cc,
                            struct mailimf_address_list * bcc,
                            char * msg_id,
                            clist * in_reply_to,
                            clist * references,
                            char * subject);

struct mailimf_fields *
mailimf_fields_new_with_data_all(struct mailimf_date_time * date,
                                 struct mailimf_mailbox_list * from,
                                 struct mailimf_mailbox * sender,
                                 struct mailimf_address_list * reply_to,
                                 struct mailimf_address_list * to,
                                 struct mailimf_address_list * cc,
                                 struct mailimf_address_list * bcc,
                                 char * message_id,
                                 clist * in_reply_to,
                                 clist * references,
                                 char * subject);

struct mailimf_fields *
mailimf_fields_new_with_data(struct mailimf_mailbox_list * from,
                             struct mailimf_mailbox * sender,
                             struct mailimf_address_list * reply_to,
                             struct mailimf_address_list * to,
                             struct mailimf_address_list * cc,
                             struct mailimf_address_list * bcc,
                             clist * in_reply_to,
                             clist * references,
                             char * subject);

char * mailimf_get_message_id(void);

struct mailimf_date_time * mailimf_get_current_date(void);

int
mailimf_resent_fields_add_data(struct mailimf_fields * fields,
    struct mailimf_date_time * resent_date,
    struct mailimf_mailbox_list * resent_from,
    struct mailimf_mailbox * resent_sender,
    struct mailimf_address_list * resent_to,
    struct mailimf_address_list * resent_cc,
    struct mailimf_address_list * resent_bcc,
    char * resent_msg_id);

struct mailimf_fields *
mailimf_resent_fields_new_with_data_all(struct mailimf_date_time *
    resent_date, struct mailimf_mailbox_list * resent_from,
    struct mailimf_mailbox * resent_sender,
    struct mailimf_address_list * resent_to,
    struct mailimf_address_list * resent_cc,
    struct mailimf_address_list * resent_bcc,
    char * resent_msg_id);

struct mailimf_fields *
mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from,
    struct mailimf_mailbox * resent_sender,
    struct mailimf_address_list * resent_to,
    struct mailimf_address_list * resent_cc,
    struct mailimf_address_list * resent_bcc);

     * from is the parsed content of the From field (see the Section
       called mailimf_from - parsed content of From header).
     * sender is the parsed content of the Sender field (see the Section
       called mailimf_sender - parsed content of Sender header).
     * reply_to is the parsed content of the Reply-To field (see the
       Section called mailimf_reply_to - parsed content of Reply-To
       header).
     * to is the parsed content of the To field (see the Section called
       mailimf_to - parsed content of To header).
     * cc is the parsed content of the Cc field (see the Section called
       mailimf_cc - parsed content of Cc).
     * bcc is the parsed content of the Bcc field (see the Section called
       mailimf_bcc - parsed content of Bcc field).
     * message_id is the parsed content of the Message-ID field (see the
       Section called mailimf_message_id - parsed content of Message-ID
       header).
     * in_reply_to is the parsed content of the In-Reply-To field (see the
       Section called mailimf_in_reply_to - parsed content of In-Reply-To
       field).
     * references is the parsed content of the References field (see the
       Section called mailimf_references - parsed content of References
       field).
     * subject is the content of the Subject field (see the Section called
       mailimf_subject - parsed content of Subject field).
     * resent_date is the parsed content of the Resent-Date field (see the
       Section called mailimf_orig_date - parsed content of date header).
     * resent_from is the parsed content of the Resent-From field (see the
       Section called mailimf_from - parsed content of From header).
     * resent_sender is the parsed content of the Resent-Sender field (see
       the Section called mailimf_sender - parsed content of Sender
       header).
     * resent_to is the parsed content of the Resent-To field (see the
       Section called mailimf_to - parsed content of To header).
     * resent_cc is the parsed content of the Resent-Cc field (see the
       Section called mailimf_cc - parsed content of Cc).
     * resent_bcc is the parsed content of the Resent-Bcc field (see the
       Section called mailimf_bcc - parsed content of Bcc field).
     * resent_msg_id is the parsed content of the Resent-Message-ID field
       (see the Section called mailimf_message_id - parsed content of
       Message-ID header).

   mailimf_fields_new_empty() creates a new empty set of headers.

   mailimf_field_new_custom() creates a new custom header.

   mailimf_fields_add() adds a header to the set of headers.

   mailimf_fields_add_data() adds some headers to the set of headers.

   mailimf_fields_new_with_data_all() creates a set of headers with some
   headers (including Date and Message-ID).

   mailimf_fields_new_with_data() creates a set of headers with some
   headers (Date and Message-ID will be generated).

   mailimf_get_message_id() generates a Message-ID. The result must be
   freed using free().

   mailimf_get_current_date() generates a Date. The result must be freed
   using mailimf_date_time_free.

   mailimf_resent_fields_add_data() adds some resent headers to the set of
   headers.

   mailimf_resent_fields_new_with_data_all() creates a set of headers with
   some resent headers (including Resent-Date and Resent-Message-ID).

   mailimf_resent_fields_new_with_data() creates a set of headers with
   some resent headers (Resent-Date and Resent-Message-ID will be
   generated)

   Example 3-45. creation of header fields
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_fields * fields;
  struct mailimf_field * field;
  struct mailimf_date_time * date;
  char * msg_id;
  struct mailimf_mailbox_list * from;
  struct mailimf_address_list * to;

  fields = mailimf_fields_new_empty();
  field = mailimf_field_new_custom(strdup("X-Mailer"), strdup("my-mailer"));
  mailimf_fields_add(fields, field);

  from = mailimf_mailbox_list_new_empty();
  mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.h
oa@free.fr");
  date = mailimf_get_current_date();
  msg_id = mailimf_get_message_id();
  to = mailimf_address_list_new_empty();
  mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org");

  mailimf_fields_add_data(fields, date, from, NULL, NULL, to, NULL, NULL,
    msg_id, NULL, NULL, strdup("hello"));

  /* do the things */

  mailimf_fields_free(fields);
}

#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_fields * fields;
  struct mailimf_mailbox_list * from;
  struct mailimf_address_list * to;
  struct mailimf_date_time * date;
  char * msg_id;

  from = mailimf_mailbox_list_new_empty();
  mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.h
oa@free.fr");
  to = mailimf_address_list_new_empty();
  mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org");
  date = mailimf_get_current_date();
  msg_id = mailimf_get_message_id();

  fields = mailimf_fields_new_with_all_data(date, from, NULL, NULL, to, NULL, NU
LL,
    msg_id, NULL, NULL, strdup("hello"));

  /* do the things */

  mailimf_fields_free(fields);
}

#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailimf_fields * fields;
  struct mailimf_mailbox_list * from;
  struct mailimf_address_list * to;

  from = mailimf_mailbox_list_new_empty();
  mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.h
oa@free.fr");
  to = mailimf_address_list_new_empty();
  mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org");

  fields = mailimf_fields_new_with_data(from, NULL, NULL, to, NULL, NULL,
    NULL, NULL, strdup("hello"));

  /* do the things */

  mailimf_fields_free(fields);
}
     __________________________________________________________________

Rendering of messages

Header fields

#include <libetpan/libetpan.h>

int mailimf_fields_write(FILE * f, int * col,
    struct mailimf_fields * fields);

int mailimf_envelope_fields_write(FILE * f, int * col,
    struct mailimf_fields * fields);

int mailimf_field_write(FILE * f, int * col,
    struct mailimf_field * field);

     * col current column is given for wrapping purpose in (* col), the
       resulting columns will be returned..
     * f is the file descriptor. It can be stdout for example.
     * fields is the header fields (see the Section called mailimf_fields
       - list of header fields).
     * field is a field (see the Section called mailimf_field - header
       field).

   mailimf_fields_write outputs the set of header fields.

   mailimf_envelope_fields_write outputs the set of header fields except
   the optional fields.

   mailimf_field_write outputs a header.

   Example 3-46. rendering of fields
int main(int argc, char ** argv)
{
  struct mailimf_fields * fields;
  int col;

  /* look at the example in mailimf_fields to see how to
     build a mailimf_fields */
  fields = build_imf_fields();

  col = 0;
  mailimf_fields_write(stdout, &col, fields);

  mailimf_fields_free(fields);
}

int main(int argc, char ** argv)
{
  struct mailimf_fields * fields;
  int col;

  /* look at the example in mailimf_fields to see how to
     build a mailimf_fields */
  fields = build_imf_fields();

  col = 0;
  mailimf_envelope_fields_write(stdout, &col, fields);

  mailimf_fields_free(fields);
}

int main(int argc, char ** argv)
{
  struct mailimf_field * field;
  int col;

  field = mailimf_field_new_custom(strdup("X-Mailer"), strdup("my mailer"));

  col = 0;
  mailimf_field_write(stdout, &col, field);

  mailimf_field_free(field);
}
     __________________________________________________________________

Chapter 4. MIME

   libEtPan! implements a MIME message parser (also known as messages with
   attachments or multipart messages). This also allows to generate MIME
   messages.

   Warning

   All allocation functions will take as argument allocated data and will
   store these data in the structure they will allocate. Data should be
   persistant during all the use of the structure and will be freed by the
   free function of the structure

   allocation functions will return NULL on failure functions returning
   integer will be returning one of the following error code:
   MAILIMF_NO_ERROR, MAILIMF_ERROR_PARSE, MAILIMF_ERROR_MEMORY,
   MAILIMF_ERROR_INVAL, or MAILIMF_ERROR_FILE.
     __________________________________________________________________

Quick start

   You will need this module when you want to parse a MIME message.
     __________________________________________________________________

Parse MIME message

   You will use the following function :

     * mailmime_parse (the Section called
       mailimf_envelope_and_optional_fields_parse in Chapter 3)
     __________________________________________________________________

Render the MIME message

   Build your MIME message, then use mailmime_write (the Section called
   mailmime_write) to render a MIME message.
     __________________________________________________________________

Data types

mailmime_composite_type - Composite MIME type

#include <libetpan/libetpan.h>

enum {
  MAILMIME_COMPOSITE_TYPE_ERROR,
  MAILMIME_COMPOSITE_TYPE_MESSAGE,
  MAILMIME_COMPOSITE_TYPE_MULTIPART,
  MAILMIME_COMPOSITE_TYPE_EXTENSION
};

struct mailmime_composite_type {
  int ct_type;
  char * ct_token;
};

struct mailmime_composite_type *
mailmime_composite_type_new(int ct_type, char * ct_token);

void mailmime_composite_type_free(struct mailmime_composite_type * ct);

   This is a MIME composite type such as message or multipart.

   ct_type can have one of the 3 following values :
   MAILMIME_COMPOSITE_TYPE_MESSAGE when the composite MIME type is
   message, MAILMIME_COMPOSITE_TYPE_MULTIPART when the composite MIME type
   is multipart, MAILMIME_COMPOSITE_TYPE_EXTENSION for other and ct_token
   is set in this case. MAILMIME_COMPOSITE_TYPE_ERROR is used internally
   on parse error.

   mailmime_composite_type_new() creates and initializes a data structure
   with a value. Structures given as argument are referenced by the
   created object and will be freed if the object is released.

   mailmime_composite_type_free() frees memory used by the structure and
   substructures will also be released.

   Example 4-1. create and display MIME composite type
#include <libetpan/libetpan.h>

int main(void)
{
  struct mailmime_composite_type * ct;

  ct = mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL);

  /* do your things ... */

  mailmime_composite_type_free(ct);

  exit(EXIT_SUCCESS);
}

void display_composite_type()
{
  switch (ct->type) {
  case MAILMIME_COMPOSITE_TYPE_MESSAGE:
    printf("composite type is message\n");
    break;
  case MAILMIME_COMPOSITE_TYPE_MULTIPART:
    printf("composite type is multipart\n");
    break;
  case MAILMIME_COMPOSITE_TYPE_EXTENSION:
    printf("composite type: %s\n", ct->ct_token);
    break;
  }
}
     __________________________________________________________________

mailmime_content - MIME content type (Content-Type)

#include <libetpan/libetpan.h>

struct mailmime_content {
  struct mailmime_type * ct_type;
  char * ct_subtype;
  clist * ct_parameters; /* elements are (struct mailmime_parameter *) */
};

struct mailmime_content *
mailmime_content_new(struct mailmime_type * ct_type,
                     char * ct_subtype,
                     clist * ct_parameters);

void mailmime_content_free(struct mailmime_content * content);

   This is a MIME content type such as message/rfc822 or text/plain.

     * ct_type is the main MIME type, for example text in plain/text (see
       the Section called mailmime_type - MIME main type).
       ct_subtype is the MIME subtype, for example plain in plain/text.
     * ct_parameters is the list of parameters for the given MIME type.
       For example, for plain/text, we can find charset=iso-8859-1,
       format=flowed. Each element of the list if of type struct
       mailmime_parameter * (see the Section called mailmime_parameter -
       MIME type parameter).

   mailmime_content_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailmime_content_free() frees memory used by the structure and
   substructures will also be released.

   Example 4-2. Creation and display of MIME content type
#include <libetpan/libetpan.h>

int main(void)
{
  struct mailmime_content * content;
  struct mailmime_type * type;
  struct mailmime_discrete_type * dt;
  struct mailmime_parameter * param;
  clist * param_list;

  dt = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, NULL);
  type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, dt, NUL);
  param_list = clist_new();
  param = mailmime_parameter_new(strdup("charset"), strdup("iso-8859-1"));
  clist_append(param_list, param);

  content = mailmime_content_new(type, strdup("plain"), param_list);

  /* do your things */

  exit(EXIT_SUCCESS);
}

void display_mime_content(struct mailmime_content * content_type)
{
  clistiter * cur;

  printf("type:\n");
  display_type(content_type->ct_type);
  printf("\n");
  printf("subtype: %s\n", content_type->ct_subtype);
  printf("\n");

  for(cur = clist_begin(content_type->ct_parameters) ; cur != NULL ;
    cur = clist_next(cur)) {
    struct mailmime_parameter * param;

    param = clist_content(cur);
    display_mime_parameter(param);
    printf("\n");
  }
  printf("\n");
}
     __________________________________________________________________

mailmime_discrete_type - MIME discrete type

#include <libetpan/libetpan.h>

enum {
  MAILMIME_DISCRETE_TYPE_ERROR,
  MAILMIME_DISCRETE_TYPE_TEXT,
  MAILMIME_DISCRETE_TYPE_IMAGE,
  MAILMIME_DISCRETE_TYPE_AUDIO,
  MAILMIME_DISCRETE_TYPE_VIDEO,
  MAILMIME_DISCRETE_TYPE_APPLICATION,
  MAILMIME_DISCRETE_TYPE_EXTENSION
};

struct mailmime_discrete_type {
  int dt_type;
  char * dt_extension;
};

struct mailmime_discrete_type *
mailmime_discrete_type_new(int dt_type, char * dt_extension);

void mailmime_discrete_type_free(struct mailmime_discrete_type *
                                 discrete_type);

   This is a MIME discrete type such as text or image. This is also known
   as single part. This kind of part does not have any child.

   dt_type is one of the given values : MAILMIME_DISCRETE_TYPE_TEXT if
   part is text, MAILMIME_DISCRETE_TYPE_IMAGE if part is an image,
   MAILMIME_DISCRETE_TYPE_AUDIO if part is audio data,
   MAILMIME_DISCRETE_TYPE_VIDEO if part is video,
   MAILMIME_DISCRETE_TYPE_APPLICATION if part is application data or
   MAILMIME_DISCRETE_TYPE_EXTENSION for other. In the case of
   MAILMIME_DISCRETE_TYPE_EXTENSION, dt_extension is filled in.
   MAILMIME_DISCRETE_TYPE_ERROR is used internally.

   mailmime_discrete_type_new() creates and initializes a data structure
   with a value. Structures given as argument are referenced by the
   created object and will be freed if the object is released.

   mailmime_discrete_type_free() frees memory used by the structure and
   substructures will also be released.

   Example 4-3. Creation and display of MIME discrete type
#include <libetpan/libetpan.h>

/* standard type */

int main(int argc, char ** argv)
{
  struct mailmime_discrete_type * discrete_type;

  discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT,
    NULL);

  /* do the things */

  mailmime_discrete_type_free(discrete_type);
}

/* extension */

int main(int argc, char ** argv)
{
  struct mailmime_discrete_type * discrete_type;

  discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_EXTENSION,
    strdup("my-type"));

  /* do the things */

  mailmime_discrete_type_free(discrete_type);
}

void display_mime_discrete_type(struct mailmime_discrete_type * discrete_type)
{
  switch (discrete_type->dt_type) {
  case MAILMIME_DISCRETE_TYPE_TEXT:
    printf("text\n");
    break;
  case MAILMIME_DISCRETE_TYPE_IMAGE:
    printf("image\n");
    break;
  case MAILMIME_DISCRETE_TYPE_AUDIO:
    printf("audio\n");
    break;
  case MAILMIME_DISCRETE_TYPE_VIDEO:
    printf("video\n");
    break;
  case MAILMIME_DISCRETE_TYPE_APPLICATION:
    printf("application\n");
    break;
  case MAILMIME_DISCRETE_TYPE_EXTENSION:
    printf("extension : %s\n", discrete_type->dt_extension);
    break;
  }
}
     __________________________________________________________________

mailmime_field - MIME header field

#include <libetpan/libetpan.h>

enum {
  MAILMIME_FIELD_NONE,
  MAILMIME_FIELD_TYPE,
  MAILMIME_FIELD_TRANSFER_ENCODING,
  MAILMIME_FIELD_ID,
  MAILMIME_FIELD_DESCRIPTION,
  MAILMIME_FIELD_VERSION,
  MAILMIME_FIELD_DISPOSITION,
  MAILMIME_FIELD_LANGUAGE,
};

struct mailmime_field {
  int fld_type;
  union {
    struct mailmime_content * fld_content;
    struct mailmime_mechanism * fld_encoding;
    char * fld_id;
    char * fld_description;
    uint32_t fld_version;
    struct mailmime_disposition * fld_disposition;
    struct mailmime_language * fld_language;
  } fld_data;
};

struct mailmime_field *
mailmime_field_new(int fld_type,
                   struct mailmime_content * fld_content,
                   struct mailmime_mechanism * fld_encoding,
                   char * fld_id,
                   char * fld_description,
                   uint32_t fld_version,
                   struct mailmime_disposition * fld_disposition,
                   struct mailmime_language * fld_language);

void mailmime_field_free(struct mailmime_field * field);

   This is a parsed MIME header field;

     * fld_type is the type of MIME header field. The value can be
       MAILMIME_FIELD_TYPE if field is Content-Type,
       MAILMIME_FIELD_TRANSFER_ENCODING if field is
       Content-Transfer-Encoding, MAILMIME_FIELD_ID if field is
       Content-ID, MAILMIME_FIELD_DESCRIPTION if field is
       Content-Description, MAILMIME_FIELD_VERSION if field is
       MIME-Version, MAILMIME_FIELD_DISPOSITION if field is
       Content-Disposition or MAILMIME_FIELD_LANGUAGE if field is
       Content-Language. MAILMIME_FIELD_NONE is used internally.
     * fld_data.fld_content is set in case of Content-Type. (see the
       Section called mailmime_content - MIME content type
       (Content-Type)).
     * fld_data.fld_encoding is set in case of Content-Transfer-Encoding.
       (see the Section called mailmime_mechanism - MIME transfer encoding
       mechanism (Content-Transfer-Encoding)).
     * fld_data.fld_id is set in case of Content-ID. This is a string.
     * fld_data.fld_description is set in case of Content-Description.
       This is a string.
     * fld_data.fld_version is set in case of MIME-Version. This is an
       integer built using the following formula : fld_version = major *
       2^16 + minor. Currenly MIME-Version is always 1.0, this means that
       fld_version will always be 2^16 (in C language, this is 1 << 16).
     * fld_data.fld_disposition is set in case of Content-Disposition.
       (see the Section called mailmime_disposition - MIME disposition
       information (Content-Disposition)).
     * fld_data.fld_language is set in case of Content-Language. (see the
       Section called mailmime_language - Language of MIME part).

   mailmime_field_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailmime_field_free() frees memory used by the structure and
   substructures will also be released.

   Example 4-4. Creation and display of MIME header field
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime_field * field;
  struct mailmime_mechanism * encoding;

  encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL);

  field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING,
    NULL, encoding, NULL, NULL, 0, NULL, NULL);

  /* do the things */

  mailmime_field_free(field);
}

void display_mime_field(struct mailmime_field * field)
{
  switch (field->fld_type) {
  case MAILMIME_FIELD_TYPE:
    printf("content-type:");
    display_mime_content(field->fld_data.fld_content);
    break;
  case MAILMIME_FIELD_TRANSFER_ENCODING:
    printf("content-transfer-encoding:");
    display_mime_mechanism(field->fld_data.fld_encoding);
    break;
  case MAILMIME_FIELD_ID:
    printf("content-id: %s\n", field->fld_data.fld_id);
    break;
  case MAILMIME_FIELD_DESCRIPTION:
    printf("content-description: %s\n", field->fld_data.fld_description);
    break;
  case MAILMIME_FIELD_VERSION:
    printf("mime-version: %i.%i\n",
      field->version>> 16, field->fld_data.fld_version & 0xFFFF);
    break;
  case MAILMIME_FIELD_DISPOSITION:
    printf("content-disposition:");
    display_mime_disposition(field->fld_data.fld_disposition);
    break;
  case MAILMIME_FIELD_LANGUAGE:
    printf("content-language:");
    display_mime_language(field->fld_data.fld_language);
    break;
  }
}
     __________________________________________________________________

mailmime_mechanism - MIME transfer encoding mechanism
(Content-Transfer-Encoding)

#include <libetpan/libetpan.h>

enum {
  MAILMIME_MECHANISM_ERROR,
  MAILMIME_MECHANISM_7BIT,
  MAILMIME_MECHANISM_8BIT,
  MAILMIME_MECHANISM_BINARY,
  MAILMIME_MECHANISM_QUOTED_PRINTABLE,
  MAILMIME_MECHANISM_BASE64,
  MAILMIME_MECHANISM_TOKEN
};

struct mailmime_mechanism {
  int enc_type;
  char * enc_token;
};

struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_toke
n);

void mailmime_mechanism_free(struct mailmime_mechanism * mechanism);

   This is a MIME transfer encoding mechanism description.

   enc_type is an encoding type. The value of this field can be
   MAILMIME_MECHANISM_7BIT if mechanism is 7bit, MAILMIME_MECHANISM_8BIT
   if mechanism is 8bit, MAILMIME_MECHANISM_BINARY if mechanism is binary,
   MAILMIME_MECHANISM_QUOTED_PRINTABLE if mechanism is quoted-printable,
   MAILMIME_MECHANISM_BASE64 if mechanism is base64 or
   MAILMIME_MECHANISM_TOKEN for other. In case of
   MAILMIME_MECHANISM_TOKEN, field enc_token is filled in.
   MAILMIME_MECHANISM_ERROR is used internally.

   mailmime_mechanism_new() creates and initializes a data structure with
   a value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailmime_mechanism_free() frees memory used by the structure and
   substructures will also be released.

   Example 4-5. Creation and display of MIME transfer encoding mechanism
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime_mechanism * encoding;

  encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_QUOTED_PRINTABLE, NULL);

  /* do the things */

  mailmime_mechanism_free(encoding);
}

int main(int argc, char ** argv)
{
  struct mailmime_mechanism * encoding;

  encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_TOKEN,
    strdup("uuencoding"));

  /* do the things */

  mailmime_mechanism_free(encoding);
}

void display_mime_mechanism(struct mailmime_mechanism * encoding)
{
  switch (encoding->enc_type) {
  case MAILMIME_MECHANISM_7BIT:
    printf("7bit\n");
    break;
  case MAILMIME_MECHANISM_8BIT:
    printf("8bit\n");
    break;
  case MAILMIME_MECHANISM_BINARY:
    printf("binary\n");
    break;
  case MAILMIME_MECHANISM_QUOTED_PRINTABLE:
    printf("quoted-printable\n");
    break;
  case MAILMIME_MECHANISM_BASE64:
    printf("base64\n");
    break;
  case MAILMIME_MECHANISM_TOKEN:
    printf("extension : %s\n", encoding->enc_token);
    break;
  }
}
     __________________________________________________________________

mailmime_fields - header fields

#include <libetpan/libetpan.h>

struct mailmime_fields {
  clist * fld_list; /* list of (struct mailmime_field *) */
};

struct mailmime_fields * mailmime_fields_new(clist * fld_list);

void mailmime_fields_free(struct mailmime_fields * fields);

   This is the header fields of a MIME part.

   fld_list is the list of the header fields. Each element of the list is
   a mailmime_field (See the Section called mailmime_field - MIME header
   field).

   mailmime_fields_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailmime_fields_free() frees memory used by the structure and
   substructures will also be released.

   Example 4-6. Creation and display of MIME fields
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime_field * field;
  struct mailmime_fields * fields;
  clist * list;
  struct mailmime_mechanism * encoding;
  struct mailmime_disposition * disposition;

  list = clist_new();

  encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL);
  field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING,
    NULL, encoding, NULL, NULL, 0, NULL, NULL);
  clist_append(list, field);

  field = mailmime_field_new(MAILMIME_FIELD_VERSION,
    NULL, NULL, NULL, NULL, 1 << 16, NULL, NULL);
  clist_append(list, field);

  /* look at the example in mailmime_disposition to see how to
     build a mailmime_disposition */
  disposition = build_mime_disposition();
  field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION,
    NULL, NULL, NULL, NULL, 0, disposition, NULL);
  clist_append(list, field);

  fields = mailmime_fields_new(list);

  /* do the things */

  mailmime_fields_free(fields);
}

void display_mime_fields(struct mailmime_fields * fields)
{
  clistiter * cur;

  for(cur = clist_begin(fields->fld_list ; cur != NULL ;
    cur = clist_next(cur)) {
    struct mailmime_field * field;

    field = clist_content(cur);
    display_field(field);
  }
}
     __________________________________________________________________

mailmime_parameter - MIME type parameter

struct mailmime_parameter {
  char * pa_name;
  char * pa_value;
};

   This is the MIME type parameter in Content-Type MIME header field. For
   example, this can be charset="iso-8859-1".

     * pa_name is the name of the parameter, for example : charset.
     * pa_value is the value of the parameter, for example : iso-8859-1.

   mailmime_parameter_new() creates and initializes a data structure with
   a value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailmime_parameter_free() frees memory used by the structure and
   substructures will also be released.

   Example 4-7. Creation and display of MIME type parameter
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime_parameter * param;

  param = mailmime_parameter_new(strdup("charset"), strdup("iso-8859-1"));

  /* do the things */

  mailmime_parameter_free(param);
}

void display_mime_parameter(struct mailmime_parameter * param)
{
  printf("%s = %s\n", param->pa_name, param->pa_value);
}
     __________________________________________________________________

mailmime_type - MIME main type

#include <libetpan/libetpan.h>

enum {
  MAILMIME_TYPE_ERROR,
  MAILMIME_TYPE_DISCRETE_TYPE,
  MAILMIME_TYPE_COMPOSITE_TYPE
};

struct mailmime_type {
  int tp_type;
  union {
    struct mailmime_discrete_type * tp_discrete_type;
    struct mailmime_composite_type * tp_composite_type;
  } tp_data;
};

struct mailmime_type *
mailmime_type_new(int tp_type,
                  struct mailmime_discrete_type * tp_discrete_type,
                  struct mailmime_composite_type * tp_composite_type);

void mailmime_type_free(struct mailmime_type * type);

   This is the MIME main type (no subtype, no parameter).

     * tp_type. The value of this field is either
       MAILMIME_TYPE_DISCRETE_TYPE for MIME discrete type, or
       MAILMIME_TYPE_COMPOSITE_TYPE for MIME composite type.
       MAILMIME_TYPE_ERROR is used internally.
     * tp_data.tp_discrete_type is set when tp_type is
       MAILMIME_TYPE_DISCRETE_TYPE (see the Section called
       mailmime_discrete_type - MIME discrete type).
     * tp_data.tp_composite_type is set when tp_type is
       MAILMIME_TYPE_COMPOSITE_TYPE (see the Section called
       mailmime_composite_type - Composite MIME type).

   mailmime_discrete_type_new() creates and initializes a data structure
   with a value. Structures given as argument are referenced by the
   created object and will be freed if the object is released.

   mailmime_discrete_type_free() frees memory used by the structure and
   substructures will also be released.

   Example 4-8. Creation and display of MIME main type
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime_type * type;
  struct mailmime_discrete_type * discrete_type;

  discrete_type =
    mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, NULL);
  type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, discrete_type, NULL);

  /* do the things */

  mailmime_type_free(type);
}

int main(int argc, char ** argv)
{
  struct mailmime_type * type;
  struct mailmime_composite_type * composite_type;

  composite_type =
    mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL);
  type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, composite_type);

  /* do the things */

  mailmime_type_free(type);
}

void display_mime_type(struct mailmime_type * type)
{
  printf("mime type:\n");
  switch (type->tp_type) {
  case MAILMIME_TYPE_DISCRETE_TYPE:
    printf("discrete type:\n");
    display_mime_discrete_type(type->tp_data.tp_discrete_type);
    break;
  case MAILMIME_TYPE_COMPOSITE_TYPE:
    printf("composite type:\n");
    display_mime_composite_type(type->tp_data.tp_composite_type);
    break;
  }
  printf("\n");
}
     __________________________________________________________________

mailmime_language - Language of MIME part

#include <libetpan/libetpan.h>

struct mailmime_language {
  clist * lg_list; /* atom (char *) */
};

struct mailmime_language * mailmime_language_new(clist * lg_list);

void mailmime_language_free(struct mailmime_language * lang);

   This is the language used in the MIME part.

   lg_list is the list of codes of languages used in the MIME part. This
   is a list of strings.

   mailmime_language_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailmime_language_free() frees memory used by the structure and
   substructures will also be released.

   Example 4-9. Creation and display of language of MIME part
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime_language * language;
  clist * list;

  list = clist_new();

  clist_append(list, strdup("fr"));
  clist_append(list, strdup("en"));

  language = mailmime_language_new(list);

  /* do the things */

  mailmime_language_free(language);
}

void display_mime_language(struct mailmime_language * language)
{
  clistiter * cur;

  printf("languages: ");
  for(cur = clist_begin(language->lg_list) ; cur != NULL ;
    cur = clist_next(cur)) {
    char * name;

    name = clist_content(cur);
    printf("%s ", name);
  }
  printf("\n");
}
     __________________________________________________________________

mailmime_data - Content of MIME part

#include <libetpan/libetpan.h>

enum {
  MAILMIME_DATA_TEXT,
  MAILMIME_DATA_FILE,
};

enum {
  MAILMIME_MECHANISM_ERROR,
  MAILMIME_MECHANISM_7BIT,
  MAILMIME_MECHANISM_8BIT,
  MAILMIME_MECHANISM_BINARY,
  MAILMIME_MECHANISM_QUOTED_PRINTABLE,
  MAILMIME_MECHANISM_BASE64,
  MAILMIME_MECHANISM_TOKEN
};

struct mailmime_data {
  int dt_type;
  int dt_encoding;
  int dt_encoded;
  union {
    struct {
      const char * dt_data;
      size_t dt_length;
    } dt_text;
    char * dt_filename;
  } dt_data;
};

struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding,
    int dt_encoded, const char * dt_data, size_t dt_length,
    char * dt_filename);

void mailmime_data_free(struct mailmime_data * mime_

   This is the content of MIME part, content of preamble or content of
   epilogue.

   dt_type can be MAILMIME_DATA_TEXT if the content is a string in memory,
   MAILMIME_DATA_FILE if the content is in a file,

   dt_encoding is the encoding mechanism of the part. The value of this
   field can be MAILMIME_MECHANISM_7BIT if mechanism is 7bit,
   MAILMIME_MECHANISM_8BIT if mechanism is 8bit, MAILMIME_MECHANISM_BINARY
   if mechanism is binary, MAILMIME_MECHANISM_QUOTED_PRINTABLE if
   mechanism is quoted-printable, MAILMIME_MECHANISM_BASE64 if mechanism
   is base64 or MAILMIME_MECHANISM_TOKEN for other. If
   MAILMIME_MECHANISM_TOKEN, the part will be considered as binary.
   MAILMIME_MECHANISM_ERROR is used internally.

   dt_encoded is set to 1 if the part is already encoded with the
   mechanism given in dt_encoding. It is set to 0 if the part is already
   decoded or if it is necessary to encode that part before rendering it.

   dt_data.dt_text.dt_data is a pointer to the content of the part and
   dt_data.dt_text.dt_length is the length of the data if dt_type is
   MAILMIME_DATA_TEXT.

   dt_data.dt_filename is the name of the file if dt_type is
   MAILMIME_DATA_FILE.

   mailmime_data_new() creates and initializes a data structure with a
   value. Structures given as argument are referenced by the created
   object and will be freed if the object is released.

   mailmime_data_free() frees memory used by the structure and
   substructures will also be released.

   Example 4-10. Creation and display of MIME part content
#include <libetpan/libetpan.h>

/* build data with a string */

int main(int argc, char ** argv)
{
  struct mailmime_data * data;

  data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_BASE64,
    0, "foo bar", 7, NULL);

  /* do the things */

  mailmime_data_free(data);
}

/* build data with a file */

int main(int argc, char ** argv)
{
  struct mailmime_data * data;

  data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_BASE64,
    0, NULL, 0, strdup("foo.txt"));

  /* do the things */

  mailmime_data_free(data);
}

void display_mime_data(struct mailmime_data * data)
{
  switch (data->dt_encoding) {
  case MAILMIME_MECHANISM_7BIT:
    printf("7bit\n");
    break;
  case MAILMIME_MECHANISM_8BIT:
    printf("8bit\n");
    break;
  case MAILMIME_MECHANISM_BINARY:
    printf("binary\n");
    break;
  case MAILMIME_MECHANISM_QUOTED_PRINTABLE:
    printf("quoted-printable\n");
    break;
  case MAILMIME_MECHANISM_BASE64:
    printf("base64\n");
    break;
  case MAILMIME_MECHANISM_TOKEN:
    printf("other\n");
    break;
  }

  if (data->dt_encoded)
    printf("already encoded\n");
  else
    printf("not encoded\n");

  switch (data->dt_type) {
  MAILMIME_DATA_TEXT:
    printf("data : %p %i\n", data->dt_data.dt_text.dt_data,
      data->dt_data.dt_text.dt_length);
    break;
  MAILMIME_DATA_FILE,
    printf("data (file) : %s\n", data->dt_data.dt_filename);
    break;
  }
}
     __________________________________________________________________

mailmime - MIME part

#include <libetpan/libetpan.h>

enum {
  MAILMIME_NONE,
  MAILMIME_SINGLE,
  MAILMIME_MULTIPLE,
  MAILMIME_MESSAGE,
};

struct mailmime {
  /* parent information */
  int mm_parent_type;
  struct mailmime * mm_parent;
  clistiter * mm_multipart_pos;

  int mm_type;
  const char * mm_mime_start;
  size_t mm_length;

  struct mailmime_fields * mm_mime_fields;
  struct mailmime_content * mm_content_type;

  struct mailmime_data * mm_body;
  union {
    /* single part */
    struct mailmime_data * mm_single; /* XXX - was body */

    /* multi-part */
    struct {
      struct mailmime_data * mm_preamble;
      struct mailmime_data * mm_epilogue;
      clist * mm_mp_list;
    } mm_multipart;

    /* message */
    struct {
      struct mailimf_fields * mm_fields;
      struct mailmime * mm_msg_mime;
    } mm_message;

  } mm_data;
};

struct mailmime * mailmime_new(int mm_type,
    const char * mm_mime_start, size_t mm_length,
    struct mailmime_fields * mm_mime_fields,
    struct mailmime_content * mm_content_type,
    struct mailmime_data * mm_body,
    struct mailmime_data * mm_preamble,
    struct mailmime_data * mm_epilogue,
    clist * mm_mp_list,
    struct mailimf_fields * mm_fields,
    struct mailmime * mm_msg_mime);

void mailmime_free(struct mailmime * mime);

   This describes the MIME structure of a message or a subpart of a
   message.
     __________________________________________________________________

common

     * mm_parent_type. MIME part type can be single part, multipart or
       message part. This describes the MIME part type of the parent. The
       value can be MAILMIME_NONE if there is no parent part,
       MAILMIME_SINGLE if parent is a single part, MAILMIME_MULTIPLE if
       parent is a multipart, MAILMIME_MESSAGE if parent is a mesage part.
     * mm_parent is the parent MIME structure.
     * mm_multipart_pos. In the case the parent is a multipart. This is
       the position in the list of children of the parent. This position
       is given by a clisiter *.
     * mm_type. This describes the MIME part type of this part. The value
       can be MAILMIME_SINGLE if this is a single part, MAILMIME_MULTIPLE
       if this is a multipart, MAILMIME_MESSAGE if this is a mesage part.
     * mm_mime_start. This is used mostly internally. This gives the
       beginning of the header of the MIME part, when this is parsed from
       a string in memory.
     * mm_length. This gives the length of the MIME part, including the
       MIME header fields.
     * mm_mime_fields is the list of parsed MIME headers of this part.
       Content-Type must be excluded and stored in mm_content_type instead
       (see the Section called mailmime_fields - header fields).
     * mm_content_type is the parsed Content-Type field (see the Section
       called mailmime_content - MIME content type (Content-Type)).
     * mm_body is the content of the MIME part (excluding MIME header),
       when it is parsed from a string in memory (see the Section called
       mailmime_data - Content of MIME part).
     __________________________________________________________________

single part

     * When the part is a single part (mm_type is MAILMIME_SINGLE). The
       following fields are valid.
     * mm_data.mm_single is the content of the MIME part (excluding MIME
       header), when it is parsed from a string in memory. This must have
       the same value as mm_body when it is set (see the Section called
       mailmime_data - Content of MIME part).
     __________________________________________________________________

multipart

     * When the part is a multipart (mm_type is MAILMIME_MULTIPLE). The
       following fields are valid.
     * mm_data.mm_multipart.mm_preamble is the content of the preamble of
       the multipart (see the Section called mailmime_data - Content of
       MIME part).
     * mm_data.mm_multipart.mm_epilogue is the content of the epilogue of
       the multipart (see the Section called mailmime_data - Content of
       MIME part).
     * mm_data.mm_multipart.mm_mp_list is the list of sub parts
     __________________________________________________________________

message part

     * When the part is a message (mm_type is MAILMIME_MESSAGE). The
       following fields are valid.
     * mm_data.mm_message.mm_fields is the list of the header fields of
       the message (see the Section called mailimf_fields - list of header
       fields in Chapter 3).
     * mm_data.mm_message.mm_msg_mime is the subpart of the message part.
     __________________________________________________________________

constructor and destructor

   mailmime_new() creates and initializes a data structure with a value.
   Structures given as argument are referenced by the created object and
   will be freed if the object is released.

   mailmime_free() frees memory used by the structure and substructures
   will also be released.

   Example 4-11. Creation and display of MIME part
#include <libetpan/libetpan.h>

/* build one single MIME part */

int main(int argc, char ** argv)
{
  struct mailmime * mime;
  struct mailimf_fields * fields;
  struct mailmime_fields * mime_fields;
  struct mailmime_content * content_type;
  struct mailmime_data * body;

  /* look at the example in mailimf_fields to see how to
     build a mailimf_fields */
  fields = build_fields();

  /* look at the example in mailmime_fields to see how to
     build a mailmime_fields */
  mime_fields = build_mime_fields();

  /* look at the example in mailmime_content to see how to
     build a mailmime_content */
  content_type = build_mime_content();

  body = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0,
    "foo", 3, NULL);

  mime = mailmime_new(MAILMIME_SINGLE,
    NULL, 0, fields, mime_fields, content_type,
    body, NULL, NULL, NULL, NULL, NULL);

  /* do the things */

  mailmime_free(mime);
}

/* build one single MIME part */

int main(int argc, char ** argv)
{
  struct mailmime * mime;
  struct mailimf_fields * fields;
  struct mailmime_fields * mime_fields;
  struct mailmime_content * content_type;
  char * str;
  struct mailmime_data * body;

  /* look at the example in mailimf_fields to see how to
     build a mailimf_fields */
  fields = build_fields();

  /* look at the example in mailmime_fields to see how to
     build a mailmime_fields */
  mime_fields = build_mime_fields();

  /* look at the example in mailmime_content to see how to
     build a mailmime_content */
  content_type = build_mime_content();

  str = malloc(4);
  strcpy(str, "foo");

  body = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0,
    str, 3, NULL);

  mime = mailmime_new(MAILMIME_SINGLE,
    NULL, 0, fields, mime_fields, content_type,
    body, NULL, NULL, NULL, NULL, NULL);

  /* do the things */

  mailmime_free(mime);
  free(str);
}

/* build a MIME part with a sub-message */

int main(int argc, char ** argv)
{
  struct mailmime * mime;
  struct mailimf_fields * fields;
  struct mailmime_fields * mime_fields;
  struct mailmime_content * content_type;
  char * str;
  struct mailmime_type * type;
  struct mailmime_composite_type * composite_type;

  /* look at the example in mailimf_fields to see how to
     build a mailimf_fields */
  fields = build_fields();

  /* look at the example in mailmime_fields to see how to
     build a mailmime_fields */
  mime_fields = build_mime_fields();

  composite_type =
    mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, NULL);
  type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL,
    composite_type);
  content_type = mailmime_content_new(type, strdup("rfc2822"), NULL);

  /* build_mime_message() is a function that will build a mime message part */
  sub_mime = build_mime_message();

  mime = mailmime_new(MAILMIME_MESSAGE,
    NULL, 0, fields, mime_fields, content_type,
    NULL, NULL, NULL, NULL, sub_mime, NULL);

  /* do the things */

  mailmime_free(mime);
}

/* build a MIME part with a sub-message (given by a string) */


int main(int argc, char ** argv)
{
  struct mailmime * mime;
  struct mailimf_fields * fields;
  struct mailmime_fields * mime_fields;
  struct mailmime_content * content_type;
  char * str;
  struct mailmime_data * msg_content;
  struct mailmime_type * type;
  struct mailmime_composite_type * composite_type;

  /* look at the example in mailimf_fields to see how to
     build a mailimf_fields */
  fields = build_fields();

  /* look at the example in mailmime_fields to see how to
     build a mailmime_fields */
  mime_fields = build_mime_fields();

  composite_type =
    mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, NULL);
  type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL,
    composite_type);
  content_type = mailmime_content_new(type, strdup("rfc2822"), NULL);

  str = malloc(sizeof(SUB_MESSAGE));
  strcpy(str, SUB_MESSAGE);

  msg_content = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0
,
    str, sizeof(SUB_MESSAGE), NULL);

  mime = mailmime_new(MAILMIME_MESSAGE,
    NULL, 0, fields, mime_fields, content_type,
    NULL, NULL, NULL, NULL, NULL, msg_content);

  /* do the things */

  mailmime_free(mime);
  free(str);
}

/* build a multipart message */



int main(int argc, char ** argv)
{
  struct mailmime * mime;
  struct mailimf_fields * fields;
  struct mailmime_fields * mime_fields;
  struct mailmime_content * content_type;
  struct mailmime_type * type;
  struct mailmime_composite_type * composite_type;
  struct mailmime_data * body;
  struct mailmime_data * preamble;
  struct mailmime_data * epilogue;
  clist * list;

  /* look at the example in mailimf_fields to see how to
     build a mailimf_fields */
  fields = build_fields();

  /* look at the example in mailmime_fields to see how to
     build a mailmime_fields */
  mime_fields = build_mime_fields();

  composite_type =
    mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL);
  type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL,
    composite_type);
  content_type = mailmime_content_new(type, strdup("mixed"), NULL);

  list = clist_new();
  /* build_mime_message() is a function that will build a mime message part */
  sub_mime = build_mime_message();
  clist_append(list, sub_mime);
  sub_mime = build_mime_message();
  clist_append(list, sub_mime);

  preamble = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0,
    PREAMBLE, sizeof(PREAMBLE), NULL);

  epilogue = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0,
    EPILOGUE, sizeof(EPILOGUE), NULL);

  mime = mailmime_new(MAILMIME_SINGLE,
    NULL, 0, fields, mime_fields, content_type,
    NULL, preamble, epilogue, list, NULL, NULL);

  /* do the things */

  mailmime_free(mime);
}

/* display mime part info */

void display_mime(struct mailmime * mime)
{
  clistiter * cur;

  switch (mime->mm_type) {
  case MAILMIME_SINGLE:
    printf("single part\n");
    break;
  case MAILMIME_MULTIPLE:
    printf("multipart\n");
    break;
  case MAILMIME_MESSAGE:
    printf("message\n");
    break;
  }

  printf("part : %p, length : %i\n",
    mime->mm_mime_start, mime->mm_length);
  printf("\n");

  if (mime->mm_mime_fields != NULL) {
    printf("MIME headers :\n");
    display_mime_fields(mime->mm_mime_fields);
    printf("\n");
  }

  printf("content type :\n");
  display_content(mime->mm_content_type);
  printf("\n");

  switch (mime->mm_type) {
  case MAILMIME_SINGLE:
    display_mime_data(mime->mm_data.mm_single);
    break;

  case MAILMIME_MULTIPLE:
    if (mime->mm_data.mm_multipart.mm_preamble) {
      printf("preamble :\n");
      display_mime_data(mime->mm_data.mm_multipart.mm_preamble);
      printf("\n");
    }

    for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
      cur != NULL ; cur = clist_next(cur)) {
      display_mime(clist_content(cur));
    }

    if (mime->mm_data.mm_multipart.mm_epilogue) {
      printf("epilogue :\n");
      display_mime_data(mime->mm_data.mm_multipart.mm_epilogue);
      printf("\n");
    }
    break;

  case MAILMIME_MESSAGE:
    if (mime->mm_data.mm_message.mm_fields) {
      printf("headers :\n");
      display_field(mime->mm_data.mm_message.mm_msg_fields);
      printf("\n");

    if (mime->mm_data.mm_message.mm_msg_mime != NULL) {
      printf("sub message %p :\n",
        mime->mm_data.mm_message.mm_msg_mime);
      display_mime(mime->mm_data.mm_message.mm_msg_mime);
      printf("end of sub message %p\n",
        mime->mm_data.mm_message.mm_msg_mime);
    }
    break;
  }
}
     __________________________________________________________________

mailmime_disposition - MIME disposition information (Content-Disposition)

#include <libetpan/libetpan.h>

struct mailmime_disposition {
  struct mailmime_disposition_type * dsp_type;
  clist * dsp_parms; /* struct mailmime_disposition_parm */
};

   This is the parsed Content-Disposition header field.

     * dsp_type is the type of disposition (see the Section called
       mailmime_disposition_type - Type of MIME disposition).
     * dsp_parms is the list of parameters of Content-Disposition header
       field. Each element is of type mailmime_disposition_parm (see the
       Section called mailmime_disposition_parm - MIME disposition
       parameter).

   Example 4-12. Creation and display of MIME disposition information
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime_disposition * disposition;
  struct mailmime_disposition_type * disposition_type;
  clist * disposition_parms;
  struct mailmime_disposition_parm * param;

  disposition_type =
    mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, NULL);

  disposition_parms = clist_new();
  param = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME,
                              strdup("foo.txt"), NULL,
                              NULL, NULL, -1, NULL);
  clist_append(disposition_parms, param);

  disposition = mailmime_disposition_new(disposition_type, disposition_parms);

  /* do the things */

  mailmime_disposition_free(disposition);
}

void display_mime_disposition(struct mailmime_disposition * disposition)
{
  clistiter * cur;

  printf("disposition type:\n");
  display_mailmime_disposition_type(disposition->dsp_type);
  printf("\n");
  printf("disposition parameters:\n");
  for(cur = clist_begin(disposition->dsp_parms) ;
    cur != NULL ; cur = clist_next(cur)) {
    struct mailmime_parm * param;

    param = clist_content(cur);
    display_mime_disposition_parm(param);
  }
  printf("\n");
}

     __________________________________________________________________

mailmime_disposition_type - Type of MIME disposition

#include <libetpan/libetpan.h>

enum {
  MAILMIME_DISPOSITION_TYPE_ERROR,
  MAILMIME_DISPOSITION_TYPE_INLINE,
  MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
  MAILMIME_DISPOSITION_TYPE_EXTENSION
};

struct mailmime_disposition_type {
  int dsp_type;
  char * dsp_extension;
};

   This is the type of MIME disposition. Parsed Content-Disposition field
   without parameters.

   dsp_type is the type of disposition. The value can be
   MAILMIME_DISPOSITION_TYPE_INLINE if MIME disposition is inline,
   MAILMIME_DISPOSITION_TYPE_ATTACHMENT if MIME disposition is attachment,
   MAILMIME_DISPOSITION_TYPE_EXTENSION for other. In this case,
   dsp_extension must be set. MAILMIME_DISPOSITION_TYPE_ERROR is used
   internally.

   Example 4-13. Creation and display of MIME disposition type
#include <libetpan/libetpan.h>

/* standard disposition type */

int main(int argc, char ** argv)
{
  struct mailmime_disposition_type * disposition_type;

  disposition_type =
    mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, NULL);

  /* do the things */

  mailmime_disposition_type_free(disposition_type);
}

/* disposition type extension */

int main(int argc, char ** argv)
{
  struct mailmime_disposition_type * disposition_type;

  disposition_type =
    mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_EXTENSION,
      strdup("mydisposition"));

  /* do the things */

  mailmime_disposition_type_free(disposition_type);
}

void display_mime_disposition_type(struct mailmime_disposition_type * dispositio
n_type)
{
  switch (disposition->dsp_type) {
  case MAILMIME_DISPOSITION_TYPE_INLINE:
    printf("inline\n");
    break;
  case MAILMIME_DISPOSITION_TYPE_ATTACHMENT:
    printf("attachment\n");
    break;
  case MAILMIME_DISPOSITION_TYPE_EXTENSION:
    printf("extension : %s\n", disposition_type->dsp_extension);
    break;
  }
}
     __________________________________________________________________

mailmime_disposition_parm - MIME disposition parameter

#include <libetpan/libetpan.h>

enum {
  MAILMIME_DISPOSITION_PARM_FILENAME,
  MAILMIME_DISPOSITION_PARM_CREATION_DATE,
  MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE,
  MAILMIME_DISPOSITION_PARM_READ_DATE,
  MAILMIME_DISPOSITION_PARM_SIZE,
  MAILMIME_DISPOSITION_PARM_PARAMETER
};

struct mailmime_disposition_parm {
  int pa_type;
  union {
    char * pa_filename;
    char * pa_creation_date;
    char * pa_modification_date;
    char * pa_read_date;
    size_t pa_size;
    struct mailmime_parameter * pa_parameter;
  } pa_data;
};

   This is a parameter of MIME disposition information. For example, this
   can be filename="foo.jpg".

     * pa_type is the type of disposition. The value can be
       MAILMIME_DISPOSITION_PARM_FILENAME for a filename parameter,
       MAILMIME_DISPOSITION_PARM_CREATION_DATE for a creation date
       parameter, MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE for a
       modification date parameter, MAILMIME_DISPOSITION_PARM_READ_DATE
       for a last read date parameter, MAILMIME_DISPOSITION_PARM_SIZE for
       a file size parameter or MAILMIME_DISPOSITION_PARM_PARAMETER for
       other parameters.
     * pa_data.pa_filename is the filename parameter when pa_type is
       MAILMIME_DISPOSITION_PARM_FILENAME This is a string containing the
       name of the file.
     * pa_data.pa_creation_date is the creation date parameter when
       pa_type is MAILMIME_DISPOSITION_PARM_CREATION_DATE. This is a
       string containing the formatted creation date.
     * pa_data.pa_modification_date is the modification date parameter
       when pa_type is MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE. This
       is a string containing the formatted modification date.
     * pa_data.pa_read_date is the last read date parameter when pa_type
       is MAILMIME_DISPOSITION_PARM_READ_DATE. This is a string containing
       the formatted last read date.
     * pa_data.pa_size is the size parameter when pa_type is
       MAILMIME_DISPOSITION_PARM_SIZE. This gives the size of the file.
     * pa_data.pa_parameter is the name and the value of the parameter
       when pa_type is MAILMIME_DISPOSITION_PARM_PARAMETER (see the
       Section called mailmime_parameter - MIME type parameter)

   Example 4-14. Creation and display of MIME disposition parameter
int main(int argc, char ** argv)
{
  struct mailmime_disposition_parm * param;

  disposition_parms = clist_new();
  param = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME,
                              strdup("foo.txt"), NULL,
                              NULL, NULL, -1, NULL);
  /* do the things */

  mailmime_disposition_parm_free(param);
}

void display_mime_dsp_parm(struct mailmime_disposition_parm * param)
{
  switch (param->pa_type) {
  case MAILMIME_DISPOSITION_PARM_FILENAME:
    printf("filename: %s\n", param->pa_data.pa_filename);
    break;
  case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
    printf("creation date: %s\n", param->pa_data.pa_creation_date);
    break;
  case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
    printf("modification date: %s\n", param->pa_data.pa_modification_date);
    break;
  case MAILMIME_DISPOSITION_PARM_READ_DATE:
    printf("read date: %s\n", param->pa_data.pa_read_date);
    break;
  case MAILMIME_DISPOSITION_PARM_SIZE:
    printf("size: %lu\n", (unsigned long) param->pa_data.pa_size);
    break;
  case MAILMIME_DISPOSITION_PARM_PARAMETER:
    printf("MIME disposition param:\n");
    display_mime_parameter(param->pa_data.pa_parameter);
    break;
  }
}
     __________________________________________________________________

mailmime_single_fields - MIME headers

#include <libetpan/libetpan.h>

struct mailmime_single_fields {
  struct mailmime_content * fld_content;
  char * fld_content_charset;
  char * fld_content_boundary;
  char * fld_content_name;
  struct mailmime_mechanism * fld_encoding;
  char * fld_id;
  char * fld_description;
  uint32_t fld_version;
  struct mailmime_disposition * fld_disposition;
  char * fld_disposition_filename;
  char * fld_disposition_creation_date;
  char * fld_disposition_modification_date;
  char * fld_disposition_read_date;
  size_t fld_disposition_size;
  struct mailmime_language * fld_language;
};

struct mailmime_single_fields *
mailmime_single_fields_new(struct mailmime_fields * fld_fields,
    struct mailmime_content * fld_content);

void mailmime_single_fields_free(struct mailmime_single_fields *
    single_fields);

void mailmime_single_fields_init(struct mailmime_single_fields * single_fields,
    struct mailmime_fields * fld_fields,
    struct mailmime_content * fld_content);

   mailmime_fields (see the Section called mailmime_fields - header
   fields) is the native structure that MIME module will use, this module
   will provide an easier structure to use when parsing fields.
   mailmime_single_fields is an easier structure to get parsed fields,
   rather than iteration over the list of fields.

     * fld_content is the MIME content type (see the Section called
       mailmime_content - MIME content type (Content-Type)).
     * fld_content_charset is the value of the MIME type parameter
       charset.
     * fld_content_boundary is the value of the MIME type parameter
       boundary.
     * fld_content_name is the value of the MIME type parameter name.
     * fld_encoding is the MIME encoding mechanism used (see the Section
       called mailmime_mechanism - MIME transfer encoding mechanism
       (Content-Transfer-Encoding)).
     * fld_id is the content of the field Content-ID.
     * fld_description is the content of the field Content-Description.
     * fld_version is the version of MIME in use.
     * fld_disposition is the MIME disposition information (see the
       Section called mailmime_disposition - MIME disposition information
       (Content-Disposition)).
     * fld_disposition_filename is the filename parameter of the MIME
       disposition information.
     * fld_disposition_creation_date is the creation-date parameter of the
       MIME disposition information.
     * fld_disposition_modification_date is the modification-date
       parameter of the MIME disposition information.
     * fld_disposition_read_date is the read-date parameter of the MIME
       disposition information.
     * fld_disposition_size is the size parameter of the MIME disposition
       information.
     * fld_language is the language of the MIME part (see the Section
       called mailmime_language - Language of MIME part).
     * single_fields is the structure to fill.
     * fld_fields is the MIME fields list to use to fill the
       single_fields.

   mailmime_single_fields_new() creates and initializes a data structure
   with a value. Structures given as argument are referenced by the
   created object and will NOT be freed if the object is released.

   mailmime_single_fields_free() frees memory used by the structure and
   substructures will NOT be released. They should be released by the
   application.

   mailimf_single_fields_init() will initialize fill the data structure,
   using the given argument (fld_fields and fld_content). The interesting
   fields will be filled into single_fields.

   Example 4-15. Creation and display of single fields
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime_single_fields * single_fields;
  struct mailmime_fields * mime_fields;
  struct mailmime_content * content_type;

  /* look at the example in mailmime_fields to see how to
     build a mailmime_fields */
  mime_fields = build_mime_fields();

  /* look at the example in mailmime_content to see how to
     build a mailmime_content */
  content_type = build_mime_content();

  single_fields = mailmime_single_fields_new(mime_fields, content_type);

  /* do the things */

  mailmime_single_fields_free(single_fields);
  mailmime_fields_free(mime_fields);
}

void display_mime_single_fields(struct mailmime_single_fields * single_fields)
{
  if (single_fields->fld_content != NULL) {
    printf("content type:\n");
    display_mime_content(single_fields->fld_content);
    printf("\n");
  }
  if (single_fields->fld_content_charset != NULL) {
    printf("content type charset: %s\n",
      single_fields->fld_content_charset);
    printf("\n");
  }
  if (single_fields->fld_content_boundary != NULL) {
    printf("content type boundary: %s\n",
      single_fields->fld_content_boundary);
    printf("\n");
  }
  if (single_fields->content_name != NULL) {
    printf("content type name: %s\n", single_fields->content_name);
    printf("\n");
  }
  if (single_fields->fld_encoding != NULL) {
    printf("content transfer encoding:\n");
    display_mime_mechanism(single_fields->fld_encoding);
    printf("\n");
  }
  if (single_fields->fld_id != NULL) {
    printf("content id: %s\n", single_fields->fld_id);
    printf("\n");
  }
  if (single_fields->fld_description != NULL) {
    printf("content description: %s\n", single_fields->fld_description);
    printf("\n");
  }
  if (single_fields->fld_version != 0) {
    printf("mime version: %i.%i\n",
      single_fields->fld_version>> 16,
      single_fields->fld_version & 0xFFFF);
    printf("\n");
  }
  if (single_fields->fld_disposition != NULL) {
    printf("content disposition:\n");
    display_mime_disposition(single_fields->fld_disposition);
    printf("\n");
  }
  if (single_fields->fld_disposition_filename != NULL) {
    printf("content disposition filename: %s\n",
      single_fields->fld_disposition_filename);
    printf("\n");
  }
  if (single_fields->fld_disposition_creation_date != NULL) {
    printf("content disposition creation date: %s\n",
      single_fields->fld_disposition_creation_date);
    printf("\n");
  }
  if (single_fields->fld_disposition_modification_date != NULL) {
    printf("content disposition modification date: %s\n",
      single_fields->fld_disposition_modification_date);
    printf("\n");
  }
  if (single_fields->fld_disposition_read_date != NULL) {
    printf("content disposition read date: %s\n",
      single_fields->fld_disposition_read_date;
    printf("\n");
  }
  if (single_fields->fld_disposition_size != (size_t) -1) {
    printf("content disposition size : %i\n",
      single_fields->fld_disposition_size);
    printf("\n");
  }
  if (single_fields->language != NULL) {
    printf("content language:\n");
    display_mime_language(single_fields->fld_language);
    printf("\n");
  }
}
     __________________________________________________________________

Parser functions

mailmime_content_parse

#include <libetpan/libetpan.h>

int mailmime_content_parse(const char * message, size_t length,
                           size_t * index,
                           struct mailmime_content ** result);

   This function will parse the content of a Content-Type header field.

     * message is a string containing the MIME content type.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * result. The result of the parse operation is stored in (* result)
       (see the Section called mailmime_content - MIME content type
       (Content-Type)).

   Example 4-16. Parsing MIME content type
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_fields_parse(mem, stat_info.st_size,
          &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
          clistiter * cur;

          for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur =
            clist_next(cur)) {
            struct mailmime_field * mime_field;
            struct mailimf_field * field;

            field = clist_content(cur);

            if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) {
              if (strcasecmp(field->fld_data.fld_optional_field->fld_name,
                "Content-Type") == 0) {
                struct mailmime_content * content_type;
                size_t current_index;

                current_index = 0;
                r = mailmime_content_parse(field->fld_data.fld_optional_field->f
ld_value,
                  strlen(field->fld_data.fld_optional_field->fld_value),
                  &current_index, &content_type);
                if (r == MAILIMF_NO_ERROR) {
                  display_mime_content(content_type);
                  /* do the things */
                  status = EXIT_SUCCESS;
                  mailmime_content_free(content_type);
                }
              }
            }
          }
          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_description_parse

#include >libetpan/libetpan.h<

int mailmime_description_parse(const char * message, size_t length,
                               size_t * index,
                               char ** result);

   This will parse the content of Content-Description MIME header field.

     * message is a string containing the MIME content description.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * result. The result of the parse operation is stored in (* result).
       The result string must be freed with free().

   Example 4-17. Parsing MIME description
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_fields_parse(mem, stat_info.st_size,
          &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
          clistiter * cur;

          for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur =
            clist_next(cur)) {
            struct mailmime_field * mime_field;
            struct mailimf_field * field;

            field = clist_content(cur);

            if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) {
              if (strcasecmp(field->fld_data.fld_optional_field->fld_name,
                "Content-Description") == 0) {
                char * description;
                size_t current_index;

                current_index = 0;
                r = mailmime_description_parse(field->fld_data.fld_optional_fiel
d->fld_value,
                  strlen(field->fld_data.fld_optional_field->fld_value),
                  &current_index, &description);
                if (r == MAILIMF_NO_ERROR) {
                  printf("%s\n", description);
                  /* do the things */
                  status = EXIT_SUCCESS;
                  free(description);
                }
              }
            }
          }
          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_encoding_parse

#include >libetpan/libetpan.h<

int mailmime_encoding_parse(const char * message, size_t length,
                            size_t * index,
                            struct mailmime_mechanism ** result);

   This function will parse the content of Content-Transfer-Encoding
   header field.

     * message is a string containing the MIME encoding mechanism.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * result. The result of the parse operation is stored in (* result)
       (see the Section called mailmime_mechanism - MIME transfer encoding
       mechanism (Content-Transfer-Encoding)).

   Example 4-18. parsing MIME encoding mechanism
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_fields_parse(mem, stat_info.st_size,
          &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
          clistiter * cur;

          for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur =
            clist_next(cur)) {
            struct mailmime_field * mime_field;
            struct mailimf_field * field;

            field = clist_content(cur);

            if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) {
              if (strcasecmp(field->fld_data.fld_optional_field->fld_name,
                "Content-Transfer-Encoding") == 0) {
                struct mailmime_content * encoding;
                size_t current_index;

                current_index = 0;
                r = mailmime_encoding_parse(field->fld_data.fld_optional_field->
fld_value,
                  strlen(field->fld_data.fld_optional_field->fld_value),
                  &current_index, &encoding);
                if (r == MAILIMF_NO_ERROR) {
                  display_mime_mechanism(encoding);
                  /* do the things */
                  status = EXIT_SUCCESS;
                  mailmime_mechanism_free(encoding);
                }
              }
            }
          }
          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_field_parse

#include <libetpan/libetpan.h>

int
mailmime_field_parse(struct mailimf_optional_field * field,
                     struct mailmime_field ** result);

   This function will parse a MIME header field.

     * field is a non-parsed field (see the Section called
       mailimf_optional_field - non-standard header in Chapter 3).
       result. The result of the parse operation is stored in (* result)
       (see the Section called mailmime_field - MIME header field).

   Example 4-19. parsing MIME header field
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_fields_parse(mem, stat_info.st_size,
          &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
          clistiter * cur;

          for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur =
            clist_next(cur)) {
            struct mailmime_field * mime_field;
            struct mailimf_field * field;

            field = clist_content(cur);

            if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) {
              r = mailmime_field_parse(field->fld_data.fld_optional_field,
                &mime_fields);
              if (r == MAILIMF_NO_ERROR) {
                display_mime_field(mime_field);
                mailmime_field_free(mime_field);
                status = EXIT_SUCCESS;
              }
            }
          }

          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_id_parse

#include >libetpan/libetpan.h<

int mailmime_id_parse(const char * message, size_t length,
                      size_t * index, char ** result);

   This will parse the content of Content-ID MIME header field.

     * message is a string containing the MIME content identifier.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * result. The result of the parse operation is stored in (* result).
       The result string must be freed with free().

   Example 4-20. Parsing MIME content identifier
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_fields_parse(mem, stat_info.st_size,
          &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
          clistiter * cur;

          for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur =
            clist_next(cur)) {
            struct mailmime_field * mime_field;
            struct mailimf_field * field;

            field = clist_content(cur);

            if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) {
              if (strcasecmp(field->fld_data.fld_optional_field->fld_name,
                "Content-ID") == 0) {
                char * id;
                size_t current_index;

                current_index = 0;
                r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_va
lue,
                  strlen(field->fld_data.fld_optional_field->fld_value),
                  &current_index, &id);
                if (r == MAILIMF_NO_ERROR) {
                  printf("%s\n", id);
                  /* do the things */
                  status = EXIT_SUCCESS;
                  free(id);
                }
              }
            }
          }
          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_fields_parse

#include <libetpan/libetpan.h>

int
mailmime_fields_parse(struct mailimf_fields * fields,
                      struct mailmime_fields ** result);

   This function will parse a MIME header fields.

     * fields is a list of RFC 2822 fields (see the Section called
       mailimf_fields - list of header fields in Chapter 3).
       result. The result of the parse operation is stored in (* result)
       (see the Section called mailmime_fields - header fields).

   Example 4-21. parsing MIME header fields
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_fields_parse(mem, stat_info.st_size,
          &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
          struct mailmime_fields * mime_fields;

          r = mailmime_fields_parse(f, &mime_fields);
          if (r == MAILIMF_NO_ERROR) {
            display_mime_fields(mime_fields);
            mailmime_fields_free(mime_fields);
            status = EXIT_SUCCESS;
          }

          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_version_parse

#include <libetpan/libetpan.h>

int mailmime_version_parse(const char * message, size_t length,
                           size_t * index,
                           uint32_t * result);

   This will parse the content of MIME-Version MIME header field.

     * message is a string containing the MIME version.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * result. The result of the parse operation is stored in (* result)
       (see the Section called mailmime_field - MIME header field).

   Example 4-22. parsing MIME version
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_fields_parse(mem, stat_info.st_size,
          &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
          clistiter * cur;

          for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur =
            clist_next(cur)) {
            struct mailmime_field * mime_field;
            struct mailimf_field * field;

            field = clist_content(cur);

            if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) {
              if (strcasecmp(field->fld_data.fld_optional_field->fld_name,
                "MIME-Version") == 0) {
                uint32_t version;
                size_t current_index;

                current_index = 0;
                r = mailmime_version_parse(field->fld_data.fld_optional_field->f
ld_value,
                  strlen(field->fld_data.fld_optional_field->fld_value),
                  &current_index, &version);
                if (r == MAILIMF_NO_ERROR) {
                  printf("%i.%i\n", version >> 16, version & 0xFFFF);
                  /* do the things */
                  status = EXIT_SUCCESS;
                  free(description);
                }
              }
            }
          }
          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_parameter_parse

#include <libetpan/libetpan.h>

int mailmime_parameter_parse(const char * message, size_t length,
                             size_t * index,
                             struct mailmime_parameter ** result);

   This will parse a MIME parameter (parameter of Content-Type or
   parameter of Content-Disposition).

     * message is a string containing the MIME parameter.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * result. The result of the parse operation is stored in (* result)
       (see the Section called mailmime_parameter - MIME type parameter).

   Example 4-23. parsing a MIME parameter
#include <libetpan/libetpan.h>

#define PARAM_STR "foo=bar"

int main(int argc, char ** argv)
{
  int fd;
  int r;
  size_t current_index;
  struct mailmime_parameter * param;
  int status;

  status = EXIT_FAILURE;

  current_index = 0;
  r = mailmime_parameter_parse(PARAM_STR, sizeof(PARAM_STR) - 1,
    &current_index, &param);
  if (r == MAILIMF_NO_ERROR) {
    display_mime_parameter(param);
    /* do the things */
    mailmime_parameter_free(param);
    status = EXIT_SUCCESS;
  }

  exit(status);
}
     __________________________________________________________________

mailmime_language_parse

#include <libetpan/libetpan.h>

int mailmime_language_parse(const char * message, size_t length,
                            size_t * index,
                            struct mailmime_language ** result);

   This function will parse the content of a Content-Language header.

     * message is a string containing the MIME content language.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * result. The result of the parse operation is stored in (* result)
       (see the Section called mailmime_language - Language of MIME part).

   Example 4-24. Parsing the MIME content langage
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_fields_parse(mem, stat_info.st_size,
          &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
          clistiter * cur;

          for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur =
            clist_next(cur)) {
            struct mailmime_field * mime_field;
            struct mailimf_field * field;

            field = clist_content(cur);

            if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) {
              if (strcasecmp(field->fld_data.fld_optional_field->fld_name,
                "Content-Language") == 0) {
                struct mailmime_language * lang;
                size_t current_index;

                current_index = 0;
                r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_va
lue,
                  strlen(field->fld_data.fld_optional_field->fld_value),
                  &current_index, &lang);
                if (r == MAILIMF_NO_ERROR) {
                  display_mime_language(lang);
                  /* do the things */
                  status = EXIT_SUCCESS;
                  free(id);
                }
              }
            }
          }
          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_disposition_parse

#include <libetpan/libetpan.h>

int mailmime_disposition_parse(const char * message, size_t length,
                               size_t * index,
                               struct mailmime_disposition ** result);

   This function will parse the content of a Content-Disposition MIME
   header field.

     * message is a string containing the MIME content disposition.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * result. The result of the parse operation is stored in (* result)
       (see the Section called mailmime_disposition - MIME disposition
       information (Content-Disposition)).

   Example 4-25. Parsing the MIME content disposition
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_fields_parse(mem, stat_info.st_size,
          &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
          clistiter * cur;

          for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur =
            clist_next(cur)) {
            struct mailmime_field * mime_field;
            struct mailimf_field * field;

            field = clist_content(cur);

            if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) {
              if (strcasecmp(field->fld_data.fld_optional_field->fld_name,
                "Content-Disposition") == 0) {
                struct mailmime_disposition * dsp;
                size_t current_index;

                current_index = 0;
                r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_va
lue,
                  strlen(field->fld_data.fld_optional_field->fld_value),
                  &current_index, &dsp);
                if (r == MAILIMF_NO_ERROR) {
                  display_mime_disposition(dsp);
                  /* do the things */
                  status = EXIT_SUCCESS;
                  free(id);
                }
              }
            }
          }
          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_disposition_type_parse

#include <libetpan/libetpan.h>

int
mailmime_disposition_type_parse(const char * message, size_t length,
                                size_t * index,
                                struct mailmime_disposition_type **
                                result);

   This function will parse the type of MIME content disposition.

     * message is a string containing the MIME content disposition type.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * result. The result of the parse operation is stored in (* result)
       (see the Section called mailmime_disposition_type - Type of MIME
       disposition).

   Example 4-26. parsing a MIME content disposition type
#include <libetpan/libetpan.h>

#define DSP_TYPE_STR "attachment"

int main(int argc, char ** argv)
{
  int fd;
  int r;
  size_t current_index;
  struct mailmime_disposition_type * dsp_type;
  int status;

  status = EXIT_FAILURE;

  current_index = 0;
  r = mailmime_disposition_type_parse(DSP_TYPE_STR, sizeof(DSP_TYPE_STR) - 1,
    &current_index, &dsp_type);
  if (r == MAILIMF_NO_ERROR) {
    display_mime_disposition_type(dsp_type);
    /* do the things */
    mailmime_disposition_type_free(dsp_type);
    status = EXIT_SUCCESS;
  }

  exit(status);
}
     __________________________________________________________________

mailmime_encoded_phrase_parse

#include <libetpan/libetpan.h>

int mailmime_encoded_phrase_parse(const char * default_fromcode,
    const char * message, size_t length,
    size_t * index, const char * tocode,
    char ** result);

   This function will decode a MIME encoded header string, encoded with
   RFC 2047.

     * default_fromcode is the default code to use for parts of string
       that are not marked with charset.
     * message is the string to decode.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * tocode is the destination charset for decoding.
     * result. The result of the parse operation is stored in (* result).

   Example 4-27. decoding a MIME encoded header string
#include <libetpan/libetpan.h>

#define TEST_STRING "=?iso-8859-1?ab?= =?iso-8859-15?cd?="

int main(int argc, char ** argv)
{
  size_t cur_token;
  char * decoded_subject;

  cur_token = 0;
  mailmime_encoded_phrase_parse("iso-8859-1",
    TEST_STRING, sizeof(TEST_STRING),
    &cur_token, "iso-8859-1", &decoded_subject);

  printf("%s\n", decoded_subject);

  /* do the things */

  free(decoded_subject);
}
     __________________________________________________________________

mailmime_parse

#include <libetpan/libetpan.h>

int mailmime_parse(const char * message, size_t length,
                   size_t * index, struct mailmime ** result);

   This will parse a MIME message.

     * message is a string containing the MIME message.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * result. The result of the parse operation is stored in (* result)
       (see the Section called mailmime - MIME part).

   Example 4-28. parsing a MIME message
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailmime * mime;
        size_t current_index;

        current_index = 0;
        r = mailmime_parse(mem, stat_info.st_size,
          &current_index, &mime);
        if (r == MAILIMF_NO_ERROR) {
            display_mime(mime);
          /* do the things */
          status = EXIT_SUCCESS;
          mailmime_free(mime);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_base64_body_parse

#include <libetpan/libetpan.h>

int mailmime_base64_body_parse(const char * message, size_t length,
                               size_t * index, char ** result,
                               size_t * result_len);

   This function will parse a body part encoded using base64.

     * message is a string encoded using base64.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * result. The result of the parse operation is stored in (* result)
       The result must be freed with mmap_string_unref().

   Example 4-29. Parsing a base64 encoded part
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;
        char * result;
        size_t result_len;

        current_index = 0;
        r = mailmime_base64_body_parse(mem, stat_info.st_size,
          &current_index, &result, &result_len);
        if (r == MAILIMF_NO_ERROR) {

          /* do the things */

          mailmime_decoded_part_free(mem);
          status = EXIT_SUCCESS;
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_quoted_printable_body_parse

#include <libetpan/libetpan.h>

int mailmime_quoted_printable_body_parse(const char * message, size_t length,
                                         size_t * index, char ** result,
                                         size_t * result_len, int in_header);

   This function will parse a body part encoded using quoted printable.

     * message is a string encoded using quoted printable.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * result. The result of the parse operation is stored in (* result)
       The result must be freed with mmap_string_unref().

   Example 4-30. Parsing a quoted printable encoded part
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;
        char * result;
        size_t result_len;

        current_index = 0;
        r = mailmime_quoted_printable_body_parse(mem, stat_info.st_size,
          &current_index, &result, &result_len);
        if (r == MAILIMF_NO_ERROR) {

          /* do the things */

          mailmime_decoded_part_free(mem);
          status = EXIT_SUCCESS;
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_binary_body_parse

#include <libetpan/libetpan.h>

int mailmime_binary_body_parse(const char * message, size_t length,
                               size_t * index, char ** result,
                               size_t * result_len);

   This function will parse a body part encoded using binary (no
   encoding).

     * message is a string encoded using binary.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * result. The result of the parse operation is stored in (* result)
       The result must be freed with mmap_string_unref().

   Example 4-31. Parsing a binary encoded part
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;
        char * result;
        size_t result_len;

        current_index = 0;
        r = mailmime_binary_body_parse(mem, stat_info.st_size,
          &current_index, &result, &result_len);
        if (r == MAILIMF_NO_ERROR) {

          /* do the things */

          mailmime_decoded_part_free(mem);
          status = EXIT_SUCCESS;
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_part_parse

#include <libetpan/libetpan.h>

enum {
  MAILMIME_MECHANISM_ERROR,
  MAILMIME_MECHANISM_7BIT,
  MAILMIME_MECHANISM_8BIT,
  MAILMIME_MECHANISM_BINARY,
  MAILMIME_MECHANISM_QUOTED_PRINTABLE,
  MAILMIME_MECHANISM_BASE64,
  MAILMIME_MECHANISM_TOKEN
};

int mailmime_part_parse(const char * message, size_t length,
                        size_t * index,
                        int encoding, char ** result, size_t * result_len);

   This function will parse a body part encoded using a given MIME
   encoding mechanism.

     * message is a string encoded using binary.
     * length is the size of the given string.
     * index is a pointer to the start of the address in the given string,
       (* index) is modified to point at the end of the parsed data.
     * encoding is a MIME encoding mechanism. The value can be
       MAILMIME_MECHANISM_7BIT, MAILMIME_MECHANISM_8BIT,
       MAILMIME_MECHANISM_BINARY, MAILMIME_MECHANISM_QUOTED_PRINTABLE,
       MAILMIME_MECHANISM_BASE64 or MAILMIME_MECHANISM_TOKEN (see the
       Section called mailmime_mechanism - MIME transfer encoding
       mechanism (Content-Transfer-Encoding)).
     * result. The result of the parse operation is stored in (* result)
       The result must be freed with mmap_string_unref().

   Example 4-32. Parsing a MIME encoded part
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;
        char * result;
        size_t result_len;

        current_index = 0;
        r = mailmime_part_parse(mem, stat_info.st_size, &current_index,
          MAILMIME_MECHANISM_QUOTED_PRINTABLE, &result, &result_len);
        if (r == MAILIMF_NO_ERROR) {

          /* do the things */

          mailmime_decoded_part_free(mem);
          status = EXIT_SUCCESS;
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

Rendering of MIME parts

mailmime_fields_write, mailmime_content_write and mailmime_content_type_write

#include <libetpan/libetpan.h>

int mailmime_fields_write(FILE * f, int * col,
                          struct mailmime_fields * fields);

int mailmime_content_write(FILE * f, int * col,
                           struct mailmime_content * content);

int mailmime_content_type_write(FILE * f, int * col,
                                struct mailmime_content * content);

   mailmime_fields_write render the MIME header fields.

   mailmime_content_write render the MIME content type header field.

   mailmime_content_write render the content of the MIME content type
   header field.

     * col current column is given for wrapping purpose in (* col), the
       resulting columns will be returned..
     * f is the file descriptor. It can be stdout for example.
     * fields is the header fields (see the Section called mailmime_fields
       - header fields).
     * content is the header fields (see the Section called
       mailmime_content - MIME content type (Content-Type)).

   Example 4-33. rendering MIME header fields
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime_mime * mime_fields;
  int col;

  /* look at the example in mailmime_fields to see how to
     build a mailmime_fields */
  mime_fields = build_mime_fields();

  col = 0;
  mailmime_fields_write(stdout, &col, mime_fields);

  mailmime_fields_free(mime_fields);
}

int main(int argc, char ** argv)
{
  struct mailmime_content * content;
  int col;

  /* look at the example in mailmime_content to see how to
     build a mailmime_fields */
  content = build_mime_content();

  col = 0;
  mailmime_content_write(stdout, &col, mime_fields);

  mailmime_content_free(content);
}

int main(int argc, char ** argv)
{
  struct mailmime_content * content;
  int col;

  /* look at the example in mailmime_content to see how to
     build a mailmime_fields */
  content = build_mime_content();

  col = 0;
  mailmime_content_type_write(stdout, &col, mime_fields);

  mailmime_content_free(content);
}
     __________________________________________________________________

mailmime_write

#include <libetpan/libetpan.h>

int mailmime_write(FILE * f, int * col,
                   struct mailmime * build_info);

   This function will render a MIME message.

     * col current column is given for wrapping purpose in (* col), the
       resulting columns will be returned..
     * f is the file descriptor. It can be stdout for example.
     * build_info is the MIME message to render.
     __________________________________________________________________

mailmime_quoted_printable_write and mailmime_base64_write

#include <libetpan/libetpan.h>

int mailmime_quoted_printable_write(FILE * f, int * col, int istext,
    const char * text, size_t size);

int mailmime_base64_write(FILE * f, int * col,
    const char * text, size_t size);

   mailmime_quoted_printable_write() will render a string to quoted
   printable.

   mailmime_base64_write() will render a string to base64.

     * col current column is given for wrapping purpose in (* col), the
       resulting columns will be returned..
     * f is the file descriptor. It can be stdout for example.
     * text is the string to render.
     * size is the size of the string to render.

   Example 4-34. render base64 or quoted printable
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  int col;

  col = 0;
  mailmime_quoted_printable_write(stdout, &col,
    "this is a test", 14);
}

#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  int col;

  col = 0;
  mailmime_base64_write(stdout, &col, "this is a test", 14);
}
     __________________________________________________________________

mailmime_data_write

#include <libetpan/libetpan.h>

int mailmime_data_write(FILE * f, int * col,
    struct mailmime_data * data,
    int istext);

   mailmime_data_write will render MIME data.

     * col current column is given for wrapping purpose in (* col), the
       resulting columns will be returned..
     * f is the file descriptor. It can be stdout for example.
     * data is the data to render (see the Section called mailmime_data -
       Content of MIME part).
     __________________________________________________________________

Creation functions

mailmime_disposition_new_filename and mailmime_disposition_new_with_data

#include <libetpan/libetpan.h>

enum {
  MAILMIME_DISPOSITION_TYPE_ERROR,
  MAILMIME_DISPOSITION_TYPE_INLINE,
  MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
  MAILMIME_DISPOSITION_TYPE_EXTENSION
};

struct mailmime_disposition *
mailmime_disposition_new_filename(int type, char * filename);

struct mailmime_disposition *
mailmime_disposition_new_with_data(int type,
    char * filename, char * creation_date, char * modification_date,
    char * read_date, size_t size);

   These functions will create a MIME content disposition information.

     * type a standard MIME disposition : MAILMIME_DISPOSITION_TYPE_INLINE
       or MAILMIME_DISPOSITION_TYPE_ATTACHMENT.
       filename is the filename.
       creation_date is the creation date.
       modification_date is the modification date.
       read_date is the last read date.
       size is the size of the file.
     * This will return a MIME content disposition (see the Section called
       mailmime_disposition - MIME disposition information
       (Content-Disposition)).

   Example 4-35. creating a MIME content disposition

#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime_disposition * disposition;

  disposition =
    mailmime_disposition_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
      strdup("foo-bar.txt"));

  /* do the things */

  mailmime_disposition_free(disposition);
}
     __________________________________________________________________

mailmime_fields_new_empty and mailmime_fields_add

#include <libetpan/libetpan.h>

struct mailmime_fields * mailmime_fields_new_empty(void);

int mailmime_fields_add(struct mailmime_fields * fields,
                        struct mailmime_field * field);

   mailmime_fields_new_empty() will create a new empty MIME header fields
   list.

   mailmime_fields_add() will add MIME header fields to the MIME header
   fields list.

     * fields. The MIME header field will be added to this MIME header
       fields list (see the Section called mailmime_fields - header
       fields).
     * field is the MIME header field to add (see the Section called
       mailmime_field - MIME header field).

   Example 4-36. creating a MIME header fields list
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime_fields * fields;
  struct mailmime_field * field;

  fields = mailmime_fields_new_empty();
  field = build_mime_field();

  /* do the things */

  mailmime_fields_add(fields, field);

  mailmime_fields_free(fields);
}
     __________________________________________________________________

mailmime_fields_new_with_data and mailmime_fields_new_with_version

#include <libetpan/libetpan.h>

struct mailmime_fields *
mailmime_fields_new_with_data(struct mailmime_mechanism * encoding,
                              char * id,
                              char * description,
                              struct mailmime_disposition * disposition,
                              struct mailmime_language * language);

struct mailmime_fields *
mailmime_fields_new_with_version(struct mailmime_mechanism * encoding,
                                 char * id,
                                 char * description,
                                 struct mailmime_disposition * disposition,
                                 struct mailmime_language * language);

   mailmime_fields_new_with_data() will create a MIME header fields list
   with all the given fields (NULL can be used for the value if the field
   must not be present). MIME-Version header field will not be added.

   mailmime_fields_new_with_version() will create a MIME header fields
   list with all the given fields (NULL can be used for the value if the
   field must not be present). MIME-Version header field will be added.

   Example 4-37. creating new fields
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime_disposition * disposition;
  struct mailmime_fields * mime_fields;
  struct mailmime_mechanism * encoding;

  encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL);

  disposition =
    mailmime_disposition_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
      strdup("foo-bar.txt"));

  mime_fields = mailmime_fields_new_with_version(encoding, NULL,
    NULL, disposition, NULL);

  /* do the things */

  mailmime_fields_free(mime_fields);
}
     __________________________________________________________________

mailmime_get_content_message

#include <libetpan/libetpan.h>

struct mailmime_content * mailmime_get_content_message(void);

struct mailmime_content * mailmime_get_content_text(void);

struct mailmime_content * mailmime_content_new_with_str(const char * str);

   mailmime_get_content_message() will create a MIME content type
   message/rfc822.

   mailmime_get_content_text() will create a MIME content type plain/text.

   mailmime_get_content_new_with_str() will create a MIME content type
   given by the string plain/text.

   str. This string will NOT be referenced by any structure. This string
   will only be parsed to create the structure.

   Example 4-38. Creating a MIME content type
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime_content * content;

  content = mailmime_get_content_message();

  /* do the things */

  mailmime_content_free(content);
}

int main(int argc, char ** argv)
{
  struct mailmime_content * content;

  content = mailmime_get_content_text();

  /* do the things */

  mailmime_content_free(content);
}

int main(int argc, char ** argv)
{
  struct mailmime_content * content;

  content = mailmime_get_content_new_with_str("multipart/mixed");

  /* do the things */

  mailmime_content_free(content);
}
     __________________________________________________________________

mailmime_data_new_data and mailmime_data_new_file

#include <libetpan/libetpan.h>

enum {
  MAILMIME_MECHANISM_ERROR,
  MAILMIME_MECHANISM_7BIT,
  MAILMIME_MECHANISM_8BIT,
  MAILMIME_MECHANISM_BINARY,
  MAILMIME_MECHANISM_QUOTED_PRINTABLE,
  MAILMIME_MECHANISM_BASE64,
  MAILMIME_MECHANISM_TOKEN
};

struct mailmime_data *
mailmime_data_new_data(int encoding, int encoded,
                       const char * data, size_t length);

struct mailmime_data *
mailmime_data_new_file(int encoding, int encoded,
                       char * filename);

   mailmime_data_new_data() will create a new MIME content, using a string
   in memory.

   mailmime_data_new_file() will create a new MIME content, using a file.

     * encoding is the MIME encoding mechanism used to encode this part.
       The value can be MAILMIME_MECHANISM_7BIT, MAILMIME_MECHANISM_8BIT,
       MAILMIME_MECHANISM_BINARY, MAILMIME_MECHANISM_QUOTED_PRINTABLE or
       MAILMIME_MECHANISM_BASE64 (see the Section called
       mailmime_mechanism - MIME transfer encoding mechanism
       (Content-Transfer-Encoding)).
     * encoded is set to 1 if the part is already encoded with the
       mechanism given in encoding.
     * data is a pointer to the content of the part.
     * length is the length of the data.
     * filename is the name of the file.

   Example 4-39. creating MIME content
#include <libetpan/libetpan.h>

#define DATA_STR "my data"

int main(int argc, char ** argv)
{
  struct mailmime_data * data;

  data = mailmime_data_new_data(MAILMIME_MECHANISM_BASE64, 0,
                                DATA_STR, sizeof(DATA_STR) - 1);

  /* do the things */

  mailmime_data_free(data);
}

int main(int argc, char ** argv)
{
  struct mailmime_data * data;

  data = mailmime_data_new_file(MAILMIME_MECHANISM_BASE64, 0,
                                strdup("foo-bar.txt"));

  /* do the things */

  mailmime_data_free(data);
}
     __________________________________________________________________

mailmime_new_message_data, mailmime_new_empty and mailmime_new_with_content

#include <libetpan/libetpan.h>

struct mailmime *
mailmime_new_message_data(struct mailmime * msg_mime);

struct mailmime *
mailmime_new_empty(struct mailmime_content * content,
                   struct mailmime_fields * mime_fields);

int
mailmime_new_with_content(const char * content_type,
                          struct mailmime_fields * mime_fields,
                          struct mailmime ** result);

struct mailmime * mailmime_multiple_new(const char * type);

   mailmime_new_message_data() will create a new MIME message with the
   given subpart.

   mailmime_new_empty() will create a new MIME part with the given content
   type and MIME fields but with no content.

   mailmime_new_with_content() will create a new MIME part with a content
   type given by a string and a given MIME fields list.

   mailmime_multiple_new() will create a new MIME multipart with a content
   type given by a string.

     * msg_mime is the sub part to add to the MIME message when creating
       it (see the Section called mailmime - MIME part).
     * content is the content type of the part to create (see the Section
       called mailmime_content - MIME content type (Content-Type)).
     * content_type is the content type of the part to create given by a
       string.
     * mime_fields is the list of MIME header fields (see the Section
       called mailmime_fields - header fields).

   Example 4-40. creating a MIME part
#include <libetpan/libetpan.h>

#define DATA_STR "my data"

int main(int argc, char ** argv)
{
  struct mailmime * mime;
  struct mailmime * single_part;

  mime_fields =
    mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE);
  mailmime_new_with_content("plain/text", mime_fields, &single_part);

  mailmime_set_body_text(single_part, DATA_STR, sizeof(DATA_STR) - 1);

  mime = mailmime_new_message_data(single_part);

  /* do the things */

  mailmime_free(mime);
}

int main(int argc, char ** argv)
{
  struct mailmime * mime;
  struct mailmime * single_part;
  struct mailmime_content * content;

  mime_fields =
    mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE);
  content = mailmime_get_content_text();
  single_part = mailmime_new_empty(content, mime_fields);

  mailmime_set_body_text(single_part, DATA_STR, sizeof(DATA_STR) - 1);

  mime = mailmime_new_message_data(single_part);

  /* do the things */

  mailmime_free(mime);
}

int main(int argc, char ** argv)
{
  struct mailmime * mime;

  mime = mailmime_multiple_new("multipart/mixed");

  /* do the things */

  mailmime_free(mime);
}
     __________________________________________________________________

mailmime_set_preamble_file, mailmime_set_epilogue_file,
mailmime_set_preamble_text and mailmime_set_epilogue_text

#include <libetpan/libetpan.h>

int mailmime_set_preamble_file(struct mailmime * build_info,
                               char * filename);

int mailmime_set_epilogue_file(struct mailmime * build_info,
                               char * filename);

int mailmime_set_preamble_text(struct mailmime * build_info,
                               char * data_str, size_t length);

int mailmime_set_epilogue_text(struct mailmime * build_info,
                               char * data_str, size_t length);

   mailmime_set_preamble_file() will define the preamble of a multipart.

   mailmime_set_preamble_text() will define the preamble of a multipart.

   mailmime_set_epilogue_file() will define the epilogue of a multipart.

   mailmime_set_preamble_text() will define the preamble of a multipart.

     * build_info is the MIME part to modify (see the Section called
       mailmime - MIME part).
     * data_str is the string to define as epilogue or prologue.
     * length is the length of the string to define as epilogue or
       prologue.
     * filename is the name of the file which content will be defined as
       epilogue or prologue.

   Example 4-41. setting preamble and epilogue
#include <libetpan/libetpan.h>

#define DATA_STR "test foo bar"

int main(int argc, char ** argv)
{
  struct mailmime * mime;

  mime = mailmime_multiple_new("multipart/mixed");

  mailmime_set_preamble_file(mime, strdup("foo-bar.txt"));

  mailmime_set_epilogue_data(mime, DATA_STR, sizeof(DATA_STR) - 1);

  /* do the things */

  mailmime_free(mime);
}
     __________________________________________________________________

mailmime_set_body_file and mailmime_set_body_text

#include <libetpan/libetpan.h>

int mailmime_set_body_file(struct mailmime * build_info,
                           char * filename);

int mailmime_set_body_text(struct mailmime * build_info,
                           char * data_str, size_t length);

   mailmime_set_body_file() will define the body of a single part.

   mailmime_set_body_text() will define the body of a single part.

     * build_info is the MIME part to modify (see the Section called
       mailmime - MIME part).
     * data_str is the string to define as the body of the part.
     * length is the length of the string to define as the body of the
       part.
     * filename is the name of the file which content will be defined as
       the body of the part.

   Example 4-42. creating a MIME part
#include <libetpan/libetpan.h>

#define DATA_STR "my data"

int main(int argc, char ** argv)
{
  struct mailmime * mime;

  mime_fields =
    mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE);
  mailmime_new_with_content("plain/text", mime_fields, &mime);

  mailmime_set_body_text(mime, DATA_STR, sizeof(DATA_STR) - 1);



  /* do the things */

  mailmime_free(mime);
}
     __________________________________________________________________

mailmime_add_part, mailmime_remove_part, mailmime_smart_add_part and
mailmime_smart_remove_part

#include <libetpan/libetpan.h>

int mailmime_add_part(struct mailmime * build_info,
                      struct mailmime * part);

void mailmime_remove_part(struct mailmime * mime);

int mailmime_smart_add_part(struct mailmime * mime,
    struct mailmime * mime_sub);

int mailmime_smart_remove_part(struct mailmime * mime);

   mailmime_add_part() will add a sub MIME part.

   mailmime_remove_part() will detach the given sub part from its parent.

   mailmime_smart_add_part() will add a sub MIME part. If the parent part
   is a message and no child exist, the part is set as the child. If the
   parent part is a message and a child already exists, if the child is
   multipart, the part to add is added as child of this multipart, else a
   multipart is added and the part is added as child of the multipart.

   mailmime_smart_remove_part() will detach the given sub part from its
   parent. The sub part will be freed.

     * build_info is the parent MIME part (see the Section called mailmime
       - MIME part).
     * part is the part to add (see the Section called mailmime - MIME
       part).
     * mime is the parent MIME part (see the Section called mailmime -
       MIME part).
     * mime_sub is the part to add or to detach (see the Section called
       mailmime - MIME part).

   Example 4-43. modifying MIME structure
#include <libetpan/libetpan.h>

int main(int argc, char ** argv)
{
  struct mailmime * sub_mime;
  struct mailmime_fields * mime_fields;
  struct mailmime_content * content;

  content = mailmime_get_content_text();

  mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64);

  sub_mime = mailmime_new_empty(content, mime_fields);

  mime = mailmime_new_message_data(NULL);

  mailmime_add_part(mime, sub_mime);

  /* do the things */

  mailmime_free(mime);

int main(int argc, char ** argv)
{
  struct mailmime * sub_mime;
  struct mailmime * other_sub_mime;
  struct mailmime_fields * mime_fields;
  struct mailmime_content * content;

  content = mailmime_get_content_text();
  mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64);
  sub_mime = mailmime_new_empty(content, mime_fields);

  content = mailmime_get_content_text();
  mime_fields =
    mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE);
  other_sub_mime = mailmime_new_empty(content, mime_fields);

  mime = mailmime_new_message_data(NULL);

  mailmime_smart_add_part(mime, sub_mime);
  mailmime_smart_add_part(mime, other_sub_mime);

  /* do the things */

  mailmime_free(mime);

int main(int argc, char ** argv)
{
  struct mailmime * sub_mime;
  struct mailmime_fields * mime_fields;
  struct mailmime_content * content;

  content = mailmime_get_content_text();

  mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64);

  sub_mime = mailmime_new_empty(content, mime_fields);

  mime = mailmime_new_message_data(NULL);

  mailmime_add_part(mime, sub_mime);

  mailmime_remove_part(sub_mime);

  /* do the things */

  mailmime_free(sub_mime);
  mailmime_free(mime);

int main(int argc, char ** argv)
{
  struct mailmime * sub_mime;
  struct mailmime_fields * mime_fields;
  struct mailmime_content * content;

  content = mailmime_get_content_text();

  mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64);

  sub_mime = mailmime_new_empty(content, mime_fields);

  mime = mailmime_new_message_data(NULL);

  mailmime_add_part(mime, sub_mime);

  mailmime_smart_remove_part(sub_mime);

  /* do the things */

  mailmime_free(mime);
}
     __________________________________________________________________

mailmime_set_imf_fields

#include <libetpan/libetpan.h>

void mailmime_set_imf_fields(struct mailmime * build_info,
    struct mailimf_fields * fields);

   mailmime_set_imf_fields() will set the fields of the given MIME
   message.

     * build_info is the MIME message to modify (see the Section called
       mailmime - MIME part).
     * fields is the header fields to set for the message (see the Section
       called mailimf_fields - list of header fields in Chapter 3).

   Example 4-44. modifying MIME structure
#include <libetpan/libetpan.h>

#define DATA_STR "test foo bar"

int main(int argc, char ** argv)
{
  struct mailmime * mime;
  struct mailmime_fields * mime_fields;
  struct mailimf_fields * imf_fields;

  mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT);

  mailmime_new_with_content("text/plain", mime_fields, &mime);

  mailmime_set_body_text(mime, DATA_STR, sizeof(DATA_STR) - 1);

  /* look at the example in mailimf_fields to see how to
     build a mailimf_fields */
  imf_fields = build_fields();

  mailmime_set_imf_fields(mime, imf_fields);

  /* do the things */

  mailmime_free(mime);
}
     __________________________________________________________________

mailmime_fields_new_encoding and mailmime_fields_new_filename

#include <libetpan/libetpan.h>

enum {
  MAILMIME_MECHANISM_ERROR,
  MAILMIME_MECHANISM_7BIT,
  MAILMIME_MECHANISM_8BIT,
  MAILMIME_MECHANISM_BINARY,
  MAILMIME_MECHANISM_QUOTED_PRINTABLE,
  MAILMIME_MECHANISM_BASE64,
  MAILMIME_MECHANISM_TOKEN
};

enum {
  MAILMIME_DISPOSITION_TYPE_ERROR,
  MAILMIME_DISPOSITION_TYPE_INLINE,
  MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
  MAILMIME_DISPOSITION_TYPE_EXTENSION
};

struct mailmime_fields * mailmime_fields_new_encoding(int encoding_type);

struct mailmime_fields * mailmime_fields_new_filename(int dsp_type,
    char * filename, int encoding_type);

   mailmime_fields_new_encoding() will create a list of MIME header fields
   with only Content-Transfer-Encoding.

   mailmime_fields_new_filename() will create a list of MIME header fields
   with Content-Transfer-Encoding and Content-Disposition.

   The result will be a list of MIME header fields (see the Section called
   mailmime_fields - header fields).

     * encoding_type is the MIME encoding mechanism. The value can be
       MAILMIME_MECHANISM_7BIT, MAILMIME_MECHANISM_8BIT,
       MAILMIME_MECHANISM_BINARY, MAILMIME_MECHANISM_QUOTED_PRINTABLE or
       MAILMIME_MECHANISM_BASE64 (see the Section called
       mailmime_mechanism - MIME transfer encoding mechanism
       (Content-Transfer-Encoding)).
     * dsp_type is the disposition type. The value can be
       MAILMIME_DISPOSITION_TYPE_INLINE or
       MAILMIME_DISPOSITION_TYPE_ATTACHMENT (see the Section called
       mailmime_disposition_type - Type of MIME disposition).
     * filename is the filename for MIME content disposition.

   Example 4-45. creating MIME fields with only Content-Transfer-Encoding
#include <libetpan/libetpan.h>

int main(void)
{
  struct mailmime_fields * fields;

  fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64);

  /* do the things */

  mailmime_fields_free(fields);
}

int main(void)
{
  struct mailmime_fields * fields;

  fields =
  mailmime_fields_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
    strdup("foo-bar.txt"), MAILMIME_MECHANISM_BASE64);

  /* do the things */

  mailmime_fields_free(fields);
}
     __________________________________________________________________

Helper functions

mailmime_transfer_encoding_get

#include <libetpan/libetpan.h>

int mailmime_transfer_encoding_get(struct mailmime_fields * fields);

   mailmime_transfer_encoding_get() will return the standard MIME encoding
   mechanism.

     * fields is the list of MIME header fields.
     * An integer representing the MIME encoding mechanism will be
       returned (see the Section called mailmime_mechanism - MIME transfer
       encoding mechanism (Content-Transfer-Encoding)).

   Example 4-46. extracting MIME encoding mechanism
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_fields_parse(mem, stat_info.st_size,
          &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
          struct mailmime_fields * mime_fields;

          r = mailmime_fields_parse(f, &mime_fields);
          if (r == MAILIMF_NO_ERROR) {
            int encoding;

            encoding = mailmime_transfer_encoding_get(mime_fields);

            /* do the things */

            mailmime_fields_free(mime_fields);
            status = EXIT_SUCCESS;
          }

          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

mailmime_content_charset_get and mailmime_content_param_get

#include <libetpan/libetpan.h>

char * mailmime_content_charset_get(struct mailmime_content * content);

char * mailmime_content_param_get(struct mailmime_content * content,
                                  char * name);

char * mailmime_extract_boundary(struct mailmime_content * content_type);

   mailmime_content_charset_get() will return the charset parameter of
   MIME content type.

   mailmime_content_param_get() will return the value of a given parameter
   of MIME content type.

   mailmime_extract_boundary() will return the charset parameter of MIME
   content type.

     * content is the MIME content type.
     * name is the name of the parameter to extract.
     * With mailmime_extract_boundary(), the returned value must be freed
       with free().

   Example 4-47. extracting information from MIME content type
#include <libetpan/libetpan.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char ** argv)
{
  int fd;
  int r;

  status = EXIT_FAILURE;

  fd = open("message.rfc2822", O_RDONLY);
  if (fd >= 0) {
    void * mem;
    struct stat stat_info;

    r = fstat(fd, &stat_info);
    if (r >= 0) {
      mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE);
      if (mem != MAP_FAILED) {
        struct mailimf_fields * f;
        size_t current_index;

        current_index = 0;
        r = mailimf_fields_parse(mem, stat_info.st_size,
          &current_index, &f);
        if (r == MAILIMF_NO_ERROR) {
          clistiter * cur;

          for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur =
            clist_next(cur)) {
            struct mailmime_field * mime_field;
            struct mailimf_field * field;

            field = clist_content(cur);

            if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) {
              if (strcasecmp(field->fld_data.fld_optional_field->fld_name,
                "Content-Type") == 0) {
                struct mailmime_content * content_type;
                size_t current_index;

                current_index = 0;
                r = mailmime_content_parse(field->fld_data.fld_optional_field->f
ld_value,
                  strlen(field->fld_data.fld_optional_field->fld_value),
                  &current_index, &content_type);
                if (r == MAILIMF_NO_ERROR) {
                  char * charset;
                  char * name;
                  char * boundary;

                  charset = mailmime_content_charset_get(content_type);
                  name = mailmime_content_param_get(content_type, "name");
                  boundary = mailmime_extract_boundary(content_type);

                  /* do the things */

                  free(boundary);

                  status = EXIT_SUCCESS;
                  mailmime_content_free(content_type);
                }
              }
            }
          }
          mailimf_fields_free(f);
        }
      }
      munmap(mem, stat_info.st_size);
    }

    close(fd);
  }

  exit(status);
}
     __________________________________________________________________

Chapter 5. Storages, folders, messages

Introduction

   This part will give the definition of some objects.
     __________________________________________________________________

Message

   A message is the common e-mail message or news message you read or
   send.
     __________________________________________________________________

MIME part

   A message can have attachment such as images or other documents. The
   attachment are organized into a tree structure. Each node of this
   structure is a MIME part.
     __________________________________________________________________

Mailbox

   A mailbox will contain a given number of messages.
     __________________________________________________________________

Storage

   A storage is a "physical" localisation of your mailbox. This can be on
   a filesystem (local or remote disk, this is the case of MH, mbox and
   maildir), or this can be on a remote host (this is the case for POP3,
   IMAP or NNTP).
     __________________________________________________________________

Folder

   A storage, for the same user, can contain a given number of mailboxes,
   depending the storage capabilities, then, the storage driver
   capabilities. With etPan!, MH, IMAP and NNTP storages can have more
   than one mailbox. The mailboxes will be called folders. On storage
   where we only have one mailbox, the unique mailbox is the unique
   folder.
     __________________________________________________________________

Session

   The session is the network connection or the entity to which the
   commands of the drivers are given.
     __________________________________________________________________

Error codes

   Error codes returned as integers can be one of the following :
enum {
  MAIL_NO_ERROR = 0,
  MAIL_NO_ERROR_AUTHENTICATED,
  MAIL_NO_ERROR_NON_AUTHENTICATED,
  MAIL_ERROR_NOT_IMPLEMENTED,
  MAIL_ERROR_UNKNOWN,
  MAIL_ERROR_CONNECT,
  MAIL_ERROR_BAD_STATE,
  MAIL_ERROR_FILE,
  MAIL_ERROR_STREAM,
  MAIL_ERROR_LOGIN,
  MAIL_ERROR_CREATE, /* 10 */
  MAIL_ERROR_DELETE,
  MAIL_ERROR_LOGOUT,
  MAIL_ERROR_NOOP,
  MAIL_ERROR_RENAME,
  MAIL_ERROR_CHECK,
  MAIL_ERROR_EXAMINE,
  MAIL_ERROR_SELECT,
  MAIL_ERROR_MEMORY,
  MAIL_ERROR_STATUS,
  MAIL_ERROR_SUBSCRIBE, /* 20 */
  MAIL_ERROR_UNSUBSCRIBE,
  MAIL_ERROR_LIST,
  MAIL_ERROR_LSUB,
  MAIL_ERROR_APPEND,
  MAIL_ERROR_COPY,
  MAIL_ERROR_FETCH,
  MAIL_ERROR_STORE,
  MAIL_ERROR_SEARCH,
  MAIL_ERROR_DISKSPACE,
  MAIL_ERROR_MSG_NOT_FOUND,  /* 30 */
  MAIL_ERROR_PARSE,
  MAIL_ERROR_INVAL,
  MAIL_ERROR_PART_NOT_FOUND,
  MAIL_ERROR_REMOVE,
  MAIL_ERROR_FOLDER_NOT_FOUND,
  MAIL_ERROR_MOVE,
  MAIL_ERROR_STARTTLS,
  MAIL_ERROR_CACHE_MISS,
  MAIL_ERROR_NO_TLS,
  MAIL_ERROR_EXPUNGE,
  /* misc errors */
  MAIL_ERROR_MISC,
  MAIL_ERROR_PROTOCOL,
  MAIL_ERROR_CAPABILITY,
  MAIL_ERROR_CLOSE,
  MAIL_ERROR_FATAL,
  MAIL_ERROR_READONLY,
  MAIL_ERROR_NO_APOP,
  MAIL_ERROR_COMMAND_NOT_SUPPORTED,
  MAIL_ERROR_NO_PERMISSION,
  MAIL_ERROR_PROGRAM_ERROR,
  MAIL_ERROR_SUBJECT_NOT_FOUND,
  MAIL_ERROR_CHAR_ENCODING_FAILED,
  MAIL_ERROR_SEND,
  MAIL_ERROR_COMMAND,
};
     __________________________________________________________________

Storage

Storage driver

#include <libetpan/libetpan.h>

typedef struct mailstorage_driver mailstorage_driver;

struct mailstorage_driver {
  char * sto_name;
  int (* sto_connect)(struct mailstorage * storage);
  int (* sto_get_folder_session)(struct mailstorage * storage,
      char * pathname, mailsession ** result);
  void (* sto_uninitialize)(struct mailstorage * storage);
};

   This is the driver for a storage.

     * sto_name is the name of the driver.
     * sto_connect() connects the storage to the remote access or to the
       path in the local filesystem.
     * sto_get_folder_session() can have two kinds of behaviour. Either it
       creates a new session and independant from the session used by the
       storage and select the given mailbox or it selects the given
       mailbox in the current session. It depends on the efficiency of the
       mail access.
       XXX - in the future, this will be moved to the folder driver
     * sto_uninitialize() frees the data created with mailstorage
       constructor.
     __________________________________________________________________

Storage

#include <libetpan/libetpan.h>

struct mailstorage {
  char * sto_id;
  void * sto_data;
  mailsession * sto_session;
  mailstorage_driver * sto_driver;
  clist * sto_shared_folders; /* list of (struct mailfolder *) */

  void * sto_user_data;
};

     * sto_id is an identifier for the storage. This can be NULL.
     * sto_data is the internal data of the storage. This can only be
       changed by the driver.
     * sto_session is the session used by the storage. The session can be
       used to send commands.
     * sto_driver is the driver of the storage.
     * sto_shared_folders is the list of folders that share the session
       with the storage. This is used internally.
     * sto_user_data is a field for free use. The user can store any data
       in that field.
     __________________________________________________________________

mailstorage_new and mailstorage_free

#include <libetpan/libetpan.h>

struct mailstorage * mailstorage_new(char * sto_id);

void mailstorage_free(struct mailstorage * storage);

   mailstorage_new() initializes a storage structure with an identifier
   (sto_id) and with no driver.

   mailstorage_free() free the memory used by a storage.
     __________________________________________________________________

mailstorage_connect and mailstorage_disconnect

#include <libetpan/libetpan.h>

int mailstorage_connect(struct mailstorage * storage);

void mailstorage_disconnect(struct mailstorage * storage);

   mailstorage_connect() connects the storage. This function can also be
   used to confirm that a storage connection is valid when the storage is
   already connected.

   mailstorage_disconnect() disconnects the storage.
     __________________________________________________________________

IMAP storage

int imap_mailstorage_init(struct mailstorage * storage,
    char * imap_servername, uint16_t imap_port,
    char * imap_command,
    int imap_connection_type, int imap_auth_type,
    char * imap_login, char * imap_password,
    int imap_cached, char * imap_cache_directory);
     __________________________________________________________________

Example

   Example 5-1. use of storage
int main(void)
{
  struct mailstorage * storage;
  int r;

  storage = mailstorage_new(NULL);

  imap_mailstorage_init(storage, "imap.my-servers.org", 0,
    NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN,
    "my-login", "my-password", 1, "/home/login/.libetpan/cache");

  r = mailstorage_connect(storage);
  if (r == MAIL_NO_ERROR) {
    mailstorage_disconnect(storage);
  }

  mailstorage_free(storage);
}
     __________________________________________________________________

Folder

Folder driver

#include <libetpan/libetpan.h>

typedef struct mailfolder_driver mailfolder_driver;

struct mailfolder_driver {
  int (* fld_get_session)(struct mailfolder * folder,
    mailsession ** result);

  int (* fld_noop)(struct mailfolder * folder);

  int (* fld_check)(struct mailfolder * folder);

  int (* fld_expunge)(struct mailfolder * folder);

  int (* fld_status)(struct mailfolder * folder,
    uint32_t * result_messages, uint32_t * result_recent,
    uint32_t * result_unseen);

  int (* fld_append_message)(struct mailfolder * folder,
    char * message, size_t size);

  int (* fld_get_messages_list)(struct mailfolder * folder,
    struct mailmessage_list ** result);

  int (* fld_get_envelopes_list)(struct mailfolder * folder,
    struct mailmessage_list * result);

  int (* fld_get_message)(struct mailfolder * folder,
    uint32_t num, mailmessage ** result);

  int (* fld_get_message_by_uid)(struct mailfolder * folder,
    const char * uid, mailmessage ** result);
}

   XXX - this will be implemented in the future.

     * fld_get_session() will return the session this folder should use.
     * For other method, you should see the Section called Session driver.
     __________________________________________________________________

Folder

#include <libetpan/libetpan.h>

struct mailfolder {
  char * fld_pathname;
  char * fld_virtual_name;

  struct mailstorage * fld_storage;

  mailsession * fld_session;
  int fld_shared_session;
  clistiter * fld_pos;

  struct mailfolder * fld_parent;
  unsigned int fld_sibling_index;
  carray * fld_children; /* array of (struct mailfolder *) */

  void * fld_user_data;
};

     * fld_pathname is the pathname specific to the driver.
     * fld_virtual_name is the identifier of this folder. This can be
       NULL.
     * fld_storage is the storage used for this folder (see the Section
       called Storage).
     * fld_session is the session used for this folder.
     * fld_shared_session is set to 1 if the folder use the same session
       as the storage. This is used internally.
     * fld_pos is the position in the list of folders of the storage. This
       is used internally.
     * use of fld_parent, fld_sibling_index and fld_children is
       deprecated.
     * fld_user_data is a field for free use. The user can store any data
       in that field.
     __________________________________________________________________

mailfolder_new and mail_folder_free

#include <libetpan/libetpan.h>

struct mailfolder * mailfolder_new(struct mailstorage * fld_storage,
    char * fld_pathname, char * fld_virtual_name);

void mailfolder_free(struct mailfolder * folder);

   mailfolder_new() initializes a folder structure with an identifier
   (fld_virtual_name) with path name (fld_pathname). The folder will be
   owned by the given storage (fld_storage).

   mailfolder_free() free the memory used by the folder.
     __________________________________________________________________

mailfolder_connect and mailfolder_disconnect

#include <libetpan/libetpan.h>

int mailfolder_connect(struct mailfolder * folder);

void mailfolder_disconnect(struct mailfolder * folder);

   mailfolder_connect() connects the folder. This function can also be
   used to confirm that a folder connection is valid when the folder is
   already connected. When doing operations with several folders, you have
   to be sure that this function has been called before making calls on
   folder.

   mailfolder_disconnect() disconnects the folder.
     __________________________________________________________________

mailfolder_noop

#include <libetpan/libetpan.h>

int mailfolder_noop(struct mailfolder * folder);

   This function will only send noop to the mail access.
     __________________________________________________________________

mailfolder_check

#include <libetpan/libetpan.h>

int mailfolder_check(struct mailfolder * folder);

   A call to this function will save to disk the internal state of the
   selected mailbox (such as flags).
     __________________________________________________________________

mailfolder_expunge

#include <libetpan/libetpan.h>

int mailfolder_expunge(struct mailfolder * folder);

   A call to this function will delete all messages marked for deletion.
     __________________________________________________________________

mailfolder_status

int mailfolder_status(struct mailfolder * folder,
    uint32_t * result_messages, uint32_t * result_recent,
    uint32_t * result_unseen);

   A call to this function will return some counts of messages in the
   mailbox.
     __________________________________________________________________

mailfolder_append_message

int mailfolder_append_message(struct mailfolder * folder,
    char * message, size_t size);

   This function will store a new message in the given folder. The message
   is given by a string in memory (message) and a size (size).
     __________________________________________________________________

mailfolder_get_messages_list

int mailfolder_get_messages_list(struct mailfolder * folder,
    struct mailmessage_list ** result);

   This function will return the list of messages in the given folder (see
   the Section called Message list).
     __________________________________________________________________

mailfolder_get_envelopes_list

int mailfolder_get_envelopes_list(struct mailfolder * folder,
    struct mailmessage_list * result);

   This function will fill the list of parsed header fields structure in
   the mailmessage structures of the given list of messages (result).
     __________________________________________________________________

mailfolder_get_message

int mailfolder_get_message(struct mailfolder * folder,
    uint32_t num, mailmessage ** result);

   This function will return the message identified by a message index
   (num) This will return a mailmessage structure in (* result) (see the
   Section called Message).
     __________________________________________________________________

mailfolder_get_message_by_uid

int mailfolder_get_message_by_uid(struct mailfolder * folder,
    const char * uid, mailmessage ** result);

   This function will return the message identified by a unique identifier
   (uid) This will return a mailmessage structure in (* result) (see the
   Section called Message).
     __________________________________________________________________

Example

   Example 5-2. use of folder
int main(void)
{
  struct mailstorage * storage;
  int r;

  storage = mailstorage_new(NULL);

  imap_mailstorage_init(storage, "imap.my-servers.org", 0,
    NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN,
    "my-login", "my-password", 1, "/home/login/.libetpan/cache");

  r = mailstorage_connect(storage);
  if (r == MAIL_NO_ERROR) {
    struct mailfolder * folder;

    folder = mailfolder_new(storage, "INBOX", NULL);

    r = mailfolder_connect(folder);
    if (r == MAIL_NO_ERROR) {
      struct mailmessage_list * msg_list;

      mailfolder_get_messages_list(folder, &msg_list);

      /* do the things */

      mailmessage_list_free(msg_list);

      mailfolder_disconnect(folder);
    }

    mailstorage_disconnect(storage);
  }

  mailstorage_free(storage);
}
     __________________________________________________________________

Message

Message driver

#include <libetpan/libetpan.h>

struct mailmessage_driver {
  char * msg_name;

  int (* msg_initialize)(mailmessage * msg_info);

  void (* msg_uninitialize)(mailmessage * msg_info);

  void (* msg_flush)(mailmessage * msg_info);

  void (* msg_check)(mailmessage * msg_info);

  void (* msg_fetch_result_free)(mailmessage * msg_info,
                             char * msg);

  int (* msg_fetch)(mailmessage * msg_info,
                char ** result,
                size_t * result_len);

  int (* msg_fetch_header)(mailmessage * msg_info,
                       char ** result,
                       size_t * result_len);

  int (* msg_fetch_body)(mailmessage * msg_info,
                     char ** result, size_t * result_len);

  int (* msg_fetch_size)(mailmessage * msg_info,
                     size_t * result);

  int (* msg_get_bodystructure)(mailmessage * msg_info,
                            struct mailmime ** result);

  int (* msg_fetch_section)(mailmessage * msg_info,
                        struct mailmime * mime,
                        char ** result, size_t * result_len);

  int (* msg_fetch_section_header)(mailmessage * msg_info,
                               struct mailmime * mime,
                               char ** result,
                               size_t * result_len);

  int (* msg_fetch_section_mime)(mailmessage * msg_info,
                             struct mailmime * mime,
                             char ** result,
                             size_t * result_len);

  int (* msg_fetch_section_body)(mailmessage * msg_info,
                             struct mailmime * mime,
                             char ** result,
                             size_t * result_len);

  int (* msg_fetch_envelope)(mailmessage * msg_info,
                         struct mailimf_fields ** result);

  int (* msg_get_flags)(mailmessage * msg_info,
                    struct mail_flags ** result);
};

     * msg_name is the name of the driver.
     * msg_initialize() will initialize the internal message state (field
       msg_data of mailmessage structure (see the Section called Message).
     * msg_uninitialize() will free the internal message state.
     * msg_flush() will release memory used by the MIME structure of the
       message.
     * msg_check() will store the flags of the message into the session,
       so that the message can be released without the flags are lost.
     * msg_fetch_result_free() will free a string returned by any
       fetch_XXX() function.
     * msg_fetch() will fetch a message.
     * msg_fetch_header() will fetch the header fields of a message.
     * msg_fetch_body() will fetch a message without its main header.
     * msg_fetch_size() will return the size of a message.
     * msg_get_bodystructure will retrieve the MIME structure of the
       message. The returned structure must NOT be freed.
     * msg_fetch_section() will fetch the content of the section of the
       message.
     * msg_fetch_section_header() will fetch the header of a section of
       the message if the content of the section is a message.
     * msg_fetch_section_mime() will fetch the MIME header of a section of
       the message.
     * msg_fetch_section_body() will fetch the body of a section (without
       the headers) of the message if the content of the section is a
       message.
     * msg_fetch_envelope() will return a given number of parsed header
       fields.
     * msg_get_flags() will return the flags of the message. The returned
       structure must NOT be freed.
     __________________________________________________________________

Message

#include <libetpan/libetpan.h>

struct mailmessage {
  mailsession * msg_session;
  mailmessage_driver * msg_driver;
  uint32_t msg_index;
  char * msg_uid;

  size_t msg_size;
  struct mailimf_fields * msg_fields;
  struct mail_flags * msg_flags;

  int msg_resolved;
  struct mailimf_single_fields msg_single_fields;
  struct mailmime * msg_mime;

  /* internal data */

  int msg_cached;
  void * msg_data;

 /*
   msg_folder field :
   used to reference the mailfolder, this is a workaround due
   to the problem with initial conception, where folder notion
   did not exist.
 */
  void * msg_folder;
  /* user data */
  void * msg_user_data;
};

     * msg_session is the session related to the message (see the Section
       called Session).
     * msg_driver is the driver used for the message (see the Section
       called Message driver).
     * msg_index is an index to indentify the message.
     * msg_uid is the unique identifier of the message, valid accross
       disconnections.
     * msg_size is the size of the message.
     * msg_fields is the list of parsed header fields of the message. This
       can be NULL (see the Section called mailimf_fields - list of header
       fields in Chapter 3).
     * msg_flags is the flags of the message. This can be NULL (see the
       Section called Message flags).
     * msg_resolved will tell if the field msg_single_fields has been
       initialized.
     * msg_single_fields will be filled using msg_fields (see the Section
       called mailimf_single_fields - simplified fields in Chapter 3).
     * msg_mime is the MIME structure of the message. It is intialized at
       least when get_bodystructure() is called once.
     * msg_cached is 1 when the message was cached. This is used
       internally.
     * msg_data is the internal state of the message. The content depends
       on the driver.
     * msg_folder is used to reference the mailfolder, this is a
       workaround due to the problem with initial conception, where folder
       notion did not exist.
     * msg_user_data is a field for free use. The user can store any data
       in that field.
     __________________________________________________________________

mailmessage_new

#include <libetpan/libetpan.h>

mailmessage * mailmessage_new(void);

void mailmessage_free(mailmessage * info);

   mailmessage_new() will create a new message (without driver). This is
   used internally by drivers.

   mailmessage_free() will free the memory used by the given message.
     __________________________________________________________________

mailmessage_init

#include <libetpan/libetpan.h>

int mailmessage_init(mailmessage * msg_info,
                     mailsession * session,
                     mailmessage_driver * driver,
                     uint32_t index, size_t size);

   mailmessage_init() will initialize a message with a driver.

     * msg_info is the message to initialize (see the Section called
       Message).
     * session is the session related to the message (see the Section
       called Session).
     * driver is the driver to use for the message (see the Section called
       Message driver).
     * index is the index of the message.
     * size is the size of the message.
     __________________________________________________________________

mailmessage_flush

#include <libetpan/libetpan.h>

int mailmessage_flush(mailmessage * info);

   This function will release the memory used by the MIME structure of the
   message.
     __________________________________________________________________

mailmessage_check

#include <libetpan/libetpan.h>

int mailmessage_check(mailmessage * info);

   After you set some flags, if you want to notify them to the session
   before destroying the message, you can use this function.
     __________________________________________________________________

mailmessage_fetch_result_free

#include <libetpan/libetpan.h>

int mailmessage_fetch_result_free(mailmessage * msg_info,
                                  char * msg);

   This function will free a string returned by any
   mailmessage_fetch_XXX() function.
     __________________________________________________________________

mailmessage_fetch

#include <libetpan/libetpan.h>

int mailmessage_fetch(mailmessage * msg_info,
                      char ** result,
                      size_t * result_len);

   This function returns the content of the message (headers and text).
     __________________________________________________________________

mailmessage_fetch_header

#include <libetpan/libetpan.h>

int mailmessage_fetch_header(mailmessage * msg_info,
                             char ** result,
                             size_t * result_len);

   This function returns the header of the message as a string.
     __________________________________________________________________

mailmessage_fetch_body

#include <libetpan/libetpan.h>

int mailmessage_fetch_body(mailmessage * msg_info,
                           char ** result, size_t * result_len);

   This function returns the content of the message (without headers).
     __________________________________________________________________

mailmessage_fetch_size

#include <libetpan/libetpan.h>

int mailmessage_fetch_size(mailmessage * msg_info,
                           size_t * result);

   This function returns the size of the message content.
     __________________________________________________________________

mailmessage_get_bodystructure

#include <libetpan/libetpan.h>

int mailmessage_get_bodystructure(mailmessage * msg_info,
                                  struct mailmime ** result);

   This functions returns the MIME structure of the message. The returned
   information MUST not be freed by hand. It is freed by
   mailmessage_flush() or mailmessage_free() (see the Section called
   mailmime - MIME part in Chapter 4).
     __________________________________________________________________

mailmessage_fetch_section

#include <libetpan/libetpan.h>

int mailmessage_fetch_section(mailmessage * msg_info,
                              struct mailmime * mime,
                              char ** result, size_t * result_len);

   This function returns the content of a MIME part.
     __________________________________________________________________

mailmessage_fetch_section_header

#include <libetpan/libetpan.h>

int mailmessage_fetch_section_header(mailmessage * msg_info,
                                     struct mailmime * mime,
                                     char ** result,
                                     size_t * result_len);

   This function returns the header of the message contained in the given
   MIME part.
     __________________________________________________________________

mailmessage_fetch_section_mime

#include <libetpan/libetpan.h>

int mailmessage_fetch_section_mime(mailmessage * msg_info,
                                   struct mailmime * mime,
                                   char ** result,
                                   size_t * result_len);

   This function returns the MIME header of the given MIME part.
     __________________________________________________________________

mailmessage_fetch_section_body

#include <libetpan/libetpan.h>

int mailmessage_fetch_section_body(mailmessage * msg_info,
                                   struct mailmime * mime,
                                   char ** result,
                                   size_t * result_len);

   This function returns the text part of the message contained in the
   given MIME part.
     __________________________________________________________________

mailmessage_fetch_envelope

#include <libetpan/libetpan.h>

int mailmessage_fetch_envelope(mailmessage * msg_info,
                               struct mailimf_fields ** result);
     __________________________________________________________________

mailmessage_get_flags

#include <libetpan/libetpan.h>

int mailmessage_get_flags(mailmessage * msg_info,
                          struct mail_flags ** result);

   This function returns the flags related to the message. The returned
   information MUST not be freed by hand. It is freed by
   mailmessage_free().
     __________________________________________________________________

mailmessage_resolve_single_fields

#include <libetpan/libetpan.h>

void mailmessage_resolve_single_fields(mailmessage * msg_info);

   This function will use the fields information to fill the single_fields
   structure in the mailmessage structure.
     __________________________________________________________________

Message list

#include <libetpan/libetpan.h>

struct mailmessage_list {
  carray * msg_tab; /* elements are (mailmessage *) */
};

struct mailmessage_list * mailmessage_list_new(carray * msg_tab);

void mailmessage_list_free(struct mailmessage_list * env_list);

   This is a list of messages.

   msg_tab is an array containing the messages (see linkend="carray").

   mailmessage_list_new() will initialize a list of messages, using a
   given array of messages.

   mailmessage_list_free() will free the memory used by the list of
   messages. This will also free the messages.
     __________________________________________________________________

Message tree

#include <libetpan/libetpan.h>

struct mailmessage_tree {
  struct mailmessage_tree * node_parent;
  char * node_msgid;
  time_t node_date;
  mailmessage * node_msg;
  carray * node_children; /* array of (struct mailmessage_tree *) */

  /* private, used for threading */
  int node_is_reply;
  char * node_base_subject;
};


struct mailmessage_tree *
mailmessage_tree_new(char * node_msgid, time_t node_date,
    mailmessage * node_msg);

void mailmessage_tree_free(struct mailmessage_tree * tree);

void mailmessage_tree_free_recursive(struct mailmessage_tree * tree);

   This is a node of a tree of messages.

     * node_parent is the parent of this node.
     * node_msgid is the content of the field Message-ID of the message.
     * node_date is the date in UNIX format.
     * node_msg is the message of the node. The message should have the
       msg_fields field initialized.
     * node_children is the list of children of this node.
     * node_is_reply is set to 1 if the message is a reply.
     * node_base_subject is the base subject of the message (base subject
       is defined in definition of IMAP thread draft).

   mailmessage_tree_new() will initialize a message node.

   mailmessage_tree_free() will release memory used by the node. This will
   NOT free the message.
     __________________________________________________________________

Message flags

#include <libetpan/libetpan.h>

enum {
  MAIL_FLAG_NEW       = 1 << 0,
  MAIL_FLAG_SEEN      = 1 << 1,
  MAIL_FLAG_FLAGGED   = 1 << 2,
  MAIL_FLAG_DELETED   = 1 << 3,
  MAIL_FLAG_ANSWERED  = 1 << 4,
  MAIL_FLAG_FORWARDED = 1 << 5,
  MAIL_FLAG_CANCELLED = 1 << 6,
};

struct mail_flags {
  uint32_t fl_flags;
  clist * fl_extension; /* elements are (char *) */
};

struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext);

void mail_flags_free(struct mail_flags * flags);

int mail_flags_add_extension(struct mail_flags * flags,
                             char * ext_flag);

int mail_flags_remove_extension(struct mail_flags * flags,
                                char * ext_flag);

int mail_flags_has_extension(struct mail_flags * flags,
                             char * ext_flag);

   This is the structure containing the message flags.

     * fl_flags will contain the standards flags. The value will be a
       combinaison (with or binary operation) of MAIL_FLAG_XXX values.
     * fl_extension will be a list (see the Section called List in Chapter
       2) of strings representing the non-standard flags.
     __________________________________________________________________

Example

   Example 5-3. use of message
#include <libetpan/libetpan.h>

#define DEST_CHARSET "iso-8859-1"

enum {
  NO_ERROR,
  ERROR_FILE,
  ERROR_MEMORY,
  ERROR_INVAL,
  ERROR_FETCH,
};

/* returns TRUE is given MIME part is a text part */

int etpan_mime_is_text(struct mailmime * build_info)
{
  if (build_info->mm_type == MAILMIME_SINGLE) {
    if (build_info->mm_content_type != NULL) {
      if (build_info->mm_content_type->ct_type->tp_type ==
          MAILMIME_TYPE_DISCRETE_TYPE) {
        if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_t
ype ==
            MAILMIME_DISCRETE_TYPE_TEXT)
          return 1;
      }
    }
    else
      return 1;
  }

  return 0;
}


/* display content type */

int show_part_info(FILE * f,
    struct mailmime_single_fields * mime_fields,
    struct mailmime_content * content)
{
  char * description;
  char * filename;
  int col;
  int r;

  description = mime_fields->fld_description;
  filename = mime_fields->fld_disposition_filename;

  col = 0;

  r = fprintf(f, " [ Part ");
  if (r < 0)
    goto err;

  if (content != NULL) {
    r = mailmime_content_type_write(f, &col, content);
    if (r != MAILIMF_NO_ERROR)
      goto err;
  }

  if (filename != NULL) {
    r = fprintf(f, " (%s)", filename);
    if (r < 0)
      goto err;
  }

  if (description != NULL) {
    r = fprintf(f, " : %s", description);
    if (r < 0)
      goto err;
  }

  r = fprintf(f, " ]\n\n");
  if (r < 0)
    goto err;

  return NO_ERROR;

 err:
  return ERROR_FILE;
}

/* fetch message and decode if it is base64 or quoted-printable */

int etpan_fetch_message(mailmessage * msg_info,
    struct mailmime * mime_part,
    struct mailmime_single_fields * fields,
    char ** result, size_t * result_len)
{
  char * data;
  size_t len;
  int r;
  int encoding;
  char * decoded;
  size_t decoded_len;
  size_t cur_token;
  int res;
  int encoded;

  encoded = 0;

  r = mailmessage_fetch_section(msg_info,
      mime_part, &data, &len);
  if (r != MAIL_NO_ERROR) {
    res = ERROR_FETCH;
    goto err;
  }

  encoded = 1;

  /* decode message */

  if (encoded) {
    if (fields->fld_encoding != NULL)
      encoding = fields->fld_encoding->enc_type;
    else
      encoding = MAILMIME_MECHANISM_8BIT;
  }
  else {
    encoding = MAILMIME_MECHANISM_8BIT;
  }

  cur_token = 0;
  r = mailmime_part_parse(data, len, &cur_token,
                          encoding, &decoded, &decoded_len);
  if (r != MAILIMF_NO_ERROR) {
    res = ERROR_FETCH;
    goto free;
  }

  mailmessage_fetch_result_free(msg_info, data);

  * result = decoded;
  * result_len = decoded_len;

  return NO_ERROR;

 free:
  mailmessage_fetch_result_free(msg_info, data);
 err:
  return res;
}

/* fetch fields */

struct mailimf_fields * fetch_fields(mailmessage * msg_info,
    struct mailmime * mime)
{
  char * data;
  size_t len;
  int r;
  size_t cur_token;
  struct mailimf_fields * fields;

  r = mailmessage_fetch_section_header(msg_info, mime,
    &data, &len);
  if (r != MAIL_NO_ERROR)
    return NULL;

  cur_token = 0;
  r = mailimf_envelopes_fields_parse(data, len,
    &cur_token, &fields);
  if (r != MAILIMF_NO_ERROR) {
    mailmessage_fetch_result_free(msg_info, data);
    return NULL;
  }

  mailmessage_fetch_result_free(msg_info, data);

  return fields;
}

/* render message */

static int etpan_render_mime(FILE * f, mailmessage * msg_info,
    struct mailmime * mime)
{
  int r;
  clistiter * cur;
  int col;
  int text;
  int show;
  struct mailmime_single_fields fields;
  int res;

  mailmime_single_fields_init(&fields, mime->mm_mime_fields,
      mime->mm_content_type);

  text = etpan_mime_is_text(mime);

  r = show_part_info(f, &fields, mime->mm_content_type);
  if (r != NO_ERROR) {
    res = r;
    goto err;
  }

  switch(mime->mm_type) {
  case MAILMIME_SINGLE:
    show = 0;
    if (text)
      show = 1;

    if (show) {
      char * data;
      size_t len;
      char * converted;
      size_t converted_len;
      char * source_charset;
      size_t write_len;

      /* viewable part */

      r = etpan_fetch_message(msg_info, mime,
          &fields, &data, &len);
      if (r != NO_ERROR) {
        res = r;
        goto err;
      }

      source_charset = fields.fld_content_charset;
      if (source_charset == NULL)
        source_charset = DEST_CHARSET;

      r = charconv_buffer(source_charset, DEST_CHARSET,
          data, len, &converted, &converted_len);
      if (r != MAIL_CHARCONV_NO_ERROR) {

        r = fprintf(f, "[ error converting charset from %s to %s ]\n",
            source_charset, DEST_CHARSET);
          if (r < 0) {
            res = ERROR_FILE;
            goto err;
          }

          write_len = fwrite(data, 1, len, f);
          if (write_len != len) {
            mailmime_decoded_part_free(data);
            res = r;
            goto err;
          }
        }
        else {
          write_len = fwrite(converted, 1, converted_len, f);
          if (write_len != len) {
            charconv_buffer_free(converted);
            mailmime_decoded_part_free(data);
            res = r;
            goto err;
          }

          charconv_buffer_free(converted);
        }

        write_len = fwrite("\r\n\r\n", 1, 4, f);
        if (write_len < 4) {
          mailmime_decoded_part_free(data);
          res = ERROR_FILE;
          goto err;
        }

      mailmime_decoded_part_free(data);
    }
    else {
      /* not viewable part */

      r = fprintf(f, "   (not shown)\n\n");
      if (r < 0) {
        res = ERROR_FILE;
        goto err;
      }
    }

    break;

  case MAILMIME_MULTIPLE:

    if (strcasecmp(mime->mm_content_type->ct_subtype,
      "alternative") == 0) {
      struct mailmime * prefered_body;
      int prefered_score;

      /* case of multiple/alternative */

      /*
        we choose the better part,
        alternative preference :

        text/plain => score 3
        text/xxx   => score 2
        other      => score 1
      */

      prefered_body = NULL;
      prefered_score = 0;

      for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
          cur != NULL ; cur = clist_next(cur)) {
        struct mailmime * submime;
        int score;

        score = 1;
        submime = clist_content(cur);
        if (etpan_mime_is_text(submime))
          score = 2;

        if (submime->mm_content_type != NULL) {
          if (strcasecmp(submime->mm_content_type->ct_subtype,
            "plain") == 0)
            score = 3;
        }

        if (score > prefered_score) {
          prefered_score = score;
          prefered_body = submime;
        }
      }

      if (prefered_body != NULL) {
        r = etpan_render_mime(f, msg_info, prefered_body);
        if (r != NO_ERROR) {
          res = r;
          goto err;
        }
      }
    }
    else {
      for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
          cur != NULL ; cur = clist_next(cur)) {

        r = etpan_render_mime(f, msg_info, clist_content(cur));
        if (r != NO_ERROR) {
          res = r;
          goto err;
        }
      }
    }

    break;

  case MAILMIME_MESSAGE:

    if (mime->mm_data.mm_message.mm_fields != NULL) {
      struct mailimf_fields * fields;

      if (msg_info != NULL) {
        fields = fetch_fields(msg_info, mime);
        if (fields == NULL) {
          res = ERROR_FETCH;
          goto err;
        }

        col = 0;
        r = mailimf_fields_write(f, &col, fields);
        if (r != NO_ERROR) {
          mailimf_fields_free(fields);
          res = r;
          goto err;
        }

        mailimf_fields_free(fields);
      }
      else {
        col = 0;
        r = fields_write(f, &col, mime->mm_data.mm_message.mm_fields);
        if (r != NO_ERROR) {
          res = r;
          goto err;
        }
      }

      r = fprintf(f, "\r\n");
      if (r < 0) {
        res = ERROR_FILE;
        goto err;
      }
    }

    if (mime->mm_data.mm_message.mm_msg_mime != NULL) {
      r = etpan_render_mime(f, msg_info,
        mime->mm_data.mm_message.mm_msg_mime);
      if (r != NO_ERROR) {
        res = r;
        goto err;
      }
    }

    break;
  }

  return NO_ERROR;

 err:
  return res;
}



int main(void)
{
  struct mailstorage * storage;
  int r;

  storage = mailstorage_new(NULL);

  imap_mailstorage_init(storage, "imap.my-servers.org", 0,
    NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN,
    "my-login", "my-password", 1, "/home/login/.libetpan/cache");

  r = mailstorage_connect(storage);
  if (r == MAIL_NO_ERROR) {
    struct mailfolder * folder;

    folder = mailfolder_new(storage, "INBOX", NULL);

    r = mailfolder_connect(folder);
    if (r == MAIL_NO_ERROR) {
      struct mailmessage_list * msg_list;
      mailmessage * msg;

      mailfolder_get_messages_list(folder, &msg_list);

      if (carray_count(msg_list->msg_tab) > 0) {
        struct mailmime * mime;

        msg = carray_get(msg_list->msg_tab, 0);

        mailmessage_get_bodystructure(msg, &mime);

        recursive_fetch(msg, mime);

        /* do the things */

        mailmessage_flush(msg);
      }
      mailmessage_list_free(msg_list);

      mailfolder_disconnect(folder);
    }

    mailstorage_disconnect(storage);
  }

  mailstorage_free(storage);
}
     __________________________________________________________________

Session

Session driver

#include <libetpan/libetpan.h>

struct mailsession_driver {
  char * sess_name;

  int (* sess_initialize)(mailsession * session);
  void (* sess_uninitialize)(mailsession * session);

  int (* sess_parameters)(mailsession * session,
      int id, void * value);

  int (* sess_connect_stream)(mailsession * session, mailstream * s);
  int (* sess_connect_path)(mailsession * session, char * path);

  int (* sess_starttls)(mailsession * session);

  int (* sess_login)(mailsession * session, char * userid, char * password);
  int (* sess_logout)(mailsession * session);
  int (* sess_noop)(mailsession * session);

  /* folders operations */

  int (* sess_build_folder_name)(mailsession * session, char * mb,
      char * name, char ** result);

  int (* sess_create_folder)(mailsession * session, char * mb);
  int (* sess_delete_folder)(mailsession * session, char * mb);
  int (* sess_rename_folder)(mailsession * session, char * mb,
      char * new_name);
  int (* sess_check_folder)(mailsession * session);
  int (* sess_examine_folder)(mailsession * session, char * mb);
  int (* sess_select_folder)(mailsession * session, char * mb);
  int (* sess_expunge_folder)(mailsession * session);
  int (* sess_status_folder)(mailsession * session, char * mb,
      uint32_t * result_num, uint32_t * result_recent,
      uint32_t * result_unseen);
  int (* sess_messages_number)(mailsession * session, char * mb,
      uint32_t * result);
  int (* sess_recent_number)(mailsession * session, char * mb,
      uint32_t * result);
  int (* sess_unseen_number)(mailsession * session, char * mb,
      uint32_t * result);

  int (* sess_list_folders)(mailsession * session, char * mb,
      struct mail_list ** result);
  int (* sess_lsub_folders)(mailsession * session, char * mb,
      struct mail_list ** result);

  int (* sess_subscribe_folder)(mailsession * session, char * mb);
  int (* sess_unsubscribe_folder)(mailsession * session, char * mb);

  /* messages operations */

  int (* sess_append_message)(mailsession * session,
      char * message, size_t size);
  int (* sess_copy_message)(mailsession * session,
      uint32_t num, char * mb);
  int (* sess_move_message)(mailsession * session,
      uint32_t num, char * mb);

  int (* sess_get_message)(mailsession * session,
      uint32_t num, mailmessage ** result);

  int (* sess_get_message_by_uid)(mailsession * session,
      const char * uid, mailmessage ** result);

  int (* sess_get_messages_list)(mailsession * session,
      struct mailmessage_list ** result);
  int (* sess_get_envelopes_list)(mailsession * session,
      struct mailmessage_list * env_list);
  int (* sess_remove_message)(mailsession * session, uint32_t num);
};

   This is a driver for a session.

     * sess_name is the name of the driver.
     * sess_initialize() is the function that will initializes a data
       structure (field sess_data in the session) specific to the driver.
       The field data (field sess_data in the session) is the state of the
       session, the internal data structure used by the driver. It is
       called when creating the mailsession structure with
       mailsession_new().
     * sess_uninitialize() frees the structure created with
       sess_initialize()
     * sess_parameters() implements functions specific to the given mail
       access.
     * sess_connect_stream() connects a stream to the session.
     * sess_connect_path() notify a main path to the session.
     * sess_starttls() changes the current stream to a TLS stream (see the
       Section called TLS stream in Chapter 2).
     * sess_login() notifies the user and the password to authenticate to
       the session.
     * sess_logout() exits the session and closes the stream.
     * sess_noop() does no operation on the session, but it can be used to
       poll for the status of the connection.
     * sess_build_folder_name() will return an allocated string with that
       contains the complete path of the folder to create. Use of this
       method is deprecated.
     * sess_create_folder() creates the folder that corresponds to the
       given name. Use of this method is deprecated.
     * sess_delete_folder() deletes the folder that corresponds to the
       given name. Use of this method is deprecated.
     * sess_rename_folder() change the name of the folder. Use of this
       method is deprecated.
     * sess_check_folder() makes a checkpoint of the session.
     * sess_examine_folder() selects a mailbox as readonly. Use of this
       method is deprecated.
     * sess_select_folder() selects a mailbox.
     * sess_expunge_folder() deletes all messages marked \Deleted.
     * sess_status_folder() queries the status of the folder (number of
       messages, number of recent messages, number of unseen messages).
     * sess_messages_number() queries the number of messages in the
       folder.
     * sess_recent_number() queries the number of recent messages in the
       folder.
     * sess_unseen_number() queries the number of unseen messages in the
       folder.
     * sess_list_folders() returns the list of all sub-mailboxes of the
       given mailbox. Use of this method is deprecated.
     * sess_lsub_folders() returns the list of subscribed sub-mailboxes of
       the given mailbox. Use of this method is deprecated.
     * sess_subscribe_folder() subscribes to the given mailbox. Use of
       this method is deprecated.
     * sess_unsubscribe_folder() unsubscribes to the given mailbox. Use of
       this method is deprecated.
     * sess_append_message() adds a RFC 2822 message to the current given
       mailbox.
     * sess_copy_message() copies a message whose number is given to a
       given mailbox. The mailbox must be accessible from the same
       session. Use of this method is deprecated.
     * sess_move_message() moves a message whose number is given to a
       given mailbox. The mailbox must be accessible from the same
       session. Use of this method is deprecated.
     * sess_get_messages_list() returns the list of message numbers of the
       current mailbox (see the Section called Message list).
     * sess_get_envelopes_list() fills the parsed fields in the
       mailmessage structures (see the Section called Message) of the
       mailmessage_list (see the Section called Message list).
     * sess_remove_message() removes the given message from the mailbox.
       The message is permanently deleted. Use of this method is
       deprecated.
     * sess_get_message() returns a mailmessage structure (see the Section
       called Message) that corresponds to the given message number. Use
       of this method is deprecated.
     * sess_get_message_by_uid() returns a mailmessage structure (see the
       Section called Message) that corresponds to the given message
       unique identifier.

   mandatory functions are the following :

     * sess_connect_stream() or connect_path()
     * sess_logout()
     * sess_get_messages_list()
     * sess_get_envelopes_list()

   we advise you to implement these functions :

     * sess_select_folder() (in case a session can access several
       folders).
     * sess_noop() (to check if the server is responding)
     * sess_check_folder() (to make a checkpoint of the session)
     * sess_status_folder(), sess_messages_number(), sess_recent_number(),
       sess_unseen_number() (to get stat of the folder)
     * sess_append_message() (but can't be done in the case of POP3 at
       least).
     * sess_login() in a case of an authenticated driver.
     * sess_starttls() in a case of a stream driver, if the procotol
       supports STARTTLS.
     * sess_get_message_by_uid() so that the application can remember the
       messages by UID and build its own list of messages.
     * Everything that is specific to the driver will be implemented in
       sess_parameters().
     __________________________________________________________________

Session

#include <libetpan/libetpan.h>

struct mailsession {
  void * sess_data;
  mailsession_driver * sess_driver;
};

mailsession * mailsession_new(mailsession_driver * sess_driver);

void mailsession_free(mailsession * session);

   This is a session. This is an abstraction used to access the storage,
   using the network or the filesystem.

     * sess_data is the state of the session. This is specific to the
       driver.
     * sess_driver is the driver of the session.

   mailsession_new() will create a new session using the given driver
   (sess_driver).

   mailsession_free() will release the memory used by the session.
     __________________________________________________________________

mailsession_parameters

#include <libetpan/libetpan.h>

int mailsession_parameters(mailsession * session,
                           int id, void * value);

   This function make calls specific to the driver
     __________________________________________________________________

mailsession_connect_stream

#include <libetpan/libetpan.h>

int mailsession_connect_stream(mailsession * session, mailstream * s);

   There are drivers of two kinds : stream drivers (driver that connects
   to servers through TCP or other means of connection) and file drivers
   (driver that are based on filesystem) This function can only be used by
   stream drivers and this connects a stream to the session
     __________________________________________________________________

mailsession_connect_path

#include <libetpan/libetpan.h>

int mailsession_connect_path(mailsession * session, char * path);

   This function can only be used by file drivers and selects the main
   path of the session.
     __________________________________________________________________

mailsession_starttls

#include <libetpan/libetpan.h>

int mailsession_starttls(mailsession * session);

   This switches the current connection to TLS (secure layer). This will
   only work with stream drivers.
     __________________________________________________________________

mailsession_login

#include <libetpan/libetpan.h>

int mailsession_login(mailsession * session,
                      char * userid, char * password);

   This notifies the login and the password to authenticate to the
   session.
     __________________________________________________________________

mailsession_logout

#include <libetpan/libetpan.h>

int mailsession_logout(mailsession * session);

   This function disconnects the session and closes the stream.
     __________________________________________________________________

mailsession_noop

#include <libetpan/libetpan.h>

int mailsession_noop(mailsession * session);

   This function does no operation on the session, but it can be used to
   poll for the status of the connection.
     __________________________________________________________________

mailsession_check_folder

#include <libetpan/libetpan.h>

int mailsession_check_folder(mailsession * session);

   This function makes a checkpoint of the session.
     __________________________________________________________________

mailsession_select_folder

#include <libetpan/libetpan.h>

int mailsession_select_folder(mailsession * session, char * mb);

   This function selects a mailbox.
     __________________________________________________________________

mailsession_expunge_folder

#include <libetpan/libetpan.h>

int mailsession_expunge_folder(mailsession * session);

   This function deletes all messages marked for deletion.
     __________________________________________________________________

mailsession_status_folder

#include <libetpan/libetpan.h>

int mailsession_status_folder(mailsession * session, char * mb,
    uint32_t * result_messages, uint32_t * result_recent,
    uint32_t * result_unseen);

   This function queries the status of the folder (number of messages,
   number of recent messages, number of unseen messages).
     __________________________________________________________________

mailsession_messages_number

#include <libetpan/libetpan.h>

int mailsession_messages_number(mailsession * session, char * mb,
                                uint32_t * result);

   This function queries the number of messages in the folder.
     __________________________________________________________________

mailsession_recent_number

#include <libetpan/libetpan.h>

int mailsession_recent_number(mailsession * session,
                              char * mb, uint32_t * result);

   This function queries the number of recent messages in the folder.
     __________________________________________________________________

mailsession_unseen_number

#include <libetpan/libetpan.h>

int mailsession_unseen_number(mailsession * session, char * mb,
                              uint32_t * result);

   This function queries the number of unseen messages in the folder.
     __________________________________________________________________

mailsession_append_message

#include <libetpan/libetpan.h>

int mailsession_append_message(mailsession * session,
                               char * message, size_t size);

   This adds a RFC 2822 message to the current mailbox.
     __________________________________________________________________

mailsession_get_messages_list

#include <libetpan/libetpan.h>

int mailsession_get_messages_list(mailsession * session,
                                  struct mailmessage_list ** result);

   This function returns the list of messages of the current mailbox.
     __________________________________________________________________

mailsession_get_envelopes_list

#include <libetpan/libetpan.h>

int mailsession_get_envelopes_list(mailsession * session,
                                   struct mailmessage_list * result);

   This function fills the parsed fields in the mailmessage structures
   (see the Section called Message) of the mailmessage_list (see the
   Section called Message list).
     __________________________________________________________________

mailsession_get_message

#include <libetpan/libetpan.h>

int mailsession_get_message(mailsession * session,
                            uint32_t num, mailmessage ** result);

   This function returns a mailmessage (see the Section called Message)
   structure that corresponds to the given message number.

   Warning

   mailsession_get_message_by_uid() should be used instead.
     __________________________________________________________________

mailsession_get_message_by_uid

#include <libetpan/libetpan.h>

int mailsession_get_message_by_uid(mailsession * session,
    const char * uid, mailmessage ** result);

   This function returns a mailmessage structure that corresponds to the
   given message unique identifier. This is currently implemented only for
   cached drivers.

   Warning

   That deprecates the use of mailsession_get_message().
