Skip to content

Commit

Permalink
Added QuirksMode detection unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jstedfast committed Dec 29, 2024
1 parent 19c4357 commit 1498edc
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 8 deletions.
15 changes: 9 additions & 6 deletions MailKit/Net/Imap/ImapEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,14 @@ enum ImapQuirksMode {
Exchange2007,
GMail,
hMailServer,
iCloud,
ProtonMail,
QQMail,
SmarterMail,
SunMicrosystems,
UW,
Yahoo,
Yandex
Yandex,
Zoho
}

class ImapFolderNameComparer : IEqualityComparer<string>
Expand Down Expand Up @@ -694,16 +695,18 @@ void DetectQuirksMode (string text)
QuirksMode = ImapQuirksMode.Exchange;
else if (text.StartsWith ("Gimap ready", StringComparison.Ordinal))
QuirksMode = ImapQuirksMode.GMail;
else if (text.Contains ("QQMail IMAP4 Server ready"))
else if (text.Contains ("QQMail "))
QuirksMode = ImapQuirksMode.QQMail;
else if (text.StartsWith ("IMAPrev1", StringComparison.Ordinal)) // https://github.com/hmailserver/hmailserver/blob/master/hmailserver/source/Server/IMAP/IMAPConnection.cpp#L127
QuirksMode = ImapQuirksMode.hMailServer;
else if (text.Contains (" IMAP4rev1 2007f.") || text.Contains (" Panda IMAP "))
QuirksMode = ImapQuirksMode.UW;
else if (text.Contains ("SmarterMail"))
QuirksMode = ImapQuirksMode.SmarterMail;
else if (text.Contains ("Yandex IMAP4rev1 "))
else if (text.Contains ("Yandex "))
QuirksMode = ImapQuirksMode.Yandex;
else if (text.Contains ("Zoho Mail "))
QuirksMode = ImapQuirksMode.Zoho;
}

/// <summary>
Expand Down Expand Up @@ -1425,8 +1428,8 @@ void ProcessCapabilityToken (string atom)
QuirksMode = ImapQuirksMode.GMail;
} else if (atom.Equals ("XSTOP", StringComparison.OrdinalIgnoreCase)) {
QuirksMode = ImapQuirksMode.ProtonMail;
} else if (atom.Equals ("X-SUN-IMAP", StringComparison.OrdinalIgnoreCase)) {
QuirksMode = ImapQuirksMode.SunMicrosystems;
} else if (atom.Equals ("XAPPLEPUSHSERVICE", StringComparison.OrdinalIgnoreCase)) {
QuirksMode = ImapQuirksMode.iCloud;
} else if (atom.Equals ("XYMHIGHESTMODSEQ", StringComparison.OrdinalIgnoreCase)) {
QuirksMode = ImapQuirksMode.Yahoo;
}
Expand Down
4 changes: 2 additions & 2 deletions MailKit/Net/Imap/ImapFolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ ImapCommand QueueOpenCommand (FolderAccess access, uint uidValidity, ulong highe

string qresync;

if ((Engine.Capabilities & ImapCapabilities.Annotate) != 0 && Engine.QuirksMode != ImapQuirksMode.SunMicrosystems)
if ((Engine.Capabilities & ImapCapabilities.Annotate) != 0 && Engine.QuirksMode != ImapQuirksMode.iCloud)
qresync = string.Format (CultureInfo.InvariantCulture, "(ANNOTATE QRESYNC ({0} {1}", uidValidity, highestModSeq);
else
qresync = string.Format (CultureInfo.InvariantCulture, "(QRESYNC ({0} {1}", uidValidity, highestModSeq);
Expand Down Expand Up @@ -573,7 +573,7 @@ ImapCommand QueueOpenCommand (FolderAccess access, CancellationToken cancellatio

if ((Engine.Capabilities & ImapCapabilities.CondStore) != 0)
@params += "CONDSTORE";
if ((Engine.Capabilities & ImapCapabilities.Annotate) != 0 && Engine.QuirksMode != ImapQuirksMode.SunMicrosystems)
if ((Engine.Capabilities & ImapCapabilities.Annotate) != 0 && Engine.QuirksMode != ImapQuirksMode.iCloud)
@params += " ANNOTATE";

if (@params.Length > 0)
Expand Down
102 changes: 102 additions & 0 deletions UnitTests/Net/Imap/ImapClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7565,5 +7565,107 @@ public void TestLowercaseImapResponses ()
Assert.That (client.Inbox, Is.Not.Null, "Inbox");
}
}

