maildir-mail.c revision 24cd47a2c8f7507e555459b7e841de771ba3c318
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "index-mail.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "maildir-storage.h"
e8bdf1be00aec45d0c6dd72ad9c8be02a3dfc778Timo Sirainen#include "maildir-filename.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "maildir-uidlist.h"
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen#include "maildir-sync.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen#include <stdlib.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <fcntl.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <unistd.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <sys/stat.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainenstruct maildir_open_context {
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen int fd;
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen char *path;
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen};
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenstatic int
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainendo_open(struct maildir_mailbox *mbox, const char *path,
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen struct maildir_open_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen ctx->fd = open(path, O_RDONLY);
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen if (ctx->fd != -1) {
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen ctx->path = i_strdup(path);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (errno == ENOENT)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen if (errno == EACCES) {
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen mail_storage_set_critical(&mbox->storage->storage, "%s",
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen mail_error_eacces_msg("open", path));
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen } else {
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen "open(%s) failed: %m", path);
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenstatic int
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainendo_stat(struct maildir_mailbox *mbox, const char *path, struct stat *st)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (stat(path, st) == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (errno == ENOENT)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen if (errno == EACCES) {
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen mail_storage_set_critical(&mbox->storage->storage, "%s",
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen mail_error_eacces_msg("stat", path));
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen } else {
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen "stat(%s) failed: %m", path);
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainenstatic int
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainenmaildir_rmdir_unexpected_dir(struct mail_storage *storage, const char *path)
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen{
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen if (rmdir(path) == 0) {
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen mail_storage_set_critical(storage,
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen "Maildir: rmdir()ed unwanted empty directory: %s",
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen path);
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen return 0;
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen } else {
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen mail_storage_set_critical(storage,
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen "Maildir: Found unwanted directory %s, "
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen "but rmdir() failed: %m", path);
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen return -1;
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen }
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen}
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct istream *
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainenmaildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail,
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen bool *deleted_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen struct mail_private *p = (struct mail_private *)mail;
d42eb03b3a4e79a2da22a1be2de59b95660af2beTimo Sirainen struct istream *input;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen const char *path;
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen struct maildir_open_context ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen *deleted_r = FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen ctx.fd = -1;
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen ctx.path = NULL;
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen
1eb17e61d3d38372674aa0c55caedb0185a985f5Timo Sirainen p->stats_open_lookup_count++;
fc40a9a002458e372ff4b9f6f4e15239520c0bcdTimo Sirainen if (!mail->saving) {
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen if (maildir_file_do(mbox, mail->uid, do_open, &ctx) < 0)
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen return NULL;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen } else {
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen path = maildir_save_file_get_path(mail->transaction, mail->seq);
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen if (do_open(mbox, path, &ctx) <= 0)
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen return NULL;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen if (ctx.fd == -1) {
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen *deleted_r = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen input = i_stream_create_fd(ctx.fd, 0, TRUE);
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen if (input->stream_errno == EISDIR) {
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen /* there's a directory in maildir. many installations seem to
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen have messed up something and causing "cur", "new" and "tmp"
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen directories to be created under the "cur" directory.
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen if the directory is empty, just get rid of it and log an
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen error */
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen i_stream_destroy(&input);
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen if (maildir_rmdir_unexpected_dir(&mbox->storage->storage,
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen ctx.path) == 0)
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen *deleted_r = TRUE;
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen } else {
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen i_stream_set_name(input, ctx.path);
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen index_mail_set_read_buffer_size(mail, input);
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen }
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen i_free(ctx.path);
d42eb03b3a4e79a2da22a1be2de59b95660af2beTimo Sirainen return input;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainenstatic int maildir_mail_stat(struct mail *mail, struct stat *st)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box;
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen struct index_mail *imail = (struct index_mail *)mail;
ee1a3e217279dcd0f1cccbd3442e481b7dc90f05Timo Sirainen const struct stat *stp;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen const char *path;
ee1a3e217279dcd0f1cccbd3442e481b7dc90f05Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ebe6df72f1309135f02b6a4d2aef1e81a073f91cTimo Sirainen if (mail->lookup_abort == MAIL_LOOKUP_ABORT_NOT_IN_CACHE)
ebe6df72f1309135f02b6a4d2aef1e81a073f91cTimo Sirainen return mail_set_aborted(mail);
ebe6df72f1309135f02b6a4d2aef1e81a073f91cTimo Sirainen
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen if (imail->data.access_part != 0 && imail->data.stream == NULL) {
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen /* we're going to open the mail anyway */
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen struct istream *input;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen (void)mail_get_stream(mail, NULL, NULL, &input);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen }
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen if (imail->data.stream != NULL) {
1eb17e61d3d38372674aa0c55caedb0185a985f5Timo Sirainen imail->mail.stats_fstat_lookup_count++;
ee1a3e217279dcd0f1cccbd3442e481b7dc90f05Timo Sirainen stp = i_stream_stat(imail->data.stream, FALSE);
ee1a3e217279dcd0f1cccbd3442e481b7dc90f05Timo Sirainen if (stp == NULL)
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen return -1;
ee1a3e217279dcd0f1cccbd3442e481b7dc90f05Timo Sirainen *st = *stp;
3eb63515855f386449c22233d1f1baf1ddfe8a2dTimo Sirainen } else if (!mail->saving) {
1eb17e61d3d38372674aa0c55caedb0185a985f5Timo Sirainen imail->mail.stats_stat_lookup_count++;
e9d29ae46d435aee85514decfe6ee27399ebf794Timo Sirainen ret = maildir_file_do(mbox, mail->uid, do_stat, st);
e9d29ae46d435aee85514decfe6ee27399ebf794Timo Sirainen if (ret <= 0) {
e9d29ae46d435aee85514decfe6ee27399ebf794Timo Sirainen if (ret == 0)
e9d29ae46d435aee85514decfe6ee27399ebf794Timo Sirainen mail_set_expunged(mail);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen return -1;
e9d29ae46d435aee85514decfe6ee27399ebf794Timo Sirainen }
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen } else {
1eb17e61d3d38372674aa0c55caedb0185a985f5Timo Sirainen imail->mail.stats_stat_lookup_count++;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen path = maildir_save_file_get_path(mail->transaction, mail->seq);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (stat(path, st) < 0) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen mail_storage_set_critical(mail->box->storage,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen "stat(%s) failed: %m", path);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen return -1;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen return 0;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen}
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic int maildir_mail_get_received_date(struct mail *_mail, time_t *date_r)
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen{
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen struct index_mail_data *data = &mail->data;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen struct stat st;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if (index_mail_get_received_date(_mail, date_r) == 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return 0;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen if (maildir_mail_stat(_mail, &st) < 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen *date_r = data->received_date = st.st_mtime;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic int maildir_mail_get_save_date(struct mail *_mail, time_t *date_r)
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen{
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen struct index_mail_data *data = &mail->data;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen struct stat st;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if (index_mail_get_save_date(_mail, date_r) == 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return 0;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen if (maildir_mail_stat(_mail, &st) < 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return -1;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen *date_r = data->save_date = st.st_ctime;
51078c3413b7ed4811bc725acbb1289723361ba9Timo Sirainen return 0;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen}
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainenstatic int
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainenmaildir_mail_get_fname(struct maildir_mailbox *mbox, struct mail *mail,
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainen const char **fname_r)
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainen{
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainen enum maildir_uidlist_rec_flag flags;
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen struct mail_index_view *view;
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen uint32_t seq;
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen bool exists;
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen int ret;
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainen
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen ret = maildir_uidlist_lookup(mbox->uidlist, mail->uid, &flags, fname_r);
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen if (ret != 0)
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen return ret;
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen /* file exists in index file, but not in dovecot-uidlist anymore. */
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen mail_set_expunged(mail);
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen /* one reason this could happen is if we delayed opening
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen dovecot-uidlist and we're trying to open a mail that got recently
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen expunged. Let's test this theory first: */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen (void)mail_index_refresh(mbox->box.index);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen view = mail_index_view_open(mbox->box.index);
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen exists = mail_index_lookup_seq(view, mail->uid, &seq);
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen mail_index_view_close(&view);
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen if (exists) {
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen /* the message still exists in index. this means there's some
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen kind of a desync, which doesn't get fixed if cur/ mtime is
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen the same as in index. fix this by forcing a resync. */
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen (void)maildir_storage_sync_force(mbox, mail->uid);
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainen }
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen return 0;
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainen}
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainen
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainenstatic int maildir_get_pop3_state(struct index_mail *mail)
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mailbox *box = mail->mail.mail.box;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen const struct mail_cache_field *fields;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen unsigned int i, count, psize_idx, vsize_idx;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen enum mail_cache_decision_type dec, vsize_dec;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen enum mail_fetch_field allowed_pop3_fields;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen bool not_pop3_only = FALSE;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen if (mail->pop3_state_set)
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen return mail->pop3_state;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen /* if this mail itself has non-pop3 fields we know we're not
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen pop3-only */
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen allowed_pop3_fields = MAIL_FETCH_FLAGS | MAIL_FETCH_STREAM_HEADER |
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen MAIL_FETCH_STREAM_BODY | MAIL_FETCH_UIDL_FILE_NAME |
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen MAIL_FETCH_VIRTUAL_SIZE;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen if (mail->wanted_headers != NULL ||
8b58939517a381db55670089c0984da39fc0f099Timo Sirainen (mail->wanted_fields & ~allowed_pop3_fields) != 0)
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen not_pop3_only = TRUE;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen /* get vsize decisions */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen psize_idx = ibox->cache_fields[MAIL_CACHE_PHYSICAL_FULL_SIZE].idx;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen vsize_idx = ibox->cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen if (not_pop3_only) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen vsize_dec = mail_cache_field_get_decision(box->cache,
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen vsize_idx);
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen vsize_dec &= ~MAIL_CACHE_DECISION_FORCED;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen } else {
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen /* also check if there are any non-[pv]size cached fields */
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen vsize_dec = MAIL_CACHE_DECISION_NO;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen fields = mail_cache_register_get_list(box->cache,
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen pool_datastack_create(),
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen &count);
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen for (i = 0; i < count; i++) {
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen if (fields[i].idx == vsize_idx)
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen vsize_dec = dec;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen else if (dec != MAIL_CACHE_DECISION_NO &&
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen fields[i].idx != psize_idx)
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen not_pop3_only = TRUE;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen }
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen }
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen if (!not_pop3_only) {
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen /* either nothing is cached, or only vsize is cached. */
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen mail->pop3_state = 1;
236bedf76e31651ea9fca63fbdc25be673819526Timo Sirainen } else if (vsize_dec != MAIL_CACHE_DECISION_YES &&
d22301419109ed4a38351715e6760011421dadecTimo Sirainen (box->flags & MAILBOX_FLAG_POP3_SESSION) == 0) {
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen /* if virtual size isn't cached permanently,
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen POP3 isn't being used */
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen mail->pop3_state = -1;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen } else {
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen /* possibly a mixed pop3/imap */
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen mail->pop3_state = 0;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen }
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen mail->pop3_state_set = TRUE;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen return mail->pop3_state;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen}
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainenstatic int maildir_quick_size_lookup(struct index_mail *mail, bool vsize,
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen uoff_t *size_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen struct mail *_mail = &mail->mail.mail;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen enum maildir_uidlist_rec_ext_key key;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen const char *path, *fname, *value;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
3eb63515855f386449c22233d1f1baf1ddfe8a2dTimo Sirainen if (!_mail->saving) {
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return -1;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen } else {
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen path = maildir_save_file_get_path(_mail->transaction,
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen _mail->seq);
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen fname = strrchr(path, '/');
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen fname = fname != NULL ? fname + 1 : path;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* size can be included in filename */
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen if (maildir_filename_get_size(fname,
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen vsize ? MAILDIR_EXTRA_VIRTUAL_SIZE :
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen MAILDIR_EXTRA_FILE_SIZE,
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen size_r))
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen return 1;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen /* size can be included in uidlist entry */
3eb63515855f386449c22233d1f1baf1ddfe8a2dTimo Sirainen if (!_mail->saving) {
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen key = vsize ? MAILDIR_UIDLIST_REC_EXT_VSIZE :
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen MAILDIR_UIDLIST_REC_EXT_PSIZE;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen value = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen key);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (value != NULL && str_to_uoff(value, size_r) == 0)
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen return 0;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainenstatic void
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainenmaildir_handle_size_caching(struct index_mail *mail, bool quick_check,
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen bool vsize)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mailbox *box = mail->mail.mail.box;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen enum mail_fetch_field field;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen uoff_t size;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen int pop3_state;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen field = vsize ? MAIL_FETCH_VIRTUAL_SIZE : MAIL_FETCH_PHYSICAL_SIZE;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen if ((mail->data.dont_cache_fetch_fields & field) != 0)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen return;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
55b6e3105184ad6a2f987346380966f556300055Timo Sirainen if (quick_check && maildir_quick_size_lookup(mail, vsize, &size) > 0) {
7aeaf23f760d86aad525d831efcac9f860a55a39Timo Sirainen /* already in filename / uidlist. don't add it anywhere,
cf49fc07f541c0f74578ac6c3b334ddade143aa1Timo Sirainen including to the uidlist if it's already in filename.
cf49fc07f541c0f74578ac6c3b334ddade143aa1Timo Sirainen do some extra checks here to catch potential cache bugs. */
cf49fc07f541c0f74578ac6c3b334ddade143aa1Timo Sirainen if (vsize && mail->data.virtual_size != size) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_cache_set_corrupted(box->cache,
63aaafe7e6b201d6633f8c25610ecd30c9cda99cTimo Sirainen "Corrupted virtual size for uid=%u: "
cf49fc07f541c0f74578ac6c3b334ddade143aa1Timo Sirainen "%"PRIuUOFF_T" != %"PRIuUOFF_T,
63aaafe7e6b201d6633f8c25610ecd30c9cda99cTimo Sirainen mail->mail.mail.uid,
cf49fc07f541c0f74578ac6c3b334ddade143aa1Timo Sirainen mail->data.virtual_size, size);
2ff23d6fb7e2ff85aa23b7f4769aeac1d0316a1bTimo Sirainen mail->data.virtual_size = size;
cf49fc07f541c0f74578ac6c3b334ddade143aa1Timo Sirainen } else if (!vsize && mail->data.physical_size != size) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_cache_set_corrupted(box->cache,
63aaafe7e6b201d6633f8c25610ecd30c9cda99cTimo Sirainen "Corrupted physical size for uid=%u: "
cf49fc07f541c0f74578ac6c3b334ddade143aa1Timo Sirainen "%"PRIuUOFF_T" != %"PRIuUOFF_T,
63aaafe7e6b201d6633f8c25610ecd30c9cda99cTimo Sirainen mail->mail.mail.uid,
cf49fc07f541c0f74578ac6c3b334ddade143aa1Timo Sirainen mail->data.physical_size, size);
2ff23d6fb7e2ff85aa23b7f4769aeac1d0316a1bTimo Sirainen mail->data.physical_size = size;
cf49fc07f541c0f74578ac6c3b334ddade143aa1Timo Sirainen }
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen mail->data.dont_cache_fetch_fields |= field;
7aeaf23f760d86aad525d831efcac9f860a55a39Timo Sirainen return;
7aeaf23f760d86aad525d831efcac9f860a55a39Timo Sirainen }
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen /* 1 = pop3-only, 0 = mixed, -1 = no pop3 */
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen pop3_state = maildir_get_pop3_state(mail);
18065635d4e79dd96eb3b3215718abd12f6a6808Timo Sirainen if (pop3_state >= 0 && mail->mail.mail.uid != 0) {
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen /* if size is wanted permanently, store it to uidlist
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen so that in case cache file gets lost we can get it quickly */
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen mail->data.dont_cache_fetch_fields |= field;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen size = vsize ? mail->data.virtual_size :
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen mail->data.physical_size;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen maildir_uidlist_set_ext(mbox->uidlist, mail->mail.mail.uid,
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen vsize ? MAILDIR_UIDLIST_REC_EXT_VSIZE :
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen MAILDIR_UIDLIST_REC_EXT_PSIZE,
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen dec2str(size));
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen }
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen}
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainenstatic int maildir_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen{
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen struct index_mail_data *data = &mail->data;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen struct message_size hdr_size, body_size;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen struct istream *input;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen uoff_t old_offset;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if (index_mail_get_cached_virtual_size(mail, size_r)) {
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen i_assert(mail->data.virtual_size != (uoff_t)-1);
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen maildir_handle_size_caching(mail, TRUE, TRUE);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen return 0;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen }
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen if (maildir_quick_size_lookup(mail, TRUE, &data->virtual_size) < 0)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen return -1;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if (data->virtual_size != (uoff_t)-1) {
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen data->dont_cache_fetch_fields |= MAIL_FETCH_VIRTUAL_SIZE;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen *size_r = data->virtual_size;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen return 0;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen }
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen /* fallback to reading the file */
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen return -1;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen i_stream_seek(data->stream, old_offset);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen maildir_handle_size_caching(mail, FALSE, TRUE);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen *size_r = data->virtual_size;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return 0;
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen}
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainenstatic int maildir_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen{
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen struct index_mail_data *data = &mail->data;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen struct stat st;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen const char *path;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen int ret;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen if (index_mail_get_physical_size(_mail, size_r) == 0) {
9fdd27b307347a06871ddab74b165122c878553cTimo Sirainen i_assert(mail->data.physical_size != (uoff_t)-1);
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen maildir_handle_size_caching(mail, TRUE, FALSE);
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen return 0;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen }
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen if (maildir_quick_size_lookup(mail, FALSE, &data->physical_size) < 0)
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen return -1;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen if (data->physical_size != (uoff_t)-1) {
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen data->dont_cache_fetch_fields |= MAIL_FETCH_PHYSICAL_SIZE;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen *size_r = data->physical_size;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen return 0;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen }
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen
3eb63515855f386449c22233d1f1baf1ddfe8a2dTimo Sirainen if (!_mail->saving) {
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen ret = maildir_file_do(mbox, _mail->uid, do_stat, &st);
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen if (ret <= 0) {
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen if (ret == 0)
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen mail_set_expunged(_mail);
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen return -1;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen }
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen } else {
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen /* saved mail which hasn't been committed yet */
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen path = maildir_save_file_get_path(_mail->transaction,
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen _mail->seq);
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen if (stat(path, &st) < 0) {
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen mail_storage_set_critical(_mail->box->storage,
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen "stat(%s) failed: %m", path);
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen return -1;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen }
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen }
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen data->physical_size = st.st_size;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen maildir_handle_size_caching(mail, FALSE, FALSE);
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen *size_r = st.st_size;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen return 0;
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen}
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic int
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenmaildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen const char **value_r)
366d6311c9d5bac6613e3cd64619eb878adce9ecTimo Sirainen{
366d6311c9d5bac6613e3cd64619eb878adce9ecTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box;
24cd47a2c8f7507e555459b7e841de771ba3c318Timo Sirainen const char *path, *fname = NULL, *end, *guid, *uidl;
366d6311c9d5bac6613e3cd64619eb878adce9ecTimo Sirainen
b19a1420da0618a10edf67c2cfd13c8c8633057aTimo Sirainen switch (field) {
b19a1420da0618a10edf67c2cfd13c8c8633057aTimo Sirainen case MAIL_FETCH_GUID:
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen /* use GUID from uidlist if it exists */
24cd47a2c8f7507e555459b7e841de771ba3c318Timo Sirainen i_assert(!_mail->saving);
24cd47a2c8f7507e555459b7e841de771ba3c318Timo Sirainen
24cd47a2c8f7507e555459b7e841de771ba3c318Timo Sirainen /* first make sure that we have a refreshed uidlist */
24cd47a2c8f7507e555459b7e841de771ba3c318Timo Sirainen if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0)
24cd47a2c8f7507e555459b7e841de771ba3c318Timo Sirainen return -1;
24cd47a2c8f7507e555459b7e841de771ba3c318Timo Sirainen
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen guid = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen MAILDIR_UIDLIST_REC_EXT_GUID);
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen if (guid != NULL) {
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen *value_r = guid;
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen return 0;
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen }
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen /* default to base filename: */
e4e7475f646d66a257d682738fbff1f206ce4924Timo Sirainen case MAIL_FETCH_UIDL_FILE_NAME:
129cc29ae6d8ad64d6d2b72f18da18fa134d0f3eTimo Sirainen if (mail->data.guid != NULL) {
129cc29ae6d8ad64d6d2b72f18da18fa134d0f3eTimo Sirainen *value_r = mail->data.guid;
129cc29ae6d8ad64d6d2b72f18da18fa134d0f3eTimo Sirainen return 0;
129cc29ae6d8ad64d6d2b72f18da18fa134d0f3eTimo Sirainen }
24cd47a2c8f7507e555459b7e841de771ba3c318Timo Sirainen if (fname != NULL) {
24cd47a2c8f7507e555459b7e841de771ba3c318Timo Sirainen /* we came here from MAIL_FETCH_GUID,
24cd47a2c8f7507e555459b7e841de771ba3c318Timo Sirainen avoid a second lookup */
24cd47a2c8f7507e555459b7e841de771ba3c318Timo Sirainen } else if (!_mail->saving) {
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return -1;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen } else {
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen path = maildir_save_file_get_path(_mail->transaction,
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen _mail->seq);
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen fname = strrchr(path, '/');
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen fname = fname != NULL ? fname + 1 : path;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen }
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen end = strchr(fname, MAILDIR_INFO_SEP);
129cc29ae6d8ad64d6d2b72f18da18fa134d0f3eTimo Sirainen mail->data.guid = end == NULL ?
129cc29ae6d8ad64d6d2b72f18da18fa134d0f3eTimo Sirainen p_strdup(mail->data_pool, fname) :
129cc29ae6d8ad64d6d2b72f18da18fa134d0f3eTimo Sirainen p_strdup_until(mail->data_pool, fname, end);
129cc29ae6d8ad64d6d2b72f18da18fa134d0f3eTimo Sirainen *value_r = mail->data.guid;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return 0;
b19a1420da0618a10edf67c2cfd13c8c8633057aTimo Sirainen case MAIL_FETCH_UIDL_BACKEND:
e76c494ad6535d3de314cc0d3ac7a44b06e53c4bTimo Sirainen uidl = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
e76c494ad6535d3de314cc0d3ac7a44b06e53c4bTimo Sirainen MAILDIR_UIDLIST_REC_EXT_POP3_UIDL);
89fb98e9eb7e95255a579c8e9d865383c2334a74Timo Sirainen if (uidl == NULL) {
89fb98e9eb7e95255a579c8e9d865383c2334a74Timo Sirainen /* use the default */
89fb98e9eb7e95255a579c8e9d865383c2334a74Timo Sirainen *value_r = "";
89fb98e9eb7e95255a579c8e9d865383c2334a74Timo Sirainen } else if (*uidl == '\0') {
89fb98e9eb7e95255a579c8e9d865383c2334a74Timo Sirainen /* special optimization case: use the base file name */
89fb98e9eb7e95255a579c8e9d865383c2334a74Timo Sirainen return maildir_mail_get_special(_mail,
89fb98e9eb7e95255a579c8e9d865383c2334a74Timo Sirainen MAIL_FETCH_UIDL_FILE_NAME, value_r);
89fb98e9eb7e95255a579c8e9d865383c2334a74Timo Sirainen } else {
89fb98e9eb7e95255a579c8e9d865383c2334a74Timo Sirainen *value_r = uidl;
89fb98e9eb7e95255a579c8e9d865383c2334a74Timo Sirainen }
0d73d91d1a1809f173d433023ccf97e6ec5ba629Timo Sirainen return 0;
b19a1420da0618a10edf67c2cfd13c8c8633057aTimo Sirainen default:
b19a1420da0618a10edf67c2cfd13c8c8633057aTimo Sirainen return index_mail_get_special(_mail, field, value_r);
366d6311c9d5bac6613e3cd64619eb878adce9ecTimo Sirainen }
366d6311c9d5bac6613e3cd64619eb878adce9ecTimo Sirainen}
366d6311c9d5bac6613e3cd64619eb878adce9ecTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic int maildir_mail_get_stream(struct mail *_mail,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen struct message_size *hdr_size,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen struct message_size *body_size,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen struct istream **stream_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct index_mail_data *data = &mail->data;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool deleted;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (data->stream == NULL) {
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen data->stream = maildir_open_mail(mbox, _mail, &deleted);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen if (data->stream == NULL) {
910fa4e4204a73d3d24c03f3059dd24e727ca057Timo Sirainen if (deleted)
910fa4e4204a73d3d24c03f3059dd24e727ca057Timo Sirainen mail_set_expunged(_mail);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return -1;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainenstatic void maildir_update_pop3_uidl(struct mail *_mail, const char *uidl)
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen{
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box;
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen const char *fname;
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen if (maildir_mail_get_special(_mail, MAIL_FETCH_UIDL_FILE_NAME,
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen &fname) == 0 &&
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen strcmp(uidl, fname) == 0) {
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen /* special case optimization: empty UIDL means the same
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen as base filename */
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen uidl = "";
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen }
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen maildir_uidlist_set_ext(mbox->uidlist, _mail->uid,
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen MAILDIR_UIDLIST_REC_EXT_POP3_UIDL, uidl);
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen}
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainenstatic void maildir_mail_set_cache_corrupted(struct mail *_mail,
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen enum mail_fetch_field field)
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box;
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen enum maildir_uidlist_rec_flag flags;
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen const char *fname;
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen uoff_t size;
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen int ret;
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen if (field == MAIL_FETCH_VIRTUAL_SIZE) {
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen /* make sure it gets removed from uidlist.
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen if it's in file name, we can't really do more than log it. */
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen ret = maildir_uidlist_lookup(mbox->uidlist, _mail->uid,
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen &flags, &fname);
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen if (ret <= 0)
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen return;
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen &size)) {
e0645d5232900a5c574780ef0c0362a5b7581abaTimo Sirainen const char *subdir =
e0645d5232900a5c574780ef0c0362a5b7581abaTimo Sirainen (flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0 ?
e0645d5232900a5c574780ef0c0362a5b7581abaTimo Sirainen "new" : "cur";
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen mail_storage_set_critical(_mail->box->storage,
e0645d5232900a5c574780ef0c0362a5b7581abaTimo Sirainen "Maildir filename has wrong W value: %s/%s/%s",
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mbox->box.path, subdir, fname);
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen } else if (maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen MAILDIR_UIDLIST_REC_EXT_VSIZE) != NULL) {
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen maildir_uidlist_set_ext(mbox->uidlist, _mail->uid,
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen MAILDIR_UIDLIST_REC_EXT_VSIZE,
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen NULL);
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen }
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen }
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen index_mail_set_cache_corrupted(_mail, field);
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen}
8c9e48cd6de80da0fa32b9c0dee003472c9a7c0dTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenstruct mail_vfuncs maildir_mail_vfuncs = {
0d86aa0d47f7393c669c084b34c0537b193688adTimo Sirainen index_mail_close,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen index_mail_free,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen index_mail_set_seq,
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainen index_mail_set_uid,
aa247243412a49f9bdebf7255e131dc6ece4ed46Timo Sirainen index_mail_set_uid_cache_updates,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
439980f88f421039dea8335e92d3fa82b3f470a1Timo Sirainen index_mail_get_flags,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen index_mail_get_keywords,
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen index_mail_get_keyword_indexes,
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen index_mail_get_modseq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_get_parts,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_get_date,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen maildir_mail_get_received_date,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen maildir_mail_get_save_date,
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen maildir_mail_get_virtual_size,
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen maildir_mail_get_physical_size,
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen index_mail_get_first_header,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_get_headers,
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen index_mail_get_header_stream,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen maildir_mail_get_stream,
366d6311c9d5bac6613e3cd64619eb878adce9ecTimo Sirainen maildir_mail_get_special,
9af6cc9ebc9986c1275ebdfa29c39e152af1557eTimo Sirainen index_mail_get_real_mail,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_update_flags,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen index_mail_update_keywords,
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen index_mail_update_modseq,
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen maildir_update_pop3_uidl,
838e367716bbd5e44b4a1691db9cbf72af53e9f0Timo Sirainen index_mail_expunge,
61e27995aadbc2f97927d3635f98d1d4ac4751e0Timo Sirainen maildir_mail_set_cache_corrupted
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};