From fd57a272b7c414788e6e541ca2d8c09a85e69f1b Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Fri, 29 Dec 2023 17:22:13 -0500 Subject: [PATCH] Added ImapFolder.GetStream() unit tests for NIL/QSTRING responses --- UnitTests/Net/Imap/ImapFolderFetchTests.cs | 212 ++++++++++++++++++ .../gmail/fetch-nil-bodystructure.txt | 2 + .../Net/Imap/Resources/gmail/fetch-nil.txt | 2 + .../fetch-quoted-string-bodystructure.txt | 2 + .../Resources/gmail/fetch-quoted-string.txt | 2 + 5 files changed, 220 insertions(+) create mode 100644 UnitTests/Net/Imap/Resources/gmail/fetch-nil-bodystructure.txt create mode 100644 UnitTests/Net/Imap/Resources/gmail/fetch-nil.txt create mode 100644 UnitTests/Net/Imap/Resources/gmail/fetch-quoted-string-bodystructure.txt create mode 100644 UnitTests/Net/Imap/Resources/gmail/fetch-quoted-string.txt diff --git a/UnitTests/Net/Imap/ImapFolderFetchTests.cs b/UnitTests/Net/Imap/ImapFolderFetchTests.cs index 5304982996..8e0eeaa0cc 100644 --- a/UnitTests/Net/Imap/ImapFolderFetchTests.cs +++ b/UnitTests/Net/Imap/ImapFolderFetchTests.cs @@ -864,6 +864,218 @@ public async Task TestFetchSimulatedPreviewTextAsync () } } + static List CreateFetchQuotedStringCommands () + { + return new List { + new ImapReplayCommand ("", "gmail.greeting.txt"), + new ImapReplayCommand ("A00000000 CAPABILITY\r\n", "gmail.capability.txt"), + new ImapReplayCommand ("A00000001 AUTHENTICATE PLAIN AHVzZXJuYW1lAHBhc3N3b3Jk\r\n", "gmail.authenticate.txt"), + new ImapReplayCommand ("A00000002 NAMESPACE\r\n", "gmail.namespace.txt"), + new ImapReplayCommand ("A00000003 LIST \"\" \"INBOX\" RETURN (SUBSCRIBED CHILDREN)\r\n", "gmail.list-inbox.txt"), + new ImapReplayCommand ("A00000004 XLIST \"\" \"*\"\r\n", "gmail.xlist.txt"), + new ImapReplayCommand ("A00000005 LIST \"\" \"%\"\r\n", "gmail.list-personal.txt"), + new ImapReplayCommand ("A00000006 EXAMINE INBOX (CONDSTORE)\r\n", "gmail.examine-inbox.txt"), + new ImapReplayCommand ("A00000007 FETCH 1:* (UID BODYSTRUCTURE)\r\n", "gmail.fetch-quoted-string-bodystructure.txt"), + new ImapReplayCommand ("A00000008 UID FETCH 1 (BODY.PEEK[1.TEXT]<0.512>)\r\n", "gmail.fetch-quoted-string.txt"), + }; + } + + [Test] + public void TestFetchQuotedString () + { + var commands = CreateFetchQuotedStringCommands (); + + 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}"); + } + + // Note: Do not try XOAUTH2 + client.AuthenticationMechanisms.Remove ("XOAUTH2"); + + try { + client.Authenticate ("username", "password"); + } catch (Exception ex) { + Assert.Fail ($"Did not expect an exception in Authenticate: {ex}"); + } + + // disable LIST-EXTENDED + client.Capabilities &= ~ImapCapabilities.ListExtended; + + var personal = client.GetFolder (client.PersonalNamespaces[0]); + var folders = personal.GetSubfolders (); + Assert.That (folders[0], Is.EqualTo (client.Inbox), "Expected the first folder to be the Inbox."); + Assert.That (folders[1].FullName, Is.EqualTo ("[Gmail]"), "Expected the second folder to be [Gmail]."); + Assert.That (folders[1].Attributes, Is.EqualTo (FolderAttributes.NoSelect | FolderAttributes.HasChildren), "Expected [Gmail] folder to be \\Noselect \\HasChildren."); + + var inbox = client.Inbox; + + inbox.Open (FolderAccess.ReadOnly); + + var messages = inbox.Fetch (0, -1, MessageSummaryItems.UniqueId | MessageSummaryItems.BodyStructure); + using (var stream = inbox.GetStream (messages[0].UniqueId, messages[0].TextBody.PartSpecifier + ".TEXT", 0, 512)) { + var text = Encoding.UTF8.GetString (((MemoryStream) stream).ToArray ()); + + Assert.That (text, Is.EqualTo ("This is the message body as a quoted-string."), "The message body does not match."); + } + + client.Disconnect (false); + } + } + + [Test] + public async Task TestFetchQuotedStringAsync () + { + var commands = CreateFetchQuotedStringCommands (); + + using (var client = new ImapClient () { TagPrefix = 'A' }) { + try { + await client.ConnectAsync (new ImapReplayStream (commands, true), "localhost", 143, SecureSocketOptions.None); + } catch (Exception ex) { + Assert.Fail ($"Did not expect an exception in Connect: {ex}"); + } + + // Note: Do not try XOAUTH2 + client.AuthenticationMechanisms.Remove ("XOAUTH2"); + + try { + await client.AuthenticateAsync ("username", "password"); + } catch (Exception ex) { + Assert.Fail ($"Did not expect an exception in Authenticate: {ex}"); + } + + // disable LIST-EXTENDED + client.Capabilities &= ~ImapCapabilities.ListExtended; + + var personal = client.GetFolder (client.PersonalNamespaces[0]); + var folders = await personal.GetSubfoldersAsync (); + Assert.That (folders[0], Is.EqualTo (client.Inbox), "Expected the first folder to be the Inbox."); + Assert.That (folders[1].FullName, Is.EqualTo ("[Gmail]"), "Expected the second folder to be [Gmail]."); + Assert.That (folders[1].Attributes, Is.EqualTo (FolderAttributes.NoSelect | FolderAttributes.HasChildren), "Expected [Gmail] folder to be \\Noselect \\HasChildren."); + + var inbox = client.Inbox; + + await inbox.OpenAsync (FolderAccess.ReadOnly); + + var messages = await inbox.FetchAsync (0, -1, MessageSummaryItems.UniqueId | MessageSummaryItems.BodyStructure); + using (var stream = await inbox.GetStreamAsync (messages[0].UniqueId, messages[0].TextBody.PartSpecifier + ".TEXT", 0, 512)) { + var text = Encoding.UTF8.GetString (((MemoryStream) stream).ToArray ()); + + Assert.That (text, Is.EqualTo ("This is the message body as a quoted-string."), "The message body does not match."); + } + + await client.DisconnectAsync (false); + } + } + + static List CreateFetchNilCommands () + { + return new List { + new ImapReplayCommand ("", "gmail.greeting.txt"), + new ImapReplayCommand ("A00000000 CAPABILITY\r\n", "gmail.capability.txt"), + new ImapReplayCommand ("A00000001 AUTHENTICATE PLAIN AHVzZXJuYW1lAHBhc3N3b3Jk\r\n", "gmail.authenticate.txt"), + new ImapReplayCommand ("A00000002 NAMESPACE\r\n", "gmail.namespace.txt"), + new ImapReplayCommand ("A00000003 LIST \"\" \"INBOX\" RETURN (SUBSCRIBED CHILDREN)\r\n", "gmail.list-inbox.txt"), + new ImapReplayCommand ("A00000004 XLIST \"\" \"*\"\r\n", "gmail.xlist.txt"), + new ImapReplayCommand ("A00000005 LIST \"\" \"%\"\r\n", "gmail.list-personal.txt"), + new ImapReplayCommand ("A00000006 EXAMINE INBOX (CONDSTORE)\r\n", "gmail.examine-inbox.txt"), + new ImapReplayCommand ("A00000007 FETCH 1:* (UID BODYSTRUCTURE)\r\n", "gmail.fetch-nil-bodystructure.txt"), + new ImapReplayCommand ("A00000008 UID FETCH 1 (BODY.PEEK[1.TEXT]<0.512>)\r\n", "gmail.fetch-nil.txt"), + }; + } + + [Test] + public void TestFetchNil () + { + var commands = CreateFetchNilCommands (); + + 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}"); + } + + // Note: Do not try XOAUTH2 + client.AuthenticationMechanisms.Remove ("XOAUTH2"); + + try { + client.Authenticate ("username", "password"); + } catch (Exception ex) { + Assert.Fail ($"Did not expect an exception in Authenticate: {ex}"); + } + + // disable LIST-EXTENDED + client.Capabilities &= ~ImapCapabilities.ListExtended; + + var personal = client.GetFolder (client.PersonalNamespaces[0]); + var folders = personal.GetSubfolders (); + Assert.That (folders[0], Is.EqualTo (client.Inbox), "Expected the first folder to be the Inbox."); + Assert.That (folders[1].FullName, Is.EqualTo ("[Gmail]"), "Expected the second folder to be [Gmail]."); + Assert.That (folders[1].Attributes, Is.EqualTo (FolderAttributes.NoSelect | FolderAttributes.HasChildren), "Expected [Gmail] folder to be \\Noselect \\HasChildren."); + + var inbox = client.Inbox; + + inbox.Open (FolderAccess.ReadOnly); + + var messages = inbox.Fetch (0, -1, MessageSummaryItems.UniqueId | MessageSummaryItems.BodyStructure); + using (var stream = inbox.GetStream (messages[0].UniqueId, messages[0].TextBody.PartSpecifier + ".TEXT", 0, 512)) { + var text = Encoding.UTF8.GetString (((MemoryStream) stream).ToArray ()); + + Assert.That (text, Is.EqualTo (string.Empty), "The message body does not match."); + } + + client.Disconnect (false); + } + } + + [Test] + public async Task TestFetchNilAsync () + { + var commands = CreateFetchNilCommands (); + + using (var client = new ImapClient () { TagPrefix = 'A' }) { + try { + await client.ConnectAsync (new ImapReplayStream (commands, true), "localhost", 143, SecureSocketOptions.None); + } catch (Exception ex) { + Assert.Fail ($"Did not expect an exception in Connect: {ex}"); + } + + // Note: Do not try XOAUTH2 + client.AuthenticationMechanisms.Remove ("XOAUTH2"); + + try { + await client.AuthenticateAsync ("username", "password"); + } catch (Exception ex) { + Assert.Fail ($"Did not expect an exception in Authenticate: {ex}"); + } + + // disable LIST-EXTENDED + client.Capabilities &= ~ImapCapabilities.ListExtended; + + var personal = client.GetFolder (client.PersonalNamespaces[0]); + var folders = await personal.GetSubfoldersAsync (); + Assert.That (folders[0], Is.EqualTo (client.Inbox), "Expected the first folder to be the Inbox."); + Assert.That (folders[1].FullName, Is.EqualTo ("[Gmail]"), "Expected the second folder to be [Gmail]."); + Assert.That (folders[1].Attributes, Is.EqualTo (FolderAttributes.NoSelect | FolderAttributes.HasChildren), "Expected [Gmail] folder to be \\Noselect \\HasChildren."); + + var inbox = client.Inbox; + + await inbox.OpenAsync (FolderAccess.ReadOnly); + + var messages = await inbox.FetchAsync (0, -1, MessageSummaryItems.UniqueId | MessageSummaryItems.BodyStructure); + using (var stream = await inbox.GetStreamAsync (messages[0].UniqueId, messages[0].TextBody.PartSpecifier + ".TEXT", 0, 512)) { + var text = Encoding.UTF8.GetString (((MemoryStream) stream).ToArray ()); + + Assert.That (text, Is.EqualTo (string.Empty), "The message body does not match."); + } + + await client.DisconnectAsync (false); + } + } + static List CreateExpungeDuringFetchCommands () { return new List { diff --git a/UnitTests/Net/Imap/Resources/gmail/fetch-nil-bodystructure.txt b/UnitTests/Net/Imap/Resources/gmail/fetch-nil-bodystructure.txt new file mode 100644 index 0000000000..fa647c4167 --- /dev/null +++ b/UnitTests/Net/Imap/Resources/gmail/fetch-nil-bodystructure.txt @@ -0,0 +1,2 @@ +* 1 FETCH (UID 1 BODYSTRUCTURE (("TEXT" "PLAIN" ("CHARSET" "utf-8") NIL NIL "7BIT" 5235 112 NIL NIL NIL)("TEXT" "HTML" ("CHARSET" "utf-8") NIL NIL "7BIT" 60479 873 NIL NIL NIL) "ALTERNATIVE")) +A######## OK Success diff --git a/UnitTests/Net/Imap/Resources/gmail/fetch-nil.txt b/UnitTests/Net/Imap/Resources/gmail/fetch-nil.txt new file mode 100644 index 0000000000..b31169e69d --- /dev/null +++ b/UnitTests/Net/Imap/Resources/gmail/fetch-nil.txt @@ -0,0 +1,2 @@ +* 3 FETCH (UID 1 BODY[1.TEXT]<0> NIL) +A######## OK Success diff --git a/UnitTests/Net/Imap/Resources/gmail/fetch-quoted-string-bodystructure.txt b/UnitTests/Net/Imap/Resources/gmail/fetch-quoted-string-bodystructure.txt new file mode 100644 index 0000000000..fa647c4167 --- /dev/null +++ b/UnitTests/Net/Imap/Resources/gmail/fetch-quoted-string-bodystructure.txt @@ -0,0 +1,2 @@ +* 1 FETCH (UID 1 BODYSTRUCTURE (("TEXT" "PLAIN" ("CHARSET" "utf-8") NIL NIL "7BIT" 5235 112 NIL NIL NIL)("TEXT" "HTML" ("CHARSET" "utf-8") NIL NIL "7BIT" 60479 873 NIL NIL NIL) "ALTERNATIVE")) +A######## OK Success diff --git a/UnitTests/Net/Imap/Resources/gmail/fetch-quoted-string.txt b/UnitTests/Net/Imap/Resources/gmail/fetch-quoted-string.txt new file mode 100644 index 0000000000..eca913ecd0 --- /dev/null +++ b/UnitTests/Net/Imap/Resources/gmail/fetch-quoted-string.txt @@ -0,0 +1,2 @@ +* 3 FETCH (UID 1 BODY[1.TEXT]<0> "This is the message body as a quoted-string.") +A######## OK Success