static void TestQuirksModeDetectionBasedOnGreeting (string greeting, string capability, ImapQuirksMode quirksMode)
{
var commands = new List<ImapReplayCommand> {
new ImapReplayCommand ("", greeting),
};

if (capability != null)
commands.Add (new ImapReplayCommand ("A00000000 CAPABILITY\r\n", capability));

using (var client = new ImapClient () { TagPrefix = 'A' }) {
try {
client.Connect (new ImapReplayStream (commands, false), "localhost", 143, SecureSocketOptions.None);
} catch (Exception ex) {
Assert.Fail ($"Did not expect an exception in Connect: {ex}");
}

Assert.That (client.IsConnected, Is.True, "Client failed to connect.");

var engine = (ImapEngine) client.SyncRoot;

Assert.That (engine.QuirksMode, Is.EqualTo (quirksMode), "QuirksMode");
}
}

[Test]
public void TestQuirksModeDetectionCourier ()
{
TestQuirksModeDetectionBasedOnGreeting ("courier.greeting.txt", null, ImapQuirksMode.Courier);
}

[Test]
public void TestQuirksModeDetectionCyrus ()
{
TestQuirksModeDetectionBasedOnGreeting ("cyrus.greeting.txt", null, ImapQuirksMode.Cyrus);
}

[Test]
public void TestQuirksModeDetectionDomino ()
{
TestQuirksModeDetectionBasedOnGreeting ("domino.greeting.txt", "domino.capability.txt", ImapQuirksMode.Domino);
}

[Test]
public void TestQuirksModeDetectionDovecot ()
{
TestQuirksModeDetectionBasedOnGreeting ("dovecot.greeting.txt", null, ImapQuirksMode.Dovecot);
}

[Test]
public void TestQuirksModeDetectionExchange2003 ()
{
TestQuirksModeDetectionBasedOnGreeting ("exchange.greeting-2003.txt", "exchange.capability-preauth.txt", ImapQuirksMode.Exchange2003);
}

[Test]
public void TestQuirksModeDetectionExchange2007 ()
{
TestQuirksModeDetectionBasedOnGreeting ("exchange.greeting-2007.txt", "exchange.capability-preauth.txt", ImapQuirksMode.Exchange2007);
}

[Test]
public void TestQuirksModeDetectionGMail ()
{
TestQuirksModeDetectionBasedOnGreeting ("gmail.greeting.txt", "gmail.capability.txt", ImapQuirksMode.GMail);
}

[Test]
public void TestQuirksModeDetectionQQMail ()
{
TestQuirksModeDetectionBasedOnGreeting ("qqmail.greeting.txt", null, ImapQuirksMode.QQMail);
}

[Test]
public void TestQuirksModeDetectionSmarterMail ()
{
TestQuirksModeDetectionBasedOnGreeting ("smartermail.greeting.txt", "common.capability.txt", ImapQuirksMode.SmarterMail);
}

[Test]
public void TestQuirksModeDetectionUW ()
{
TestQuirksModeDetectionBasedOnGreeting ("uw.greeting.txt", null, ImapQuirksMode.UW);
}

[Test]
public void TestQuirksModeDetectionYahooMail ()
{
TestQuirksModeDetectionBasedOnGreeting ("yahoo.greeting.txt", "yahoo.capabilities.txt", ImapQuirksMode.Yahoo);
}

[Test]
public void TestQuirksModeDetectionYandex ()
{
TestQuirksModeDetectionBasedOnGreeting ("yandex.greeting.txt", "yandex.capability.txt", ImapQuirksMode.Yandex);
}

[Test]
public void TestQuirksModeDetectionZoho ()
{
TestQuirksModeDetectionBasedOnGreeting ("zoho.greeting.txt", "zoho.capability.txt", ImapQuirksMode.Zoho);
}
}
}
1 change: 1 addition & 0 deletions UnitTests/Net/Imap/Resources/icloud/greeting.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* OK [CAPABILITY XAPPLEPUSHSERVICE IMAP4 IMAP4rev1 SASL-IR AUTH=ATOKEN AUTH=PLAIN] (2313B20-3ff771b405ab) pv50p00im-tygg10010601.me.com
2 changes: 2 additions & 0 deletions UnitTests/Net/Imap/Resources/protonmail/capability.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* CAPABILITY IMAP4rev1 AUTH=PLAIN AUTH=LOGIN ID XSTOP APPENDLIMIT
A######## OK CAPABILITY Complete
1 change: 1 addition & 0 deletions UnitTests/Net/Imap/Resources/protonmail/greeting.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* OK [CAPABILITY IMAP4rev1 STARTTLS AUTH=PLAIN AUTH=LOGIN ID APPENDLIMIT] IMAP4rev1 Service Ready
1 change: 1 addition & 0 deletions UnitTests/Net/Imap/Resources/qqmail/greeting.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* OK [CAPABILITY IMAP4 IMAP4rev1 ID AUTH=PLAIN AUTH=LOGIN NAMESPACE] QQMail IMAP4Server ready
1 change: 1 addition & 0 deletions UnitTests/Net/Imap/Resources/smartermail/greeting.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* OK IMAP4rev1 SmarterMail

0 comments on commit 1498edc

Please sign in to comment.