IMAP COPY creates invalid index data with zlib and mail_log plugins enabled but zlib_save off

Robert L Mathews lists at tigertech.com
Fri Oct 30 22:06:56 UTC 2015


I've noticed that maildir IMAP COPY commands can generate invalid
dovecot.index entries when all seven of the following are true:

- The zlib plugin is enabled;
- The zlib_save/zlib_save_level options are NOT enabled;
- The source message being copied is compressed;
- The mail_log plugin is logging "copy" events;
- The mail_log_fields setting includes at least one message header;
- The destination mailbox folder has an index file that is recording the
logged headers;
- The source mailbox folder does NOT have an index file recording the
logged headers.

In this situation, copying a message results in an index entry in the
destination that has all the headers blank, like this:

RECORD: seq=5, uid=182415, flags=0x08 (Seen)
 - ext 1 modseq    :          3 (0300000000000000)
 - ext 2 cache     :       2352 (30090000)
 - cache offset=2352 size=120, prev_offset = 0
    - hdr.FROM:
    - hdr.MESSAGE-ID:
    - hdr.SUBJECT:
    - hdr.DATE:
    - hdr.BCC:
    - hdr.CC:
    - hdr.CONTENT-TYPE:
    - hdr.IN-REPLY-TO:
    - hdr.NEWSGROUPS:
    - hdr.PRIORITY:
    - hdr.REFERENCES:
    - hdr.REPLY-TO:
    - hdr.TO:
    - hdr.X-PRIORITY:

For these copies, the mail_log plugin records blank header data in the
log, too, like this (despite the message having a valid message-ID,
from, and subject):

Oct 29 21:11:42 wheezy dovecot: imap[31763]: user=<1 at example.com>
ip=192.168.0.4 session=RV/MmUojyADAqAAE copy from INBOX.Saved:
box=INBOX.Trash, uid=182412, msgid=, size=1357, vsize=1392, from=,
subject=, flags=(\Seen)

I've found this occurs in at least Dovecot 2.1.7, 2.2.13, and 2.2.18
(all packaged Debian versions).

Changing any of the seven things I mentioned above fixes it. I've tried
to find the code that causes this, but not yet been successful. My
theory is that when the mail_log plugin calls mail_get_first_header(),
and there's no index header record to read it from, it looks at the real
message on disk. Perhaps it somehow operates on a compressed copy of the
message although it expects uncompressed plaintext, so it doesn't find
any of the headers. The "missing" headers then get cached to the
destination index file as a side-effect.

The copied maildir message itself is fine, by the way. It's an
identical, still-compressed copy of the original message. And deleting
the destination "dovecot.index*" files that contain the bad data causes
Dovecot to rebuild the index with the correct header data.

It's unusual to use the zlib plugin without the
zlib_save/zlib_save_level options enabled, of course. That's probably
why (as far as I can tell) there have been no reports of this before. I
noticed it only because I was testing a small amount of manual mail
compression before deploying it for all mail.

Here's the "doveconf -n" of a system in the "has the problem" state:

# 2.2.18: /etc/dovecot/dovecot.conf
# Pigeonhole version 0.4.8 (0c4ae064f307+)
# OS: Linux 3.2.0-4-686-pae i686 Debian stretch/sid
auth_mechanisms = plain login
auth_username_format =
auth_verbose = yes
auth_verbose_passwords = sha1
default_vsz_limit = 1 G
disable_plaintext_auth = no
lda_mailbox_autosubscribe = yes
listen = *
log_timestamp = "%Y-%m-%d %H:%M:%S "
login_log_format_elements = user=<%u> pid=[%{mail_pid}] method=%m rip=%r
lip=%l %c
mail_fsync = never
mail_location = maildir:~/
mail_log_prefix = "%s[%{pid}]: user=<%u> ip=%{rip} session=%{session} "
mail_max_userip_connections = 100
mail_plugins = mail_log notify zlib
managesieve_notify_capability = mailto
managesieve_sieve_capability = fileinto envelope encoded-character
vacation subaddress comparator-i;ascii-numeric relational regex
imap4flags copy include variables body enotify environment mailbox date
index ihave duplicate spamtest spamtestplus
namespace {
  inbox = yes
  location =
  prefix = INBOX.
  separator = .
  type = private
}
namespace {
  hidden = yes
  inbox = no
  list = no
  location =
  prefix =
  separator = .
  type = private
}
passdb {
  args = /etc/dovecot/dovecot.users
  driver = passwd-file
}
plugin {
  fts = lucene
  fts_lucene = whitespace_chars=@.
  mail_log_events = copy delete undelete expunge mailbox_delete
mailbox_rename flag_change save mailbox_create
  mail_log_fields = vsize size flags box uid box msgid size flags vsize
from subject
  sieve = %h/mailbox.sieve
  sieve_after = %h/../../domain-after.sieve
  sieve_before = %h/../../domain-before.sieve
  sieve_dir = %h/sieve
  sieve_extensions = -reject +spamtest +spamtestplus
  sieve_global_dir = %h/../../sieve-global-include-scripts
  sieve_spamtest_max_value = 7
  sieve_spamtest_status_header = X-Spam-Level
  sieve_spamtest_status_type = strlen
}
protocols = pop3 imap lmtp sieve
service auth {
  unix_listener /var/spool/postfix/private/auth {
    group = postfix
    mode = 0660
    user = postfix
  }
}
service imap-login {
  process_min_avail = 8
  service_count = 0
}
service imap {
  process_limit = 2000
}
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    group = postfix
    mode = 0660
    user = postfix
  }
}
service pop3-login {
  process_min_avail = 8
  service_count = 0
}
service pop3 {
  process_limit = 2000
}
ssl = no
userdb {
  args = /etc/dovecot/dovecot.users
  driver = passwd-file
}
verbose_proctitle = yes
protocol imap {
  imap_client_workarounds = delay-newmail
  imap_logout_format = %i bytes in, %o bytes out
}
protocol pop3 {
  pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
  pop3_logout_format = ; %i bytes in, %o bytes out, %t top (%p bytes),
%r retr (%b bytes), %d of %m deleted, mailbox size %s bytes
  pop3_uidl_format = UID%u-%v
}
protocol lda {
  mail_fsync = optimized
  mail_plugins = mail_log notify zlib sieve
}
protocol lmtp {
  mail_fsync = optimized
  mail_plugins = mail_log notify zlib sieve
}

-- 
Robert L Mathews, Tiger Technologies, http://www.tigertech.net/


More information about the dovecot mailing list