mailbox.texi
16.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
Mail boxes come in different formats and may be on a remote hosts,
only accessible through Mail Delivery Agent(MDA). Regardless
of the format and the protocol use, some common actions are needed like
reading, saving, deleting, scanning ... Those actions are provided via a
unify API mailbox_t.
All functions of the mailbox_t API return 0 if successful or non-zero
for failure, unless specify otherwise.
@section Init/Destroy
Initializing and destroying a mailbox_t object.
@deftypefun int mailbox_init (mailbox_t *@var{mbx}, const char * @var{url}, int @var{id})
Based on the type of the @var{url}, @var{mbx} is initialize to a known type,
if @var{id} is not zero, it represents the id of the mailbox, it will be use
instead of doing heuristic search on the @var{url}.
@example
#include <mailutils.h>
@dots{}
mailbox_t foo, popmbx, bar;
/* same as @url{file:///var/mail/foo} */
mailbox_init (&mbox, "/var/mail/foo", 0);
mailbox_init (&mbox, "pop://popserver.bar.com/foo", 0);
mailbox_init (&mbox, "file:///home/bar/.hiddenmail/bar", 0);
@end example
@end deftypefun
@deftypefun int mailbox_init_default (mailbox_t *@var{mbx}, const char * @var{user})
Initialize the default mailbox of the system as set by the mail administrator.
It could be hardcoded or override by a configuration
@file{$@{sysconfig@}/mailutils.conf}.
@example
#include <mailutils.h>
@dots{}
/* If the default mailbox on this system is @file{/var/mail} */
mailbox_t mbx;
/* sets the mailbox name to @url{file:///var/mail/foo} */
mailbox_init_default (&mbx, "foo");
/*
If the user is log as @emph{bar}, sets the mailbox name
to @url{file:///var/mail/bar}
*/
mailbox_init_default (&mbx, NULL);
@end example
@end deftypefun
@deftypefun int mailbox_destroy (mailbox_t *@var{mbx})
All resources allocated are release. If the stream is not open,
@code{mailbox_close} is call.
@end deftypefun
@section Open/Close
Opening and closing mailbox can be done any number of times. But be warned
on some cases like POP3, when opening, the lock can be persistent until
the stream is closed as required by the RFC.
@deftypefun int mailbox_open (mailbox_t @var{mbx}, int @var{flag})
Open the mailbox box stream. This function will call @code{mailbox_scan}.
@defmac MU_MB_RDONLY
Stream is open read-only.
@end defmac
@defmac MU_MB_WRONLY
Stream is open write-only.
@end defmac
@defmac MU_MB_RDWR
Stream is open read-write.
@end defmac
@defmac MU_MB_CREAT
If Folder does not exist it is created. May be a noop on remote hosts mailbox.
@end defmac
@defmac MU_MB_APPEND
The stream is opened in append mode.
@end defmac
@defmac MU_MB_ONONBLOCK
For sockets, open() nonblocking. Not supported.
@end defmac
@end deftypefun
@deftypefun int mailbox_close (mailbox_t @var{mbx})
Close the streams and release the locks.
@end deftypefun
@deftypefun int mailbox_is_open (mailbox_t @var{mbx})
Return a non-zero value if the stream is open, zero otherwise.
@end deftypefun
This is a very simple implementation of Unix @command{biff}.
@example
#include <mailutils.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define NAP 120
int
main ()
@{
mailbox_t mbx;
size_t size = 0, size2 = 0;
if (mailbox_init_default (&mbx, NULL) != 0)
@{
fprintf ("Can't initialize system mailbox\n");
exit (EXIT_FAILURE);
@}
/* the open may fail if no mailbox was created,
will check this later */
mailbox_open (mbx, MU_MB_RDONLY);
mailbox_size (mbx, &size);
for (;;)
@{
if (! mailbox_is_open (mbx))
@{
if (mailbox_open (mbx, MU_MB_RDONLY) != 0);
@{
//fprintf (stderr, "Not exist ?\n");
@}
@}
else
@{
if (mailbox_size (mbx, &size2) == 0)
@{
if (size2 > size)
@{
printf ("You got mail\a\n");
@}
size = size2;
@}
@}
/* rest a while */
sleep (NAP);
/* It is a good habit to close the resources.
A mailbox could be on a remote host and the locking
may interfere with normal delivery, for example with
POP, the lock is hold during the entire session.
*/
mailbox_close (mbx);
@}
return 0;
@}
@end example
@section Deletion
Messages can be marked for deletion but destructive action is only taken
when @code{mailbox_expunge} is called.
@deftypefun int mailbox_delete (mailbox_t @var{mbx}, size_t @var{msgno})
Mark message @var{msgno} for deletion.
@end deftypefun
@deftypefun int mailbox_undelete (mailbox_t @var{mbx}, size_t @var{msgno})
Unmark message @var{msgno} for deletion.
@end deftypefun
@deftypefun int mailbox_is_deleted (mailbox_t @var{mbx}, size_t @var{msgno})
Return non-zero if message @var{msgno} is mark deleted.
@end deftypefun
@deftypefun int mailbox_num_deleted (mailbox_t @var{mbx})
Return the number of Mailbox marked to be delete.
@end deftypefun
@deftypefun int mailbox_expunge (mailbox_t @var{mbx})
All messages marked for deletion will be removed and the mailbox updated,
and notification functions of all messages for @var{mbx} executed.
@end deftypefun
@section Message
@code{message_t} are objects that hold the offsets of the message in the
mailbox. Certain mailboxes allow new messages to be appended to the existing
folder, in this case the stream must be @code{mailbox_open} with the proper
permission.
@deftypefun int mailbox_new_message (mailbox_t @var{mbx}, message_t *@var{msg})
Create a new message.
@end deftypefun
@deftypefun int mailbox_append_message (mailbox_t @var{mbx}, message_t @var{msg}, int @var{destroy})
@var{msg} will be append to the mailbox. When appending the header may be
modified. In the case of Unix Mbox, the header "From " is prepend.
If @var{destroy} is set non-zero @code{message_destroy} will be call after delivery.
@end deftypefun
@deftypefun int mailbox_get_message (mailbox_t @var{mbx}, size_t @var{msgno}, message_t *@var{msg})
@var{msg} is initialize, be warn when doing @code{mailbox_expunge} the
offsets to the mailbox are lost and accessing the @var{msg} is undefined.
To prevent this, it is possible to @code{message_clone} or set a notification
to take appropriate action.
@end deftypefun
@deftypefun int mailbox_destroy_message (mailbox_t @var{mbx}, message_t @var{msg})
Resources allocated to @var{msg} will be release. Notification functions for
this @var{msg} are executed.
@end deftypefun
@section Reading Contents/Headers
Low level Reading functions for contents and headers.
@comment @deftypefun int mailbox_set_header (mailbox_t @var{mbx}, size_t @var{msgno}, const char *@var{header}, size_t @var{len}, int @var{replace})
@comment Fill the header of new message @var{msgno}. If @var{replace} is zero the
@comment buffer @var{header} will be append, otherwise it will overwrite any
@comment existing one.
@comment @end deftypefun
@comment @deftypefun int mailbox_set_body (mailbox_t @var{mbx}, message_t @var{msg}, const char *@var{body}, size_t @var{len}, int @var{replace})
@comment Fill the body of new @var{msg}. If @var{replace} is zero the buffer
@comment @var{body} will be append, otherwise it will overwrite any existing one.
@comment @end deftypefun
@deftypefun int mailbox_get_content (mailbox_t @var{mbx}, size_t @var{msgno}, off_t @var{off}, char *@var{buffer}, size_t @var{len}, size_t *@var{nread})
Read the body of message @var{msgno} starting at offset @var{off} in
@var{buffer} of size @var{len}. The number of bytes read is returned in
@var{nread}.
@end deftypefun
@deftypefun int mailbox_get_mcontent (mailbox_t @var{mbx}, size_t @var{msgno}, off_t @var{off}, char **@var{buffer}, size_t *@var{nread})
A buffer is allocated with @code{malloc(3)} return memory containing the body
of message @var{msgno} starting at offset @var{off} in @var{buffer}.
The number of bytes read is returned in @var{nread}.
@end deftypefun
@deftypefun int mailbox_get_header (mailbox_t @var{mbx}, size_t @var{msgno}, off_t @var{off}, char *@var{buffer}, size_t @var{len}, size_t *@var{nread})
Read the header of message @var{msgno} starting at offset @var{off} in
@var{buffer} of size @var{len}. The number of bytes read is returned
in @var{nread}.
@end deftypefun
@deftypefun int mailbox_get_mheader (mailbox_t @var{mbx}, size_t @var{msgno}, off_t @var{off}, char **@var{buffer}, size_t *@var{nread})
A buffer allocate with @code{malloc(3)} is return containing the header of
message @var{msgno} starting at offset @var{off} in @var{buffer}.
The number of bytes read is returned in @var{nread}.
@end deftypefun
@section Locking
Most mailboxes will lock before changing their contents. External usage of
those functions are discourage, since they may interfere with normal
operation and cause deadlocks. If however there is need to access the
mailbox outside the functions provided by the library, locking and unlocking
can be done explicitly. There is another level of internal
locking to provide synchronization to the mailbox_t object.
@deftypefun int mailbox_lock (mailbox_t @var{mbx}, int @var{flag})
Grab the lock. In some cases, i.e Unix mbox this may involve creating
a .lock file in the spool directory.
@comment Say something about permission the program be gid on some OS.
@defmac MU_MB_RDLOCK
Read lock.
@end defmac
@defmac MU_MB_WRLOCK
Write lock.
@end defmac
@defmac MU_MB_RWLOCK
Read/Write lock.
@end defmac
@end deftypefun
Note on many mailboxes, RDLOCK is a noop.
@deftypefun int mailbox_unlock (mailbox_t @var{mbx})
Release the lock.
@end deftypefun
@section Mailbox Attributes
When creating certain mailboxes, you can set the owner, group and mode
@deftypefun int mailbox_set_owner (mailbox_t @var{mbx}, uid_t @var{uid})
Set the owner to @var{uid}. If the Mailbox was not @code{mailbox_open}
the action is delayed until the stream is opened.
@end deftypefun
@deftypefun int mailbox_set_group (mailbox_t @var{mbx}, gid_t @var{gid})
Set the group to @var{gid}. If the Mailbox was not @code{mailbox_open}
the action is delayed until the stream is opened.
@end deftypefun
@deftypefun int mailbox_set_mode (mailbox_t @var{mbx}, mode_t @var{mode})
Set the file permission to @var{mode}. If the Mailbox was not
@code{mailbox_open} the action is delayed until the stream is opened.
@end deftypefun
@section Scanning
Scan is done implicitly on @code{mailbox_open}.
@deftypefun int mailbox_scan (mailbox_t @var{mbx}, size_t *@var{msgs})
The mailbox is parse and @var{msgs} if not NULL contain the message count.
A notification function can be set to monitor progress.
@end deftypefun
@comment @deftypefun int mailbox_scan_progress (mailbox_t @var{mbx}, int (*@var{progress}) (mailbox_t @var{mbx}, int @var{count}, void *@var{arg}), void *@var{arg})
@comment When doing @var{mailbox_scan}, function @var{progress}(@var{mbx}, @var{count},
@comment @var{arg}) is called for each new message.
@comment @end deftypefun
@deftypefun int mailbox_is_updated (mailbox_t @var{mbx})
Return 1 if @var{mbx} is up to date 0 otherwise.
@end deftypefun
@deftypefun int mailbox_size (mailbox_t @var{mbx}, off_t *@var{size})
@var{size} is assign the mailbox total size.
@end deftypefun
@deftypefun int mailbox_get_size (mailbox_t @var{mbx}, size_t @var{msgno}, size_t *@var{header}, size_t *@var{body})
For message @var{msgno} set @var{header} size and @var{body} size.
@end deftypefun
@deftypefun int mailbox_count (mailbox_t @var{mbx})
Return the number of messages in @var{mbx}.
@end deftypefun
@section Timeout
On remote mailboxes it is sometimes possible to reset the timeout. On most
local mailbox it is a noop.
@deftypefun int mailbox_set_timeout (mailbox_t @var{mbx}, size_t @var{millis})
Not Implemented.
@end deftypefun
@deftypefun int mailbox_get_timeout (mailbox_t @var{mbx}, size_t @var{millis})
Not Implemented.
@end deftypefun
@section Notifications
A number of callbacks are provided on the mailbox to monitor the changes.
Setting timeout and notifications.
@deftypefun int mailbox_set_refresh (mailbox_t @var{mbx}, size_t @var{millis})
Sets the refresh time on how often @code{mailbox_scan} should be called.
By default it is disabled. Not Implemented.
@end deftypefun
@deftypefun int mailbox_get_refresh (mailbox_t @var{mbx}, size_t @var{millis})
Return the refresh time. Not Implemented.
@end deftypefun
@deftypefun int mailbox_set_update_cb (mailbox_t @var{mbx}, int (*@var{notification}) (mailbox_t @var{mbx}, void *@var{arg}), void *@var{arg})
@code{mailbox_scan} can be called periodically to see if new messages have
arrived, if the number of total messages has changed the notification
function is called, @code{notification (mbx, arg)}. Not Implemented.
@end deftypefun
@deftypefun int mailbox_set_scan_cb (mailbox_t @var{mbx}, int (*@var{notification}) (int @var{msgcount}, void *@var{arg}))
When parsing the mailbox every count call @code{notification (msgcount, arg)}.
Note that all locks are held, and @var{notification} should be very small and
simple, it should not access or do any action on the mailbox doing this may
cause undefined behavior.
@end deftypefun
@deftypefun int mailbox_set_msg_destroy_cb (mailbox_t @var{mbx}, int (*@var{notification}) (mailbox_t @var{mbx}, message_t @var{msg}, void *@var{arg}))
@end deftypefun
@section Registration and Type
Mailbox_t comes with a certain number of builtin types, you can query them
or add you own to the list.
@deftp {Data type} struct mailbox_type
@example
@{
char *name;
int id;
struct url_type *utype;
int (*_init) __P ((mailbox_t *, const char *name));
void (*_destroy) __P ((mailbox_t *));
@};
@end example
@end deftp
@deftypefun int mailbox_list_type (struct mailbox_type *@var{mtype}, size_t @var{len}, size_t *@var{n})
The @var{mtype} array will be initialize with the list of builtins up to
@var{len}. The number of struct mailbox_type is put in @var{n}.
@end deftypefun
@deftypefun int mailbox_list_mtype (struct mailbox_type **@var{mtype}, size_t *@var{n})
An array of size @var{n} is @code{malloc(3)} to hold the builtin list.
@end deftypefun
@deftypefun int mailbox_add_type (struct mailbox_type *@var{mtype})
Add a mailbox @var{mtype} to the list of builtin.
@end deftypefun
@deftypefun int mailbox_remove_type (struct mailbox_type *@var{mtype})
Remove a mailbox @var{mtype} to the list of builtin.
@end deftypefun
@deftypefun int mailbox_get_type (struct mailbox_type **@var{mtype}, int @var{urlid})
Base on the @var{urlid} return the mailbox_type.
@end deftypefun
@deftypefun int mailbox_get_name_type (mailbox_t @var{mbx}, int *@var{mbxid}, char *@var{name}, size_t @var{len}, size_t *@var{n})
Return the name type of the mailbox identify by @var{mbxid},
in buffer @var{name} of size @var{len}. The number of byte is put in @var{n}.
@end deftypefun
@deftypefun int mailbox_get_mname_type(mailbox_t @var{mbx}, int *@var{mbxid}, char **@var{name}, size_t *@var{n})
Return the name type of the mailbox identify by @var{mbxid}, in
a @code{malloc(3)} buffer @var{name} of size @var{n}.
@end deftypefun
All mailbox implementations provide this minimum set of the API. By using
the registration new mailbox type can be added.
@example
#include <mailutils.h>
#include <ftp0.h>
#include <stdlib.h>
/* extern url_ftp_init (url_t *url, const char *name); in <ftp0.h> */
/* extern url_ftp_destroy (url_t *url, const char *name); in <ftp0.h> */
struct url_type url_ftp =
@{
"ftp://", 6, /* protocol and len */
"ftp://<user>:<passwd>@@<hostname>:<port>", /* help string */
(int)&url_ftp, /* need a uniq id */
url_ftp_init, url_ftp_destroy /* constructor and destructor */
@};
/* extern mailbox_unix_init (); in <ftp0.h> */
/* extern mailbox_unix_destroy (); in <ftp0.h> */
struct mailbox_type mbx_ftp =
@{
"FTP MBOX", /* name type */
(int)&mbx_ftp, /* need a uniq id */
&url_ftp, /* url id */
mailbox_unix_init, /* constructor */
mailbox_unix_destroy /* destructor */
@};
int main ()
@{
struct mailbox_type *mtype;
size_t size=0, i;
mailbox_add_type (&mbx_ftp);
/* check if it is added */
mailbox_list_mtype (&mtype, &size)
for (i = 0; i < size; i++)
@{
puts (mtype[i].name)
puts (mtype[i].description)
@}
free(*mtype);
@dots{}
return 0;
@}
@end example
@section Unix Mbox
@cindex Unix Mbox
TODO: describe particularities :
locking policy, appending envelope, describe the flags use in _open(..), etc...
@section POP3 Mbox
@cindex POP3 Mbox
TODO: describe timeout policies, describe the flags use in _open(..),
describe different authorization supported.
@section IMAP Mbox
@cindex IMAP Mbox
Not implemented.
@section QMail Mbox
@cindex QMail Mbox
Not implemented.
@section MMDF Mbox
@cindex MMDF Mbox
Not implemented.