pop3-migration-plugin.c revision af99ca825f4b7674ec6dd0269bbca665775205aa
5e0ce63bb65db34d7f48b34bbb5545fa791781c4Timo Sirainen/* Copyright (c) 2007-2016 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen MODULE_CONTEXT(obj, pop3_migration_storage_module)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen MODULE_CONTEXT(obj, pop3_migration_mail_module)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen /* LIST size */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* sha1(TOP 0) - set only when needed */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* sha1(header) - set only when needed */
af81f402ddc897c74c1e85abd02879612ce44882Timo Sirainen/* NOTE: these headers must be sorted */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic const char *hdr_hash_skip_headers[] = {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen "Content-Length",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Return-Path", /* Yahoo IMAP has Return-Path, Yahoo POP3 doesn't */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen "X-IMAPbase",
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen "X-Keywords",
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen "X-Message-Flag",
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainenconst char *pop3_migration_plugin_version = DOVECOT_ABI_VERSION;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(pop3_migration_storage_module,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(pop3_migration_mail_module,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic int imap_msg_map_uid_cmp(const struct imap_msg_map *map1,
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainenstatic int pop3_uidl_map_pop3_seq_cmp(const struct pop3_uidl_map *map1,
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainenstatic int pop3_uidl_map_hdr_cmp(const struct pop3_uidl_map *map1,
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen return memcmp(map1->hdr_sha1, map2->hdr_sha1, sizeof(map1->hdr_sha1));
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainenstatic int imap_msg_map_hdr_cmp(const struct imap_msg_map *map1,
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen return memcmp(map1->hdr_sha1, map2->hdr_sha1, sizeof(map1->hdr_sha1));
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenpop3_header_filter_callback(struct header_filter_istream *input ATTR_UNUSED,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* matched is handled differently for eoh by
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen istream-header-filter. a design bug I guess.. */
b3142c8e513bc78da821fa70f479016148fa95e5Timo Sirainen if (strspn(hdr->name, "\r") == hdr->name_len) {
b3142c8e513bc78da821fa70f479016148fa95e5Timo Sirainen /* CR+CR+LF - some servers stop the header processing
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen here while others don't. To make sure they can be
b3142c8e513bc78da821fa70f479016148fa95e5Timo Sirainen matched correctly we want to stop here entirely. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenint pop3_migration_get_hdr_sha1(uint32_t mail_seq, struct istream *input,
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen const unsigned char *data, *p;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen input2 = i_stream_create_limit(input, hdr_size);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* hide headers that might change or be different in IMAP vs. POP3 */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen while (i_stream_read_data(input, &data, &size, 0) > 0) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* if there are NULs in header, replace them with 0x80
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen character. This is done by at least Dovecot IMAP and also
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen POP3 with outlook-no-nuls workaround. */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen while ((p = memchr(data, '\0', size)) != NULL) {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen i_error("pop3_migration: Failed to read header for msg %u: %s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenget_hdr_sha1(struct mail *mail, unsigned char sha1_r[SHA1_RESULTLEN])
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (mail_get_hdr_stream(mail, &hdr_size, &input) < 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_error("pop3_migration: Failed to get header for msg %u: %s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail->seq, mailbox_get_last_error(mail->box, NULL));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (pop3_migration_get_hdr_sha1(mail->seq, input,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* The empty "end of headers" line is missing. Either this means that
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen the headers ended unexpectedly (which is ok) or that the remote
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen server is buggy. Some servers have problems with
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen 1) header line continuations that contain only whitespace and
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainen 2) headers that have no ":". The header gets truncated when such
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen line is reached.
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainen At least Oracle IMS IMAP FETCH BODY[HEADER] handles 1) by not
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen returning the whitespace line and 2) by returning the line but
struct mailbox_transaction_context *t;
const char *uidl;
int ret = 0;
(void)mailbox_transaction_commit(&t);
return ret;
unsigned first_seq)
struct mailbox_transaction_context *t;
int ret = 0;
(void)mailbox_transaction_commit(&t);
return ret;
struct mailbox_transaction_context *t;
int ret = 0;
(void)mailbox_transaction_commit(&t);
return ret;
struct mailbox_transaction_context *t;
int ret = 0;
(void)mailbox_transaction_commit(&t);
return ret;
for (i = 0; i < count; i++) {
return i == count;
int ret;
pop3_idx++;
imap_idx++;
if (ret < 0)
pop3_idx++;
else if (ret > 0)
imap_idx++;
missing_uids_count = 0;
unsigned int i, count;
prev_uid = 0;
for (i = 0; i < count; i++) {
const char **value_r)
const char *pop3_box_vname;
void pop3_migration_plugin_deinit(void)