mbox-mail.c revision e6aa82aeb50948cb47a45a1b61a9c16d6a162388
183bea41fa640dc8117f3eb45ff935cd81377a84Timo Sirainen/* Copyright (c) 2003-2011 Dovecot authors, see the included COPYING file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "lib.h"
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen#include "ioloop.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "istream.h"
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen#include "hex-binary.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "index-mail.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-storage.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-file.h"
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen#include "mbox-lock.h"
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen#include "mbox-sync-private.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "istream-raw-mbox.h"
18565c69efcd7db003dbf27cf625ed822e889fb1Timo Sirainen#include "istream-header-filter.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <fcntl.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <unistd.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <sys/stat.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstatic void mbox_prepare_resync(struct mail *mail)
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen{
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen struct mbox_transaction_context *t =
d22301419109ed4a38351715e6760011421dadecTimo Sirainen (struct mbox_transaction_context *)mail->transaction;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mbox_mailbox *mbox = (struct mbox_mailbox *)mail->box;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (mbox->mbox_lock_type == F_RDLCK) {
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (mbox->mbox_lock_id == t->mbox_lock_id)
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen t->mbox_lock_id = 0;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen (void)mbox_unlock(mbox, mbox->mbox_lock_id);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen i_assert(mbox->mbox_lock_type == F_UNLCK);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen }
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen}
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic int mbox_mail_seek(struct index_mail *mail)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
af1f4b17a92ca7b2661737e65c7849df289d3070Timo Sirainen struct mbox_transaction_context *t =
af1f4b17a92ca7b2661737e65c7849df289d3070Timo Sirainen (struct mbox_transaction_context *)mail->trans;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mail *_mail = &mail->mail.mail;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mbox_mailbox *mbox = (struct mbox_mailbox *)_mail->box;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen enum mbox_sync_flags sync_flags = 0;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen int ret, try;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool deleted;
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (_mail->expunged || mbox->syncing)
4b41116563110d00330896a568eff1078c382827Timo Sirainen return -1;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (_mail->lookup_abort != MAIL_LOOKUP_ABORT_NEVER)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return mail_set_aborted(_mail);
ebe6df72f1309135f02b6a4d2aef1e81a073f91cTimo Sirainen
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen if (mbox->mbox_stream != NULL &&
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen istream_raw_mbox_is_corrupted(mbox->mbox_stream)) {
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen /* clear the corruption by forcing a full resync */
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen sync_flags |= MBOX_SYNC_UNDIRTY | MBOX_SYNC_FORCE_SYNC;
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen }
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen for (try = 0; try < 2; try++) {
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen if ((sync_flags & MBOX_SYNC_FORCE_SYNC) != 0) {
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen /* dirty offsets are broken. make sure we can sync. */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mbox_prepare_resync(_mail);
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen }
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (mbox->mbox_lock_type == F_UNLCK) {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen sync_flags |= MBOX_SYNC_LOCK_READING;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (mbox_sync(mbox, sync_flags) < 0)
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen return -1;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen t->mbox_lock_id = mbox->mbox_lock_id;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen i_assert(t->mbox_lock_id != 0);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen /* refresh index file after mbox has been locked to
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen make sure we get only up-to-date mbox offsets. */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (mail_index_refresh(mbox->box.index) < 0) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_storage_set_index_error(&mbox->box);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen return -1;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen }
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen i_assert(mbox->mbox_lock_type != F_UNLCK);
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen } else if (t->mbox_lock_id == 0) {
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen /* file is already locked by another transaction, but
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen we must keep it locked for the entire transaction,
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen so increase the lock counter. */
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen if (mbox_lock(mbox, mbox->mbox_lock_type,
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen &t->mbox_lock_id) < 0)
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen i_unreached();
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen }
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (mbox_file_open_stream(mbox) < 0)
597dce34068d603fb759b4dff404b34049213e51Timo Sirainen return -1;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen ret = mbox_file_seek(mbox, _mail->transaction->view,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen _mail->seq, &deleted);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (ret > 0) {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen /* success */
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen break;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen }
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (ret < 0) {
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (deleted)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_set_expunged(_mail);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* we'll need to re-sync it completely */
6060b7c8edf8fce73470d0df6a2479b69b01c537Timo Sirainen sync_flags |= MBOX_SYNC_UNDIRTY | MBOX_SYNC_FORCE_SYNC;
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen }
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (ret == 0) {
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen mail_storage_set_critical(&mbox->storage->storage,
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen "Losing sync for mail uid=%u in mbox file %s",
d22301419109ed4a38351715e6760011421dadecTimo Sirainen _mail->uid, mbox->box.path);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen }
4b41116563110d00330896a568eff1078c382827Timo Sirainen return 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic int mbox_mail_get_received_date(struct mail *_mail, time_t *date_r)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct index_mail_data *data = &mail->data;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mbox_mailbox *mbox = (struct mbox_mailbox *)_mail->box;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if (index_mail_get_received_date(_mail, date_r) == 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (mbox_mail_seek(mail) < 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen data->received_date =
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen istream_raw_mbox_get_received_time(mbox->mbox_stream);
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen if (data->received_date == (time_t)-1) {
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen /* it's broken and conflicts with our "not found"
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen return value. change it. */
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen data->received_date = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen *date_r = data->received_date;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic int mbox_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
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if (index_mail_get_save_date(_mail, date_r) == 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return 0;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen /* no way to know this. save the current time into cache and use
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen that from now on. this works only as long as the index files
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen are permanent */
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen data->save_date = ioloop_time;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen *date_r = data->save_date;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return 0;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen}
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainenstatic bool
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainenmbox_mail_get_md5_header(struct index_mail *mail, const char **value_r)
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen{
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen static uint8_t empty_md5[16] =
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mbox_mailbox *mbox = (struct mbox_mailbox *)mail->mail.mail.box;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen const void *ext_data;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen
e6aa82aeb50948cb47a45a1b61a9c16d6a162388Timo Sirainen if (mail->data.guid != NULL) {
e6aa82aeb50948cb47a45a1b61a9c16d6a162388Timo Sirainen *value_r = mail->data.guid;
e6aa82aeb50948cb47a45a1b61a9c16d6a162388Timo Sirainen return TRUE;
e6aa82aeb50948cb47a45a1b61a9c16d6a162388Timo Sirainen }
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen mail_index_lookup_ext(mail->mail.mail.transaction->view,
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen mail->mail.mail.seq, mbox->md5hdr_ext_idx,
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen &ext_data, NULL);
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen if (ext_data != NULL && memcmp(ext_data, empty_md5, 16) != 0) {
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen mail->data.guid = p_strdup(mail->data_pool,
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen binary_to_hex(ext_data, 16));
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen *value_r = mail->data.guid;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen return TRUE;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen } else {
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen return FALSE;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen }
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen}
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic int
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenmbox_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen const char **value_r)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mbox_mailbox *mbox = (struct mbox_mailbox *)_mail->box;
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen uoff_t offset;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen switch (field) {
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen case MAIL_FETCH_FROM_ENVELOPE:
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (mbox_mail_seek(mail) < 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen *value_r = istream_raw_mbox_get_sender(mbox->mbox_stream);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return 0;
ee3e01f75b1db691bf20dd4e2558965421b8f937Timo Sirainen case MAIL_FETCH_GUID:
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen case MAIL_FETCH_HEADER_MD5:
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen if (mbox_mail_get_md5_header(mail, value_r))
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen return 0;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen /* i guess in theory the empty_md5 is valid and can happen,
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen but it's almost guaranteed that it means the MD5 sum is
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen missing. recalculate it. */
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen offset = mbox->mbox_lock_type == F_UNLCK ? 0 :
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen istream_raw_mbox_get_start_offset(mbox->mbox_stream);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen mbox->mbox_save_md5 = TRUE;
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen if (mbox_sync(mbox, MBOX_SYNC_FORCE_SYNC |
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen MBOX_SYNC_READONLY) < 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return -1;
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen if (mbox->mbox_lock_type != F_UNLCK) {
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen if (istream_raw_mbox_seek(mbox->mbox_stream,
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen offset) < 0) {
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen i_error("mbox %s sync lost during MD5 syncing",
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen _mail->box->name);
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen return -1;
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen }
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen }
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen if (!mbox_mail_get_md5_header(mail, value_r)) {
e48c10b9db945fd72e2315e3ec343174fa55c7c7Timo Sirainen i_error("mbox %s resyncing didn't save header MD5 values",
e48c10b9db945fd72e2315e3ec343174fa55c7c7Timo Sirainen _mail->box->name);
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen return -1;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen }
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen return 0;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen default:
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen break;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return index_mail_get_special(_mail, field, value_r);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainenstatic bool
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainenmbox_mail_get_next_offset(struct index_mail *mail, uoff_t *next_offset_r)
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mbox_mailbox *mbox = (struct mbox_mailbox *)mail->mail.mail.box;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen struct mail_index_view *view;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen const struct mail_index_header *hdr;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen uint32_t seq;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen int trailer_size;
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen int ret = 1;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen hdr = mail_index_get_header(mail->mail.mail.transaction->view);
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen if (mail->mail.mail.seq > hdr->messages_count) {
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen /* we're appending a new message */
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen return 0;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen }
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen /* We can't really trust trans_view. The next message may already be
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen expunged from it. Also hdr.messages_count may be incorrect there.
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen So refresh the index to get the latest changes and get the next
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen message's offset using a new view. */
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen i_assert(mbox->mbox_lock_type != F_UNLCK);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (mbox_sync_header_refresh(mbox) < 0)
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen return -1;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen view = mail_index_view_open(mail->mail.mail.box->index);
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen hdr = mail_index_get_header(view);
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen if (!mail_index_lookup_seq(view, mail->mail.mail.uid, &seq))
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen i_panic("Message unexpectedly expunged from index");
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen if (seq == hdr->messages_count) {
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen /* last message, use the synced mbox size */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen trailer_size =
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mbox->storage->storage.set->mail_save_crlf ? 2 : 1;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen *next_offset_r = mbox->mbox_hdr.sync_size - trailer_size;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen } else {
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen if (mbox_file_lookup_offset(mbox, view, seq + 1,
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen next_offset_r) <= 0)
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen ret = -1;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen }
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen mail_index_view_close(&view);
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen return ret;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen}
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic int mbox_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen{
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen struct index_mail_data *data = &mail->data;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mbox_mailbox *mbox = (struct mbox_mailbox *)_mail->box;
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen struct istream *input;
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen struct message_size hdr_size;
a5c8dc283ef673fcdae158513b8032e74b45f59aTimo Sirainen uoff_t old_offset, body_offset, body_size, next_offset;
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen if (index_mail_get_physical_size(_mail, size_r) == 0)
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen return 0;
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen /* we want to return the header size as seen by mail_get_stream(). */
a5c8dc283ef673fcdae158513b8032e74b45f59aTimo Sirainen old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen if (mail_get_stream(_mail, &hdr_size, NULL, &input) < 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return -1;
a1808be0774cbcb28fec45341aabf803ec44bae5Timo Sirainen
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen /* our header size varies, so don't do any caching */
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen body_offset = istream_raw_mbox_get_body_offset(mbox->mbox_stream);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (body_offset == (uoff_t)-1) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen mail_storage_set_critical(_mail->box->storage,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen "Couldn't get mbox size");
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return -1;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen }
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen /* use the next message's offset to avoid reading through the entire
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen message body to find out its size */
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen if (mbox_mail_get_next_offset(mail, &next_offset) > 0)
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen body_size = next_offset - body_offset;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen else
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen body_size = (uoff_t)-1;
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen /* verify that the calculated body size is correct */
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen body_size = istream_raw_mbox_get_body_size(mbox->mbox_stream,
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen body_size);
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen data->physical_size = hdr_size.physical_size + body_size;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen *size_r = data->physical_size;
a5c8dc283ef673fcdae158513b8032e74b45f59aTimo Sirainen
a5c8dc283ef673fcdae158513b8032e74b45f59aTimo Sirainen i_stream_seek(input, old_offset);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return 0;
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen}
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainenstatic int mbox_mail_init_stream(struct index_mail *mail)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mbox_mailbox *mbox = (struct mbox_mailbox *)mail->mail.mail.box;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen struct istream *raw_stream;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen uoff_t hdr_offset, next_offset;
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen int ret;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (mbox_mail_seek(mail) < 0)
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen return -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen ret = mbox_mail_get_next_offset(mail, &next_offset);
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen if (ret < 0) {
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (mbox_mail_seek(mail) < 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return -1;
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen ret = mbox_mail_get_next_offset(mail, &next_offset);
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen if (ret < 0) {
f480b30abdddf6f1beb8a2c5b1ce4bf8999400dbTimo Sirainen i_warning("mbox %s: Can't find next message offset "
f480b30abdddf6f1beb8a2c5b1ce4bf8999400dbTimo Sirainen "for uid=%u",
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mbox->box.path, mail->mail.mail.uid);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen }
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen }
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen if (ret <= 0)
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen next_offset = (uoff_t)-1;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen raw_stream = mbox->mbox_stream;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen hdr_offset = istream_raw_mbox_get_header_offset(raw_stream);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen i_stream_seek(raw_stream, hdr_offset);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (next_offset != (uoff_t)-1)
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen istream_raw_mbox_set_next_offset(raw_stream, next_offset);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen raw_stream = i_stream_create_limit(raw_stream, (uoff_t)-1);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen mail->data.stream =
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen i_stream_create_header_filter(raw_stream,
8f017a40470ef2f4b530000d947a8bce44350a5eTimo Sirainen HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR,
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen mbox_hide_headers, mbox_hide_headers_count,
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen null_header_filter_callback, NULL);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen i_stream_unref(&raw_stream);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen return 0;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen}
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainenstatic int mbox_mail_get_stream(struct mail *_mail,
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen struct message_size *hdr_size,
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen struct message_size *body_size,
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen struct istream **stream_r)
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen{
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (mail->data.stream == NULL) {
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (mbox_mail_init_stream(mail) < 0)
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen return -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainenstatic void mbox_mail_set_seq(struct mail *_mail, uint32_t seq)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen{
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen index_mail_set_seq(_mail, seq);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen mail->data.dont_cache_fetch_fields |= MAIL_FETCH_PHYSICAL_SIZE;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen}
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainenstatic bool mbox_mail_set_uid(struct mail *_mail, uint32_t uid)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen{
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen bool ret;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen ret = index_mail_set_uid(_mail, uid);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen mail->data.dont_cache_fetch_fields |= MAIL_FETCH_PHYSICAL_SIZE;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen return ret;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen}
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenstruct mail_vfuncs mbox_mail_vfuncs = {
0d86aa0d47f7393c669c084b34c0537b193688adTimo Sirainen index_mail_close,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen index_mail_free,
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen mbox_mail_set_seq,
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen mbox_mail_set_uid,
aa247243412a49f9bdebf7255e131dc6ece4ed46Timo Sirainen index_mail_set_uid_cache_updates,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen index_mail_get_flags,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen index_mail_get_keywords,
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen index_mail_get_keyword_indexes,
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen index_mail_get_modseq,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen index_mail_get_parts,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen index_mail_get_date,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen mbox_mail_get_received_date,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen mbox_mail_get_save_date,
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen index_mail_get_virtual_size,
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen mbox_mail_get_physical_size,
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen index_mail_get_first_header,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen index_mail_get_headers,
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen index_mail_get_header_stream,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen mbox_mail_get_stream,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen mbox_mail_get_special,
9af6cc9ebc9986c1275ebdfa29c39e152af1557eTimo Sirainen index_mail_get_real_mail,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen index_mail_update_flags,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen index_mail_update_keywords,
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen index_mail_update_modseq,
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen NULL,
838e367716bbd5e44b4a1691db9cbf72af53e9f0Timo Sirainen index_mail_expunge,
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen index_mail_set_cache_corrupted,
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen index_mail_opened
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen};