mail-storage.h revision 0bf480bb3496197a1849d3677ae83296c95c1302
#ifndef MAIL_STORAGE_H
#define MAIL_STORAGE_H
struct message_size;
#include "seq-range-array.h"
#include "file-lock.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. */
};
enum mailbox_flags {
/* Mailbox must not be modified even if asked */
MAILBOX_FLAG_READONLY = 0x01,
MAILBOX_FLAG_SAVEONLY = 0x02,
/* Don't reset MAIL_RECENT flags when syncing */
MAILBOX_FLAG_KEEP_RECENT = 0x08,
/* 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
};
enum mailbox_feature {
/* Enable tracking modsequences */
MAILBOX_FEATURE_CONDSTORE = 0x01,
/* Enable tracking expunge modsequences */
MAILBOX_FEATURE_QRESYNC = 0x02
};
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_GUID = 0x100,
STATUS_CACHE_FIELDS = 0x200
};
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 {
/* Maximum size for sort program (each one separately + END) */
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_SEARCH_SCORE = 0x0080,
MAIL_SORT_DISPLAYFROM = 0x0100,
MAIL_SORT_DISPLAYTO = 0x0200,
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_SCORE = 0x00100000,
MAIL_FETCH_GUID = 0x00200000
};
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. */
};
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
};
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 {
/* Fields that have "temp" or "yes" caching decision. */
/* Modseqs aren't permanent (index is in memory) */
unsigned int nonpermanent_modseqs:1;
};
struct mailbox_update {
/* All non-zero fields are changed. */
/* Add these fields to be temporarily cached, if they aren't already. */
const char *const *cache_fields;
};
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. */
unsigned int ignored_uid_changes;
unsigned int ignored_modseq_changes;
};
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;
};
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);
/* Returns TRUE if mailboxes are files. */
/* Initialize mailbox without actually opening any files or verifying that
it exists. If input stream is given, mailbox is opened read-only
using it as a backend.
Note that append and copy may open the selected mailbox again
with possibly different readonly-state. */
/* Open the mailbox. If this function isn't called explicitly, it's also called
internally by lib-storage when necessary. */
/* 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 non-existing 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. */
/* 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 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 mailbox currently supports adding keywords. */
/* 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. */
struct mailbox_status *status_r);
/* 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). */
/* If box is a virtual mailbox, look up UID for the given backend message.
Returns TRUE if found, FALSE if not. */
/* If box is a virtual mailbox, return all backend mailboxes. If
only_with_msgs=TRUE, return only those mailboxes that have at least one
message existing in the virtual mailbox. */
bool only_with_msgs);
/* If mailbox is a virtual mailbox, return all mailbox list patterns that
are used to figure out which mailboxes belong to the virtual mailbox. */
/* Initialize new search request. charset specifies the character set used in
the search argument strings. 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);
/* 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 *
struct mail_keywords **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);
/* 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. */
/* Copy the given message. You'll need to specify the flags etc. using the
mailbox_save_*() functions. */
/* Initialize header lookup for given headers. */
struct mailbox_header_lookup_ctx *
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. */
/* 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. */
const char **value_r);
/* Return a NULL-terminated list of values for each found field. */
const char *const **value_r);
/* Like mail_get_headers(), but decode MIME encoded words to UTF-8.
Also multiline headers are returned unfolded. */
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. */
/* Get any of the "special" fields. Unhandled specials are returned as "". */
const char **value_r);
/* 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 UID. The new UID must not be lower than next_uid at the
commit time, otherwise the UID update fails and is just ignored. */
/* Update message's POP3 UIDL (if possible). */
/* Expunge this message. Sequence numbers don't change until commit. */
/* Mark a cached field corrupted and have it recalculated. */
/* Generate a GUID (contains host name) */
const char *mail_generate_guid_string(void);
/* Generate 128 bit GUID */
/* 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. */
void mail_generate_guid_128_hash(const char *guid,
/* Returns TRUE if GUID is empty (not set / unknown). */
#endif