diff --git a/src/engine/api/geary-engine.vala b/src/engine/api/geary-engine.vala index 749f0ad5..69089c08 100644 --- a/src/engine/api/geary-engine.vala +++ b/src/engine/api/geary-engine.vala @@ -284,10 +284,7 @@ public class Geary.Engine : BaseObject { (security, cx) => account.untrusted_host(service, security, cx) ); - var client = new Imap.ClientSession( - endpoint, - Imap.ClientService.new_quirks_for_provider(account.service_provider) - ); + var client = new Imap.ClientSession(endpoint, new Imap.Quirks()); GLib.Error? imap_err = null; try { yield client.connect_async( diff --git a/src/engine/imap/api/imap-client-service.vala b/src/engine/imap/api/imap-client-service.vala index 21a2e4aa..044a7c05 100644 --- a/src/engine/imap/api/imap-client-service.vala +++ b/src/engine/imap/api/imap-client-service.vala @@ -39,36 +39,6 @@ public class Geary.Imap.ClientService : Geary.ClientService { private const int CHECK_NOOP_THRESHOLD_SEC = 5; - public static Quirks new_quirks_for_provider(ServiceProvider provider) { - var quirks = new Quirks(); - switch (provider) { - case GMAIL: - // As of 2020-05-02, GMail doesn't seem to quote flag - // atoms containing reserved characters, and at least one - // use of both `]` and ` ` have been found. This works - // around the former. See #746 - quirks.flag_atom_exceptions = "]"; - break; - - case ServiceProvider.OUTLOOK: - // As of June 2016, outlook.com's IMAP servers have a bug - // where a large number (~50) of pipelined STATUS commands - // on mailboxes with many messages will eventually cause - // it to break command parsing and return a BAD response, - // causing us to drop the connection. Limit the number of - // pipelined commands per batch to work around this. See - // b.g.o Bug 766552 - quirks.max_pipeline_batch_size = 25; - break; - - default: - // noop - break; - } - return quirks; - } - - /** * Set to zero or negative value if keepalives should be disabled when a connection has not * selected a mailbox. (This is not recommended.) @@ -131,7 +101,7 @@ public class Geary.Imap.ClientService : Geary.ClientService { get { return LOGGING_DOMAIN; } } - private Quirks quirks; + private Quirks quirks = new Quirks(); private Nonblocking.Mutex sessions_mutex = new Nonblocking.Mutex(); private Gee.Set all_sessions = @@ -147,7 +117,6 @@ public class Geary.Imap.ClientService : Geary.ClientService { ServiceInformation configuration, Endpoint remote) { base(account, configuration, remote); - this.quirks = new_quirks_for_provider(account.service_provider); } /** @@ -403,6 +372,7 @@ public class Geary.Imap.ClientService : Geary.ClientService { // An error was thrown, so close the pool this.close_pool.begin(true); } else { + this.quirks.update_for_server(new_session); try { yield this.sessions_mutex.execute_locked(() => { this.all_sessions.add(new_session); diff --git a/src/engine/imap/api/imap-quirks.vala b/src/engine/imap/api/imap-quirks.vala index 79ef3267..61fe9cd7 100644 --- a/src/engine/imap/api/imap-quirks.vala +++ b/src/engine/imap/api/imap-quirks.vala @@ -39,4 +39,46 @@ public class Geary.Imap.Quirks : BaseObject { public uint max_pipeline_batch_size { get; set; default = 0; } + + public void update_for_server(ClientSession session) { + if (session.server_greeting != null) { + var greeting = session.server_greeting.get_text() ?? ""; + if (greeting.has_prefix("Gimap")) { + update_for_gmail(); + } else if (greeting.has_prefix("The Microsoft Exchange")) { + update_for_outlook(); + } + } + } + + /** + * Updates this quirks object with known quirks for GMail. + * + * As of 2020-05-02, GMail doesn't seem to quote flag + * atoms containing reserved characters, and at least one + * use of both `]` and ` ` have been found. This works + * around the former. + * + * See [[https://gitlab.gnome.org/GNOME/geary/-/issues/746]] + */ + public void update_for_gmail() { + this.flag_atom_exceptions = "]"; + } + + /** + * Updates this quirks object with known quirks for Outlook.com. + * + * As of June 2016, outlook.com's IMAP servers have a bug where a + * large number (~50) of pipelined STATUS commands on mailboxes + * with many messages will eventually cause it to break command + * parsing and return a BAD response, causing us to drop the + * connection. Limit the number of pipelined commands per batch to + * work around this. + * + * See [[https://bugzilla.gnome.org/show_bug.cgi?id=766552]] + */ + public void update_for_outlook() { + this.max_pipeline_batch_size = 25; + } + } diff --git a/test/engine/imap/transport/imap-deserializer-test.vala b/test/engine/imap/transport/imap-deserializer-test.vala index b9c456d8..e5e642df 100644 --- a/test/engine/imap/transport/imap-deserializer-test.vala +++ b/test/engine/imap/transport/imap-deserializer-test.vala @@ -202,7 +202,6 @@ class Geary.Imap.DeserializerTest : TestCase { string greeting = "* OK Gimap ready for requests from 115.187.245.46 c194mb399904375ivc"; this.stream.add_data(greeting.data); this.stream.add_data(EOL.data); - this.deser.quirks = ClientService.new_quirks_for_provider(GMAIL); this.process.begin(Expect.MESSAGE, this.async_completion); RootParameters? message = this.process.end(async_result()); @@ -249,7 +248,8 @@ class Geary.Imap.DeserializerTest : TestCase { string flags = """* FLAGS (\Answered \Flagged \Draft \Deleted \Seen $NotPhishing $Phishing)"""; this.stream.add_data(flags.data); this.stream.add_data(EOL.data); - this.deser.quirks = ClientService.new_quirks_for_provider(GMAIL); + this.deser.quirks = new Imap.Quirks(); + this.deser.quirks.update_for_gmail(); this.process.begin(Expect.MESSAGE, this.async_completion); RootParameters? message = this.process.end(async_result()); @@ -261,7 +261,8 @@ class Geary.Imap.DeserializerTest : TestCase { string flags = """* OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen $NotPhishing $Phishing \*)] Flags permitted."""; this.stream.add_data(flags.data); this.stream.add_data(EOL.data); - this.deser.quirks = ClientService.new_quirks_for_provider(GMAIL); + this.deser.quirks = new Imap.Quirks(); + this.deser.quirks.update_for_gmail(); this.process.begin(Expect.MESSAGE, this.async_completion); RootParameters? message = this.process.end(async_result()); @@ -275,7 +276,8 @@ class Geary.Imap.DeserializerTest : TestCase { string flags = """* FLAGS (\Answered \Flagged \Draft \Deleted \Seen $Forwarded $MDNSent $NotPhishing $Phishing Junk LoadRemoteImages NonJunk OIB-Seen-INBOX OIB-Seen-Unsubscribe OIB-Seen-[Gmail]/Important OIB-Seen-[Gmail]/Spam OIB-Seen-[Gmail]/Tous les messages)"""; this.stream.add_data(flags.data); this.stream.add_data(EOL.data); - this.deser.quirks = ClientService.new_quirks_for_provider(GMAIL); + this.deser.quirks = new Imap.Quirks(); + this.deser.quirks.update_for_gmail(); this.process.begin(Expect.MESSAGE, this.async_completion); RootParameters? message = this.process.end(async_result()); diff --git a/test/integration/imap/client-session.vala b/test/integration/imap/client-session.vala index ad48e545..ca813b79 100644 --- a/test/integration/imap/client-session.vala +++ b/test/integration/imap/client-session.vala @@ -29,9 +29,7 @@ class Integration.Imap.ClientSession : TestCase { public override void set_up() { this.session = new Geary.Imap.ClientSession( this.config.target, - Geary.Imap.ClientService.new_quirks_for_provider( - this.config.provider - ) + new Geary.Imap.Quirks() ); }