libpostal is a mail library.
What more can be said? libpostal is intended to handle all variety of mail access and processing tasks, with a current concentration on reading from and (for thost that support it) writing to various mail storage formats. We currently have a very workable POP3 implementation, a reasonably complete (though rough around the edges) mbox implementation, and a similarly complete-though-rough Maildir implementation.
The current ongoing thrust is to improve the robustness of the extant parts of the library, with better error handling and memory management, as well as algorithmic work on the actual functional code. Then, down the line, we have our eyes on formats like MH folders, IMAP, and possibly more esoteric formats and protocols like MAPI etc.
The current section in development is libpost_raw. This is the 'raw' interfaces to the mbox's, POP servers, etc. Later, we plan to write a more 'refined' interface, with a full abstraction, where after opening a 'mailbox connection', you don't have to worry about what kind of connection it is, just what you want to do with it. But, that's for the future. First things first.
This document is currently a combination of a documentation of libpostal's interfaces (i.e., "Programming using libpostal"), and of its structure and internals (i.e., "Developing libpostal"). Eventually, these will probably be split into two seperate documents. For now, just take note that certain data structures and functions are 'private', and intended for internal usage only. These structures/functions are *NOT* specified or prototyped in the public header file, so attempting to use them should cause compilation errors, unless you have such warnings turned off. Data types or functions in this document which are intended to be private have a notice after their short description saying so. See, for instance, postal_flock() .
Also, bear in mind that all data structures are intended to be opaque. No program using libpostal should ever mess around inside the structures, their contents are provided only for instructional purposes, and are subject to change. A set of macros are currently provided (though undocumented, except in the sample/test programs and the header file) for such access; these will be replaced down the road by full functions, to provide a little more security against API changes.
Note: libpostal is currently still in a fairly early development phase. We don't recommend using it for Real Work (tm) as of yet. Current releases are all intended for developers to use as reference bases, or for the world at large to use to see what we're doing and where we're going. Until our first true release (i.e., Version 1.0), all API's described here are subject to possible change. You've Been Warned.
Note:
Use the postal_free_conn() function to free the memory associated with this datatype, and the postal_alloc_conn() function to allocate and initialize the structure.
Note:
Use the postal_free_msg() function to free the memory associated with this datatype, and the postal_alloc_msg() function to allocate and initialize the structure.
Note:
Use the postal_alloc_msggroup() function to initialize this structure. Use the postal_free_msggroup() function to free the memory associated with this datatype.
Note:
This is used as a member of the ->loc union in the POSTAL_MSG structure.
Use the maildir_free_mdmsg() function to free the memory associated with this datatype, and the maildir_alloc_mdmsg() function to allocate and initialize the structure.
Note:
Use the pop_free_retlist() function to free the memory associated with this datatype.
Note:
This is subject to inherent race conditions, since you have no guarantee that no new mail has been delivered since you queried, unless the POP server itself locks the mailbox and keeps a static view of what's in it throughout the POP session (most do).
Use the pop_free_retstat() function to free the memory associated with this datatype.
Note:
This is used as a member of the ->spec union in the POSTAL_CONN structure.
Use the mbox_free_spec() function to free the memory associated with this datatype, and the mbox_alloc_spec() function to allocate and initialize the structure.
Note:
This is used as a member of the ->spec union in the POSTAL_CONN structure.
Use the maildir_free_spec() function to free the memory associated with this datatype, and the maildir_alloc_spec() function to allocate and initialize the structure.
Note:
This is used as a member of the ->spec union in the POSTAL_CONN structure.
Use the pop_free_spec() function to free the memory associated with this datatype, and the pop_alloc_spec() function to allocate and initialize the structure.
This datatype is intended for internal use only
Note:
This is used slightly differently in the normal and pthreads variants of the library, but in neither case should it ever be touched directly. If you're setting values in it (which should only happen inside the library), use postal_err_set() . If you're checking errors from a user program, use postal_errno() and postal_errstr() . Never manipulate, extern, declare, or otherwise use this datatype.
Takes a message and a header line, and adds that header line into the header section of the message.
Note that this does no duplicate checking or any other similar things. It just adds the header onto the end of the header block.
int
Returns 0 on success. Returns -1 on error.
Allocate and initialize a POSTAL_MSG_GROUP for use by the program.
Remember to use the postal_free_msggroup() function to free the structure when you're done with it.
Returns a pointer to an initialized POSTAL_MSG_GROUP on success. Returns NULL on failure.
Takes a message, a header name, and a header content. Finds the current instance (or the first current, if more than one) of that header, and adjusts its content to the supplied value.
NOTE: The hdr argument should include the terminating colon, but no space after it. Thus, "From:", but not "From" or "From: ".
NOTE: This function only works with headers that already exist. If the header doesn't exist, use postal_add_header() .
int
Returns 0 on success. Returns -1 on error.
Takes a message and a header line, and deletes that header line from the header section of the message.
Note that this does no duplicate checking or any other similar things. It just deletes the first instance of the specified header.
int
Returns 0 on success. Returns -1 on error.
Returns a numeric code representing the last error encountered inside the library. This is the moral equivalent of C's errno facility. If no error has occured, its value is indeterminate.
unsigned int
Returns a numeric error code. See individual functions for descriptions of what error codes each may set.
Sometimes an error may have additional information available in a freeform string. If so, this function will return it. If no error has occured, or no string value has been set for an error, the value is indeterminate.
In practice, this is rarely set, and even more rarely of any real use to anybody. This is provided because occasionally there might be a gem, and in the future we might want to expand use of this. Right now, unless you're really anal, it's probably never worth calling this function.
const char *
If a string error has been set, return a pointer to it. If not, return NULL.
NOTE: Do NOT attempt to free() or otherwise manipulate the string returned. It's the private property of postal_errstr() . Read from it, or use it as the source of a strdup() or strcpy() or in a printf() format string, fine. Try to write into it or free() it or realloc() it or some such, and goblins will hunt you down and kill you in your sleep. Or your program will SIGBUS and laugh at you. Whichever.
Takes a POSTAL_MSG_GROUP structure and free() 's all its component parts.
void
Searches through the given headers for the requested header and returns its contents.
NOTE: The hdr argument should include the terminating colon, but no space after it. Thus, "From:", but not "From" or "From: ".
char *
If the header is found, a string is returned containing the contents of the header.
Example:
(headers)
...
From: Me <me@some.where>
...
(end)
postal_get_header(msg->header, "From:") will return a
string containing "Me <me@some.where>".
If the requested header is not found, NULL will be returned and the error code will be set to POSTAL_E_NOERR. If some other error occurs, NULL will be returned and the error code set to something else.
Setup necessary bits and pieces for a thread in a pthreads-enabled process using libpostal. This is only available in the pthreads variant of the library. This function (and the pthreads variant itself) should only be used when you're using libpostal functions in multiple threads simultaneously, in which case it will keep them from stomping on each other's error messages.
This function should be called once in the process, before any threads using libpostal are spawned off. See also postal_pthread_thread_init() and postal_pthread_thread_fini() .
int
Returns 0 on success. Returns -1 on error (errors come from pthread_key_create() )
Destroy necessary bits and pieces for a thread in a pthreads-enabled process using libpostal. This is only available in the pthreads variant of the library. This function (and the pthreads variant itself) should only be used when you're using libpostal functions in multiple threads simultaneously, in which case it will keep them from stomping on each other's error messages.
This function should be called once in each thread using libpostal functions, after finished calling any of them. If you fail to call this function before destroying the thread, you'll leak memory. See also postal_pthread_thread_init() .
void
Setup necessary bits and pieces for a pthreads-enabled process using libpostal. This is only available in the pthreads variant of the library. This function (and the pthreads variant itself) should only be used when you're using libpostal functions in multiple threads simultaneously, in which case it will keep them from stomping on each other's error messages.
This function should be called once in each thread using libpostal functions, because any of them are called. See also postal_pthread_thread_fini() .
int
Returns 0 on success. Returns -1 on error from malloc() . Returns -2 on error from pthread_setspecific() .
Takes a message, a header name, and a header content. Searches through the headers of the message; if header already exists, call postal_change_header() to change it to the given value. If header doesn't exist, call postal_add_header() to add the value in.
NOTE: The hdr argument should include the terminating colon, but no space after it. Thus, "From:", but not "From" or "From: ".
int
Returns 0 on success. Returns non-zero on error (no current cases).
Note:
postal_set_header() can also fail and return any error codes specified for postal_get_header() or postal_add_header()
An error number from postal_errno() is precise, but not too descriptive. This function lets you get a more useful string out of it for presenting to a user. It's the moral equivalent of your system's strerror() function.
const char *
A string describing the error.
NOTE: Do NOT attempt to free() or otherwise manipulate the string returned.
This function is passed an open maildir connection structure. It free() 's the memory associated with the structure. The obvious counterpart to maildir_open() .
void
This function takes a filesystem location as an argument, and constructs (if possible) a full valid Maildir there.
int
0 if successful. -1 on error.
This function retrieves a given message from a Maildir.
The message to get is determined by a combination of the Maildir currently open in the given POSTAL_CONN , and the individual file indicated in the POSTAL_MSG .
This function is called internally by maildir_get_message_all() when called in GET_HEADER or GET_BODY modes. You can also call this function directly using a POSTAL_MSG populated either manually (tricky!) or by a previous call to maildir_get_message_all() in GET_OFFSET or similar mode.
int
0 on success. -1 on error.
This function retrieves all messages from a Maildir.
This functions works by calling the postal_list_dir() function, then iteratively calling maildir_get_message() for each message in the Maildir, cur/ and then new/.
However, if called in GET_OFFSET mode, it will only create and populate the POSTAL_MSG_GROUP within the open POSTAL_CONN for the Maildir in question, and not call maildir_get_message() for it. When called in this mode, the POSTAL_MSG items created in the POSTAL_MSG_GROUP can be used for later direct calls to maildir_get_message() .
long
Number of messages retrieved on success. -1 on error.
Note:
maildir_get_message_all() may also fail and set an error for any of the codes listed for postal_list_dir() , maildir_get_message() , maildir_msg_filename_dissect() , or postal_alloc_msg() .
This function allows getting the 'status' of a message
from a Maildir. It currently supports the following
statae:
STATUS_NULL: Error (no message, uninitialized status,
etc
STATUS_NEW: A new message
STATUS_OLD: A not-new message
STATUS_READ: A message that has been 'read'
STATUS_REPLIED: A message that has been replied to
The precise meanings of these flags will vary depending on
the mail client's precise semantics.
The value returned is a bitmask, based on which flags are
set. So, to test for 'read' status, you'd use a construct
like:
status = maildir_get_status(msg);
if( (status & STATUS_READ) )
/* Message is read */
The calling and returning semantics of this function are intentionally nigh-on identical to those of the mbox_get_status() function.
int
Returns a bitmask of the statae that exist on the message. Returns -1 on error.
This function opens (and verified) a Maildir as a POSTAL_CONN connection.
If the 'create' argument is 1, maildir_open() will call maildir_create() internally to create the Maildir. Otherwise, it will return an error if the Maildir isn't pre-created.
Populated POSTAL_CONN structure on success. NULL on error
Note:
maildir_open() may also fail and set an error for any of the codes listed for maildir_create() .
Writes a given message into a given Maildir connection.
This function internally double-checks things like \r\n translation. This doesn't mean you should rely on it doing those things for you; just that it double-checks.
It also handles changing around filenames for status changes, size changes, and all that jazz. You SHOULD rely on it to do that; don't mess with the internals yourself!
int
0 on success. -1 on error.
Note:
maildir_write_msg() can also fail and return any error codes specified for postal_whack_cr() , postal_del_header() , postal_set_header() , postal_get_header() , maildir_msg_filename_construct() , maildir_msg_filename_dissect() , maildir_status2info() .
This function is passed an open mbox connection structure. It flushes and closes all associated files, and free() 's the memory associated with the structure.
void
This function is used after a mbox has been scanned, and you've gotten a POSTAL_MSG partially populated, with at least an offset, and possibly the headers, of a message. It then retrieves the headers (and possibly the body, depending on what you request) for the associated message.
It's also used internally by the mbox_get_message_next() function to get messages by faking up a previously-grabbed message structure. Don't try this at home, kids.
Its primary use is to MUA's which will, for instance, scan a mbox and get the offsets and headers for each message (to build a list and have a message 'index'), but will NOT load the bodies of the messages for memory usage purposes. mbox_get_message() can be used to then quickly grab the body of a given message.
What the function grabs depends on the contents of the
get_type argument. It should be one of the following:
GET_HEADER: Get the header of the message
GET_BODY: Get the body (and header) of the message
Each type includes the type before, so GET_HEADER will get
offsets as well, and GET_BODY will also gets offsets and
headers. If the get_type specifies to get a portion of the
message that already exists in the passed message structure,
the old contents will be overwritten.
Note: This is a very simplistic function as things currently stand. It has no real provisions for handling the mbox having changed out from under it since the POSTAL_MSG structure was originally populated. We'll be making a slightly more all-encompassing method of handling this somewhere down the road. mbox's suck.
int
0 if successful. -1 on error.
Note:
mbox_get_message() can also fail and return any error codes specified for postal_get_header() or mbox_get_status() .
mbox_get_message_all() is passed an open mbox connection. It retrieves all the messages in that mbox, and puts them in the POSTAL_CONN that it's passed. Depending on the value of the get_type argument, the POSTAL_MSG_GROUP may contain just the offsets of each message, offsets and headers, or the offsets, header, and full body.
long
Returns the number of messages read, or -1 on error.
Note:
mbox_get_message_all() can also fail and return any error codes specified for postal_get_header() , postal_alloc_msg() , or mbox_get_status() .
This function currently assumes that the current 'position' in the mbox is the beginning of a new message. We should probably fix that.
This function retrieves and returns the 'next' message in the mbox. It uses the mbox_get_message() function on the backend to do the actual work.
What the function grabs depends on the contents of the
get_type argument. It should be one of the following:
GET_OFFSET: Get the offsets of each message
GET_HEADER: Get the header of the message
GET_BODY: Get the body of the message
Each type includes the type before, so GET_HEADER will get
offsets as well, and GET_BODY will also gets offsets and
headers.
Returns a populated POSTAL_MSG structure on success. Returns NULL on error.
Note:
mbox_get_message_next() can also fail and return any error codes specified for mbox_get_message() .
This function allows getting the 'status' of a message in
a mbox. It currently supports the following statae:
STATUS_OLD: A not-new message
STATUS_READ: A message that has been 'read'
STATUS_REPLIED: A message that has been replied to
The precise meanings of these flags will vary depending on
the mail client's precise semantics.
The value returned is a bitmask, based on which flags are
set. So, to test for 'read' status, you'd use a construct
like:
status = mbox_get_status(msg);
if( (status & STATUS_READ) )
/* Message is read */
int
Returns a bitmask of the statae that exist on the message. Returns -1 on error.
Note:
mbox_get_status() can also fail and return any error codes specified for postal_get_header() .
Well, just what it says, for cryin' out loud. Open a file as a mbox connection, and prepare it for whatever we're going to do to it. The position is set to the beginning of the file.
The file can be opened with either OPEN_READONLY or OPEN_READWRITE as the method flag. If the file is not opened READWRITE, it will be created if it doesn't already exist. In the future, checks may be added to double-check that a pre-existing file is really in mbox format.
Currently, there are 3 locktypes implemented: LOCK_FLOCK, LOCK_DOTLOCK, and LOCK_FCNTL. They do pretty much what you'd expect them to do. Further, there is an additional locktype, LOCK_DEFAULT, which defines a sort of default. If you don't have a specific reason to need whatever it is that you need, use LOCK_DEFAULT (which currently applies LOCK_FCNTL and LOCK_DOTLOCK).
Returns a populated POSTAL_CONN structure for the mbox connection on success. Returns NULL on failure.
Note:
mbox_open_file() can also fail and return any error codes specified for mbox_lock_read() or mbox_lock_write() .
Writes a given message into a given mbox connection.
Currently, there are two choices of location:
POS_CUR: The current position
POS_END: End of file
This function internally double-checks things like \r\n translation, and the derivation of the From_ line. This doesn't mean you should rely on the function doing those things for you; just that it double-checks.
int
0 if successful. -1 on error.
Note:
mbox_write_msg() can also fail and return any error codes specified for mbox_derive_from() , mbox_set_conlen() , mbox_set_status() , postal_whack_cr() , or postal_alloc_msg() .
This function handles all the goobleygook involved in closing an active POP3 mailbox connection. It closes the appropriate network connection nicely (i.e., a real logout, not just a close() ), and free() 's all memory resources associated with it.
void
This is the normal entry point to connect to a POP server. It accepts a hostname to connect to, and a username/password pair for authentication.
It internally does a hostname lookup, and calls the pop_network_connect() and pop_login() functions to do the grunt work of connecting and authenticating.
Populated POSTAL_CONN structure if successful. NULL on failure.
Note:
pop_connect() may also fail and set errors for any of the reasons listed in pop_network_connect() or pop_login() .
Uses the POP3 'DELE' command to delete a message from the POP server.
int
Returns 0 on success. Returns -1 on error.
Note:
pop_dele() may fail and set errors for any of the reasons listed in pop_answer_check() .
POP_RET_LIST is the data type returned by the pop_list() function, containing the data from a POP 'LIST' command. This function free() 's all the memory associated with that returned info.
void
Free the resources associated with the given POP_RET_STAT data structure.
void
Run a POP 'LIST' query, and sort the results into a POP_RET_LIST structure.
Note that this returned structure should be freed with the pop_free_retlist() function when its usefullness has come to an end.
Returns a POP_RET_LIST structure containing the results of the POP 'LIST' command. Returns NULL on error
This function handles the 'login' procedure to an already-connected POP server. It does *NOT* do lookups, or even connect() to the server.
This is INTENDED only to be used internally by the pop_connect() function, and not to be called directly, along with the pop_network_connect() function. However, this have been set as exported functions so that, in case a user of the library REALLY needs the extra flexibility, the functions are available seperately.
int
Returns 0 on success. Returns -1 on error.
Note:
pop_login() may fail and set errors for any of the reasons listed in pop_answer_check() .
This function connects to a specified POP server, but does NOT do any sort of authentication.
Like the pop_login() function, this is INTENDED only to be used internally by the pop_connect() function, and not to be called directly. However, this have been set as exported functions so that, in case a user of the library REALLY needs the extra flexibility, the functions are available seperately.
Returns a created POSTAL_CONN structure pointing at the created connection if successful. Returns NULL on error.
Note:
pop_network_connect() may also fail and set errors for any of the reasons listed in postal_get_line() , pop_answer_check() .
Retrieve a message from a POP server and parse it out into a POSTAL_MSG structure.
Returns a parsed-out POSTAL_MSG containing the requested message from the POP server. Returns NULL on error.
Note:
pop_retr() may also fail and set errors for any of the reasons listed in postal_alloc_msg() .
Retrieve all messages (and optionally delete them) from a POP server. Set the 'dele' argument to 1 to delete messages, 0 to not. Build a POSTAL_MSG_GROUP for the results.
Returns a parsed-out POSTAL_MSG_GROUP containing the requested message from the POP server. Returns NULL on error.
Note:
pop_retr_all() may also fail and set errors for any of the reasons listed in pop_dele() , pop_stat() , or pop_retr() .
This function runs the POP3 'STAT' request, and returns the results, which contains the number of messages waiting on the server, and the total size of the messages.
The returned data is in a POP_RET_STAT structure. You should use pop_free_retstat() to free up the memory used by the structure when you're finished with it.
Returns a populated POP_RET_STAT with the results of the 'STAT' query. Returns NULL on error.
This function is intended for internal use only
Allocate and initialize a POSTAL_CONN for use by the program.
Remember to use the postal_free_conn() function to free the structure when you're done with it.
Returns a pointer to an initialized POSTAL_CONN on success. Returns NULL on failure.
This function is intended for internal use only
Allocate and initialize a POSTAL_MSG for use by the program.
Remember to use the postal_free_msg() function to free the structure when you're done with it.
Returns a pointer to an initialized POSTAL_MSG on success. Returns NULL on failure.
This function is intended for internal use only
This function performs the equivalent of strstr() in a case-insensitive manner.
FreeBSD (and probably several other systems) have a strcasestr() function in libc to do this, but not all systems have it. The implementation provided here is derived from the FreeBSD version.
char *
Returns big if little is an empty string. Returns NULL if little occurs nowhere in big. Otherwise, returns a pointer to the first character of the first occurance of little within big.
This function is intended for internal use only
This is a general-purpose function to apply a dotlock-style lock to a file.
It uses non-blocking locks, attempts a certain number (default 5) of times, with a certain pause between attempts (default 1 second). These numbers are hard-coded in global variables; we really need to come up with a better way of doing it if we're going to ever be thread-safe.
The lock type should be either LOCK_SH for 'shared', or LOCK_EX for 'exclusive'.
int
Returns 0 on success. Returns -1 on error.
If an error is returned, no locks are applied to the file.
This function is intended for internal use only
This function allows you to set a numeric error code which will be readable by a higher level function, either part of libpostal, or part of a user program. This information will be accessed via postal_errno() and postal_errstr() .
It's the moral equivalent of C's errno facility.
Note that in the pthreads variant of the library (append '_pthread' to the lib name), this uses thread-specific data fields, so you can use libpostal functions in multiple threads at once and they won't stomp on each other's error codes. See postal_pthread_init() , postal_pthread_thread_init() , and postal_pthread_thread_fini() for details on the pthreads interface.
void
This function is intended for internal use only
This is a general-purpose function to apply a fcntl() -style lock to a file.
It uses non-blocking locks, attempts a certain number (default 5) of times, with a certain pause between attempts (default 1 second). These numbers are hard-coded in global variables; we really need to come up with a better way of doing it if we're going to ever be thread-safe.
The lock type should be either LOCK_SH for 'shared', or LOCK_EX for 'exclusive'.
int
Returns 0 on success. Returns -1 on error.
If an error is returned, no locks are applied to the file.
This function is intended for internal use only
This is a general-purpose function to apply a flock() -style lock to a file.
It uses non-blocking locks, attempts a certain number (default 5) of times, with a certain pause between attempts (default 1 second). These numbers are hard-coded in global variables; we really need to come up with a better way of doing it if we're going to ever be thread-safe.
The lock type should be one of the types defined in the manpage for flock() . To wit, either LOCK_SH for 'shared', or LOCK_EX for 'exclusive'.
int
Returns 0 on success. Returns -1 on error.
If an error is returned, no locks are applied to the file.
This function is intended for internal use only
This function is given a socket descriptor, and flushes the input until a newline (\n) is reached.
int
Returns 0 on success. Returns -1 on failure.
This function is intended for internal use only
Takes a char ** and free() 's all its component parts.
The char ** is required to be constructed so that it has a NULL entry as its 'last' item, with no NULL's prior to that, or it'll leak some memory.
void
This function is intended for internal use only
Takes a POSTAL_CONN structure and free() 's all its component parts.
void
This function is intended for internal use only
Takes a POSTAL_MSG structure and free() 's all its component parts.
void
This function is intended for internal use only
This function will read from a socket until it gets a newline, or until the specified character limit is reached, whichever occurs first.
Be careful that the buffer you give it will hold the number of characters you specify, since otherwise you can overflow your buffer.
int
Returns 0 if specified length exceeded, or amount read if newline found. Returns -1 on error.
This function is intended for internal use only
Flips through the given directory, and assembles a list of the files in it.
The returned list contains only regular files (no directories, sockets, devices, symlinks, etc). It also does not recurse through any subdirectories.
The returned char ** should be free() 'd using the postal_free_charpp() function.
char **
A list of the regular files found in the directory. If no files are found, return NULL and set postal_errno() to POSTAL_E_NOERR. If error occurs, return NULL with an error set as below.
This function is intended for internal use only
This is used to translate network-style (or DOS-style) \r\n line-terminators to Unix-style \n's.
A new buffer is allocated for the returned string. Note that this function does *NOT*, however, free() the string it's fed to process.
char *
Returns a string with all \r\n's in the input string translated to \n's. Returns NULL on failure.
This function is intended for internal use only
Allocate and initialize a MAILDIR_MSG for use by the program.
Remember to use the maildir_free_mdmsg() function to free the structure when you're done with it.
Returns a pointer to an initialized MAILDIR_MSG on success. Returns NULL on failure.
This function is intended for internal use only
Allocate and initialize a SPEC_MDIR for use by the program.
Remember to use the maildir_free_spec() function to free the structure when you're done with it.
Returns a pointer to an initialized SPEC_MDIR on success. Returns NULL on failure.
This function is intended for internal use only
Takes a MAILDIR_MSG structure and free() 's all its component parts.
void
This function is intended for internal use only
This function is intended for internal use only
Take in a MAILDIR_MSG structure containing a message in a Maildir. Build up the filename element from the other elements in the structure (unique, info, etc).
int
0 for no error. -1 for error.
This function is intended for internal use only
Take in a MAILDIR_MSG structure containing the filename and location of a message in a Maildir. Populate the other fields of the structure with info derived from the filename (i.e., the 'unique' and 'info' fields, and any other future subdivisions).
int
0 for no error. -1 for error.
This function is intended for internal use only
This function returns a string of an 'info' filename segment corresponding to the given message status.
char *
Proper 'info' filename segment (Example: "2,RS" for replied-to-and-seen). NULL with postal_errno() set to POSTAL_E_NOERR if no info string necessary. NULL on error.
This function is intended for internal use only
Allocate and initialize a SPEC_MBOX for use by the program.
Remember to use the mbox_free_spec() function to free the structure when you're done with it.
Returns a pointer to an initialized SPEC_MBOX on success. Returns NULL on failure.
This function is intended for internal use only
This function takes the header section of a mail message, and (if necessary) derives the mbox-style From_ header for it. It uses a number of reasonably intelligent heuristics to make the 'best guess' it can at what the header should be.
Note that the argument is a doubly-dereferenced pointer. This is necessary because adding a From_ header will increase the size of the string that stores the header, which means that it will (probably) need a new block of memory to hold the increased size. The old storage area will be free() 'd internally.
int
0 on success. -1 on error.
This function is intended for internal use only
This function is intended for internal use only
Locks the designated mbox file for reading (i.e., "shared").
int
Returns 0 if successful. Returns -1 if errors were encountered.
If an error is encountered, then any locks which did succeed were released before returning.
Note:
mbox_lock_read() may fail and set errors for any of the reasons listed in postal_flock() , postal_dotlock() , or postal_fcntl_lock() , depending on the locking mechanisms requested.
This function is intended for internal use only
Locks the designated mbox file for writing (i.e., "exclusive").
int
Returns 0 if successful. Returns -1 if errors were encountered.
If an error is encountered, then any locks which did succeed were released before returning.
Note:
mbox_lock_write() may fail and set errors for any of the reasons listed in postal_flock() , postal_dotlock() , or postal_fcntl_lock() , depending on the locking mechanisms requested.
This function is intended for internal use only
Prepares the given message to be written into a mbox by setting (or correcting) the Content-Length: header.
int
0 if successful. -1 on error.
Note:
mbox_set_conlen() may fail and set errors for any of the reasons listed in postal_set_header() .
This function is intended for internal use only
Updates the status information given in the headers of the message to match what's been set to be the new status in the POSTAL_MSG structure.
This is done from within mbox_write_msg() to bring things into line before the message is commited to disk. It should be used anytime a message with status information stored mbox-style in the headers is committed to stable storage.
int
0 on success. -1 on error.
Note:
mbox_set_conlen() may fail and set errors for any of the reasons listed in postal_del_header() or postal_set_header() .
This function is intended for internal use only
Remove any and all locks applied to a mbox connection.
int
Returns 0 on success. Returns -1 on failure to unlock.
If this returns an error, the locking may be in an indeterminate state. Bend over and kiss your ass goodbye.
Note:
mbox_unlock() may fail and set errors for any of the reasons listed in postal_flock() , postal_dotlock() , postal_fcntl_lock() , depending on the locking mechanisms used.
This function is intended for internal use only
Check a candidate From_ line with some simple heuristics to determine if it really IS a From_ line.
int
Returns 0 if From_ is valid (according to our heuristics). Returns -1 if invalid.
This function is intended for internal use only
Allocate and initialize a SPEC_POP for use by the program.
Remember to use the pop_free_spec() function to free the structure when you're done with it.
SPEC_POP *
Returns a pointer to an initialized SPEC_POP on success. Returns NULL on failure.
This function is intended for internal use only
This function checks whether the response from the server to the previously sent command was affirmative or negative.
int
Returns 0 if the response is affirmative ("OK"). Returns -1 if the answer is negative or error occured
This function is intended for internal use only
This function is intended for internal use only
This closes a POP server connection in the quickest and dirtiest way possible. Never use it unless you're backed into a corner with error situations. pop_close() is a *MUCH* better way to close a connection.
This function will also free the memory used by the POSTAL_CONN structure you hand it.
void