pop3c-mail.c revision d2cf6522779802d0edeab7dcf960ffea2f2e1828
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2011-2013 Dovecot authors, see the included COPYING file */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "lib.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "istream.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "index-mail.h"
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi#include "pop3c-client.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "pop3c-sync.h"
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi#include "pop3c-storage.h"
c5f932968281763df360b9c97cef60f5f80d5e3dTimo Sirainen
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainenstatic int pop3c_mail_get_received_date(struct mail *_mail, time_t *date_r)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen int tz;
d951320d498ae0800b677b754dde71574102123bTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* FIXME: we could also parse the first Received: header and get
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen the date from there, but since this code is unlikely to be called
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen except during migration, I don't think it really matters. */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return index_mail_get_date(_mail, date_r, &tz);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic int pop3c_mail_get_save_date(struct mail *_mail, time_t *date_r)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct index_mail_data *data = &mail->data;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (data->save_date == (time_t)-1) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* FIXME: we could use a value stored in cache */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return pop3c_mail_get_received_date(_mail, date_r);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *date_r = data->save_date;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic int pop3c_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct message_size hdr_size, body_size;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct istream *input;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
a21f618de284dc22a480af1371d5f5cea50a39dfTimo Sirainen if (mail->data.virtual_size != (uoff_t)-1) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* virtual size is already known. it's the same as our
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen (correct) physical size */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *size_r = mail->data.virtual_size;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (index_mail_get_physical_size(_mail, size_r) == 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *size_r = mail->data.physical_size;
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen if (_mail->lookup_abort == MAIL_LOOKUP_ABORT_READ_MAIL &&
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen (_mail->box->flags & MAILBOX_FLAG_POP3_SESSION) != 0) {
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen /* kludge: we want output for POP3 LIST with
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen pop3_fast_size_lookups=yes. use the remote's LIST values
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen regardless of their correctness */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (mbox->msg_sizes == NULL) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (pop3c_sync_get_sizes(mbox) < 0)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_assert(_mail->seq <= mbox->msg_count);
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen *size_r = mbox->msg_sizes[_mail->seq-1];
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen return 0;
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen }
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* slow way: get the whole message body */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_assert(mail->data.physical_size != (uoff_t)-1);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *size_r = mail->data.physical_size;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic void pop3c_mail_cache_size(struct index_mail *mail)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct mail *_mail = &mail->mail.mail;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen uoff_t size;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen unsigned int cache_idx;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (i_stream_get_size(mail->data.stream, TRUE, &size) <= 0)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen mail->data.virtual_size = size;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen cache_idx = mail->ibox->cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (mail_cache_field_exists(_mail->transaction->cache_view,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen _mail->seq, cache_idx) == 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_cache_add_idx(mail, cache_idx, &size, sizeof(size));
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* make sure it's not cached twice */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen mail->data.dont_cache_fetch_fields |=
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen MAIL_CACHE_VIRTUAL_FULL_SIZE;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic int
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenpop3c_mail_get_stream(struct mail *_mail, bool get_body,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct message_size *hdr_size,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct message_size *body_size, struct istream **stream_r)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen enum pop3c_capability capa;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *name, *cmd, *error;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct istream *input;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (get_body && mail->data.stream != NULL) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen name = i_stream_get_name(mail->data.stream);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (strncmp(name, "RETR", 4) == 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* we've fetched the body */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen } else if (strncmp(name, "TOP", 3) == 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* we've fetched the header, but we need the body
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen now too */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_close_streams(mail);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen } else {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_panic("Unexpected POP3 stream name: %s", name);
a5b64f1abb1cb0a9718d5bf7f0ae808072237259Timo Sirainen }
a5b64f1abb1cb0a9718d5bf7f0ae808072237259Timo Sirainen }
a5b64f1abb1cb0a9718d5bf7f0ae808072237259Timo Sirainen
a5b64f1abb1cb0a9718d5bf7f0ae808072237259Timo Sirainen if (mail->data.stream == NULL) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen capa = pop3c_client_get_capabilities(mbox->client);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (get_body || (capa & POP3C_CAPABILITY_TOP) == 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen cmd = t_strdup_printf("RETR %u\r\n", _mail->seq);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen get_body = TRUE;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen } else {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen cmd = t_strdup_printf("TOP %u 0\r\n", _mail->seq);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (pop3c_client_cmd_stream(mbox->client, cmd,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen &input, &error) < 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen mail_storage_set_error(mbox->box.storage,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen !pop3c_client_is_connected(mbox->client) ?
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen MAIL_ERROR_TEMP : MAIL_ERROR_EXPUNGED, error);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen mail->data.stream = input;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (mail->mail.v.istream_opened != NULL) {
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi if (mail->mail.v.istream_opened(_mail,
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi &mail->data.stream) < 0) {
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi index_mail_close_streams(mail);
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi return -1;
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi }
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi }
d48e40d6c77d673ad402d96571198d1cce4da225Timo Sirainen i_stream_set_name(mail->data.stream, t_strcut(cmd, '\r'));
b78d8dbe4179aabcbf9fda41d282673558dae4d6Timo Sirainen if (get_body)
b78d8dbe4179aabcbf9fda41d282673558dae4d6Timo Sirainen pop3c_mail_cache_size(mail);
b78d8dbe4179aabcbf9fda41d282673558dae4d6Timo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomistatic int
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomipop3c_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi const char **value_r)
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi{
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
a327d9301f593433c228c4cc8cca05c95b37f6fbTimo Sirainen
8a4a0ef8264d95ffb2ba8f6f109f94ea7f3454e8Timo Sirainen switch (field) {
d48e40d6c77d673ad402d96571198d1cce4da225Timo Sirainen case MAIL_FETCH_UIDL_BACKEND:
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (mbox->msg_uidls == NULL) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (pop3c_sync_get_uidls(mbox) < 0)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return -1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_assert(_mail->seq <= mbox->msg_count);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *value_r = mbox->msg_uidls[_mail->seq-1];
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen default:
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return index_mail_get_special(_mail, field, value_r);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen}
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainenstruct mail_vfuncs pop3c_mail_vfuncs = {
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen index_mail_close,
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen index_mail_free,
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen index_mail_set_seq,
2c5c70e12365d7910848259f88eb237ce3a15947Timo Sirainen index_mail_set_uid,
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen index_mail_set_uid_cache_updates,
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen index_mail_prefetch,
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen index_mail_precache,
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen index_mail_add_temp_wanted_fields,
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen index_mail_get_flags,
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen index_mail_get_keywords,
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen index_mail_get_keyword_indexes,
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen index_mail_get_modseq,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_get_pvt_modseq,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_get_parts,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_get_date,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen pop3c_mail_get_received_date,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen pop3c_mail_get_save_date,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_get_virtual_size,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen pop3c_mail_get_physical_size,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_get_first_header,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_get_headers,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_get_header_stream,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen pop3c_mail_get_stream,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_get_binary_stream,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen pop3c_mail_get_special,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_get_real_mail,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_update_flags,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_update_keywords,
a618726eb3eb09a3866fe93208baf923d593f4d3Timo Sirainen index_mail_update_modseq,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_update_pvt_modseq,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen NULL,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_expunge,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen index_mail_set_cache_corrupted,
009217abb57a24a4076092e8e4e165545747839eStephan Bosch index_mail_opened
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen};
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen