Skip to content

Commit 19c4357

Browse files
committed
Work around a QQMail/Yandex IMAP BODYSTRUCTURE response for empty multipart
Fixes issue #1861
1 parent 1ffd722 commit 19c4357

File tree

2 files changed

+11
-2
lines changed

2 files changed

+11
-2
lines changed

MailKit/Net/Imap/ImapEngine.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ enum ImapQuirksMode {
101101
GMail,
102102
hMailServer,
103103
ProtonMail,
104+
QQMail,
104105
SmarterMail,
105106
SunMicrosystems,
106107
UW,
@@ -693,6 +694,8 @@ void DetectQuirksMode (string text)
693694
QuirksMode = ImapQuirksMode.Exchange;
694695
else if (text.StartsWith ("Gimap ready", StringComparison.Ordinal))
695696
QuirksMode = ImapQuirksMode.GMail;
697+
else if (text.Contains ("QQMail IMAP4 Server ready"))
698+
QuirksMode = ImapQuirksMode.QQMail;
696699
else if (text.StartsWith ("IMAPrev1", StringComparison.Ordinal)) // https://github.com/hmailserver/hmailserver/blob/master/hmailserver/source/Server/IMAP/IMAPConnection.cpp#L127
697700
QuirksMode = ImapQuirksMode.hMailServer;
698701
else if (text.Contains (" IMAP4rev1 2007f.") || text.Contains (" Panda IMAP "))

MailKit/Net/Imap/ImapUtils.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,7 +1693,7 @@ static bool ShouldParseMultipart (ImapEngine engine, CancellationToken cancellat
16931693
case ImapTokenType.Atom: // Note: Technically, we should never get an Atom here, but if we do, we'll treat it as a QString.
16941694
case ImapTokenType.QString:
16951695
case ImapTokenType.Literal:
1696-
if (engine.QuirksMode == ImapQuirksMode.GMail && token.Type != ImapTokenType.Literal) {
1696+
if (engine.QuirksMode is ImapQuirksMode.GMail or ImapQuirksMode.QQMail or ImapQuirksMode.Yandex && token.Type != ImapTokenType.Literal) {
16971697
// Note: GMail's IMAP server implementation breaks when it encounters nested multiparts with the same
16981698
// boundary and returns a BODYSTRUCTURE like the example in https://github.com/jstedfast/MailKit/issues/205
16991699
// or like the example in https://github.com/jstedfast/MailKit/issues/777. There's also an issue with BODY
@@ -1710,6 +1710,9 @@ static bool ShouldParseMultipart (ImapEngine engine, CancellationToken cancellat
17101710
// If it is '(', then that would indicate the start of the Content-Type parameter list.
17111711
// If it is ')', then that would indicate a BODY response without a Content-Type parameter list.
17121712
// If it is NIL, then it would signify that the Content-Type has no parameters.
1713+
//
1714+
// Note: Yandex also has this problem. See https://github.com/jstedfast/MailKit/issues/1861
1715+
// As does QQMail: https://github.com/jstedfast/MailKit/issues/1076
17131716

17141717
// Peek at the next token to see what we've got. If we get a '(' or NIL, then treat this as a multipart.
17151718
nextToken = engine.PeekToken (cancellationToken);
@@ -1780,7 +1783,7 @@ static async Task<bool> ShouldParseMultipartAsync (ImapEngine engine, Cancellati
17801783
case ImapTokenType.Atom: // Note: Technically, we should never get an Atom here, but if we do, we'll treat it as a QString.
17811784
case ImapTokenType.QString:
17821785
case ImapTokenType.Literal:
1783-
if (engine.QuirksMode == ImapQuirksMode.GMail && token.Type != ImapTokenType.Literal) {
1786+
if (engine.QuirksMode is ImapQuirksMode.GMail or ImapQuirksMode.QQMail or ImapQuirksMode.Yandex && token.Type != ImapTokenType.Literal) {
17841787
// Note: GMail's IMAP server implementation breaks when it encounters nested multiparts with the same
17851788
// boundary and returns a BODYSTRUCTURE like the example in https://github.com/jstedfast/MailKit/issues/205
17861789
// or like the example in https://github.com/jstedfast/MailKit/issues/777. There's also an issue with BODY
@@ -1797,6 +1800,9 @@ static async Task<bool> ShouldParseMultipartAsync (ImapEngine engine, Cancellati
17971800
// If it is '(', then that would indicate the start of the Content-Type parameter list.
17981801
// If it is ')', then that would indicate a BODY response without a Content-Type parameter list.
17991802
// If it is NIL, then it would signify that the Content-Type has no parameters.
1803+
//
1804+
// Note: Yandex also has this problem. See https://github.com/jstedfast/MailKit/issues/1861
1805+
// As does QQMail: https://github.com/jstedfast/MailKit/issues/1076
18001806

18011807
// Peek at the next token to see what we've got. If we get a '(' or NIL, then treat this as a multipart.
18021808
nextToken = await engine.PeekTokenAsync (cancellationToken).ConfigureAwait (false);

0 commit comments

Comments
 (0)