dovecot-2.2: pop3: Added pop3_deleted_flag setting.

dovecot at dovecot.org dovecot at dovecot.org
Tue May 14 16:32:39 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/5984de096e3e
changeset: 16347:5984de096e3e
user:      Timo Sirainen <tss at iki.fi>
date:      Tue May 14 16:32:30 2013 +0300
description:
pop3: Added pop3_deleted_flag setting.

diffstat:

 doc/example-config/conf.d/20-pop3.conf |   7 ++++
 src/pop3/pop3-client.c                 |  49 +++++++++++++++++++++++++++++++--
 src/pop3/pop3-client.h                 |   6 ++++
 src/pop3/pop3-commands.c               |  17 +++++++++--
 src/pop3/pop3-settings.c               |   4 ++-
 src/pop3/pop3-settings.h               |   1 +
 6 files changed, 76 insertions(+), 8 deletions(-)

diffs (224 lines):

diff -r 139ab37f69df -r 5984de096e3e doc/example-config/conf.d/20-pop3.conf
--- a/doc/example-config/conf.d/20-pop3.conf	Tue May 14 14:14:16 2013 +0300
+++ b/doc/example-config/conf.d/20-pop3.conf	Tue May 14 16:32:30 2013 +0300
@@ -59,6 +59,13 @@
   #   rename: Append a temporary -2, -3, etc. counter after the UIDL.
   #pop3_uidl_duplicates = allow
 
+  # This option changes POP3 behavior so that it's not possible to actually
+  # delete mails via POP3, only hide them from future POP3 sessions. The mails
+  # will still be counted towards user's quota until actually deleted via IMAP.
+  # Use e.g. "$POP3Deleted" as the value (it will be visible as IMAP keyword).
+  # Make sure you can legally archive mails before enabling this setting.
+  #pop3_deleted_flag =
+
   # POP3 logout format string:
   #  %i - total number of bytes read from client
   #  %o - total number of bytes sent to client
diff -r 139ab37f69df -r 5984de096e3e src/pop3/pop3-client.c
--- a/src/pop3/pop3-client.c	Tue May 14 14:14:16 2013 +0300
+++ b/src/pop3/pop3-client.c	Tue May 14 16:32:30 2013 +0300
@@ -141,6 +141,7 @@
         struct mailbox_status status;
         struct mailbox_transaction_context *t;
 	struct mail_search_args *search_args;
+	struct mail_search_arg *sarg;
 	struct mail_search_context *ctx;
 	struct mail *mail;
 	uoff_t size;
@@ -158,7 +159,17 @@
 	t = mailbox_transaction_begin(client->mailbox, 0);
 
 	search_args = mail_search_build_init();
-	mail_search_build_add_all(search_args);
+	if (client->deleted_kw != NULL) {
+		sarg = mail_search_build_add(search_args, SEARCH_KEYWORDS);
+		sarg->match_not = TRUE;
+		sarg->value.str = p_strdup(search_args->pool,
+					   client->set->pop3_deleted_flag);
+		i_array_init(&client->all_seqs, 32);
+	} else {
+		mail_search_build_add_all(search_args);
+	}
+	mail_search_args_init(search_args, client->mailbox, TRUE, NULL);
+
 	ctx = mailbox_search_init(t, search_args, pop3_sort_program,
 				  client->set->pop3_fast_size_lookups ? 0 :
 				  MAIL_FETCH_VIRTUAL_SIZE, NULL);
@@ -175,6 +186,8 @@
 			*failed_uid_r = mail->uid;
 			break;
 		}
+		if (array_is_created(&client->all_seqs))
+			seq_range_array_add(&client->all_seqs, mail->seq);
 		msgnum_to_seq_map_add(&msgnum_to_seq_map, client, mail, msgnum);
 
 		if ((mail_get_flags(mail) & MAIL_SEEN) != 0)
@@ -197,7 +210,13 @@
 			array_free(&msgnum_to_seq_map);
 		return ret;
 	}
-	i_assert(msgnum == client->messages_count);
+	i_assert(msgnum <= client->messages_count);
+	client->messages_count = msgnum;
+
+	if (!array_is_created(&client->all_seqs)) {
+		i_array_init(&client->all_seqs, 1);
+		seq_range_array_add_range(&client->all_seqs, 1, msgnum);
+	}
 
 	client->trans = t;
 	client->message_sizes =
@@ -211,6 +230,26 @@
 	return 1;
 }
 
+static int init_pop3_deleted_flag(struct client *client, const char **error_r)
+{
+	const char *deleted_keywords[2];
+
+	if (client->set->pop3_deleted_flag[0] == '\0')
+		return 0;
+
+	deleted_keywords[0] = client->set->pop3_deleted_flag;
+	deleted_keywords[1] = NULL;
+	if (mailbox_keywords_create(client->mailbox, deleted_keywords,
+				    &client->deleted_kw) < 0) {
+		*error_r = t_strdup_printf(
+			"pop3_deleted_flags: Invalid keyword '%s': %s",
+			client->set->pop3_deleted_flag,
+			mailbox_get_last_error(client->mailbox, NULL));
+		return -1;
+	}
+	return 0;
+}
+
 static int init_mailbox(struct client *client, const char **error_r)
 {
 	uint32_t failed_uid = 0, last_failed_uid = 0;
@@ -392,7 +431,8 @@
 	}
 	client->mail_set = mail_storage_get_settings(storage);
 
