diff --git a/src/lib/dyn_dns/MailinaboxProvider.php b/src/lib/dyn_dns/MailinaboxProvider.php
new file mode 100644
index 0000000..8ee92cc
--- /dev/null
+++ b/src/lib/dyn_dns/MailinaboxProvider.php
@@ -0,0 +1,46 @@
+credentials['mabEmail'] ?? null;
+ $apiKey = $this->credentials['mabApiKey'] ?? null;
+ $force = !empty($this->credentials['mabForce']) && $this->credentials['mabForce'] == '1';
+
+ if (!$email || !$apiKey) {
+ $this->logger->error("Missing credentials for Mail‑in‑a‑Box DDNS: {$this->domain}");
+ return false;
+ }
+
+ $url = "https://{$this->credentials['mabHost']}/admin/dns/update";
+ $postFields = http_build_query([
+ 'force' => $force ? 1 : 0,
+ ]);
+
+ $ch = curl_init($url);
+ curl_setopt_array($ch, [
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_USERPWD => "$email:$apiKey",
+ CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
+ CURLOPT_POST => true,
+ CURLOPT_POSTFIELDS => $postFields,
+ CURLOPT_HTTPHEADER => ["Content-Type: application/x-www-form-urlencoded"],
+ ]);
+
+ $resp = curl_exec($ch);
+ if ($resp === false) {
+ $this->logger->error("Mail‑in‑a‑Box /dns/update request failed: {$this->domain}");
+ return false;
+ }
+ curl_close($ch);
+
+ if (strpos($resp, 'updated DNS:') !== false) {
+ $this->logger->info("Mail‑in‑a‑Box DDNS updated for {$this->domain}: $resp");
+ return true;
+ } else {
+ $this->logger->error("Mail‑in‑a‑Box DDNS update failed for {$this->domain}: $resp");
+ return false;
+ }
+ }
+}
diff --git a/src/lib/dyn_dns_update.php b/src/lib/dyn_dns_update.php
index 862c770..5db1ea1 100644
--- a/src/lib/dyn_dns_update.php
+++ b/src/lib/dyn_dns_update.php
@@ -7,6 +7,7 @@
require_once __DIR__ . '/dyn_dns/StratoProvider.php';
require_once __DIR__ . '/dyn_dns/NamecheapProvider.php';
require_once __DIR__ . '/dyn_dns/CloudflareProvider.php';
+require_once __DIR__ . '/dyn_dns/MailinaboxProvider.php';
require_once __DIR__ . '/dyn_dns/HetznerProvider.php';
$domainManager = new PersistentEntityManager(Domain::class, $logger, DB, 'domains');
@@ -34,6 +35,7 @@
'strato' => StratoProvider::class,
'namecheap' => NamecheapProvider::class,
'cloudflare' => CloudflareProvider::class,
+ 'mailinabox' => MailinaboxProvider::class,
'hetzner' => HetznerProvider::class,
default => null,
};
diff --git a/src/public/domains.php b/src/public/domains.php
index ebcac4c..4288572 100644
--- a/src/public/domains.php
+++ b/src/public/domains.php
@@ -219,6 +219,7 @@
+
@@ -350,6 +351,12 @@
{ label: 'API Token', id: 'cfApiToken', type: 'text' },
{ label: 'Zone ID', id: 'cfZoneId', type: 'text' }
],
+ mailinabox: [
+ { label: 'Host (box.example.com)', id: 'mabHost', type: 'text' },
+ { label: 'Email (admin user)', id: 'mabEmail', type: 'text' },
+ { label: 'API Key', id: 'mabApiKey', type: 'password' },
+ { label: 'Force Update (0 or 1)', id: 'mabForce', type: 'text' }
+ ],
hetzner: [
{ label: 'API Token', id: 'hetznerApiToken', type: 'text' },
{ label: 'Zone ID', id: 'hetznerZoneId', type: 'text' }