pop3c-mail.c revision afc77c5375cdb8f2bf0ab6280d9229ac27c933c6
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2011-2016 Dovecot authors, see the included COPYING file */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen#include "lib.h"
46552a931924c2d743f045e95b08c3ce6beda91aTimo Sirainen#include "ioloop.h"
c5f932968281763df360b9c97cef60f5f80d5e3dTimo Sirainen#include "istream.h"
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include "index-mail.h"
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include "pop3c-settings.h"
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include "pop3c-client.h"
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include "pop3c-sync.h"
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen#include "pop3c-storage.h"
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstruct mail *
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainenpop3c_mail_alloc(struct mailbox_transaction_context *t,
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen enum mail_fetch_field wanted_fields,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
53dfcefa9440a49d703e49193819a79be99c9ba6Timo Sirainen struct pop3c_mail *mail;
f0d93763f210ecdb85a115fdd0210a16cfc5ff5cTimo Sirainen pool_t pool;
53dfcefa9440a49d703e49193819a79be99c9ba6Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen pool = pool_alloconly_create("mail", 2048);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen mail = p_new(pool, struct pop3c_mail, 1);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen mail->imail.mail.pool = pool;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_init(&mail->imail, t, wanted_fields, wanted_headers);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen return &mail->imail.mail.mail;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
2e78f05b11df23ec2731afaf8f19d5b5240cb29fTimo Sirainenstatic void pop3c_mail_close(struct mail *_mail)
2e78f05b11df23ec2731afaf8f19d5b5240cb29fTimo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct pop3c_mail *pmail = (struct pop3c_mail *)_mail;
d1e7425048c61d71f41f737ba947687198842dc2Timo Sirainen struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* wait for any prefetch to finish before closing the mail */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen while (pmail->prefetching)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen pop3c_client_wait_one(mbox->client);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_close(_mail);
660b99a7059824676b2b8d6f79b8e15d47df25a2Timo Sirainen}
660b99a7059824676b2b8d6f79b8e15d47df25a2Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic int pop3c_mail_get_received_date(struct mail *_mail, time_t *date_r)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen int tz;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
b9c76fe9d9ca194816606342da1ddbd9be6bc8abTimo Sirainen if (mbox->storage->set->pop3c_quick_received_date) {
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen /* we don't care about the date, just return the current date */
b9c76fe9d9ca194816606342da1ddbd9be6bc8abTimo Sirainen *date_r = ioloop_time;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen return 0;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* FIXME: we could also parse the first Received: header and get
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen the date from there, but since this code is unlikely to be called
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen except during migration, I don't think it really matters. */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return index_mail_get_date(_mail, date_r, &tz);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenstatic int pop3c_mail_get_save_date(struct mail *_mail, time_t *date_r)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen{
b9c76fe9d9ca194816606342da1ddbd9be6bc8abTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct index_mail_data *data = &mail->data;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (data->save_date == (time_t)-1) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* FIXME: we could use a value stored in cache */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return pop3c_mail_get_received_date(_mail, date_r);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen *date_r = data->save_date;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic int pop3c_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct message_size hdr_size, body_size;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct istream *input;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (mail->data.virtual_size != (uoff_t)-1) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* virtual size is already known. it's the same as our
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen (correct) physical size */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen *size_r = mail->data.virtual_size;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (index_mail_get_physical_size(_mail, size_r) == 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen *size_r = mail->data.physical_size;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen if (_mail->lookup_abort == MAIL_LOOKUP_ABORT_READ_MAIL &&
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen (_mail->box->flags & MAILBOX_FLAG_POP3_SESSION) != 0) {
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen /* kludge: we want output for POP3 LIST with
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen pop3_fast_size_lookups=yes. use the remote's LIST values
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen regardless of their correctness */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (mbox->msg_sizes == NULL) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (pop3c_sync_get_sizes(mbox) < 0)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e7dd5065d21c569e5e6ddd713bd345dadd1cf51dTimo Sirainen }
e7dd5065d21c569e5e6ddd713bd345dadd1cf51dTimo Sirainen i_assert(_mail->seq <= mbox->msg_count);
d694a52bce62c52080c3f87a56dcf77030fd2712Timo Sirainen *size_r = mbox->msg_sizes[_mail->seq-1];
d694a52bce62c52080c3f87a56dcf77030fd2712Timo Sirainen return 0;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch }
009217abb57a24a4076092e8e4e165545747839eStephan Bosch
009217abb57a24a4076092e8e4e165545747839eStephan Bosch /* slow way: get the whole message body */
009217abb57a24a4076092e8e4e165545747839eStephan Bosch if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
009217abb57a24a4076092e8e4e165545747839eStephan Bosch return -1;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_assert(mail->data.physical_size != (uoff_t)-1);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen *size_r = mail->data.physical_size;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return 0;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch}
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Boschstatic void pop3c_mail_cache_size(struct index_mail *mail)
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch{
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch struct mail *_mail = &mail->mail.mail;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch uoff_t size;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch unsigned int cache_idx;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch if (i_stream_get_size(mail->data.stream, TRUE, &size) <= 0)
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch return;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch mail->data.virtual_size = size;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen cache_idx = mail->ibox->cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx;
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen if (mail_cache_field_exists(_mail->transaction->cache_view,
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen _mail->seq, cache_idx) == 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_cache_add_idx(mail, cache_idx, &size, sizeof(size));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* make sure it's not cached twice */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen mail->data.dont_cache_fetch_fields |=
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen MAIL_CACHE_VIRTUAL_FULL_SIZE;
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen }
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen}
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen
5a250816ffc4cc5db203f9410ea99b6601c7b91aTimo Sirainenstatic void pop3c_mail_prefetch_done(enum pop3c_command_state state,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *reply, void *context)
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen{
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen struct pop3c_mail *pmail = context;
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen switch (state) {
8ce3071e80b9973230048ecadfcb073fb82cc69fTimo Sirainen case POP3C_COMMAND_STATE_OK:
8ce3071e80b9973230048ecadfcb073fb82cc69fTimo Sirainen break;
8ce3071e80b9973230048ecadfcb073fb82cc69fTimo Sirainen case POP3C_COMMAND_STATE_ERR:
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen case POP3C_COMMAND_STATE_DISCONNECTED:
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk i_stream_unref(&pmail->imail.data.stream);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen pmail->imail.data.stream =
2e2a1d720ed53490e8e5c5031e773d395bd5683dTimo Sirainen i_stream_create_error_str(EIO, "%s failed: %s",
5a250816ffc4cc5db203f9410ea99b6601c7b91aTimo Sirainen pmail->prefetching_body ? "RETR" : "TOP", reply);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen break;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen pmail->prefetching = FALSE;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic bool pop3c_mail_prefetch(struct mail *_mail)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct pop3c_mail *pmail = (struct pop3c_mail *)_mail;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen enum pop3c_capability capa;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *cmd;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (pmail->imail.data.access_part != 0 &&
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen pmail->imail.data.stream == NULL) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen capa = pop3c_client_get_capabilities(mbox->client);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen pmail->prefetching_body = (capa & POP3C_CAPABILITY_TOP) == 0 ||
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen (pmail->imail.data.access_part & (READ_BODY | PARSE_BODY)) != 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (pmail->prefetching_body)
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen cmd = t_strdup_printf("RETR %u\r\n", _mail->seq);
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen else
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen cmd = t_strdup_printf("TOP %u 0\r\n", _mail->seq);
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen pmail->prefetching = TRUE;
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen pmail->imail.data.stream =
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen pop3c_client_cmd_stream_async(mbox->client, cmd,
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen pop3c_mail_prefetch_done, pmail);
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen i_stream_set_name(pmail->imail.data.stream, t_strcut(cmd, '\r'));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return !pmail->prefetching;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return index_mail_prefetch(_mail);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic int
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenpop3c_mail_get_stream(struct mail *_mail, bool get_body,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct message_size *hdr_size,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct message_size *body_size, struct istream **stream_r)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct pop3c_mail *pmail = (struct pop3c_mail *)_mail;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct index_mail *mail = &pmail->imail;
ec23e16ed879e289d12c6e1a5f9745dd3979004aTimo Sirainen struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen enum pop3c_capability capa;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *name, *cmd, *error;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct istream *input;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if ((mail->data.access_part & (READ_BODY | PARSE_BODY)) != 0)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen get_body = TRUE;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen while (pmail->prefetching) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* wait for prefetch to finish */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen pop3c_client_wait_one(mbox->client);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (get_body && mail->data.stream != NULL) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen name = i_stream_get_name(mail->data.stream);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (strncmp(name, "RETR", 4) == 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* we've fetched the body */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen } else if (strncmp(name, "TOP", 3) == 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* we've fetched the header, but we need the body
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen now too */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_close_streams(mail);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen } else {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_panic("Unexpected POP3 stream name: %s", name);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (mail->data.stream == NULL) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen capa = pop3c_client_get_capabilities(mbox->client);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (get_body || (capa & POP3C_CAPABILITY_TOP) == 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen cmd = t_strdup_printf("RETR %u\r\n", _mail->seq);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen get_body = TRUE;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen } else {
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen cmd = t_strdup_printf("TOP %u 0\r\n", _mail->seq);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (pop3c_client_cmd_stream(mbox->client, cmd,
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen &input, &error) < 0) {
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen mail_storage_set_error(mbox->box.storage,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen !pop3c_client_is_connected(mbox->client) ?
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MAIL_ERROR_TEMP : MAIL_ERROR_EXPUNGED, error);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen mail->data.stream = input;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (mail->mail.v.istream_opened != NULL) {
660b99a7059824676b2b8d6f79b8e15d47df25a2Timo Sirainen if (mail->mail.v.istream_opened(_mail,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen &mail->data.stream) < 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_close_streams(mail);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen i_stream_set_name(mail->data.stream, t_strcut(cmd, '\r'));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (get_body)
77f1da4b5e2b800197d8db548235497d5e9d6a4fTimo Sirainen pop3c_mail_cache_size(mail);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* if this stream is used by some filter stream, make the
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen filter stream blocking */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen mail->data.stream->blocking = TRUE;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic int
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenpop3c_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char **value_r)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen switch (field) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen case MAIL_FETCH_UIDL_BACKEND:
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen case MAIL_FETCH_GUID:
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (mbox->msg_uidls == NULL) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (pop3c_sync_get_uidls(mbox) < 0)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_assert(_mail->seq <= mbox->msg_count);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen *value_r = mbox->msg_uidls[_mail->seq-1];
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen default:
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return index_mail_get_special(_mail, field, value_r);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen}
77f1da4b5e2b800197d8db548235497d5e9d6a4fTimo Sirainen
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainenstruct mail_vfuncs pop3c_mail_vfuncs = {
77f1da4b5e2b800197d8db548235497d5e9d6a4fTimo Sirainen pop3c_mail_close,
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen index_mail_free,
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen index_mail_set_seq,
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen index_mail_set_uid,
c5f932968281763df360b9c97cef60f5f80d5e3dTimo Sirainen index_mail_set_uid_cache_updates,
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen pop3c_mail_prefetch,
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen index_mail_precache,
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen index_mail_add_temp_wanted_fields,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_get_flags,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_get_keywords,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_get_keyword_indexes,
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen index_mail_get_modseq,
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen index_mail_get_pvt_modseq,
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen index_mail_get_parts,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_get_date,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen pop3c_mail_get_received_date,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen pop3c_mail_get_save_date,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_get_virtual_size,
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen pop3c_mail_get_physical_size,
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen index_mail_get_first_header,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_get_headers,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_get_header_stream,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen pop3c_mail_get_stream,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_get_binary_stream,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen pop3c_mail_get_special,
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen index_mail_get_real_mail,
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen index_mail_update_flags,
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen index_mail_update_keywords,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_update_modseq,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_update_pvt_modseq,
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen NULL,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_expunge,
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen index_mail_set_cache_corrupted,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen index_mail_opened
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen};
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen