| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
4.1 Framework The Core Library. 4.2 Authentication Library Auxiliary Library for Authenticating Users. 4.3 Mailutils to Scheme Interface 4.4 Sieve Library GNU Implementation of Sieve Mail Filtering.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
4.1.1 Folder 4.1.2 Mailbox 4.1.3 Mailer Protocol Used to Send Mail. 4.1.4 Message 4.1.5 Envelope 4.1.6 Headers 4.1.7 Body 4.1.8 Attribute 4.1.9 Stream 4.1.10 Iterator 4.1.11 Authenticator 4.1.12 Address 4.1.13 Locker 4.1.14 URL Uniform Resource Locators. 4.1.15 Parse822 Parsing RFC 822 headers. 4.1.16 Mailcap Parsing RFC 1524 file.
Wherever the mail is and whatever format it is stored in, it is operated upon using the same set of functions. To unified the C API, GNU Mailutils offers a heteroclite set of objects that work in aggregation to do operations on emails. Each object does a specific task and delegates non-related tasks to others. The object comes alive by specifying a URL parameter when created, it will indicate the storage format or protocol (POP3, IMAP4, MH, MAILDIR, etc ..).
folder_t url_t
-/var/mail- +- .. ->+-----------------+ +-->+------------+
( alain *-)-+ | | url_t *-|---+ | port |
---------- | | |-----------------| | hostname |
( jakob *-)-+--+ | auth_t *-|---+ | file |
---------- | |-----------------| | | ... |
( jeff *-)-+ | stream_t | | +------------+
---------- | |-----------------| |
( shaleh*-)-+ | ..... | | auth_t
---------- |-----------------| +-->+------------+
+---|-* mailbox_t[] | | ticket_t |
mailbox_t | +-----------------+ +------------+
+----------------+<-+
| locker_t *--|-------------+
|----------------| |
| url_t | | locker_t
|----------------| +-------->+---------+
| stream_t | | lock |
|----------------| | unlock |
| message_t[] *-|-------+ +---------+
+----------------+ | envelope_t
| +-------->+-----------+
message_t | | | date |
+----------------+<------+ | | from |
| envelope_t *-|------------------+ | to |
|----------------| header_t +-----------+
| header_t *-|------------>+--------------+
|----------------| | stream_t |
| body_t *-|----+ +--------------+
+----------------+ | body_t
+-->+--------------+
| stream_t |
+--------------+
|
As an example, here is a simplified version of from command. It
lists the `From' and `Subject' headers of every mail in a mailbox.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <mailutils/mailutils.h>
int
main (int argc, const char **argv)
{
char *from;
char *subject;
mailbox_t mbox;
size_t msgno, total = 0;
int status;
/* Register the formats. */
mu_register_all_mbox_formats ();
status = mailbox_create_default (&mbox, argv[1]);
if (status != 0)
{
mu_error ("mailbox_create: %s", mu_strerror (status));
exit (EXIT_FAILURE);
}
status = mailbox_open (mbox, MU_STREAM_READ);
if (status != 0)
{
mu_error ("mailbox_open: %s", mu_strerror (status));
exit (EXIT_FAILURE);
}
mailbox_messages_count (mbox, &total);
for (msgno = 1; msgno <= total; msgno++)
{
message_t msg;
header_t hdr;
if ((status = mailbox_get_message (mbox, msgno, &msg)) != 0
|| (status = message_get_header (msg, &hdr)) != 0)
{
mu_error ("Error message: %s", mu_strerror (status));
exit (EXIT_FAILURE);
}
if (header_aget_value (hdr, MU_HEADER_FROM, &from))
from = strdup ("(NO FROM)");
if (header_aget_value (hdr, MU_HEADER_SUBJECT, &subject))
subject = strdup ("(NO SUBJECT)");
printf ("%s\t%s\n", from, subject);
free (from);
free (subject);
}
status = mailbox_close (mbox);
if (status != 0)
{
mu_error ("mailbox_close: %s", mu_strerror (status));
exit (EXIT_FAILURE);
}
mailbox_destroy (&mbox);
return 0;
}
|
Here is a sample output produced by this program:
% ./sfrom pop://alain@localhost Passwd: xxxx Jim Meyering <meyering@foo.org> fetish(shellutils) beta François Pinard <pinard@bar.org> recode new alpha ... |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
folder_t url_t
-/var/mail- +---//--->/-----------------\ +-->/-----------\
( alain *-)-+ | | url_t *-|---+ | port |
---------- | | |-----------------+ | hostname |
( jakob *-)-+--+ | observer_t *-| | file |
---------- | |-----------------+ | ... |
( jeff *-)-+ | stream_t | \-----------/
---------- | |-----------------|
( sean *-)-+ | auth_t |
---------- |-----------------|
| mailbox_t(1) |
|-----------------|
| mailbox_t(2) |
| ...... |
| mailbox_t(n) |
\-----------------/
|
Data structures:
struct list_response
{
int type;
int separator;
char *name;
};
struct folder_list
{
struct list_response **element;
size_t num;
};
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
mailbox_t object is used to hold information and it is an opaque
data structure to the user. Functions are provided to retrieve information
from the data structure.
mailbox_t url_t
-/var/mail- +---//--->/-----------------\ +-->/-----------\
( alain ) | | url_t *-|---+ | port |
---------- | |-----------------+ | hostname |
( jakob *-)----+ | observer_t *-| | file |
---------- |-----------------+ | ... |
( jeff ) | stream_t | \-----------/
---------- |-----------------|
( sean ) | locker_t |
---------- |-----------------|
| message_t(1) |
|-----------------|
| message_t(2) |
| ...... |
| message_t(n) |
\-----------------/
|
mailbox_create allocates and initializes mbox.
The concrete mailbox type instantiate is based on the scheme of the url name.
The return value is 0 on success and a code number on error conditions:
MU_ERR_OUT_PTR_NULL
NULL.
MU_ERR_NO_HANDLER
EINVAL
ENOMEM
mailbox_create() based on the environment
variable MAIL or the string formed by
_PATH_MAILDIR/user" or LOGNAME if user is null,
stream_create() for flag's description.
The return value is 0 on success and a code number on error conditions:
EAGAIN
EINPROGRESS
EBUSY
MU_ERROR_INVALID_PARAMETER
NULL or flag is invalid.
ENOMEM
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL or msgno is invalid.
ENOMEM
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL or message is invalid.
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
ENOMEM
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
ENOMEM
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
ENOMEM
The return value is 0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL.
ENOMEM
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
If from is not NULL, it must contain a single fully qualified
RFC2822 email address which will be used as the envelope from
address. This is the address to which delivery status notifications
are sent, so it never matters what it is set to until it really
matters. This is equivalent to Sendmail's `-f' flag.
The default for from is provided by the specific mailer.
If to is not NULL, then the message will be sent to the list of
addresses that it specifies.
The default for to is to use the contents of the standard "To:", "Cc:", and "Bcc:" fields, this is equivalent to Sendmail's `-t' flag.
Some possible use cases the API must support are:
- original submission
1 - fill in header addresses
2 - mailer_send_message(mailer, msg, NULL, NULL)
- from will be filled in if missing,
- Bcc's will be deleted before delivery to a non-bcc address,
- message-id and date will be added, if missing,
- a To: or Apparently-To: will be added if non is present (for RFC compliance)
- MTA-style `.forward' (and Sieve-style redirect)
1 - get the envelope from of the message to be forwarded
2 - mailer_send_message(mailer, msg, from, to)
- MUA-style bounce
1 - add Resent-[To,From,...]
2 - mailer_send_message(mailer, msg, NULL, to)
- DSN "bounce"
1 - compose DSN
2 - mailer_deliver(mailer, msg, address_t("<>"), to)
Don't want mail loops, so the null but valid SMTP address of `<>' is the envelope From.
`/sbin/sendmail' isn't always Sendmail... Sometimes it's a Sendmail-compatible wrapper, so assume `/sbin/sendmail' understands only a recipient list, `-f' and `-oi', these seem to be pretty basic. Cross fingers.
Pipe to "/sbin/sendmail -oi [-f from] [to...]", supplying `-f' if there was a from, and supplying the recipient list from the to (if there is no recipient list, assume it will read the message contents for the recipients).
Caution: since the stdout and stderr of Sendmail
is closed, we have no way of ever giving feedback on failure. Also, what
should the return code be from mailer_send_message() when Sendmail
returns `1'? `1' maps to EPERM, which is less than
descriptive!
This mailer does not canonicalize the message. This must be done before sending the message, or it may be assumed that the MTA will do so.
It does blind out the Bcc: header before sending, though.
Caution: Mutt always puts the recipient addresses on the command line, even Bcc: ones, do we strip the Bcc: before forwarding with SMTP?
An address that has no domain is not and RFC822 email address. What do I do with them? Should the user of the API be responsible for determining what is mean by email to "John" means? Or should the be able to configure Sendmail to decide globally what this means. If so, we can pass the address to Sendmail, but we have to decide for SMTP! So, right now these addresses are rejected. This could be changed.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
The message_t object is a convenient way to manipulate messages. It
encapsulates the envelope_t, the header_t and the body_t.
mailbox_t
---------- message_t
(message[1]) +------>+--------------------+
---------- | | envelope_t |
(message[2]) | |--------------------|
---------- | | header_t |
(message[3])--------+ |--------------------|
---------- | body_t |
(message[n]) |--------------------|
---------- | attribute_t |
|--------------------|
| stream_t |
+--------------------+
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
envelope_t depends
on the mailbox type, this allows the function which actually gets
the sender to be set by the creator of an envelope_t.
ctime() format: Mon Jul 05 13:08:27 1999.
envelope_t depends
on the mailbox type, this allows the function which actually gets
the date to be set by the creator of an envelope_t.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
So far we plan support for RFC822 and plan for RFC1522. With RFC1522 non-ASCII characters will be encoded.
NULL,
it is parsed.
Some basic macros are already provided for RFC822.
MU_HEADER_UNIX_FROM
MU_HEADER_RETURN_PATH
MU_HEADER_RECEIVED
MU_HEADER_DATE
MU_HEADER_FROM
MU_HEADER_SENDER
MU_HEADER_RESENT_FROM
MU_HEADER_SUBJECT
MU_HEADER_SENDER
MU_HEADER_RESENT_SENDER
MU_HEADER_TO
MU_HEADER_RESENT_TO
MU_HEADER_CC
MU_HEADER_RESENT_CC
MU_HEADER_BCC
MU_HEADER_RESENT_BCC
MU_HEADER_REPLY_TO
MU_HEADER_RESENT_REPLY_TO
MU_HEADER_MESSAGE_ID
MU_HEADER_RESENT_MESSAGE_ID
MU_HEADER_IN_REPLY_TO
MU_HEADER_REFERENCE
MU_HEADER_REFERENCES
MU_HEADER_ENCRYPTED
MU_HEADER_PRECEDENCE
MU_HEADER_STATUS
MU_HEADER_CONTENT_LENGTH
MU_HEADER_CONTENT_LANGUAGE
MU_HEADER_CONTENT_TRANSFER_ENCODING
MU_HEADER_CONTENT_ID
MU_HEADER_CONTENT_TYPE
MU_HEADER_CONTENT_DESCRIPTION
MU_HEADER_CONTENT_DISPOSITION
MU_HEADER_CONTENT_MD5
MU_HEADER_MIME_VERSION
MU_HEADER_X_UIDL
MU_HEADER_X_UID
MU_HEADER_X_IMAPBASE
MU_HEADER_ENV_SENDER
MU_HEADER_ENV_DATE
MU_HEADER_FCC
MU_HEADER_DELIVERY_DATE
MU_HEADER_ENVELOPE_TO
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
These generic flags are interpreted as appropriate to the specific streams.
MU_STREAM_READ
MU_STREAM_WRITE
MU_STREAM_RDWR
MU_STREAM_APPEND
MU_STREAM_CREAT
MU_STREAM_NONBLOCK
MU_STREAM_NO_CHECK
MU_STREAM_SEEKABLE
MU_STREAM_NO_CLOSE
MU_STREAM_ALLOW_LINKS
MU_STREAM_NO_CLOSE is specified, fclose() will not be called on
stdio when the stream is closed.
MU_STREAM_STATE_OPEN
stream_open.
MU_STREAM_STATE_READ
stream_read or stream_readline.
MU_STREAM_STATE_WRITE
stream_write.
MU_STREAM_STATE_CLOSE
stream_close.
An example using tcp_stream_create() to make a simple web client:
/* This is an example program to illustrate the use of stream functions.
It connects to a remote HTTP server and prints the contents of its
index page */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <mailutils/mailutils.h>
const char *wbuf = "GET / HTTP/1.0\r\n\r\n";
char rbuf[1024];
int
main (void)
{
int ret, off = 0;
stream_t stream;
size_t nb;
ret = tcp_stream_create (&stream, "www.gnu.org", 80, MU_STREAM_NONBLOCK);
if (ret != 0)
{
mu_error ("tcp_stream_create: %s", mu_strerror (ret));
exit (EXIT_FAILURE);
}
connect_again:
ret = stream_open (stream);
if (ret != 0)
{
if (ret == EAGAIN)
{
int wflags = MU_STREAM_READY_WR;
stream_wait (stream, &wflags, NULL);
goto connect_again;
}
mu_error ("stream_open: %s", mu_strerror (ret));
exit (EXIT_FAILURE);
}
write_again:
ret = stream_write (stream, wbuf + off, strlen (wbuf), 0, &nb);
if (ret != 0)
{
if (ret == EAGAIN)
{
int wflags = MU_STREAM_READY_WR;
stream_wait (stream, &wflags, NULL);
off += nb;
goto write_again;
}
mu_error ("stream_write: %s", mu_strerror (ret));
exit (EXIT_FAILURE);
}
if (nb != strlen (wbuf))
{
mu_error ("stream_write: %s", "nb != wbuf length");
exit (EXIT_FAILURE);
}
do
{
ret = stream_read (stream, rbuf, sizeof (rbuf), 0, &nb);
if (ret != 0)
{
if (ret == EAGAIN)
{
int wflags = MU_STREAM_READY_RD;
stream_wait (stream, &wflags, NULL);
}
else
{
mu_error ("stream_read: %s", mu_strerror (ret));
exit (EXIT_FAILURE);
}
}
write (1, rbuf, nb);
}
while (nb || ret == EAGAIN);
ret = stream_close (stream);
if (ret != 0)
{
mu_error ("stream_close: %s", mu_strerror (ret));
exit (EXIT_FAILURE);
}
stream_destroy (&stream, NULL);
exit (EXIT_SUCCESS);
}
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
There are many ways to authenticate to a server. To be flexible the
authentication process is provided by three objects authority_t,
ticket_t, and wicket_t. The authority_t can implement
different protocol like APOP, MD5-AUTH, One Time Passwd, etc. By default
if a mailbox does not understand or know how to authenticate it falls back
to user/passwd authentication. The ticket_t is a way for
Mailboxes and Mailers provide a way to authenticate when the URL does not
contain enough information. The default action is to call the function
authority_authenticate() which will get the user and passwd
if not set, this function can be overridden by a custom method.
A simple example of an authenticate function:
#include <stdio.h>
#include <string.h>
#include <mailutils/auth.h>
int
my_authenticate (auth_t auth, char **user, char **passwd)
{
char u[128] = "";
char p[128] = "";
/* prompt the user name */
printf ("User: ");
fflush (stdout);
fgets (u, sizeof (u), stdin);
u[strlen (u) - 1] = '\0'; /* nuke the trailing NL */
/* prompt the passwd */
printf ("Passwd: "); fflush (stdout);
echo_off ();
fgets (p, sizeof(p), stdin);
echo_on ();
p[strlen (p) - 1] = '\0';
/* duplicate */
*user = strdup (u);
*passwd = strdup (p);
return 0;
}
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
The Internet address format is defined in RFC 822. RFC 822 has been updated, and is now superceeded by RFC 2822, which makes some corrections and clarifications. References to RFC 822 here apply equally to RFC 2822.
The RFC 822 format is more flexible than many people realize, here is a quick summary of the syntax this parser implements, see RFC 822 for the details. `[]' pairs mean "optional", `/' means "one or the other", and double-quoted characters are literals.
addr-spec = local-part "@" domain
mailbox = addr-spec ["(" display-name ")"] /
[display-name] "<" [route] addr-spec ">"
mailbox-list = mailbox ["," mailbox-list]
group = display-name ":" [mailbox-list] ";"
address = mailbox / group / unix-mbox
address-list = address ["," address-list]
|
Unix-mbox is a non-standard extension meant to deal with the common practice of using user names as addresses in mail utilities. It allows addresses such as "root" to be parsed correctly. These are not valid internet email addresses, they must be qualified before use.
Several address functions have a set of common arguments with consistent semantics, these are described here to avoid repetition.
Since an address-list may contain multiple addresses, they are accessed by a one-based index number, no. The index is one-based because pop, imap, and other message stores commonly use one-based counts to access messages and attributes of messages.
If len is greater than 0 it is the length of the buffer
buf, and as much of the component as possible will be copied
into the buffer. The buffer will be NULL terminated.
The size of a particular component may be queried by providing 0
for the len of the buffer, in which case the buffer is optional.
In this case, if n is provided *n is assigned the length of
the component string.
address_t object is used to hold information about a parsed
RFC822 address list, and is an opaque
data structure to the user. Functions are provided to retrieve information
about an address in the address list.
The return value is 0 on success and a code number on error conditions:
EINVAL
NULL.
ENOMEM
ENOENT
-1, then sv must be NULL terminated in the fashion of argv,
otherwise len is the length of the array.
The return value is 0 on success and a code number on error conditions:
EINVAL
NULL.
ENOMEM
ENOENT
Note that the entry may be valid, but be a group name. In this case success
is returned, but the length of the address is 0.
The return value is 0 on success and a code number on error conditions:
EINVAL
NULL.
ENOENT
The return value is 0 on success and a code number on error conditions:
EINVAL
NULL.
ENOENT
0
length for a unix-mbox.
The return value is 0 on success and a code number on error conditions:
EINVAL
NULL.
ENOENT
A group is a kind of a special case. It has a display-name, followed
by an optional mailbox-list. The display-name will be allocated an address
all it's own, but all the other elements (local-part, domain, etc.) will
be zero-length. So "a group: ;" is valid, will have a count of 1, but
address_get_email(), and all the rest, will return zero-length output.
The return value is 0 on success and a code number on error conditions:
EINVAL
NULL.
ENOENT
The return value is 0 on success and a code number on error conditions:
EINVAL
NULL.
ENOENT
The return value is 0 on success and a code number on error conditions:
EINVAL
NULL.
ENOENT
NULL
if there is no email address to return.
The return value is 0 on success and a code number on error conditions:
EINVAL
NULL.
ENOENT
1 if this address is just the name of a group,
0 otherwise. This is faster than checking if the address has
a non-zero length personal, and a zero-length local_part and domain.
yes can be NULL, though that doesn't serve much purpose other
than determining that no refers to an address.
Currently, there is no way to determine the end of the group.
The return value is 0 on success and a code number on error conditions:
EINVAL
NULL.
ENOENT
The return value is 0 on success and a code number on error conditions:
EINVAL
NULL.
ENOMEM
If addr is NULL, the count is 0. If count is
not NULL, the count will be written to *count.
The return value is 0.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <mailutils/address.h>
#include <mailutils/errno.h>
#include <mailutils/mutil.h>
#define EPARSE MU_ERR_NOENT
static int
parse (const char *str)
{
size_t no = 0;
size_t pcount = 0;
int status;
char buf[BUFSIZ];
address_t address = NULL;
mu_set_user_email_domain ("localhost");
status = address_create (&address, str);
address_get_count (address, &pcount);
if (status)
{
printf ("%s=> error %s\n\n", str, mu_errname (status));
return 0;
}
else
{
printf ("%s=> pcount %lu\n", str, (unsigned long) pcount);
}
for (no = 1; no <= pcount; no++)
{
size_t got = 0;
int isgroup;
address_is_group (address, no, &isgroup);
printf ("%lu ", (unsigned long) no);
if (isgroup)
{
address_get_personal (address, no, buf, sizeof (buf), &got);
printf ("group <%s>\n", buf);
}
else
{
address_get_email (address, no, buf, sizeof (buf), 0);
printf ("email <%s>\n", buf);
}
address_get_personal (address, no, buf, sizeof (buf), &got);
if (got && !isgroup)
printf (" personal <%s>\n", buf);
address_get_comments (address, no, buf, sizeof (buf), &got);
if (got)
printf (" comments <%s>\n", buf);
address_get_local_part (address, no, buf, sizeof (buf), &got);
if (got)
{
printf (" local-part <%s>", buf);
address_get_domain (address, no, buf, sizeof (buf), &got);
if (got)
printf (" domain <%s>", buf);
printf ("\n");
}
address_get_route (address, no, buf, sizeof (buf), &got);
if (got)
printf (" route <%s>\n", buf);
}
address_destroy (&address);
printf ("\n");
return 0;
}
static int
parseinput (void)
{
char buf[BUFSIZ];
while (fgets (buf, sizeof (buf), stdin) != 0)
{
buf[strlen (buf) - 1] = 0;
parse (buf);
}
return 0;
}
int
main (int argc, const char *argv[])
{
argc = 1;
if (!argv[argc])
return parseinput ();
for (; argv[argc]; argc++)
{
if (strcmp (argv[argc], "-") == 0)
parseinput ();
else
parse (argv[argc]);
}
return 0;
}
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
A flags of 0 means that the default will be used.
Time is measured in seconds.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A mailbox or a mailer can be described in a URL, the string will contain the
necessary information to initialize mailbox_t, or mailer_t
properly.
pop://[<user>[;AUTH=<auth>]@]<host>[:<port>] or pop://[<user>[:<passwd>]@]<host>[:<port>] |
If :port is omitted the default value is 110. Different forms of authentication can be specified with ;AUTH=type. The special string ;AUTH=* indicates that the client will use a default scheme base on the capability of the server.
pop://obelix@gaulois.org pop://asterix;AUTH=*@france.com pop://falbala;AUTH=+APOP@france.com pop://obelix;AUTH=+APOP@village.gaulois.org:2000 pop://obelix:menhir@village.gaulois.org:2000 |
For more complete information see RFC 2368.
imap://[<user>[;AUTH=<type>]]@<host>[:port][/<mailbox>] or imap://[<user>[:<passwd>]]@<host>[:port][/<mailbox>] |
If :port is omitted the default value is 143. Different forms of authentication can be specified with ;AUTH=type. The special string ;AUTH=* indicates that the client will use a default scheme base on the capability of the server.
imap://obelix@imap.gaulois.org imap://asterix;AUTH=*@imap.france.com imap://asterix:potion@imap.france.com |
For more complete information see RFC 2192.
Local folder should be handle by this URL. It is preferable to let the mailbox recognize the type of mailbox and take the appropriate action.
file://path file://var/mail/user file://home/obelix/Mail |
For MMDF, MH local mailboxes URLs are provided, but it is preferable to use file://path and let the library figure out which one.
mmdf://path mh://path |
After setting a mailer, mailto: is used to tell the mailer where and to whom the message is for.
mailto://hostname |
Mailto can be used to generate short messages, for example to subscribe to mailing lists.
mailto://bug-mailutils@gnu.org?body=subscribe mailto://bug-mailutils@gnu.org?Subject=hello&body=subscribe |
For more complete information see RFC 2368.
Helper functions are provided to retrieve and set the URL fields.
The syntax, condensed from RFC 1738, and extended with the ;auth= of RFC 2384 (for POP) and RFC 2192 (for IMAP) is:
url =
scheme ":" [ "//"
[ user [ ( ":" password ) | ( ";auth=" auth ) ] "@" ]
host [ ":" port ]
[ ( "/" urlpath ) | ( "?" query ) ] ]
|
This is a generalized URL syntax, and may not be exactly appropriate for any particular scheme.
strdup().
#include <stdio.h>
#include <string.h>
#include <mailutils/errno.h>
#include <mailutils/url.h>
int
main ()
{
char str[1024];
char buffer[1024];
long port = 0;
int len = sizeof (buffer);
url_t u = NULL;
while (fgets (str, sizeof (str), stdin) != NULL)
{
int rc;
str[strlen (str) - 1] = '\0'; /* chop newline */
if (strspn (str, " \t") == strlen (str))
continue; /* skip empty lines */
if ((rc = url_create (&u, str)) != 0)
{
fprintf (stderr, "url_create %s ERROR: [%d] %s",
str, rc, mu_strerror (rc));
exit (1);
}
if ((rc = url_parse (u)) != 0)
{
printf ("%s => FAILED: [%d] %s\n",
str, rc, mu_strerror (rc));
continue;
}
printf ("%s => SUCCESS\n", str);
url_get_scheme (u, buffer, len, NULL);
printf ("\tscheme <%s>\n", buffer);
url_get_user (u, buffer, len, NULL);
printf ("\tuser <%s>\n", buffer);
url_get_passwd (u, buffer, len, NULL);
printf ("\tpasswd <%s>\n", buffer);
url_get_auth (u, buffer, len, NULL);
printf ("\tauth <%s>\n", buffer);
url_get_host (u, buffer, len, NULL);
printf ("\thost <%s>\n", buffer);
url_get_port (u, &port);
printf ("\tport %ld\n", port);
url_get_path (u, buffer, len, NULL);
printf ("\tpath <%s>\n", buffer);
url_get_query (u, buffer, len, NULL);
printf ("\tquery <%s>\n", buffer);
url_destroy (&u);
}
return 0;
}
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
|
The standard RFC 1524 (A User Agent Configuration Mechanism) suggests a file format to be used to inform a mail user agent about facilities for handling mail in various format. The configuration file is known also as mailcap and it is tipically found in UNIX platforms, a example of `/etc/mailcap':
application/pgp; gpg < %s | metamail; needsterminal; \
test=test %{encapsulation}=entity ; copiousoutput
|
A mailcap file consits of a set of mailcap entries per line, lines beginning with `#' are considered comments and ignored. Long mailcap entry may be continued on multiple lines if each line ends with a backslash character `\', the multiline will be considered a single mailcap entry. The overall format in BNF:
Mailcap-File = *mailcap-line Mailcap-Line = comment | mailcap-entry Comment = newline | "#" * char newline Newline = <newline as defined by OS convention> |
Each mailcap entry consists of a number of fields, separated by semi-colons. The first two filds are required and must occur in the secified order, the remaining fields are optional.
Mailcap-Entry = typefield ";" view-command ";" *[ ";" field ] |
mu_mailcap_t and mu_mailcap_entry_t objects
are used to hold information and it is an opaque data structure
to the user. Functions are provided to retrieve information
from the data structure.
mu_mailcap_t mu_mailcap_entry_t
-/etc/mailcap- +--->/------------------------\ +-->/------------------\
( alain ) | mu_mailcap_entry[0]*--|--+ | typefield |
| mu_mailcap_entry[1] | | view-command |
| ..... | | field[0] |
| mu_mailcap_entry[n] | | ..... |
\------------------------/ | field[n] |
\------------------/
|
#include <stdio.h>
#include <mailutils/mailcap.h>
#include <mailutils/stream.h>
#include <mailutils/error.h>
int
main (int argc, char **argv)
{
stream_t stream = NULL;
int status = 0;
char *file = argc == 1 ? "/etc/mailcap" : argv[1];
mu_mailcap_t mailcap = NULL;
status = file_stream_create (&stream, file, MU_STREAM_READ);
if (status)
{
mu_error ("cannot create file stream %s: %s",
file, mu_strerror (status));
exit (1);
}
status = stream_open (stream);
if (status)
{
mu_error ("cannot open file stream %s: %s",
file, mu_strerror (status));
exit (1);
}
status = mu_mailcap_create (&mailcap, stream);
if (status == 0)
{
int i;
size_t count = 0;
char buffer[256];
mu_mailcap_entries_count (mailcap, &count);
for (i = 1; i <= count; i++)
{
size_t j;
mu_mailcap_entry_t entry = NULL;
size_t fields_count = 0;
printf ("entry[%d]\n", i);
mu_mailcap_get_entry (mailcap, i, &entry);
/* typefield. */
mu_mailcap_entry_get_typefield (entry, buffer,
sizeof (buffer), NULL);
printf ("\ttypefield: %s\n", buffer);
/* view-command. */
mu_mailcap_entry_get_viewcommand (entry, buffer,
sizeof (buffer), NULL);
printf ("\tview-command: %s\n", buffer);
/* fields. */
mu_mailcap_entry_fields_count (entry, &fields_count);
for (j = 1; j <= fields_count; j++)
{
int status = mu_mailcap_entry_get_field (entry, j, buffer,
sizeof (buffer), NULL);
if (status)
{
mu_error ("cannot retrieve field %lu: %s",
(unsigned long) j,
mu_strerror (status));
break;
}
printf ("\tfields[%d]: %s\n", j, buffer);
}
printf ("\n");
}
mu_mailcap_destroy (&mailcap);
}
return 0;
}
|
0 on success and a code number on error conditions:
MU_ERROR_INVALID_PARAMETER
NULL or stream is invalid.
0 on success and a code number on error conditions:
EINVAL
NULL.