diff --git a/docs/superpowers/plans/2026-05-26-multi-mail-accounts.md b/docs/superpowers/plans/2026-05-26-multi-mail-accounts.md
new file mode 100644
index 0000000..6f6621c
--- /dev/null
+++ b/docs/superpowers/plans/2026-05-26-multi-mail-accounts.md
@@ -0,0 +1,832 @@
+# Multi Mail Accounts Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Replace the single Azure-account Email tab with a full multi-account mail management system supporting Microsoft 365 (Azure AD) and SMTP accounts.
+
+**Architecture:** New `mail_accounts` DB table with encrypted JSON config; `MailAccount` model with `buildTransport()` factory; `MailAccountController` for CRUD + test + toggle; `AppServiceProvider` registers all accounts as named Laravel mailers; Email tab in integrations view rebuilt as account list + AJAX modal.
+
+**Tech Stack:** Laravel 12, Alpine.js v3, `PromoSeven\AzureMailer` (local package), `Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport`, `Setting` model (existing).
+
+---
+
+## File Map
+
+| File | Change |
+|------|--------|
+| `database/migrations/2026_05_26_000001_create_mail_accounts_table.php` | Create |
+| `app/Models/MailAccount.php` | Create |
+| `app/Http/Controllers/MailAccountController.php` | Create |
+| `app/Providers/AppServiceProvider.php` | Add dynamic mailer registration |
+| `routes/web.php` | Add 7 new routes; remove 3 old azure routes |
+| `app/Http/Controllers/SettingsController.php` | Remove azure methods + `$azureSettings` |
+| `resources/views/settings/integrations.blade.php` | Replace Email tab with account list + modal |
+
+---
+
+### Task 1: Migration and MailAccount model
+
+**Files:**
+- Create: `database/migrations/2026_05_26_000001_create_mail_accounts_table.php`
+- Create: `app/Models/MailAccount.php`
+
+- [ ] **Step 1: Create the migration**
+
+```php
+id();
+ $table->string('name', 100)->unique();
+ $table->string('label', 150);
+ $table->enum('type', ['azure', 'smtp']);
+ $table->string('from_address', 255);
+ $table->string('from_name', 150)->nullable();
+ $table->text('config');
+ $table->boolean('enabled')->default(true);
+ $table->timestamps();
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::dropIfExists('mail_accounts');
+ }
+};
+```
+
+- [ ] **Step 2: Run the migration**
+
+```bash
+php artisan migrate
+```
+
+Expected: `mail_accounts` table created with no errors.
+
+- [ ] **Step 3: Create `app/Models/MailAccount.php`**
+
+```php
+ 'encrypted:array',
+ 'enabled' => 'boolean',
+ ];
+
+ public function buildTransport(): TransportInterface
+ {
+ if ($this->type === 'azure') {
+ $config = array_merge($this->config, [
+ 'from_address' => $this->from_address,
+ 'graph_api_version' => 'v1.0',
+ 'timeout' => 30,
+ 'save_to_sent_items' => false,
+ ]);
+ return new AzureTransport(
+ new GraphClient(new TokenManager($config), $config),
+ $config
+ );
+ }
+
+ $cfg = $this->config;
+ $tls = ($cfg['encryption'] ?? 'tls') === 'ssl';
+ $transport = new EsmtpTransport($cfg['host'], (int) ($cfg['port'] ?? 587), $tls);
+ if (!empty($cfg['username'])) {
+ $transport->setUsername($cfg['username']);
+ $transport->setPassword($cfg['password'] ?? '');
+ }
+ return $transport;
+ }
+}
+```
+
+- [ ] **Step 4: Verify model is autoloaded**
+
+```bash
+php artisan tinker --execute="echo App\Models\MailAccount::count();"
+```
+
+Expected: prints `0` with no errors.
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add database/migrations/2026_05_26_000001_create_mail_accounts_table.php app/Models/MailAccount.php
+git commit -m "feat: add mail_accounts migration and MailAccount model"
+```
+
+---
+
+### Task 2: MailAccountController and routes
+
+**Files:**
+- Create: `app/Http/Controllers/MailAccountController.php`
+- Modify: `routes/web.php`
+
+- [ ] **Step 1: Create `app/Http/Controllers/MailAccountController.php`**
+
+```php
+get()->map(fn($a) => $this->accountData($a));
+ return response()->json(['accounts' => $accounts]);
+ }
+
+ public function show(MailAccount $mailAccount): JsonResponse
+ {
+ return response()->json([
+ 'account' => array_merge($this->accountData($mailAccount), ['config' => $mailAccount->config]),
+ ]);
+ }
+
+ public function store(Request $request): JsonResponse
+ {
+ $data = $this->validated($request);
+ $account = MailAccount::create($data);
+ return response()->json(['success' => true, 'account' => $this->accountData($account)], 201);
+ }
+
+ public function update(Request $request, MailAccount $mailAccount): JsonResponse
+ {
+ $data = $this->validated($request, $mailAccount->id);
+ $mailAccount->update($data);
+ return response()->json(['success' => true, 'account' => $this->accountData($mailAccount->fresh())]);
+ }
+
+ public function destroy(MailAccount $mailAccount): JsonResponse
+ {
+ $mailAccount->delete();
+ return response()->json(['success' => true]);
+ }
+
+ public function testConnection(MailAccount $mailAccount): JsonResponse
+ {
+ try {
+ if ($mailAccount->type === 'azure') {
+ $config = array_merge($mailAccount->config, ['from_address' => $mailAccount->from_address]);
+ (new TokenManager($config))->getToken();
+ } else {
+ $cfg = $mailAccount->config;
+ $host = $cfg['host'] ?? '';
+ $port = (int) ($cfg['port'] ?? 587);
+ $socket = @fsockopen($host, $port, $errno, $errstr, 5);
+ if (! $socket) {
+ throw new \RuntimeException("Cannot connect to {$host}:{$port} — {$errstr}");
+ }
+ fclose($socket);
+ }
+ return response()->json(['success' => true]);
+ } catch (\Exception $e) {
+ return response()->json(['success' => false, 'message' => $e->getMessage()]);
+ }
+ }
+
+ public function toggleEnabled(MailAccount $mailAccount): JsonResponse
+ {
+ $mailAccount->update(['enabled' => ! $mailAccount->enabled]);
+ return response()->json(['success' => true, 'enabled' => $mailAccount->fresh()->enabled]);
+ }
+
+ private function validated(Request $request, ?int $ignoreId = null): array
+ {
+ $nameUnique = 'unique:mail_accounts,name' . ($ignoreId ? ",{$ignoreId}" : '');
+ $rules = [
+ 'name' => ['required', 'string', 'max:100', 'regex:/^[a-z0-9\-]+$/', $nameUnique],
+ 'label' => ['required', 'string', 'max:150'],
+ 'type' => ['required', 'in:azure,smtp'],
+ 'from_address' => ['required', 'email', 'max:255'],
+ 'from_name' => ['nullable', 'string', 'max:150'],
+ 'enabled' => ['boolean'],
+ ];
+
+ if ($request->input('type') === 'azure') {
+ $rules['config.tenant_id'] = ['required', 'string', 'max:100'];
+ $rules['config.client_id'] = ['required', 'string', 'max:100'];
+ $rules['config.client_secret'] = ['required', 'string', 'max:500'];
+ } else {
+ $rules['config.host'] = ['required', 'string', 'max:255'];
+ $rules['config.port'] = ['required', 'integer', 'min:1', 'max:65535'];
+ $rules['config.encryption'] = ['required', 'in:tls,ssl,none'];
+ $rules['config.username'] = ['nullable', 'string', 'max:255'];
+ $rules['config.password'] = ['nullable', 'string', 'max:500'];
+ }
+
+ $v = $request->validate($rules);
+ return [
+ 'name' => $v['name'],
+ 'label' => $v['label'],
+ 'type' => $v['type'],
+ 'from_address' => $v['from_address'],
+ 'from_name' => $v['from_name'] ?? null,
+ 'config' => $v['config'],
+ 'enabled' => $v['enabled'] ?? true,
+ ];
+ }
+
+ private function accountData(MailAccount $account): array
+ {
+ return [
+ 'id' => $account->id,
+ 'name' => $account->name,
+ 'label' => $account->label,
+ 'type' => $account->type,
+ 'from_address' => $account->from_address,
+ 'from_name' => $account->from_name,
+ 'enabled' => $account->enabled,
+ ];
+ }
+}
+```
+
+- [ ] **Step 2: Add the 7 new routes and remove the 3 old azure routes in `routes/web.php`**
+
+Find the block:
+```php
+Route::post('settings/integrations/azure-mail', [SettingsController::class, 'updateAzureMail'])->name('settings.integrations.azure-mail');
+Route::post('settings/integrations/test-azure-mail', [SettingsController::class, 'testAzureMailConnection'])->name('settings.integrations.test-azure-mail');
+Route::post('settings/integrations/send-test-email', [SettingsController::class, 'sendTestEmail'])->name('settings.integrations.send-test-email');
+```
+
+Replace it with:
+```php
+Route::get('settings/integrations/mail-accounts', [MailAccountController::class, 'index'])->name('settings.mail-accounts.index');
+Route::post('settings/integrations/mail-accounts', [MailAccountController::class, 'store'])->name('settings.mail-accounts.store');
+Route::get('settings/integrations/mail-accounts/{mailAccount}', [MailAccountController::class, 'show'])->name('settings.mail-accounts.show');
+Route::put('settings/integrations/mail-accounts/{mailAccount}', [MailAccountController::class, 'update'])->name('settings.mail-accounts.update');
+Route::delete('settings/integrations/mail-accounts/{mailAccount}', [MailAccountController::class, 'destroy'])->name('settings.mail-accounts.destroy');
+Route::post('settings/integrations/mail-accounts/{mailAccount}/test', [MailAccountController::class, 'testConnection'])->name('settings.mail-accounts.test');
+Route::patch('settings/integrations/mail-accounts/{mailAccount}/toggle', [MailAccountController::class, 'toggleEnabled'])->name('settings.mail-accounts.toggle');
+```
+
+Also add the `MailAccountController` use statement at the top of `routes/web.php` alongside the existing controller use statements:
+```php
+use App\Http\Controllers\MailAccountController;
+```
+
+- [ ] **Step 3: Verify routes**
+
+```bash
+php artisan route:list --name=settings.mail-accounts
+```
+
+Expected: 7 rows — index, store, show, update, destroy, test, toggle.
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add app/Http/Controllers/MailAccountController.php routes/web.php
+git commit -m "feat: add MailAccountController with CRUD + test + toggle routes"
+```
+
+---
+
+### Task 3: AppServiceProvider + SettingsController cleanup
+
+**Files:**
+- Modify: `app/Providers/AppServiceProvider.php`
+- Modify: `app/Http/Controllers/SettingsController.php`
+
+- [ ] **Step 1: Update `app/Providers/AppServiceProvider.php`**
+
+Replace the entire file content with:
+
+```php
+ Setting::get('ultramsg_instance_id', config('ultra-message.instance_id')),
+ 'token' => Setting::get('ultramsg_token', config('ultra-message.token')),
+ 'webhook_secret' => Setting::get('ultramsg_webhook_secret', config('ultra-message.webhook_secret')),
+ 'webhook_path' => Setting::get('ultramsg_webhook_path', config('ultra-message.webhook_path', 'ultra-message/webhook')),
+ 'timeout' => config('ultra-message.timeout', 30),
+ 'enabled' => (bool) Setting::get('ultramsg_enabled', config('ultra-message.enabled', true)),
+ ];
+ });
+
+ $this->callAfterResolving(MailManager::class, function (MailManager $manager) {
+ try {
+ foreach (MailAccount::all() as $account) {
+ $manager->extend($account->name, fn () => $account->buildTransport());
+ }
+ } catch (\Exception) {
+ // DB not ready on fresh install — skip silently
+ }
+ });
+ }
+}
+```
+
+- [ ] **Step 2: Clean up `app/Http/Controllers/SettingsController.php`**
+
+Remove the `use Illuminate\Support\Facades\Mail;` and `use PromoSeven\AzureMailer\Graph\TokenManager;` use statements.
+
+Change `integrations()` to only pass `$whatsappSettings` (remove `$azureSettings`):
+
+```php
+public function integrations(): View
+{
+ $whatsappSettings = [
+ 'enabled' => Setting::get('ultramsg_enabled', false),
+ 'instance_id' => Setting::get('ultramsg_instance_id', ''),
+ 'token' => Setting::get('ultramsg_token', ''),
+ 'webhook_secret' => Setting::get('ultramsg_webhook_secret', ''),
+ 'webhook_path' => Setting::get('ultramsg_webhook_path', 'ultra-message/webhook'),
+ ];
+
+ return view('settings.integrations', compact('whatsappSettings'));
+}
+```
+
+Delete the three azure methods entirely: `updateAzureMail()`, `testAzureMailConnection()`, `sendTestEmail()`.
+
+- [ ] **Step 3: Verify no parse errors**
+
+```bash
+php artisan route:list --name=settings.integrations 2>&1 | tail -3
+```
+
+Expected: shows 4 rows (GET + whatsapp POST + test-whatsapp POST + send-test-message POST), no errors.
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add app/Providers/AppServiceProvider.php app/Http/Controllers/SettingsController.php
+git commit -m "feat: register dynamic mailers in AppServiceProvider, remove single-azure methods from SettingsController"
+```
+
+---
+
+### Task 4: Rewrite Email tab in integrations.blade.php
+
+**Files:**
+- Modify: `resources/views/settings/integrations.blade.php`
+
+Replace the entire `{{-- ===== Email tab ===== --}}` section (and the old Email modal/accordion) with the following.
+
+- [ ] **Step 1: Replace the Email tab panel and add the modal**
+
+The complete replacement for everything from `{{-- ===== Email tab ===== --}}` to `{{-- end Email tab --}}` (inclusive), plus the new modal added just before the closing `` of the outer wrapper, plus the new JS block replacing the old azure JS functions:
+
+**Email tab panel** (replaces old email tab div):
+
+```blade
+{{-- ===== Email tab ===== --}}
+
+
+
+
+
Mail Accounts
+
Loading…
+
+
+
+
+
+
+
+
✉️
+
No mail accounts configured
+
Click Add Account to get started.
+
+
+
{{-- end Email tab --}}
+```
+
+**Modal** (add just before the closing `` of the outer Alpine wrapper, after the email tab div):
+
+```blade
+{{-- Mail Accounts Modal --}}
+
+
+
+ {{-- Header --}}
+
+
Add Mail Account
+
+
+
+ {{-- Body --}}
+
+
+ {{-- Account Name --}}
+
+
+
+
Lowercase letters, numbers and hyphens only.
+
+
+ {{-- Label --}}
+
+
+
+
+
+ {{-- Type --}}
+
+
+
+
+
+ {{-- Azure section --}}
+
+
Azure AD Credentials
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{-- SMTP section --}}
+
+
SMTP Server
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{-- Sender --}}
+
+
Sender
+
+
+
+
+
+
+
+
+
+
+
+
+ {{-- Footer --}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+- [ ] **Step 2: Update the Email tab button to also load accounts**
+
+In the pill tab row, change the Email tab button's `@click` from:
+```blade
+
-
✉️ Email
@@ -190,146 +190,165 @@
{{-- end WhatsApp tab --}}
{{-- ===== Email tab ===== --}}
-
+
-
-
-
✉️
-
-
Microsoft 365 (Azure Mail)
-
Send emails via Microsoft Graph API using Azure AD
-
+
+
+
Mail Accounts
+
Loading…
+
+
+ + Add Account
+
+
+
+
+
+
+
✉️
+
No mail accounts configured
+
Click Add Account to get started.
+
+
+
{{-- end Email tab --}}
+
+ {{-- Mail Accounts Modal --}}
+
+
+
+ {{-- Header --}}
+
+
Add Mail Account
+ ×
+ {{-- Body --}}
- {{-- Enable toggle --}}
-
-
-
Enable Email Notifications
-
When disabled, no emails will be sent.
+ {{-- Account Name --}}
+
+
+
+
Lowercase letters, numbers and hyphens only.
+
+
+ {{-- Label --}}
+
+
+
+
+
+ {{-- Type --}}
+
+
+
+
+
+ {{-- Azure section --}}
+
+
Azure AD Credentials
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
- {{-- Tenant ID --}}
-
-
-
-
-
- {{-- Client ID --}}
-
-
-
-
-
- {{-- Client Secret --}}
-
-
-
-
-
-
-
-
+ {{-- SMTP section --}}
+
+
SMTP Server
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- {{-- From Address --}}
-
-
-
-
Must be a mailbox in your Microsoft 365 tenant.
-
-
- {{-- Actions --}}
-
-
-
-
- Test Connection
-
-
+ {{-- Sender --}}
+
+
Sender
+
+
+
+
+
+
+
- Save Settings
-
- {{-- Send Test Email accordion --}}
-
-
-
- 📧
- Send Test Email
- — verify the connection works end-to-end
-