mail-storage.h revision 6f691748802e32634fdfca2efa2a2058a47a4264
#ifndef MAIL_STORAGE_H
#define MAIL_STORAGE_H
struct message_size;
#include "seq-range-array.h"
#include "file-lock.h"
#include "guid.h"
#include "mail-types.h"
#include "mail-error.h"
#include "mailbox-list.h"
/* If some operation is taking long, call notify_ok every n seconds. */
#define MAIL_STORAGE_STAYALIVE_SECS 15
enum mail_storage_flags {
/* Remember message headers' MD5 sum */
/* Don't try to autodetect anything, require that the given data
contains all the necessary information. */
/* Don't autocreate any directories. If they don't exist,
fail to create the storage. */
MAIL_STORAGE_FLAG_NO_AUTOCREATE = 0x04,
/* Don't verify existence or accessibility of any directories.
Create the storage in any case. */
};
enum mailbox_flags {
/* Mailbox must not be modified even if asked */
MAILBOX_FLAG_READONLY = 0x01,
MAILBOX_FLAG_SAVEONLY = 0x02,
/* Remove MAIL_RECENT flags when syncing */
MAILBOX_FLAG_DROP_RECENT = 0x04,
/* Don't create index files for the mailbox */
MAILBOX_FLAG_NO_INDEX_FILES = 0x10,
/* Keep mailbox exclusively locked all the time while it's open */
MAILBOX_FLAG_KEEP_LOCKED = 0x20,
/* Enable if mailbox is used for serving POP3. This allows making
better caching decisions. */
MAILBOX_FLAG_POP3_SESSION = 0x40,
/* Enable if mailbox is used for saving a mail delivery using MDA.
This causes ACL plugin to use POST right rather than INSERT. */
MAILBOX_FLAG_POST_SESSION = 0x80,
/* Force opening mailbox and ignoring any ACLs */
MAILBOX_FLAG_IGNORE_ACLS = 0x100,
/* Open mailbox even if it's already marked as deleted */
MAILBOX_FLAG_OPEN_DELETED = 0x200
};
enum mailbox_feature {
/* Enable tracking modsequences */
MAILBOX_FEATURE_CONDSTORE = 0x01,
/* Enable tracking expunge modsequences */
MAILBOX_FEATURE_QRESYNC = 0x02
};
enum mailbox_existence {
};
enum mailbox_status_items {
STATUS_MESSAGES = 0x01,
STATUS_RECENT = 0x02,
STATUS_UIDNEXT = 0x04,
STATUS_UIDVALIDITY = 0x08,
STATUS_UNSEEN = 0x10,
STATUS_FIRST_UNSEEN_SEQ = 0x20,
STATUS_KEYWORDS = 0x40,
STATUS_HIGHESTMODSEQ = 0x80,
STATUS_PERMANENT_FLAGS = 0x200,
STATUS_FIRST_RECENT_UID = 0x400,
STATUS_LAST_CACHED_SEQ = 0x800
};
enum mailbox_metadata_items {
MAILBOX_METADATA_GUID = 0x01,
MAILBOX_METADATA_VIRTUAL_SIZE = 0x02,
MAILBOX_METADATA_CACHE_FIELDS = 0x04,
};
enum mailbox_search_result_flags {
/* Update search results whenever the mailbox view is synced.
Expunged messages are removed even without this flag. */
/* Queue changes so _sync() can be used. */
};
enum mail_sort_type {
MAIL_SORT_ARRIVAL = 0x0001,
MAIL_SORT_CC = 0x0002,
MAIL_SORT_DATE = 0x0004,
MAIL_SORT_FROM = 0x0008,
MAIL_SORT_SIZE = 0x0010,
MAIL_SORT_SUBJECT = 0x0020,
MAIL_SORT_TO = 0x0040,
MAIL_SORT_RELEVANCY = 0x0080,
MAIL_SORT_DISPLAYFROM = 0x0100,
MAIL_SORT_DISPLAYTO = 0x0200,
MAIL_SORT_POP3_ORDER = 0x0400,
/* Maximum size for sort program (each one separately + END) */
MAIL_SORT_MASK = 0x0fff,
};
enum mail_fetch_field {
MAIL_FETCH_FLAGS = 0x00000001,
MAIL_FETCH_MESSAGE_PARTS = 0x00000002,
MAIL_FETCH_STREAM_HEADER = 0x00000004,
MAIL_FETCH_STREAM_BODY = 0x00000008,
MAIL_FETCH_DATE = 0x00000010,
MAIL_FETCH_RECEIVED_DATE = 0x00000020,
MAIL_FETCH_SAVE_DATE = 0x00000040,
MAIL_FETCH_PHYSICAL_SIZE = 0x00000080,
MAIL_FETCH_VIRTUAL_SIZE = 0x00000100,
/* Set has_nuls / has_no_nuls fields */
MAIL_FETCH_NUL_STATE = 0x00000200,
/* specials: */
MAIL_FETCH_IMAP_BODY = 0x00001000,
MAIL_FETCH_IMAP_BODYSTRUCTURE = 0x00002000,
MAIL_FETCH_IMAP_ENVELOPE = 0x00004000,
MAIL_FETCH_FROM_ENVELOPE = 0x00008000,
MAIL_FETCH_HEADER_MD5 = 0x00010000,
MAIL_FETCH_UIDL_FILE_NAME = 0x00020000,
MAIL_FETCH_UIDL_BACKEND = 0x00040000,
MAIL_FETCH_MAILBOX_NAME = 0x00080000,
MAIL_FETCH_SEARCH_RELEVANCY = 0x00100000,
MAIL_FETCH_GUID = 0x00200000,
MAIL_FETCH_POP3_ORDER = 0x00400000
};
enum mailbox_transaction_flags {
/* Hide changes done in this transaction from next view sync */
MAILBOX_TRANSACTION_FLAG_HIDE = 0x01,
/* External transaction. Should be used for copying and appends,
but nothing else. */
is done only if it can be done easily. */
MAILBOX_TRANSACTION_FLAG_REFRESH = 0x08,
/* Don't update caching decisions no matter what we do in this
transaction (useful for e.g. precaching) */
};
enum mailbox_sync_flags {
/* Make sure we sync all external changes done to mailbox */
MAILBOX_SYNC_FLAG_FULL_READ = 0x01,
/* Make sure we write all our internal changes into the mailbox */
MAILBOX_SYNC_FLAG_FULL_WRITE = 0x02,
/* If it's not too much trouble, check if there are some changes */
MAILBOX_SYNC_FLAG_FAST = 0x04,
/* Don't sync expunges from our view */
MAILBOX_SYNC_FLAG_NO_EXPUNGES = 0x08,
/* If mailbox is currently inconsistent, fix it instead of failing. */
/* Syncing after an EXPUNGE command. This is just an informational
flag for plugins. */
MAILBOX_SYNC_FLAG_EXPUNGE = 0x80,
/* Force doing a full resync of indexes. */
MAILBOX_SYNC_FLAG_FORCE_RESYNC = 0x100,
/* FIXME: kludge until something better comes along:
Request full text search index optimization */
MAILBOX_SYNC_FLAG_OPTIMIZE = 0x400
};
enum mailbox_sync_type {
MAILBOX_SYNC_TYPE_EXPUNGE = 0x01,
MAILBOX_SYNC_TYPE_FLAGS = 0x02,
MAILBOX_SYNC_TYPE_MODSEQ = 0x04
};
struct message_part;
struct mail_namespace;
struct mail_storage;
struct mail_search_args;
struct mail_search_result;
struct mail_keywords;
struct mail_save_context;
struct mailbox;
struct mailbox_transaction_context;
struct mailbox_status {
/* NULL-terminated array of keywords */
/* These flags can be permanently modified */
enum mail_flags permanent_flags;
/* Modseqs aren't permanent (index is in memory) */
unsigned int nonpermanent_modseqs:1;
/* All keywords can be permanently modified */
unsigned int permanent_keywords:1;
/* More keywords can be created */
unsigned int allow_new_keywords:1;
};
struct mailbox_cache_field {
const char *name;
int decision; /* enum mail_cache_decision_type */
/* last_used is unchanged, if it's (time_t)-1 */
};
struct mailbox_metadata {
/* sum of virtual size of all messages in mailbox */
/* Fields that have "temp" or "yes" caching decision. */
/* Fields that should be precached */
};
struct mailbox_update {
/* All non-zero fields are changed. */
/* Modify caching decisions, terminated by name=NULL */
const struct mailbox_cache_field *cache_updates;
};
struct mail_transaction_commit_changes {
/* Unreference the pool to free memory used by these changes. */
/* UIDVALIDITY for assigned UIDs. */
/* UIDs assigned to saved messages. Not necessarily ascending. */
/* number of modseq changes that couldn't be changed as requested */
unsigned int ignored_modseq_changes;
/* TRUE if anything actually changed with this commit */
bool changed;
};
struct mailbox_sync_rec {
enum mailbox_sync_type type;
};
struct mailbox_sync_status {
/* There are expunges that haven't been synced yet */
unsigned int sync_delayed_expunges:1;
};
struct mailbox_expunge_rec {
/* IMAP UID */
/* 128 bit GUID. If the actual GUID has a different size, this
contains last bits of its SHA1 sum. */
};
enum mail_lookup_abort {
/* Perform everything no matter what it takes */
/* Abort if the operation can't be done fully using cache file */
};
struct mail {
/* always set */
struct mailbox_transaction_context *transaction;
unsigned int expunged:1;
/* If the lookup is aborted, error is set to MAIL_ERROR_NOTPOSSIBLE */
};
struct mail_storage_callbacks {
/* "* OK <text>" */
void *context);
/* "* NO <text>" */
void *context);
};
struct mailbox_virtual_pattern {
struct mail_namespace *ns;
const char *pattern;
};
void mail_storage_init(void);
void mail_storage_deinit(void);
/* register all mail storages */
void mail_storage_register_all(void);
/* Register mail storage class with given name - all methods that are NULL
are set to default methods */
/* Find mail storage class by name */
/* Create a new instance of registered mail storage class with given
storage-specific data. If driver is NULL, it's tried to be autodetected
from ns location. If ns location is NULL, it uses the first storage that
exists. The storage is put into ns->storage. */
/* Returns the mail storage settings. */
const struct mail_storage_settings *
/* Set storage callback functions to use. */
struct mail_storage_callbacks *callbacks,
void *context);
/* Purge storage's mailboxes (freeing disk space from expunged mails),
if supported by the storage. Otherwise just a no-op. */
/* Returns the error message of last occurred error. */
enum mail_error *error_r);
/* Wrapper for mail_storage_get_last_error(); */
enum mail_error *error_r);
/* Wrapper for mail_storage_get_last_error(); */
/* Returns TRUE if mailboxes are files. */
/* Initialize mailbox without actually opening any files or verifying that
it exists. Note that append and copy may open the selected mailbox again
with possibly different readonly-state. */
enum mailbox_flags flags);
/* Like mailbox_alloc(), but use mailbox GUID. */
const guid_128_t guid,
enum mailbox_flags flags);
/* Get mailbox existence state. If auto_boxes=FALSE, return
MAILBOX_EXISTENCE_NONE for autocreated mailboxes that haven't been
physically created yet */
enum mailbox_existence *existence_r);
/* Open the mailbox. If this function isn't called explicitly, it's also called
internally by lib-storage when necessary. */
/* Open mailbox as read-only using the given stream as input. */
/* Close mailbox. Same as if mailbox was freed and re-allocated. */
/* Close and free the mailbox. */
/* Create a mailbox. Returns failure if it already exists. Mailbox name is
allowed to contain multiple new nonexistent hierarchy levels. If directory
is TRUE, the mailbox should be created so that it can contain children. The
mailbox itself doesn't have to be created as long as it shows up in LIST.
If update is non-NULL, its contents are used to set initial mailbox
metadata. */
bool directory);
/* Update existing mailbox's metadata. */
/* Delete mailbox (and its parent directory, if it has no siblings) */
/* Delete mailbox, but only if it's empty. If it's not, fails with
MAIL_ERROR_EXISTS. */
/* Rename mailbox. Renaming across different mailbox lists is possible only
between private namespaces and storages of the same type. If the rename
fails, the error is set to src's storage. */
bool rename_children);
/* Subscribe/unsubscribe mailbox. Subscribing to
nonexistent mailboxes is optional. */
/* Enable the given feature for the mailbox. */
/* Returns all enabled features. */
enum mailbox_feature
/* Returns storage of given mailbox */
/* Return namespace of given mailbox. */
struct mail_namespace *
/* Returns the storage's settings. */
const struct mail_storage_settings *
/* Returns the mailbox's settings, or NULL if there are none. */
const struct mailbox_settings *
/* Returns name of given mailbox */
/* Returns the virtual name of the given mailbox. This is the same as using
mail_namespace_get_vname(). */
/* Returns TRUE if mailbox is read-only. */
/* Returns TRUE if two mailboxes point to the same physical mailbox. */
/* Returns TRUE if mailbox is now in inconsistent state, meaning that
the message IDs etc. may have changed - only way to recover this
would be to fully close the mailbox and reopen it. With IMAP
connection this would mean a forced disconnection since we can't
do forced CLOSE. */
/* Gets the mailbox status information, opening the mailbox if necessary. */
struct mailbox_status *status_r);
/* Gets the mailbox status, requires that mailbox is already opened. */
enum mailbox_status_items items,
struct mailbox_status *status_r);
/* Gets mailbox metadata */
struct mailbox_metadata *metadata_r);
/* Returns a mask of flags that are private to user in this mailbox
(as opposed to flags shared between users). */
/* Synchronize the mailbox. */
struct mailbox_sync_context *
struct mailbox_sync_rec *sync_rec_r);
struct mailbox_sync_status *status_r);
/* One-step mailbox synchronization. Use this if you don't care about
changes. */
/* Call given callback function when something changes in the mailbox. */
#ifdef CONTEXT_TYPE_SAFETY
#else
#endif
struct mailbox_transaction_context *
enum mailbox_transaction_flags flags);
int mailbox_transaction_commit(struct mailbox_transaction_context **t);
struct mailbox_transaction_context **t,
struct mail_transaction_commit_changes *changes_r);
void mailbox_transaction_rollback(struct mailbox_transaction_context **t);
/* Return the number of active transactions for the mailbox. */
modseq is larger than max_modseq. Save those messages' sequences to the
given array. */
void mailbox_transaction_set_max_modseq(struct mailbox_transaction_context *t,
struct mailbox *
mailbox_transaction_get_mailbox(const struct mailbox_transaction_context *t)
/* Convert uid range to sequence range. */
/* Convert sequence range to uid range. If sequences contain
(uint32_t)-1 to specify "*", they're preserved. */
/* Get list of messages' that have been expunged after prev_modseq and that
exist in uids_filter range. UIDs that have been expunged after the last
mailbox sync aren't returned. Returns TRUE if ok, FALSE if modseq is lower
than we can check for (but expunged_uids is still set as best as it can). */
/* Same as mailbox_get_expunges(), but return only list of UIDs. Not caring
about GUIDs is slightly faster. */
/* Initialize header lookup for given headers. */
struct mailbox_header_lookup_ctx *
/* Initialize new search request. If sort_program is non-NULL, the messages are
returned in the requested order, otherwise from first to last. */
struct mail_search_context *
mailbox_search_init(struct mailbox_transaction_context *t,
struct mail_search_args *args,
const enum mail_sort_type *sort_program,
struct mailbox_header_lookup_ctx *wanted_headers);
/* Deinitialize search request. */
/* Search the next message. Returns TRUE if found, FALSE if not. */
/* Like mailbox_search_next(), but don't spend too much time searching.
Returns FALSE with tryagain_r=FALSE if finished, and tryagain_r=TRUE if
more results will be returned by calling the function again. */
/* Returns TRUE if some messages were already expunged and we couldn't
determine correctly if those messages should have been returned in this
search. */
/* Remember the search result for future use. This must be called before the
first mailbox_search_next*() call. */
struct mail_search_result *
enum mailbox_search_result_flags flags);
/* Free memory used by search result. */
/* A simplified API for searching and saving the result. */
int mailbox_search_result_build(struct mailbox_transaction_context *t,
struct mail_search_args *args,
struct mail_search_result **result_r);
/* Return all messages' UIDs in the search result. */
const ARRAY_TYPE(seq_range) *
/* Return messages that have been removed and added since the last sync call.
This function must not be called if search result wasn't saved with
_QUEUE_SYNC flag. */
/* Build mail_keywords from NULL-terminated keywords list.
Returns 0 if successful, -1 if there are invalid keywords (error is set). */
struct mail_keywords **keywords_r);
/* Like mailbox_keywords_create(), except ignore invalid keywords. */
struct mail_keywords *
const char *const keywords[]);
struct mail_keywords *
/* Returns TRUE if keyword is valid, FALSE and error if not. */
const char **error_r);
/* Initialize saving a new mail. You must not try to save more than one mail
at a time. */
struct mail_save_context *
mailbox_save_alloc(struct mailbox_transaction_context *t);
/* Set the flags and keywords. Nothing is set by default. */
enum mail_flags flags,
struct mail_keywords *keywords);
/* Copy flags and keywords from given mail. */
/* Set message's modseq to be at least min_modseq. */
/* If received date isn't specified the current time is used. timezone_offset
specifies the preferred timezone in minutes, but it may be ignored if
backend doesn't support storing it. */
/* Set the "message saved" date. This should be set only when you're
replicating/restoring an existing mailbox. */
/* Set the envelope sender. This is currently used only with mbox files to
specify the address in From_-line. */
const char *envelope);
/* Set message's UID. If UID is smaller than the current next_uid, it's given
a new UID anyway. */
/* Set globally unique ID for the saved mail. A new GUID is generated by
default. This function should usually be called only when copying an
existing mail (or restoring a mail from backup). */
/* Set message's POP3 UIDL, if the backend supports it. */
const char *uidl);
/* Specify ordering for POP3 messages. The default is to add them to the end
of the mailbox. Not all backends support this. */
unsigned int order);
/* If dest_mail is set, the saved message can be accessed using it. Note that
setting it may require mailbox syncing, so don't set it unless you need
it. Also you shouldn't try to access it before mailbox_save_finish() is
called. */
/* Begin saving the message. All mail_save_set_*() calls must have been called
before this function. If the save initialization fails, the context is freed
and -1 is returned. After beginning the save you should keep calling
i_stream_read() and calling mailbox_save_continue() as long as there's
more input. */
struct mailbox_transaction_context *
/* Copy the given message. You'll need to specify the flags etc. using the
mailbox_save_*() functions. */
/* Same as mailbox_copy(), but treat the message as if it's being saved,
not copied. (For example: New mail delivered to multiple maildirs, with
each mails being hard link copies.) */
struct mailbox_header_lookup_ctx *wanted_headers);
/* Returns TRUE if successful, FALSE if message doesn't exist.
mail_*() functions shouldn't be called if FALSE is returned. */
after the next mail_set_seq/uid(). */
enum mail_fetch_field fields,
struct mailbox_header_lookup_ctx *headers);
/* Returns message's flags */
/* Returns message's keywords */
/* Returns message's keywords */
/* Returns message's modseq */
/* Returns message's MIME parts */
/* Get the Date-header of the mail. Timezone is in minutes. date=0 if it
wasn't found or it was invalid. */
/* Get the time when the mail was received (IMAP INTERNALDATE). */
/* Get the time when the mail was saved into this mailbox. This time may not
always be entirely reliable. */
/* Get the space used by the mail as seen by the reader. Linefeeds are always
counted as being CR+LF. */
/* Get the size of the stream returned by mail_get_stream(). */
/* Get value for single header field, or NULL if header wasn't found.
Returns 1 if header was found, 0 if not, -1 if error. */
const char **value_r);
/* Like mail_get_first_header(), but decode MIME encoded words to UTF-8.
Also multiline headers are returned unfolded.
Do not use this function for getting structured fields (e.g. address fields),
because decoding may break the structuring. Instead parse them first and
only afterwards decode the encoded words. */
const char **value_r);
/* Return a NULL-terminated list of values for each found field.
Returns -1 if error, 0 otherwise (with or without headers found). */
const char *const **value_r);
/* Like mail_get_headers(), but decode MIME encoded words to UTF-8.
Also multiline headers are returned unfolded.
Do not use for structured fields (see mail_get_first_header_utf8()). */
const char *const **value_r);
/* Returns stream containing specified headers. */
struct mailbox_header_lookup_ctx *headers,
/* Returns input stream pointing to beginning of message header.
hdr_size and body_size are updated unless they're NULL. The returned stream
is destroyed automatically, don't unreference it. */
/* Similar to mail_get_stream(), but the stream may or may not contain the
message body. */
/* Get any of the "special" fields. Unhandled specials are returned as "". */
const char **value_r);
/* Returns the mail for the physical message. Normally this is the mail itself,
but in virtual mailboxes it points to the backend mailbox. */
/* Update message flags. */
enum mail_flags flags);
/* Update message keywords. */
struct mail_keywords *keywords);
/* Update message's modseq to be at least min_modseq. */
/* Update message's POP3 UIDL (if possible). */
/* Expunge this message. Sequence numbers don't change until commit. */
/* Add missing fields to cache. */
/* Mark a cached field corrupted and have it recalculated. */
/* Return 128 bit GUID using input string. If guid is already 128 bit hex
encoded, it's returned as-is. Otherwise SHA1 sum is taken and its last
128 bits are returned. */
#endif