211
212
str_printfa(str, "UID FETCH %u (", _mail->uid);
212
213
if ((fields & MAIL_FETCH_RECEIVED_DATE) != 0)
213
214
str_append(str, "INTERNALDATE ");
214
if ((fields & MAIL_FETCH_PHYSICAL_SIZE) != 0)
215
if ((fields & (MAIL_FETCH_PHYSICAL_SIZE | MAIL_FETCH_VIRTUAL_SIZE)) != 0)
215
216
str_append(str, "RFC822.SIZE ");
216
217
if ((fields & MAIL_FETCH_GUID) != 0) {
217
218
str_append(str, mbox->guid_fetch_field_name);
218
219
str_append_c(str, ' ');
221
if ((fields & MAIL_FETCH_STREAM_BODY) != 0)
222
str_append(str, "BODY.PEEK[] ");
223
else if ((fields & MAIL_FETCH_STREAM_HEADER) != 0)
222
if ((fields & MAIL_FETCH_STREAM_BODY) != 0) {
223
if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_ZIMBRA_WORKAROUNDS))
224
str_append(str, "BODY.PEEK[] ");
226
/* BODY.PEEK[] can return different headers than
227
BODY.PEEK[HEADER] (e.g. invalid 8bit chars replaced
228
with '?' in HEADER) - this violates IMAP protocol
229
and messes up dsync since it sometimes fetches the
230
full body and sometimes only the headers. */
231
str_append(str, "BODY.PEEK[HEADER] BODY.PEEK[TEXT] ");
233
} else if ((fields & MAIL_FETCH_STREAM_HEADER) != 0)
224
234
str_append(str, "BODY.PEEK[HEADER] ");
225
235
else if (headers != NULL) {
226
236
mail->fetching_headers =
285
296
if ((data->wanted_fields & MAIL_FETCH_SAVE_DATE) != 0 &&
286
297
data->save_date == (time_t)-1 && data->received_date == (time_t)-1)
287
298
fields |= MAIL_FETCH_RECEIVED_DATE;
288
if ((data->wanted_fields & MAIL_FETCH_PHYSICAL_SIZE) != 0 &&
299
if ((data->wanted_fields & (MAIL_FETCH_PHYSICAL_SIZE |
300
MAIL_FETCH_VIRTUAL_SIZE)) != 0 &&
289
301
data->physical_size == (uoff_t)-1 &&
290
302
IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_RFC822_SIZE))
291
fields |= MAIL_FETCH_PHYSICAL_SIZE;
303
fields |= MAIL_FETCH_PHYSICAL_SIZE | MAIL_FETCH_VIRTUAL_SIZE;
292
304
if ((data->wanted_fields & MAIL_FETCH_GUID) != 0 &&
293
305
data->guid == NULL && mbox->guid_fetch_field_name != NULL)
294
306
fields |= MAIL_FETCH_GUID;
491
503
imapc_fetch_stream(struct imapc_mail *mail,
492
504
const struct imapc_untagged_reply *reply,
493
const struct imap_arg *arg, bool body)
505
const struct imap_arg *arg,
506
bool have_header, bool have_body)
495
508
struct index_mail *imail = &mail->imail;
509
struct istream *hdr_stream = NULL;
496
510
const char *value;
499
513
if (imail->data.stream != NULL) {
514
i_assert(mail->header_fetched);
515
if (mail->body_fetched || !have_body)
502
/* maybe the existing stream has no body. replace it. */
518
/* replace the existing stream */
519
} else if (mail->fd == -1) {
520
/* append this body stream to the existing
522
hdr_stream = imail->data.stream;
523
i_stream_ref(hdr_stream);
525
/* append this body stream to the existing
526
header stream. we'll need to recreate the stream
527
with autoclosed fd. */
528
if (lseek(mail->fd, 0, SEEK_SET) < 0)
529
i_error("lseek(imapc) failed: %m");
530
hdr_stream = i_stream_create_fd_autoclose(&mail->fd, 0);
503
532
index_mail_close_streams(imail);
504
533
if (mail->fd != -1) {
505
534
if (close(mail->fd) < 0)
506
535
i_error("close(imapc mail) failed: %m");
540
/* BODY.PEEK[TEXT] received - we can't currently handle
541
this before receiving BODY.PEEK[HEADER] reply */
511
546
if (arg->type == IMAP_ARG_LITERAL_SIZE) {
512
if (!imapc_find_lfile_arg(reply, arg, &fd))
547
if (!imapc_find_lfile_arg(reply, arg, &fd)) {
548
if (hdr_stream != NULL)
549
i_stream_unref(&hdr_stream);
514
552
if ((fd = dup(fd)) == -1) {
515
553
i_error("dup() failed: %m");
554
if (hdr_stream != NULL)
555
i_stream_unref(&hdr_stream);
519
559
imail->data.stream = i_stream_create_fd(fd, 0, FALSE);
521
561
if (!imap_arg_get_nstring(arg, &value))
523
563
if (value == NULL) {
524
564
mail_set_expunged(&imail->mail.mail);
565
if (hdr_stream != NULL)
566
i_stream_unref(&hdr_stream);
527
569
if (mail->body == NULL) {
528
570
mail->body = buffer_create_dynamic(default_pool,
529
571
arg->str_len + 1);
572
} else if (!have_header && hdr_stream != NULL) {
573
/* header is already in the buffer - add body now
574
without destroying the existing header data */
575
i_stream_unref(&hdr_stream);
577
buffer_set_used_size(mail->body, 0);
531
buffer_set_used_size(mail->body, 0);
532
579
buffer_append(mail->body, value, arg->str_len);
533
580
imail->data.stream = i_stream_create_from_data(mail->body->data,
534
581
mail->body->used);
536
mail->body_fetched = body;
538
imapc_mail_init_stream(mail, body);
584
mail->header_fetched = TRUE;
585
mail->body_fetched = have_body;
587
if (hdr_stream != NULL) {
588
struct istream *inputs[3];
590
inputs[0] = hdr_stream;
591
inputs[1] = imail->data.stream;
593
imail->data.stream = i_stream_create_concat(inputs);
594
i_stream_unref(&inputs[0]);
595
i_stream_unref(&inputs[1]);
598
imapc_mail_init_stream(mail);
625
685
if (strcasecmp(key, "BODY[]") == 0) {
626
imapc_fetch_stream(mail, reply, &args[i+1], TRUE);
686
imapc_fetch_stream(mail, reply, &args[i+1], TRUE, TRUE);
628
688
} else if (strcasecmp(key, "BODY[HEADER]") == 0) {
629
imapc_fetch_stream(mail, reply, &args[i+1], FALSE);
689
imapc_fetch_stream(mail, reply, &args[i+1], TRUE, FALSE);
691
} else if (strcasecmp(key, "BODY[TEXT]") == 0) {
692
imapc_fetch_stream(mail, reply, &args[i+1], FALSE, TRUE);
631
694
} else if (strcasecmp(key, "BODY[HEADER.FIELDS") == 0) {
632
695
imapc_fetch_header_stream(mail, reply, &args[i+1]);