bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "lib.h"
e130bb802c8bfb6c6cc44e5c8bc098b4fa5af789Timo Sirainen#include "ioloop.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "istream.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "index-mail.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "pop3c-client.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "pop3c-sync.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "pop3c-storage.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainenstruct mail *
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainenpop3c_mail_alloc(struct mailbox_transaction_context *t,
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen enum mail_fetch_field wanted_fields,
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen{
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen struct pop3c_mail *mail;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen pool_t pool;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen pool = pool_alloconly_create("mail", 2048);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen mail = p_new(pool, struct pop3c_mail, 1);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen mail->imail.mail.pool = pool;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen index_mail_init(&mail->imail, t, wanted_fields, wanted_headers);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen return &mail->imail.mail.mail;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen}
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainenstatic void pop3c_mail_close(struct mail *_mail)
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen{
120e61ccce21fd33d6b55b6f27346e1690b64bd8Josef 'Jeff' Sipek struct pop3c_mail *pmail = POP3C_MAIL(_mail);
95d62f8d6d281cc488dc4f488d4388701e559012Josef 'Jeff' Sipek struct pop3c_mailbox *mbox = POP3C_MAILBOX(_mail->box);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen /* wait for any prefetch to finish before closing the mail */
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen while (pmail->prefetching)
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen pop3c_client_wait_one(mbox->client);
204ee6ed414f5e4eeb6f6c10763b55daf56f11acJosef 'Jeff' Sipek i_stream_unref(&pmail->prefetch_stream);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen index_mail_close(_mail);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen}
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic int pop3c_mail_get_received_date(struct mail *_mail, time_t *date_r)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
95d62f8d6d281cc488dc4f488d4388701e559012Josef 'Jeff' Sipek struct pop3c_mailbox *mbox = POP3C_MAILBOX(_mail->box);
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen int tz;
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen
5f4e547bb810403e8cfb19a49d8fe34713507ffdTimo Sirainen if (mbox->storage->set->pop3c_quick_received_date) {
5f4e547bb810403e8cfb19a49d8fe34713507ffdTimo Sirainen /* we don't care about the date, just return the current date */
5f4e547bb810403e8cfb19a49d8fe34713507ffdTimo Sirainen *date_r = ioloop_time;
5f4e547bb810403e8cfb19a49d8fe34713507ffdTimo Sirainen return 0;
5f4e547bb810403e8cfb19a49d8fe34713507ffdTimo Sirainen }
5f4e547bb810403e8cfb19a49d8fe34713507ffdTimo Sirainen
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen /* FIXME: we could also parse the first Received: header and get
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen the date from there, but since this code is unlikely to be called
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen except during migration, I don't think it really matters. */
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen return index_mail_get_date(_mail, date_r, &tz);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic int pop3c_mail_get_save_date(struct mail *_mail, time_t *date_r)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
87490012895b4f371635ded00add04c9107dcfefJosef 'Jeff' Sipek struct index_mail *mail = INDEX_MAIL(_mail);
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen struct index_mail_data *data = &mail->data;
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen if (data->save_date == (time_t)-1) {
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen /* FIXME: we could use a value stored in cache */
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen return pop3c_mail_get_received_date(_mail, date_r);
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen }
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen *date_r = data->save_date;
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen return 0;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic int pop3c_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
87490012895b4f371635ded00add04c9107dcfefJosef 'Jeff' Sipek struct index_mail *mail = INDEX_MAIL(_mail);
95d62f8d6d281cc488dc4f488d4388701e559012Josef 'Jeff' Sipek struct pop3c_mailbox *mbox = POP3C_MAILBOX(_mail->box);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct message_size hdr_size, body_size;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct istream *input;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
fcb5f4cd72b413a5356a8db55e679403c6a1adb5Timo Sirainen if (mail->data.virtual_size != (uoff_t)-1) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* virtual size is already known. it's the same as our
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen (correct) physical size */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen *size_r = mail->data.virtual_size;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return 0;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (index_mail_get_physical_size(_mail, size_r) == 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen *size_r = mail->data.physical_size;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return 0;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (_mail->lookup_abort == MAIL_LOOKUP_ABORT_READ_MAIL &&
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen (_mail->box->flags & MAILBOX_FLAG_POP3_SESSION) != 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* kludge: we want output for POP3 LIST with
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen pop3_fast_size_lookups=yes. use the remote's LIST values
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen regardless of their correctness */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (mbox->msg_sizes == NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (pop3c_sync_get_sizes(mbox) < 0)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return -1;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_assert(_mail->seq <= mbox->msg_count);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen *size_r = mbox->msg_sizes[_mail->seq-1];
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return 0;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* slow way: get the whole message body */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return -1;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_assert(mail->data.physical_size != (uoff_t)-1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen *size_r = mail->data.physical_size;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return 0;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic void pop3c_mail_cache_size(struct index_mail *mail)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen uoff_t size;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (i_stream_get_size(mail->data.stream, TRUE, &size) <= 0)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail->data.virtual_size = size;
cee43a7b0fe3934efc863f533428989173682e0bTimo Sirainen /* it'll be actually added to index when closing the mail in
cee43a7b0fe3934efc863f533428989173682e0bTimo Sirainen index_mail_cache_sizes() */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
5f8d497e88fae77fbeb625246bc18260f6775b83Timo Sirainenstatic void
5f8d497e88fae77fbeb625246bc18260f6775b83Timo Sirainenpop3c_mail_prefetch_done(enum pop3c_command_state state,
5f8d497e88fae77fbeb625246bc18260f6775b83Timo Sirainen const char *reply ATTR_UNUSED, void *context)
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen{
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen struct pop3c_mail *pmail = context;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen switch (state) {
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen case POP3C_COMMAND_STATE_OK:
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen break;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen case POP3C_COMMAND_STATE_ERR:
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen case POP3C_COMMAND_STATE_DISCONNECTED:
84a5175b9768da401404635c9b606264585739bdTimo Sirainen i_stream_unref(&pmail->prefetch_stream);
f2686912e0156c04296d6dc306f39d61089a1363Timo Sirainen /* let pop3c_mail_get_stream() figure out the error handling.
f2686912e0156c04296d6dc306f39d61089a1363Timo Sirainen in case of a -ERR a retry might even work. */
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen break;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen }
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen pmail->prefetching = FALSE;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen}
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainenstatic bool pop3c_mail_prefetch(struct mail *_mail)
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen{
120e61ccce21fd33d6b55b6f27346e1690b64bd8Josef 'Jeff' Sipek struct pop3c_mail *pmail = POP3C_MAIL(_mail);
95d62f8d6d281cc488dc4f488d4388701e559012Josef 'Jeff' Sipek struct pop3c_mailbox *mbox = POP3C_MAILBOX(_mail->box);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen enum pop3c_capability capa;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen const char *cmd;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen if (pmail->imail.data.access_part != 0 &&
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen pmail->imail.data.stream == NULL) {
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen capa = pop3c_client_get_capabilities(mbox->client);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen pmail->prefetching_body = (capa & POP3C_CAPABILITY_TOP) == 0 ||
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen (pmail->imail.data.access_part & (READ_BODY | PARSE_BODY)) != 0;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen if (pmail->prefetching_body)
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen cmd = t_strdup_printf("RETR %u\r\n", _mail->seq);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen else
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen cmd = t_strdup_printf("TOP %u 0\r\n", _mail->seq);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen pmail->prefetching = TRUE;
84a5175b9768da401404635c9b606264585739bdTimo Sirainen pmail->prefetch_stream =
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen pop3c_client_cmd_stream_async(mbox->client, cmd,
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen pop3c_mail_prefetch_done, pmail);
84a5175b9768da401404635c9b606264585739bdTimo Sirainen i_stream_set_name(pmail->prefetch_stream, t_strcut(cmd, '\r'));
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen return !pmail->prefetching;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen }
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen return index_mail_prefetch(_mail);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen}
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic int
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenpop3c_mail_get_stream(struct mail *_mail, bool get_body,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct message_size *hdr_size,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct message_size *body_size, struct istream **stream_r)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
120e61ccce21fd33d6b55b6f27346e1690b64bd8Josef 'Jeff' Sipek struct pop3c_mail *pmail = POP3C_MAIL(_mail);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen struct index_mail *mail = &pmail->imail;
95d62f8d6d281cc488dc4f488d4388701e559012Josef 'Jeff' Sipek struct pop3c_mailbox *mbox = POP3C_MAILBOX(_mail->box);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen enum pop3c_capability capa;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen const char *name, *cmd, *error;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct istream *input;
dc7a24adeabfc9372a9d5fe34e7f8761e325ed68Timo Sirainen bool new_stream = FALSE;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen if ((mail->data.access_part & (READ_BODY | PARSE_BODY)) != 0)
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen get_body = TRUE;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen while (pmail->prefetching) {
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen /* wait for prefetch to finish */
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen pop3c_client_wait_one(mbox->client);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen }
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
84a5175b9768da401404635c9b606264585739bdTimo Sirainen if (pmail->prefetch_stream != NULL && mail->data.stream == NULL) {
84a5175b9768da401404635c9b606264585739bdTimo Sirainen mail->data.stream = pmail->prefetch_stream;
84a5175b9768da401404635c9b606264585739bdTimo Sirainen pmail->prefetch_stream = NULL;
dc7a24adeabfc9372a9d5fe34e7f8761e325ed68Timo Sirainen new_stream = TRUE;
84a5175b9768da401404635c9b606264585739bdTimo Sirainen }
84a5175b9768da401404635c9b606264585739bdTimo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (get_body && mail->data.stream != NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen name = i_stream_get_name(mail->data.stream);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (strncmp(name, "RETR", 4) == 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* we've fetched the body */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen } else if (strncmp(name, "TOP", 3) == 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* we've fetched the header, but we need the body
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen now too */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_close_streams(mail);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen } else {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_panic("Unexpected POP3 stream name: %s", name);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (mail->data.stream == NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen capa = pop3c_client_get_capabilities(mbox->client);
0d6ae58916bee3452c91d9d81be72227761ec33dTimo Sirainen if (get_body || (capa & POP3C_CAPABILITY_TOP) == 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen cmd = t_strdup_printf("RETR %u\r\n", _mail->seq);
0d6ae58916bee3452c91d9d81be72227761ec33dTimo Sirainen get_body = TRUE;
0d6ae58916bee3452c91d9d81be72227761ec33dTimo Sirainen } else {
9f0a996c22ebe39dcfe5cb84c8fd2f22ef5ce9d8Timo Sirainen cmd = t_strdup_printf("TOP %u 0\r\n", _mail->seq);
0d6ae58916bee3452c91d9d81be72227761ec33dTimo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (pop3c_client_cmd_stream(mbox->client, cmd,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen &input, &error) < 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_storage_set_error(mbox->box.storage,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen !pop3c_client_is_connected(mbox->client) ?
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen MAIL_ERROR_TEMP : MAIL_ERROR_EXPUNGED, error);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return -1;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail->data.stream = input;
dc7a24adeabfc9372a9d5fe34e7f8761e325ed68Timo Sirainen i_stream_set_name(mail->data.stream, t_strcut(cmd, '\r'));
dc7a24adeabfc9372a9d5fe34e7f8761e325ed68Timo Sirainen new_stream = TRUE;
dc7a24adeabfc9372a9d5fe34e7f8761e325ed68Timo Sirainen }
dc7a24adeabfc9372a9d5fe34e7f8761e325ed68Timo Sirainen if (new_stream) {
b13d76faf0c82162c29050382cd7f4a808294622Timo Sirainen if (mail->mail.v.istream_opened != NULL) {
b13d76faf0c82162c29050382cd7f4a808294622Timo Sirainen if (mail->mail.v.istream_opened(_mail,
b13d76faf0c82162c29050382cd7f4a808294622Timo Sirainen &mail->data.stream) < 0) {
b13d76faf0c82162c29050382cd7f4a808294622Timo Sirainen index_mail_close_streams(mail);
b13d76faf0c82162c29050382cd7f4a808294622Timo Sirainen return -1;
b13d76faf0c82162c29050382cd7f4a808294622Timo Sirainen }
b13d76faf0c82162c29050382cd7f4a808294622Timo Sirainen }
0d6ae58916bee3452c91d9d81be72227761ec33dTimo Sirainen if (get_body)
0d6ae58916bee3452c91d9d81be72227761ec33dTimo Sirainen pop3c_mail_cache_size(mail);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen /* if this stream is used by some filter stream, make the
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen filter stream blocking */
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen mail->data.stream->blocking = TRUE;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic int
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenpop3c_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen const char **value_r)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
95d62f8d6d281cc488dc4f488d4388701e559012Josef 'Jeff' Sipek struct pop3c_mailbox *mbox = POP3C_MAILBOX(_mail->box);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen switch (field) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen case MAIL_FETCH_UIDL_BACKEND:
e130bb802c8bfb6c6cc44e5c8bc098b4fa5af789Timo Sirainen case MAIL_FETCH_GUID:
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (mbox->msg_uidls == NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (pop3c_sync_get_uidls(mbox) < 0)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return -1;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_assert(_mail->seq <= mbox->msg_count);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen *value_r = mbox->msg_uidls[_mail->seq-1];
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return 0;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen default:
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return index_mail_get_special(_mail, field, value_r);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstruct mail_vfuncs pop3c_mail_vfuncs = {
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen pop3c_mail_close,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_free,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_set_seq,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_set_uid,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_set_uid_cache_updates,
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen pop3c_mail_prefetch,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_precache,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_add_temp_wanted_fields,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_get_flags,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_get_keywords,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_get_keyword_indexes,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_get_modseq,
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen index_mail_get_pvt_modseq,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_get_parts,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_get_date,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen pop3c_mail_get_received_date,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen pop3c_mail_get_save_date,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_get_virtual_size,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen pop3c_mail_get_physical_size,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_get_first_header,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_get_headers,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_get_header_stream,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen pop3c_mail_get_stream,
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen index_mail_get_binary_stream,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen pop3c_mail_get_special,
21aaa6affb9f134112b75b5db737309fc35ef1cfMartti Rannanjärvi index_mail_get_backend_mail,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_update_flags,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_update_keywords,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_update_modseq,
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen index_mail_update_pvt_modseq,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen NULL,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_expunge,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_mail_set_cache_corrupted,
6de6ec228a41275ddda972d4a554699ea75cd06dTimo Sirainen index_mail_opened,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen};