[geary/wip/768422-namespace-support] Add support for creating special use mailboxes.



commit 2015a7280208d5b30c00bc23925d8408c4bda178
Author: Michael James Gratton <mike vee net>
Date:   Fri Nov 3 13:53:14 2017 +1100

    Add support for creating special use mailboxes.
    
    The IMAP CREATE-SPECIAL-USE extension allows specifying the use of a
    mailbox being created. We should use it if present.
    
    * src/engine/imap/api/imap-account.vala (Account::create_folder_async):
      Add optional SpecialFolderType param, if present use command variant
      that accepts it.
    
    * src/engine/imap/command/imap-create-command.vala (Command): Add
      additional ctor that accepts a SpecialFolderType param. If present,
      add a USE list to the command sent.
    
    * src/engine/imap/response/imap-capabilities.vala (Capabilities): Add
      CREATE-SPECIAL-USE to the list of known capabilities, sort the list.

 .../imap-engine/imap-engine-generic-account.vala   |    7 +-
 src/engine/imap/api/imap-account.vala              |   31 ++++++++--
 src/engine/imap/command/imap-create-command.vala   |   60 ++++++++++++++++++--
 src/engine/imap/response/imap-capabilities.vala    |   21 ++++---
 4 files changed, 94 insertions(+), 25 deletions(-)
---
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala 
b/src/engine/imap-engine/imap-engine-generic-account.vala
index 3403a75..10ddf82 100644
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
@@ -716,16 +716,15 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
             minimal_folder = folder_map.get(path);
         } else {
             debug("Creating %s to use as special folder %s", path.to_string(), special.to_string());
-            
             // TODO: ignore error due to already existing.
-            yield remote.create_folder_async(path, cancellable);
+            yield remote.create_folder_async(path, special, cancellable);
             minimal_folder = (MinimalFolder) yield fetch_folder_async(path, cancellable);
         }
-        
+
         minimal_folder.set_special_folder_type(special);
         return minimal_folder;
     }
