]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
workaround: outlook-idle
authorTimo Sirainen <tss@iki.fi>
Thu, 20 Feb 2003 00:46:17 +0000 (02:46 +0200)
committerTimo Sirainen <tss@iki.fi>
Thu, 20 Feb 2003 00:46:17 +0000 (02:46 +0200)
--HG--
branch : HEAD

12 files changed:
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

index b19485991272e3a9072a780b04287f7226c6643f..279be79cfa5c1d742850f794ea48d195c0f97364 100644 (file)
@@ -220,6 +220,11 @@ login = pop3
 #     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
index 36395cc8bf917f4442cda7fcb5a6dbace183474e..1d1bf88be67e6e2c1ba325008cad59968afef36a 100644 (file)
@@ -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 @@ void client_destroy(struct client *client)
        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);
 
index 30004b919a9827f447ded8fca0fc93bd8fc9709a..6a61fdf50a902ce05efce8dd78028aa7a50d54ef 100644 (file)
@@ -34,6 +34,9 @@ struct client {
        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;
index 2032e2e6cab9451ee25a9822de98823776c0f619..1275c676be7ebe2f1f6f36cafa193fc84aa8c5b8 100644 (file)
@@ -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;
index 470c26e81e06cbed650653783b54c23cc27e20bc..fcddf68ce1eea15536963b3b46a5a691506b76e3 100644 (file)
 
 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_client_input(void *context)
        }
 }
 
+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 @@ int cmd_idle(struct client *client)
        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)
index 8170cfcc2fdfe2a3b1ab16e60a20a00468a114fc..770db9544ea54795e0f294cde363a4caf4e9f1ee 100644 (file)
@@ -14,9 +14,10 @@ int _cmd_select_full(struct client *client, int readonly)
                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,
index 221085fcd1e3050879b2e06c7d1c22e22d13c4db..a44475de84aa3d875e653dbb00428c342ae3992d 100644 (file)
@@ -5,14 +5,16 @@
 
 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;
 
+       if (!mailbox->close(mailbox))
+               client_send_untagged_storage_error(client);
+
        client_send_tagline(client, "OK Unselect completed.");
        return TRUE;
 }
index 2d09d2576d8ca73449087fc3251d33a66513ed27..f067bbd440d2489dc8c0208711d36cdf9056ff3f 100644 (file)
@@ -121,11 +121,19 @@ void client_send_storage_error(struct client *client)
                                                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));
index e9ed43cd49225fe0c1dea68d15630850e4fb0104..6202d42ab3ea33bf68ef3bcf97dec19c5b7e8f52 100644 (file)
@@ -26,9 +26,8 @@ void client_sync_without_expunges(struct client *client);
 /* 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. */
index b87df823584481ae7e8e35372028b96c83d80c6b..89f83e59cd63a7a0c4c592b57950f66f271322bd 100644 (file)
@@ -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;
index 58c008d8115d742199dcc8bc9fec646ca46c1da7..931d9f278b9bb8d294ded2bb22b3d69cc0a18770 100644 (file)
@@ -24,6 +24,7 @@ struct client_workaround_list {
 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 }
 };
 
index af969ff8d7a17d6bbc91e1629552d93a28c57a15..360aa6201cdfcd36426fb6a04599f591f4564356 100644 (file)
@@ -92,7 +92,8 @@ enum mail_fetch_field {
 
 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 {