changeset 1212:9ced30dda6c3 HEAD

workaround: outlook-idle
author Timo Sirainen <tss@iki.fi>
date Thu, 20 Feb 2003 02:46:17 +0200
parents 6fd1f2e82c9a
children fee90d8ad273
files dovecot-example.conf src/imap/client.c src/imap/client.h src/imap/cmd-close.c src/imap/cmd-idle.c src/imap/cmd-select.c src/imap/cmd-unselect.c src/imap/commands-util.c src/imap/commands-util.h src/imap/common.h src/lib-storage/mail-storage.c src/lib-storage/mail-storage.h
diffstat 12 files changed, 78 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/dovecot-example.conf	Thu Feb 20 02:01:57 2003 +0200
+++ b/dovecot-example.conf	Thu Feb 20 02:46:17 2003 +0200
@@ -220,6 +220,11 @@
 #     mailboxes are sent before any of their children. This is mostly
 #     maildir-specific, mbox list replies are always sorted. MacOS X's Mail.app
 #     at least wants this.
+#   outlook-idle:
+#     Outlook and Outlook Express never abort IDLE command, so if no mail
+#     arrives in half a hour, Dovecot closes the connection. This is still
+#     fine, except Outlook doesn't connect back so you don't see if new mail
+#     arrives.
 #client_workarounds = 
 
 # Dovecot can notify client of new mail in selected mailbox soon after it's
--- a/src/imap/client.c	Thu Feb 20 02:01:57 2003 +0200
+++ b/src/imap/client.c	Thu Feb 20 02:46:17 2003 +0200
@@ -22,9 +22,6 @@
 /* Disconnect client when it sends too many bad commands in a row */
 #define CLIENT_MAX_BAD_COMMANDS 20
 
-/* Disconnect client after idling this many seconds */
-#define CLIENT_IDLE_TIMEOUT (60*30)
-
 extern struct mail_storage_callbacks mail_storage_callbacks;
 
 static struct client *my_client; /* we don't need more than one currently */
@@ -92,6 +89,9 @@
 	imap_parser_destroy(client->parser);
 	io_remove(client->io);
 
+	if (client->idle_to != NULL)
+		timeout_remove(client->idle_to);
+
 	i_stream_unref(client->input);
 	o_stream_unref(client->output);
 
--- a/src/imap/client.h	Thu Feb 20 02:01:57 2003 +0200
+++ b/src/imap/client.h	Thu Feb 20 02:46:17 2003 +0200
@@ -34,6 +34,9 @@
 	const char *cmd_name; /* command name (allocated from parser pool) */
 	client_command_func_t *cmd_func;
 
+	struct timeout *idle_to;
+	unsigned int idle_expunge;
+
 	unsigned int cmd_error:1;
 	unsigned int cmd_uid:1; /* used UID command */
 	unsigned int sync_flags_send_uid:1;
--- a/src/imap/cmd-close.c	Thu Feb 20 02:01:57 2003 +0200
+++ b/src/imap/cmd-close.c	Thu Feb 20 02:46:17 2003 +0200
@@ -5,16 +5,18 @@
 
 int cmd_close(struct client *client)
 {
+	struct mailbox *mailbox = client->mailbox;
+
 	if (!client_verify_open_mailbox(client))
 		return TRUE;
 
-	if (!client->mailbox->expunge(client->mailbox, FALSE))
-                client_send_closing_mailbox_error(client);
+	client->mailbox = NULL;
 
-	if (!client->mailbox->close(client->mailbox))
-		client_send_closing_mailbox_error(client);
+	if (!mailbox->expunge(mailbox, FALSE))
+                client_send_untagged_storage_error(client);
 
-	client->mailbox = NULL;
+	if (!mailbox->close(mailbox))
+                client_send_untagged_storage_error(client);
 
 	client_send_tagline(client, "OK Close completed.");
 	return TRUE;
--- a/src/imap/cmd-idle.c	Thu Feb 20 02:01:57 2003 +0200
+++ b/src/imap/cmd-idle.c	Thu Feb 20 02:46:17 2003 +0200
@@ -11,6 +11,16 @@
 
 static void idle_finish(struct client *client)
 {
+	if (client->idle_to != NULL) {
+		timeout_remove(client->idle_to);
+		client->idle_to = NULL;
+	}
+
+	if (client->idle_expunge) {
+		client_send_line(client,
+			t_strdup_printf("* %u EXPUNGE", client->idle_expunge));
+	}
+
 	io_remove(client->io);
 	client->io = io_add(i_stream_get_fd(client->input),
 			    IO_READ, _client_input, client);
@@ -60,6 +70,25 @@
 	}
 }
 