-	if (init_mailbox(client, &errmsg) < 0) {
+	if (init_pop3_deleted_flag(client, &errmsg) < 0 ||
+	    init_mailbox(client, &errmsg) < 0) {
 		i_error("Couldn't init INBOX: %s", errmsg);
 		client_destroy(client, "Mailbox init failed");
 		return -1;
@@ -553,6 +593,9 @@
 		   message sizes. */
 		(void)mailbox_transaction_commit(&client->trans);
 	}
+	array_free(&client->all_seqs);
+	if (client->deleted_kw != NULL)
+		mailbox_keywords_unref(&client->deleted_kw);
 	if (client->mailbox != NULL)
 		mailbox_free(&client->mailbox);
 	if (client->anvil_sent) {
diff -r 139ab37f69df -r 5984de096e3e src/pop3/pop3-client.h
--- a/src/pop3/pop3-client.h	Tue May 14 14:14:16 2013 +0300
+++ b/src/pop3/pop3-client.h	Tue May 14 16:32:30 2013 +0300
@@ -1,6 +1,8 @@
 #ifndef POP3_CLIENT_H
 #define POP3_CLIENT_H
 
+#include "seq-range-array.h"
+
 struct client;
 struct mail_storage;
 
@@ -48,6 +50,7 @@
 	struct mail_namespace *inbox_ns;
 	struct mailbox *mailbox;
 	struct mailbox_transaction_context *trans;
+	struct mail_keywords *deleted_kw;
 
 	struct timeout *to_session_dotlock_refresh;
 	struct dotlock *session_dotlock;
@@ -63,6 +66,9 @@
 	uoff_t deleted_size;
 	uint32_t last_seen_pop3_msn, lowest_retr_pop3_msn;
 
+	/* All sequences currently visible in the mailbox. */
+	ARRAY_TYPE(seq_range) all_seqs;
+
 	/* [msgnum] contains mail seq. anything after it has seq = msgnum+1 */
 	uint32_t *msgnum_to_seq_map;
 	uint32_t msgnum_to_seq_map_count;
diff -r 139ab37f69df -r 5984de096e3e src/pop3/pop3-commands.c
--- a/src/pop3/pop3-commands.c	Tue May 14 14:14:16 2013 +0300
+++ b/src/pop3/pop3-commands.c	Tue May 14 16:32:30 2013 +0300
@@ -196,11 +196,12 @@
 pop3_search_build(struct client *client, uint32_t seq)
 {
 	struct mail_search_args *search_args;
+	struct mail_search_arg *sarg;
 
 	search_args = mail_search_build_init();
 	if (seq == 0) {
-		mail_search_build_add_seqset(search_args,
-					     1, client->messages_count);
+		sarg = mail_search_build_add(search_args, SEARCH_SEQSET);
+		sarg->value.seqset = client->all_seqs;
 	} else {
 		mail_search_build_add_seqset(search_args, seq, seq);
 	}
@@ -222,6 +223,15 @@
 	return 0;
 }
 
+static void client_expunge(struct client *client, struct mail *mail)
+{
+	if (client->deleted_kw != NULL)
+		mail_update_keywords(mail, MODIFY_ADD, client->deleted_kw);
+	else
+		mail_expunge(mail);
+	client->expunged_count++;
+}
+
 bool client_update_mails(struct client *client)
 {
 	struct mail_search_args *search_args;
@@ -250,8 +260,7 @@
 		bit = 1 << (msgnum % CHAR_BIT);
 		if (client->deleted_bitmask != NULL &&
 		    (client->deleted_bitmask[msgnum / CHAR_BIT] & bit) != 0) {
-			mail_expunge(mail);
-			client->expunged_count++;
+			client_expunge(client, mail);
 		} else if (client->seen_bitmask != NULL &&
 			   (client->seen_bitmask[msgnum / CHAR_BIT] & bit) != 0) {
 			mail_update_flags(mail, MODIFY_ADD, MAIL_SEEN);
diff -r 139ab37f69df -r 5984de096e3e src/pop3/pop3-settings.c
--- a/src/pop3/pop3-settings.c	Tue May 14 14:14:16 2013 +0300
+++ b/src/pop3/pop3-settings.c	Tue May 14 16:32:30 2013 +0300
@@ -71,6 +71,7 @@
 	DEF(SET_STR, pop3_client_workarounds),
 	DEF(SET_STR, pop3_logout_format),
 	DEF(SET_ENUM, pop3_uidl_duplicates),
+	DEF(SET_STR, pop3_deleted_flag),
 
 	SETTING_DEFINE_LIST_END
 };
@@ -86,7 +87,8 @@
 	.pop3_fast_size_lookups = FALSE,
 	.pop3_client_workarounds = "",
 	.pop3_logout_format = "top=%t/%p, retr=%r/%b, del=%d/%m, size=%s",
-	.pop3_uidl_duplicates = "allow:rename"
+	.pop3_uidl_duplicates = "allow:rename",
+	.pop3_deleted_flag = ""
 };
 
 static const struct setting_parser_info *pop3_setting_dependencies[] = {
diff -r 139ab37f69df -r 5984de096e3e src/pop3/pop3-settings.h
--- a/src/pop3/pop3-settings.h	Tue May 14 14:14:16 2013 +0300
+++ b/src/pop3/pop3-settings.h	Tue May 14 16:32:30 2013 +0300
@@ -23,6 +23,7 @@
 	const char *pop3_client_workarounds;
 	const char *pop3_logout_format;
 	const char *pop3_uidl_duplicates;
+	const char *pop3_deleted_flag;
 
 	enum pop3_client_workarounds parsed_workarounds;
 };


More information about the dovecot-cvs mailing list