diff --git a/src/app/Backends/IMAP.php b/src/app/Backends/IMAP.php
--- a/src/app/Backends/IMAP.php
+++ b/src/app/Backends/IMAP.php
@@ -346,7 +346,7 @@
         $imap = self::initIMAP($config);
 
         $settings = $folder->getSettings(['acl', 'folder']);
-        $acl = !empty($settings['acl']) ? json_decode($settings['acl'], true) : null;
+        $acl = !empty($settings['acl']) ? json_decode($settings['acl'], true) : [];
         $folder = $settings['folder'];
         $mailbox = self::toUTF7($folder);
 
diff --git a/src/app/Handlers/Auth2F.php b/src/app/Handlers/Auth2F.php
--- a/src/app/Handlers/Auth2F.php
+++ b/src/app/Handlers/Auth2F.php
@@ -2,6 +2,8 @@
 
 namespace App\Handlers;
 
+use App\Entitlement;
+
 class Auth2F extends \App\Handlers\Base
 {
     /**
@@ -14,6 +16,19 @@
         return \App\User::class;
     }
 
+    /**
+     * Handle entitlement deletion event.
+     */
+    public static function entitlementDeleted(Entitlement $entitlement): void
+    {
+        // Remove all configured 2FA methods from Roundcube database
+        if ($entitlement->entitleable && !$entitlement->entitleable->trashed()) {
+            // TODO: This should be an async job
+            $sf = new \App\Auth\SecondFactor($entitlement->entitleable);
+            $sf->removeFactors();
+        }
+    }
+
     /**
      * SKU handler metadata.
      *
diff --git a/src/app/Handlers/Base.php b/src/app/Handlers/Base.php
--- a/src/app/Handlers/Base.php
+++ b/src/app/Handlers/Base.php
@@ -2,6 +2,8 @@
 
 namespace App\Handlers;
 
+use App\Entitlement;
+
 abstract class Base
 {
     /**
@@ -14,6 +16,22 @@
         return '';
     }
 
+    /**
+     * Handle entitlement creation event.
+     */
+    public static function entitlementCreated(Entitlement $entitlement): void
+    {
+        // NOP
+    }
+
+    /**
+     * Handle entitlement deletion event.
+     */
+    public static function entitlementDeleted(Entitlement $entitlement): void
+    {
+        // NOP
+    }
+
     /**
      * Check if the SKU is available to the user. An SKU is available
      * to the user/domain when either it is active or there's already an
diff --git a/src/app/Handlers/Storage.php b/src/app/Handlers/Storage.php
--- a/src/app/Handlers/Storage.php
+++ b/src/app/Handlers/Storage.php
@@ -2,6 +2,8 @@
 
 namespace App\Handlers;
 
+use App\Entitlement;
+
 class Storage extends \App\Handlers\Base
 {
     public const MAX_ITEMS = 100;
@@ -17,6 +19,24 @@
         return \App\User::class;
     }
 
+    /**
+     * Handle entitlement creation event.
+     */
+    public static function entitlementCreated(Entitlement $entitlement): void
+    {
+        // Update the user IMAP mailbox quota
+        \App\Jobs\User\UpdateJob::dispatch($entitlement->entitleable_id);
+    }
+
+    /**
+     * Handle entitlement deletion event.
+     */
+    public static function entitlementDeleted(Entitlement $entitlement): void
+    {
+        // Update the user IMAP mailbox quota
+        \App\Jobs\User\UpdateJob::dispatch($entitlement->entitleable_id);
+    }
+
     /**
      * SKU handler metadata.
      *
diff --git a/src/app/Observers/EntitlementObserver.php b/src/app/Observers/EntitlementObserver.php
--- a/src/app/Observers/EntitlementObserver.php
+++ b/src/app/Observers/EntitlementObserver.php
@@ -57,15 +57,9 @@
      */
     public function created(Entitlement $entitlement)
     {
-        $entitlement->entitleable->updated_at = Carbon::now();
-        $entitlement->entitleable->save();
-
         $entitlement->createTransaction(\App\Transaction::ENTITLEMENT_CREATED);
 
-        // Update the user IMAP mailbox quota
-        if ($entitlement->sku->title == 'storage') {
-            \App\Jobs\User\UpdateJob::dispatch($entitlement->entitleable_id);
-        }
+        $entitlement->sku->handler_class::entitlementCreated($entitlement);
     }
 
     /**
@@ -77,27 +71,9 @@
      */
     public function deleted(Entitlement $entitlement)
     {
-        if (!$entitlement->entitleable->trashed()) {
-            // TODO: This is useless, remove this, but also maybe refactor the whole method,
-            // i.e. move job invoking to App\Handlers (don't depend on SKU title).
-            // Also make sure the transaction is always being created
-            $entitlement->entitleable->updated_at = Carbon::now();
-            $entitlement->entitleable->save();
-
-            $entitlement->createTransaction(\App\Transaction::ENTITLEMENT_DELETED);
-        }
+        $entitlement->createTransaction(\App\Transaction::ENTITLEMENT_DELETED);
 
-        // Remove all configured 2FA methods from Roundcube database
-        if ($entitlement->sku->title == '2fa') {
-            // FIXME: Should that be an async job?
-            $sf = new \App\Auth\SecondFactor($entitlement->entitleable);
-            $sf->removeFactors();
-        }
-
-        // Update the user IMAP mailbox quota
-        if ($entitlement->sku->title == 'storage') {
-            \App\Jobs\User\UpdateJob::dispatch($entitlement->entitleable_id);
-        }
+        $entitlement->sku->handler_class::entitlementDeleted($entitlement);
     }
 
     /**