-    
+
     public override async Geary.Folder get_required_special_folder_async(Geary.SpecialFolderType special,
         Cancellable? cancellable) throws Error {
         if (!(special in get_supported_special_folders())) {
diff --git a/src/engine/imap/api/imap-account.vala b/src/engine/imap/api/imap-account.vala
index f09ebf0..782fc3d 100644
--- a/src/engine/imap/api/imap-account.vala
+++ b/src/engine/imap/api/imap-account.vala
@@ -111,19 +111,36 @@ private class Geary.Imap.Account : BaseObject {
         return exists;
     }
 
-    public async void create_folder_async(FolderPath path, Cancellable? cancellable)
+    /**
+     * Creates a new special folder on the remote server.
+     *
+     * The given path must be a fully-qualified path, including
+     * namespace prefix.
+     *
+     * If the optional special folder type is specified, and
+     * CREATE-SPECIAL-USE is supported by the connection, that will be
+     * used to specify the type of the new folder.
+     */
+    public async void create_folder_async(FolderPath path,
+                                          Geary.SpecialFolderType? type,
+                                          Cancellable? cancellable)
     throws Error {
         ClientSession session = yield claim_session_async(cancellable);
+        MailboxSpecifier mailbox = session.get_mailbox_for_path(path);
+        bool can_create_special = session.capabilities.has_capability(Capabilities.CREATE_SPECIAL_USE);
+        CreateCommand cmd = (type != null && can_create_special)
+            ? new CreateCommand.special_use(mailbox, type)
+            : new CreateCommand(mailbox);
+
         StatusResponse response = yield send_command_async(
-            session,
-            new CreateCommand(session.get_mailbox_for_path(path)),
-            null, null,
-            cancellable
+            session, cmd, null, null, cancellable
         );
 
         if (response.status != Status.OK) {
-            throw new ImapError.SERVER_ERROR("Server reports error creating path %s: %s", path.to_string(),
-                response.to_string());
+            throw new ImapError.SERVER_ERROR(
+                "Server reports error creating folder %s: %s",
+                mailbox.to_string(), response.to_string()
+            );
         }
     }
 
diff --git a/src/engine/imap/command/imap-create-command.vala 
b/src/engine/imap/command/imap-create-command.vala
index 5b5998d..5da3d1e 100644
--- a/src/engine/imap/command/imap-create-command.vala
+++ b/src/engine/imap/command/imap-create-command.vala
@@ -1,4 +1,6 @@
-/* Copyright 2016 Software Freedom Conservancy Inc.
+/*
+ * Copyright 2017 Michael Gratton <mike vee net>
+ * Copyright 2016 Software Freedom Conservancy Inc.
  *
  * This software is licensed under the GNU Lesser General Public License
  * (version 2.1 or later).  See the COPYING file in this distribution.
@@ -10,14 +12,60 @@
 
 public class Geary.Imap.CreateCommand : Command {
     public const string NAME = "create";
-    
+    public const string USE = "use";
+
     public MailboxSpecifier mailbox { get; private set; }
-    
+    public Geary.SpecialFolderType? use { get; private set; default = null; }
+
+
+    private static MailboxAttribute? get_special_folder_type(Geary.SpecialFolderType type) {
+        switch (type) {
+        case Geary.SpecialFolderType.TRASH:
+            return MailboxAttribute.SPECIAL_FOLDER_TRASH;
+
+        case Geary.SpecialFolderType.DRAFTS:
+            return MailboxAttribute.SPECIAL_FOLDER_DRAFTS;
+
+        case Geary.SpecialFolderType.SENT:
+            return MailboxAttribute.SPECIAL_FOLDER_SENT;
+
+        case Geary.SpecialFolderType.ARCHIVE:
+            return MailboxAttribute.SPECIAL_FOLDER_ARCHIVE;
+
+        case Geary.SpecialFolderType.SPAM:
+            return MailboxAttribute.SPECIAL_FOLDER_JUNK;
+
+        case Geary.SpecialFolderType.FLAGGED:
+            return MailboxAttribute.SPECIAL_FOLDER_STARRED;
+
+        case Geary.SpecialFolderType.ALL_MAIL:
+            return MailboxAttribute.SPECIAL_FOLDER_ALL;
+
+        default:
+            return null;
+        }
+    }
+
     public CreateCommand(MailboxSpecifier mailbox) {
-        base (NAME);
-        
+        base(NAME);
         this.mailbox = mailbox;
-        
         add(mailbox.to_parameter());
     }
+
+    public CreateCommand.special_use(MailboxSpecifier mailbox, Geary.SpecialFolderType use) {
+        this(mailbox);
+
+        MailboxAttribute? attr = get_special_folder_type(use);
+        if (attr != null) {
+            ListParameter use_types = new ListParameter();
+            use_types.add(new AtomParameter(attr.to_string()));
+
+            ListParameter use_param = new ListParameter();
+            use_param.add(new AtomParameter(USE));
+            use_param.add(use_types);
+
+            add(use_param);
+        }
+    }
+
 }
diff --git a/src/engine/imap/response/imap-capabilities.vala b/src/engine/imap/response/imap-capabilities.vala
index 67a3dfb..c66d6d5 100644
--- a/src/engine/imap/response/imap-capabilities.vala
+++ b/src/engine/imap/response/imap-capabilities.vala
@@ -5,20 +5,25 @@
  */
 
 public class Geary.Imap.Capabilities : Geary.GenericCapabilities {
-    public const string IDLE = "IDLE";
-    public const string STARTTLS = "STARTTLS";
-    public const string XLIST = "XLIST";
+
+
+    public const string CREATE_SPECIAL_USE = "CREATE-SPECIAL-USE";
     public const string COMPRESS = "COMPRESS";
     public const string DEFLATE_SETTING = "DEFLATE";
-    public const string UIDPLUS = "UIDPLUS";
-    public const string SPECIAL_USE = "SPECIAL-USE";
+    public const string IDLE = "IDLE";
     public const string NAMESPACE = "NAMESPACE";
+    public const string SPECIAL_USE = "SPECIAL-USE";
+    public const string STARTTLS = "STARTTLS";
+    public const string UIDPLUS = "UIDPLUS";
+    public const string XLIST = "XLIST";
 
     public const string NAME_SEPARATOR = "=";
     public const string? VALUE_SEPARATOR = null;
-    
+
+
     public int revision { get; private set; }
-    
+
+
     /**
      * Creates an empty set of capabilities.  revision represents the different variations of
      * capabilities that an IMAP session might offer (i.e. changes after login or STARTTLS, for
@@ -26,7 +31,7 @@ public class Geary.Imap.Capabilities : Geary.GenericCapabilities {
      */
     public Capabilities(int revision) {
         base (NAME_SEPARATOR, VALUE_SEPARATOR);
-        
+
         this.revision = revision;
     }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]