/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "str.h"
#include "ioloop.h"
#include "istream.h"
#include "istream-concat.h"
#include "istream-header-filter.h"
#include "message-header-parser.h"
#include "imap-arg.h"
#include "imap-date.h"
#include "imap-quote.h"
#include "imap-bodystructure.h"
#include "imap-resp-code.h"
#include "imapc-mail.h"
#include "imapc-storage.h"
const struct imapc_command_reply *reply)
{
case IMAPC_COMMAND_STATE_OK:
break;
case IMAPC_COMMAND_STATE_NO:
/* fetch-fix-broken-mails feature disabled -
fail any mails with missing replies */
break;
}
/* this is a temporary error, retrying should work.
Yahoo sends * BYE +
NO [LIMIT] UID FETCH Rate limit hit. */
} else {
/* hopefully this is a permanent failure */
}
break;
case IMAPC_COMMAND_STATE_BAD:
break;
}
}
static void
void *context)
{
unsigned int i, count;
if (--mail->fetch_count == 0)
mail->fetching_fields = 0;
}
for (i = 0; i < count; i++) {
break;
}
}
;
reply);
/* The disconnection message was already logged */
} else {
}
}
static bool
{
unsigned int i;
return FALSE;
return FALSE;
}
}
return TRUE;
}
static const char *const *
{
const char *value;
unsigned int i;
}
}
}
}
}
}
static bool
{
/* skip over UID range */
return FALSE;
/* append the new UID to the pending FETCH UID range */
return TRUE;
}
static void
{
/* send the previous FETCH and create a new one */
}
}
/* we're now prefetching the maximum number of mails. this
most likely means that we need to flush out the command now
before sending anything else. delay it a little bit though
in case the sending code doesn't actually use
mail_prefetch_count and wants to fetch more.
note that we don't want to add this timeout too early,
because we want to optimize the maximum number of messages
placed into a single FETCH. even without timeout the command
gets flushed by imapc_mail_fetch() call. */
}
}
static int
const char *const *headers)
{
unsigned int i;
return -1;
}
/* drop any fields that we may already be fetching currently */
/* if we already know that the mail is expunged,
don't try to FETCH it */
return -1;
}
/* opened as save-only. we'll need to fetch the mail,
if (imapc_mailbox_select(mbox) < 0)
return -1;
}
if ((fields & MAIL_FETCH_STREAM_BODY) != 0)
if ((fields & MAIL_FETCH_RECEIVED_DATE) != 0)
if ((fields & MAIL_FETCH_GUID) != 0) {
}
if ((fields & MAIL_FETCH_IMAP_BODY) != 0)
if ((fields & MAIL_FETCH_IMAP_BODYSTRUCTURE) != 0)
if ((fields & MAIL_FETCH_STREAM_BODY) != 0) {
else {
/* BODY.PEEK[] can return different headers than
BODY.PEEK[HEADER] (e.g. invalid 8bit chars replaced
with '?' in HEADER) - this violates IMAP protocol
and messes up dsync since it sometimes fetches the
full body and sometimes only the headers. */
}
} else if ((fields & MAIL_FETCH_STREAM_HEADER) != 0)
if (i > 0)
}
}
mail->fetch_count++;
return 1;
}
struct imapc_mail_cache *cache)
{
if (mail->body_fetched)
return;
} else {
return;
}
}
static enum mail_fetch_field
{
MAIL_FETCH_VIRTUAL_SIZE)) != 0 &&
}
return fields;
}
{
}
{
/* try to get as much from cache as possible */
/* If mail is already cached we can avoid re-FETCHing the mail.
However, don't initialize the stream if we don't actually want to
access the mail. */
(fields & MAIL_FETCH_STREAM_HEADER) == 0 &&
/* fetch specific headers */
else
}
} T_END;
}
static bool
{
if ((fields & MAIL_FETCH_RECEIVED_DATE) != 0) {
return FALSE;
}
return FALSE;
}
if ((fields & MAIL_FETCH_GUID) != 0) {
return FALSE;
fields &= ~MAIL_FETCH_GUID;
}
if ((fields & MAIL_FETCH_IMAP_BODY) != 0) {
return FALSE;
}
if ((fields & MAIL_FETCH_IMAP_BODYSTRUCTURE) != 0) {
return FALSE;
}
if ((fields & (MAIL_FETCH_STREAM_HEADER |
MAIL_FETCH_STREAM_BODY)) != 0) {
return FALSE;
}
return TRUE;
}
const char *const *headers)
{
int ret;
if ((fields & MAIL_FETCH_GUID) != 0 &&
"Message GUID not available in this server");
return -1;
}
"Attempting to issue FETCH for a mail not yet committed");
return -1;
}
T_BEGIN {
} T_END;
if (ret < 0)
return -1;
/* we'll continue waiting until we've got all the fields we wanted,
or until all FETCH replies have been received (i.e. some FETCHes
failed) */
if (ret > 0)
while (imail->fetch_count > 0 &&
!imail->header_list_fetched)) {
}
if (imail->fetch_failed) {
return -1;
}
return 0;
}
{
return;
}
}
{
unsigned int i, count;
for (i = 0; i < reply->file_args_count; i++) {
return TRUE;
}
}
return FALSE;
}
{
static const char *imapc_hide_headers[] = {
/* Added by MS Exchange 2010 when \Flagged flag is set.
This violates IMAP guarantee of messages being immutable. */
"X-Message-Flag"
};
*input = filter_input;
}
{
int ret;
/* enable filtering only when we're not passing through
RFC822.SIZE. otherwise we'll get size mismatches. */
}
return;
}
} else if (mail->body_fetched) {
if (ret < 0) {
return;
}
/* we'll assume that the remote server is working properly and
sending CRLF linefeeds */
}
}
static void
const struct imapc_untagged_reply *reply,
bool have_header, bool have_body)
{
const char *value;
int fd;
return;
if (have_header) {
/* replace the existing stream */
/* append this body stream to the existing
header stream */
} else {
/* append this body stream to the existing
header stream. we'll need to recreate the stream
with autoclosed fd. */
i_error("lseek(imapc) failed: %m");
}
} else {
if (!have_header) {
/* BODY.PEEK[TEXT] received - we can't currently handle
this before receiving BODY.PEEK[HEADER] reply */
return;
}
}
return;
}
i_error("dup() failed: %m");
return;
}
} else {
(value[0] == '\0' &&
return;
}
/* header is already in the buffer - add body now
without destroying the existing header data */
} else {
}
}
if (have_header)
if (hdr_stream != NULL) {
inputs[0] = hdr_stream;
i_stream_unref(&inputs[0]);
}
}
static void
const struct imapc_untagged_reply *reply,
{
const char *value;
return;
return;
args += 2;
/* see if this is reply to the latest headers list request
(parse it even if it's not) */
hdr_list++;
}
return;
return;
} else {
return;
return;
}
}
}
static const char *
{
"imapc: Server sent invalid BODYSTRUCTURE parameters");
return NULL;
}
"imapc: Server sent invalid BODYSTRUCTURE: %s", error);
} else {
}
pool_unref(&pool);
return ret;
}
const struct imapc_untagged_reply *reply,
{
unsigned int i;
time_t t;
int tz;
break;
}
}
}
}
}
if (!match) {
/* this is only a FETCH FLAGS update for the wanted mail */
} else {
}
}