diff --git a/MailKit/Net/Imap/ImapFolder.cs b/MailKit/Net/Imap/ImapFolder.cs index 780f17c082..cbdf511376 100644 --- a/MailKit/Net/Imap/ImapFolder.cs +++ b/MailKit/Net/Imap/ImapFolder.cs @@ -796,18 +796,21 @@ public override async Task CloseAsync (bool expunge = false, CancellationToken c Close (); } - async Task GetCreatedFolderAsync (string encodedName, string id, bool specialUse, bool doAsync, CancellationToken cancellationToken) + ImapCommand QueueGetCreatedFolder (string encodedName, CancellationToken cancellationToken) { var ic = new ImapCommand (Engine, cancellationToken, null, "LIST \"\" %S\r\n", encodedName); - var list = new List (); - ImapFolder folder; - ic.RegisterUntaggedHandler ("LIST", ImapUtils.UntaggedListHandler); - ic.UserData = list; + ic.UserData = new List (); Engine.QueueCommand (ic); - await Engine.RunAsync (ic, doAsync).ConfigureAwait (false); + return ic; + } + + IMailFolder ProcessGetCreatedFolderResponse (ImapCommand ic, string encodedName, string id, bool specialUse) + { + var list = (List) ic.UserData; + ImapFolder folder; ProcessResponseCodes (ic, null); @@ -820,12 +823,14 @@ async Task GetCreatedFolderAsync (string encodedName, string id, bo if (specialUse) Engine.AssignSpecialFolder (folder); + + Engine.OnFolderCreated (folder); } return folder; } - async Task CreateAsync (string name, bool isMessageFolder, bool doAsync, CancellationToken cancellationToken) + ImapCommand QueueCreate (string name, bool isMessageFolder, CancellationToken cancellationToken, out string encodedName) { if (name == null) throw new ArgumentNullException (nameof (name)); @@ -839,29 +844,51 @@ async Task CreateAsync (string name, bool isMessageFolder, bool doA throw new InvalidOperationException ("Cannot create child folders."); var fullName = !string.IsNullOrEmpty (FullName) ? FullName + DirectorySeparator + name : name; - var encodedName = Engine.EncodeMailboxName (fullName); + encodedName = Engine.EncodeMailboxName (fullName); var createName = encodedName; if (!isMessageFolder && Engine.QuirksMode != ImapQuirksMode.GMail) createName += DirectorySeparator; - var ic = Engine.QueueCommand (cancellationToken, null, "CREATE %S\r\n", createName); - - await Engine.RunAsync (ic, doAsync).ConfigureAwait (false); + return Engine.QueueCommand (cancellationToken, null, "CREATE %S\r\n", createName); + } + MailboxIdResponseCode ProcessCreateResponse (ImapCommand ic) + { ProcessResponseCodes (ic, null); if (ic.Response != ImapCommandResponse.Ok && ic.GetResponseCode (ImapResponseCodeType.AlreadyExists) == null) throw ImapCommandException.Create ("CREATE", ic); - var code = (MailboxIdResponseCode) ic.GetResponseCode (ImapResponseCodeType.MailboxId); - var id = code?.MailboxId; + return (MailboxIdResponseCode) ic.GetResponseCode (ImapResponseCodeType.MailboxId); + } + + IMailFolder Create (ImapCommand ic, string encodedName, bool specialUse, CancellationToken cancellationToken) + { + Engine.Run (ic); + + var mailboxIdResponseCode = ProcessCreateResponse (ic); + var id = mailboxIdResponseCode?.MailboxId; + + ic = QueueGetCreatedFolder (encodedName, cancellationToken); + + Engine.Run (ic); + + return ProcessGetCreatedFolderResponse (ic, encodedName, id, specialUse); + } + + async Task CreateAsync (ImapCommand ic, string encodedName, bool specialUse, CancellationToken cancellationToken) + { + await Engine.RunAsync (ic).ConfigureAwait (false); + + var mailboxIdResponseCode = ProcessCreateResponse (ic); + var id = mailboxIdResponseCode?.MailboxId; - var created = await GetCreatedFolderAsync (encodedName, id, false, doAsync, cancellationToken).ConfigureAwait (false); + ic = QueueGetCreatedFolder (encodedName, cancellationToken); - Engine.OnFolderCreated (created); + await Engine.RunAsync (ic).ConfigureAwait (false); - return created; + return ProcessGetCreatedFolderResponse (ic, encodedName, id, specialUse); } /// @@ -906,7 +933,9 @@ async Task CreateAsync (string name, bool isMessageFolder, bool doA /// public override IMailFolder Create (string name, bool isMessageFolder, CancellationToken cancellationToken = default) { - return CreateAsync (name, isMessageFolder, false, cancellationToken).GetAwaiter ().GetResult (); + var ic = QueueCreate (name, isMessageFolder, cancellationToken, out var encodedName); + + return Create (ic, encodedName, false, cancellationToken); } /// @@ -951,10 +980,12 @@ public override IMailFolder Create (string name, bool isMessageFolder, Cancellat /// public override Task CreateAsync (string name, bool isMessageFolder, CancellationToken cancellationToken = default) { - return CreateAsync (name, isMessageFolder, true, cancellationToken); + var ic = QueueCreate (name, isMessageFolder, cancellationToken, out var encodedName); + + return CreateAsync (ic, encodedName, false, cancellationToken); } - async Task CreateAsync (string name, IEnumerable specialUses, bool doAsync, CancellationToken cancellationToken) + ImapCommand QueueCreate (string name, IEnumerable specialUses, CancellationToken cancellationToken, out string encodedName) { if (name == null) throw new ArgumentNullException (nameof (name)); @@ -1001,7 +1032,7 @@ async Task CreateAsync (string name, IEnumerable spe } var fullName = !string.IsNullOrEmpty (FullName) ? FullName + DirectorySeparator + name : name; - var encodedName = Engine.EncodeMailboxName (fullName); + encodedName = Engine.EncodeMailboxName (fullName); string command; if (uses.Length > 0) @@ -1009,23 +1040,7 @@ async Task CreateAsync (string name, IEnumerable spe else command = "CREATE %S\r\n"; - var ic = Engine.QueueCommand (cancellationToken, null, command, encodedName); - - await Engine.RunAsync (ic, doAsync).ConfigureAwait (false); - - ProcessResponseCodes (ic, null); - - if (ic.Response != ImapCommandResponse.Ok) - throw ImapCommandException.Create ("CREATE", ic); - - var code = (MailboxIdResponseCode) ic.GetResponseCode (ImapResponseCodeType.MailboxId); - var id = code?.MailboxId; - - var created = await GetCreatedFolderAsync (encodedName, id, true, doAsync, cancellationToken).ConfigureAwait (false); - - Engine.OnFolderCreated (created); - - return created; + return Engine.QueueCommand (cancellationToken, null, command, encodedName); } /// @@ -1075,7 +1090,9 @@ async Task CreateAsync (string name, IEnumerable spe /// public override IMailFolder Create (string name, IEnumerable specialUses, CancellationToken cancellationToken = default) { - return CreateAsync (name, specialUses, false, cancellationToken).GetAwaiter ().GetResult (); + var ic = QueueCreate (name, specialUses, cancellationToken, out var encodedName); + + return Create (ic, encodedName, true, cancellationToken); } /// @@ -1125,10 +1142,12 @@ public override IMailFolder Create (string name, IEnumerable spec /// public override Task CreateAsync (string name, IEnumerable specialUses, CancellationToken cancellationToken = default) { - return CreateAsync (name, specialUses, true, cancellationToken); + var ic = QueueCreate (name, specialUses, cancellationToken, out var encodedName); + + return CreateAsync (ic, encodedName, true, cancellationToken); } - async Task RenameAsync (IMailFolder parent, string name, bool doAsync, CancellationToken cancellationToken) + ImapCommand QueueRename (IMailFolder parent, string name, CancellationToken cancellationToken, out string encodedName) { if (parent == null) throw new ArgumentNullException (nameof (parent)); @@ -1157,11 +1176,14 @@ async Task RenameAsync (IMailFolder parent, string name, bool doAsync, Cancellat else newFullName = name; - var encodedName = Engine.EncodeMailboxName (newFullName); - var ic = Engine.QueueCommand (cancellationToken, null, "RENAME %F %S\r\n", this, encodedName); - var oldFullName = FullName; + encodedName = Engine.EncodeMailboxName (newFullName); - await Engine.RunAsync (ic, doAsync).ConfigureAwait (false); + return Engine.QueueCommand (cancellationToken, null, "RENAME %F %S\r\n", this, encodedName); + } + + void ProcessRenameResponse (ImapCommand ic, IMailFolder parent, string name, string encodedName) + { + var oldFullName = FullName; ProcessResponseCodes (ic, this); @@ -1236,7 +1258,11 @@ async Task RenameAsync (IMailFolder parent, string name, bool doAsync, Cancellat /// public override void Rename (IMailFolder parent, string name, CancellationToken cancellationToken = default) { - RenameAsync (parent, name, false, cancellationToken).GetAwaiter ().GetResult (); + var ic = QueueRename (parent, name, cancellationToken, out var encodedName); + + Engine.Run (ic); + + ProcessRenameResponse (ic, parent, name, encodedName); } /// @@ -1286,9 +1312,13 @@ public override void Rename (IMailFolder parent, string name, CancellationToken /// /// The server replied with a NO or BAD response. /// - public override Task RenameAsync (IMailFolder parent, string name, CancellationToken cancellationToken = default) + public override async Task RenameAsync (IMailFolder parent, string name, CancellationToken cancellationToken = default) { - return RenameAsync (parent, name, true, cancellationToken); + var ic = QueueRename (parent, name, cancellationToken, out var encodedName); + + await Engine.RunAsync (ic).ConfigureAwait (false); + + ProcessRenameResponse (ic, parent, name, encodedName); } async Task DeleteAsync (bool doAsync, CancellationToken cancellationToken)