diff options
Diffstat (limited to 'doc/wiki/Design.Storage.Mail.txt')
-rw-r--r-- | doc/wiki/Design.Storage.Mail.txt | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/doc/wiki/Design.Storage.Mail.txt b/doc/wiki/Design.Storage.Mail.txt new file mode 100644 index 0000000..a86d722 --- /dev/null +++ b/doc/wiki/Design.Storage.Mail.txt @@ -0,0 +1,100 @@ +Mail +==== + +Mail is first allocated with 'mail_alloc()'. Mails always belong to a +<transaction> [Design.Storage.Mailbox.Transaction.txt]. Even if mail is treated +read-only, Dovecot might write data to cache file, so whenever possible, mail +transactions should be committed. When mail is allocated, you can specify a +list of fields and headers that you're (most likely) going to need. This allows +Dovecot to optimize the later 'mail_get_*()' lookups so that it doesn't need to +parse the message multiple times. These fields are also added to cache file, so +you shouldn't list fields unless you're fairly certain you need them. + +If you need to jump around in the mailbox based on already known sequences or +UIDs, you can do this with 'mail_set_seq()' and 'mail_set_uid()'. This way you +don't have to go through all the trouble of setting up a mailbox search. + +Getting data +------------ + +Some of the mail fields can be accessed directly: + + * 'box': Mail's mailbox, same as the transaction's. + * 'transaction': Mail's transaction, the same that was given to + 'mail_alloc()'. + * 'seq': Currently selected message's sequence number. + * 'uid': Currently selected message's UID. + * 'expunged': We already detected that the message is expunged and can't be + accessed. This may also be set (and looked up) later when some + 'mail_get_*()' function fails. + * 'has_nuls' and 'has_no_nuls': Message body is known to (not) have NUL + characters. + +The final field is 'lookup_abort', which is write-only. Normally when doing a +'mail_get_*()' operation for a field that isn't in a cache, the field is +generated and added to cache. If you don't want this, but instead have figured +out some better optimized way to do non-cached lookups, you can change this +field so that 'mail_get_*()' lookups fail instead. This is primarily used by +searching code internally. + + * 'MAIL_LOOKUP_ABORT_NEVER': The default - do whatever it takes to return the + value. + * 'MAIL_LOOKUP_ABORT_READ_MAIL': If returning the value would require reading + message headers/body, abort. + * 'MAIL_LOOKUP_ABORT_NOT_IN_CACHE': If the value isn't already in cache, + abort. For example if looking up message's physical size would require + 'stat()'ing the file this wouldn't be done. + +Most of the 'mail_get_*()' should be fairly obvious in how they work. Only +functions returning int can fail, others don't. + + * Keywords can be looked up either by getting an array of keyword strings or + keyword indexes. The index lookups are slightly faster. Keyword indexes can + be converted to strings by using the 'status.keywords' array returned by + 'mailbox_get_status()'. + * 'mail_get_first_header()' return 0 if header wasn't found, 1 if it was. + * 'mail_get_special()' can return various special fields. If a special isn't + implemented by some backend, the call returns success and sets the value to + "". + * 'mail_get_stream()' returns an input stream that can be used to access the + mail. If this function is called multiple times, each call seeks the stream + to beginning. Don't unreference the stream, it's destroyed automatically. + * Typically the input contains the raw data in disk, lines may end with LF + or CRLF depending on how they're on disk. + * mbox drops Dovecot's internal headers from the stream (X-UID:, Status:, + etc.). + * Plugins (e.g. zlib) can also hook into this call and modify the input + stream. + +Sometimes you might notice that some looked up field is actually corrupted. For +example you might notice that input stream returns EOF earlier than previous +'mail_get_physical_size()' said. This might have been caused by various +different things, but in any case all you can really do then is to just call +'mail_set_cache_corrupted()' and try again. + +Setting data +------------ + +Some of the messages' metadata can be updated: + + * 'mail_update_flags()' and 'mail_update_keywords()' changes flags/keywords. + * Usually you should set 'modify_type' parameter to 'MODIFY_ADD' or + 'MODIFY_REMOVE', instead of replacing all the flags. That allows + concurrent flag updates not to overwrite each others changes. + * 'mail_expunge()' expunges a message. + +Other functions are mainly intended for mailbox replication or restoring an +existing mailbox (e.g. dsync): + + * 'mail_update_modseq()' can be used to increase message's modseq + * 'mail_update_uid()' can be used to give a new (higher) UID for the message. + If such UID can't be given, this call is just ignored. + * 'mail_update_pop3_uidl()' can be used to give a specific POP3 UIDL for the + message. This is used internally when 'pop3_save_uidl=yes'. + +Other metadata can't be changed. IMAP protocol requires that messages are +immutable, so it's not possible to change message's received date, headers or +body. If you wish to modify any of them, you need to create a new message and +expunge the old one. + +(This file was created from the wiki on 2019-06-19 12:42) |