+static void idle_timeout(void *context)
+{
+	struct client *client = context;
+	struct mailbox_status status;
+
+	timeout_remove(client->idle_to);
+	client->idle_to = NULL;
+
+	if (!client->mailbox->get_status(client->mailbox, STATUS_MESSAGES,
+					 &status)) {
+		client_send_untagged_storage_error(client);
+		idle_finish(client);
+	} else {
+                client->idle_expunge = status.messages+1;
+		client_send_line(client,
+			t_strdup_printf("* %u EXISTS", client->idle_expunge));
+	}
+}
+
 int cmd_idle(struct client *client)
 {
 	const char *str;
@@ -68,6 +97,12 @@
 	if (!client_verify_open_mailbox(client))
 		return TRUE;
 
+        client->idle_expunge = 0;
+	if ((client_workarounds & WORKAROUND_OUTLOOK_IDLE) != 0) {
+		client->idle_to = timeout_add((CLIENT_IDLE_TIMEOUT - 60) * 1000,
+					      idle_timeout, client);
+	}
+
 	str = getenv("MAILBOX_IDLE_CHECK_INTERVAL");
 	interval = str == NULL ? 0 : (unsigned int)strtoul(str, NULL, 10);
 	if (interval == 0)
--- a/src/imap/cmd-select.c	Thu Feb 20 02:01:57 2003 +0200
+++ b/src/imap/cmd-select.c	Thu Feb 20 02:46:17 2003 +0200
@@ -14,9 +14,10 @@
 		return FALSE;
 
 	if (client->mailbox != NULL) {
-		if (!client->mailbox->close(client->mailbox))
-                        client_send_closing_mailbox_error(client);
+		box = client->mailbox;
 		client->mailbox = NULL;
+		if (!box->close(box))
+                        client_send_untagged_storage_error(client);
 	}
 
 	box = client->storage->open_mailbox(client->storage, mailbox,
--- a/src/imap/cmd-unselect.c	Thu Feb 20 02:01:57 2003 +0200
+++ b/src/imap/cmd-unselect.c	Thu Feb 20 02:46:17 2003 +0200
@@ -5,13 +5,15 @@
 
 int cmd_unselect(struct client *client)
 {
+	struct mailbox *mailbox = client->mailbox;
+
 	if (!client_verify_open_mailbox(client))
 		return TRUE;
 
-	if (!client->mailbox->close(client->mailbox))
-		client_send_closing_mailbox_error(client);
+	client->mailbox = NULL;
 
-	client->mailbox = NULL;
+	if (!mailbox->close(mailbox))
+		client_send_untagged_storage_error(client);
 
 	client_send_tagline(client, "OK Unselect completed.");
 	return TRUE;
--- a/src/imap/commands-util.c	Thu Feb 20 02:01:57 2003 +0200
+++ b/src/imap/commands-util.c	Thu Feb 20 02:46:17 2003 +0200
@@ -121,11 +121,19 @@
 						error, NULL));
 }
 
-void client_send_closing_mailbox_error(struct client *client)
+void client_send_untagged_storage_error(struct client *client)
 {
 	const char *error;
 	int syntax;
 
+	if (client->mailbox != NULL &&
+	    client->mailbox->is_inconsistency_error(client->mailbox)) {
+		/* we can't do forced CLOSE, so have to disconnect */
+		client_disconnect_with_error(client,
+			"Mailbox is in inconsistent state, please relogin.");
+		return;
+	}
+
 	error = client->storage->get_last_error(client->storage, &syntax);
 	client_send_line(client,
 			 t_strconcat(syntax ? "* BAD " : "* NO ", error, NULL));
--- a/src/imap/commands-util.h	Thu Feb 20 02:01:57 2003 +0200
+++ b/src/imap/commands-util.h	Thu Feb 20 02:46:17 2003 +0200
@@ -26,9 +26,8 @@
 /* Send last mail storage error message to client. */
 void client_send_storage_error(struct client *client);
 
-/* Send untagged error message to client. Doesn't check for inconsistency,
-   so should be called only by CLOSE, SELECT and UNSELECT. */
-void client_send_closing_mailbox_error(struct client *client);
+/* Send untagged error message to client. */
+void client_send_untagged_storage_error(struct client *client);
 
 /* Parse flags. Returns TRUE if successful, if not sends an error message to
    client. */
--- a/src/imap/common.h	Thu Feb 20 02:01:57 2003 +0200
+++ b/src/imap/common.h	Thu Feb 20 02:46:17 2003 +0200
@@ -8,6 +8,9 @@
    for command from user is around MAX_INBUF_SIZE * MAX_IMAP_ARG_ELEMENTS */
 #define MAX_IMAP_ARG_ELEMENTS 128
 
+/* Disconnect client after idling this many seconds */
+#define CLIENT_IDLE_TIMEOUT (60*30)
+
 #define DEFAULT_MAX_CUSTOM_FLAG_LENGTH 50
 
 extern struct ioloop *ioloop;
--- a/src/lib-storage/mail-storage.c	Thu Feb 20 02:01:57 2003 +0200
+++ b/src/lib-storage/mail-storage.c	Thu Feb 20 02:46:17 2003 +0200
@@ -24,6 +24,7 @@
 struct client_workaround_list client_workaround_list[] = {
 	{ "oe6-fetch-no-newmail", WORKAROUND_OE6_FETCH_NO_NEWMAIL },
 	{ "list-sort", WORKAROUND_LIST_SORT },
+	{ "outlook-idle", WORKAROUND_OUTLOOK_IDLE },
 	{ NULL, 0 }
 };
 
--- a/src/lib-storage/mail-storage.h	Thu Feb 20 02:01:57 2003 +0200
+++ b/src/lib-storage/mail-storage.h	Thu Feb 20 02:46:17 2003 +0200
@@ -92,7 +92,8 @@
 
 enum client_workarounds {
 	WORKAROUND_OE6_FETCH_NO_NEWMAIL	= 0x01,
-	WORKAROUND_LIST_SORT		= 0x02
+	WORKAROUND_LIST_SORT		= 0x02,
+	WORKAROUND_OUTLOOK_IDLE		= 0x04
 };
 
 struct mail_full_flags {