Browse Source

Autoconfig harmonization

- use $autodiscover_config everywhere
- non-443 HTTPS ports in autoconfig etc.
- disabling POP service via SRV record
- fix display name in Outlook IMAP autodiscover
- allow multiple calls to TLSA generator and support Sieve STARTTLS
- iOS mobileconfig generator
Michael Kuron 8 years ago
parent
commit
5abeb313ba
5 changed files with 267 additions and 56 deletions
  1. 32 15
      data/web/autoconfig.php
  2. 30 24
      data/web/autodiscover.php
  3. 14 10
      data/web/inc/functions.inc.php
  4. 24 7
      data/web/inc/vars.inc.php
  5. 167 0
      data/web/mobileconfig.php

+ 32 - 15
data/web/autoconfig.php

@@ -5,6 +5,16 @@ if (empty($mailcow_hostname)) {
   exit();
   exit();
 }
 }
 
 
+$domain_dot = strpos($_SERVER['HTTP_HOST'], '.');
+$domain_port = strpos($_SERVER['HTTP_HOST'], ':');
+if ($domain_port === FALSE) {
+  $domain = substr($_SERVER['HTTP_HOST'], $domain_dot+1);
+  $port = 443;
+} else {
+  $domain = substr($_SERVER['HTTP_HOST'], $domain_dot+1, $domain_port-$domain_dot-1);
+  $port = substr($_SERVER['HTTP_HOST'], $domain_port+1);
+}
+
 header('Content-Type: application/xml');
 header('Content-Type: application/xml');
 ?>
 ?>
 <?= '<?xml version="1.0"?>'; ?>
 <?= '<?xml version="1.0"?>'; ?>
@@ -15,52 +25,59 @@ header('Content-Type: application/xml');
       <displayShortName>mail server</displayShortName>
       <displayShortName>mail server</displayShortName>
 
 
       <incomingServer type="imap">
       <incomingServer type="imap">
-         <hostname><?= $mailcow_hostname; ?></hostname>
-         <port>993</port>
+         <hostname><?= $autodiscover_config['imap']['server']; ?></hostname>
+         <port><?= $autodiscover_config['imap']['port']; ?></port>
          <socketType>SSL</socketType>
          <socketType>SSL</socketType>
          <username>%EMAILADDRESS%</username>
          <username>%EMAILADDRESS%</username>
          <authentication>password-cleartext</authentication>
          <authentication>password-cleartext</authentication>
       </incomingServer>
       </incomingServer>
       <incomingServer type="imap">
       <incomingServer type="imap">
-         <hostname><?= $mailcow_hostname; ?></hostname>
-         <port>143</port>
+         <hostname><?= $autodiscover_config['imap']['server']; ?></hostname>
+         <port><?= $autodiscover_config['imap']['tlsport']; ?></port>
          <socketType>STARTTLS</socketType>
          <socketType>STARTTLS</socketType>
          <username>%EMAILADDRESS%</username>
          <username>%EMAILADDRESS%</username>
          <authentication>password-cleartext</authentication>
          <authentication>password-cleartext</authentication>
       </incomingServer>
       </incomingServer>
 
 
+<?php
+$records = dns_get_record('_pop3s._tcp.' . $domain, DNS_SRV); // check if POP3 is announced as "not provided" via SRV record
+if (count($records) == 0 || $records[0]['target'] != '') { ?>
       <incomingServer type="pop3">
       <incomingServer type="pop3">
-         <hostname><?= $mailcow_hostname; ?></hostname>
-         <port>995</port>
+         <hostname><?= $autodiscover_config['pop3']['server']; ?></hostname>
+         <port><?= $autodiscover_config['pop3']['port']; ?></port>
          <socketType>SSL</socketType>
          <socketType>SSL</socketType>
          <username>%EMAILADDRESS%</username>
          <username>%EMAILADDRESS%</username>
          <authentication>password-cleartext</authentication>
          <authentication>password-cleartext</authentication>
       </incomingServer>
       </incomingServer>
+<?php } ?>
+<?php
+$records = dns_get_record('_pop3._tcp.' . $domain, DNS_SRV); // check if POP3 is announced as "not provided" via SRV record
+if (count($records) == 0 || $records[0]['target'] != '') { ?>
       <incomingServer type="pop3">
       <incomingServer type="pop3">
-         <hostname><?= $mailcow_hostname; ?></hostname>
-         <port>110</port>
+         <hostname><?= $autodiscover_config['pop3']['server']; ?></hostname>
+         <port><?= $autodiscover_config['pop3']['tlsport']; ?></port>
          <socketType>STARTTLS</socketType>
          <socketType>STARTTLS</socketType>
          <username>%EMAILADDRESS%</username>
          <username>%EMAILADDRESS%</username>
          <authentication>password-cleartext</authentication>
          <authentication>password-cleartext</authentication>
       </incomingServer>
       </incomingServer>
+<?php } ?>
 
 
       <outgoingServer type="smtp">
       <outgoingServer type="smtp">
-         <hostname><?= $mailcow_hostname; ?></hostname>
-         <port>465</port>
+         <hostname><?= $autodiscover_config['smtp']['server']; ?></hostname>
+         <port><?= $autodiscover_config['smtp']['port']; ?></port>
          <socketType>SSL</socketType>
          <socketType>SSL</socketType>
          <username>%EMAILADDRESS%</username>
          <username>%EMAILADDRESS%</username>
          <authentication>password-cleartext</authentication>
          <authentication>password-cleartext</authentication>
       </outgoingServer>
       </outgoingServer>
-
       <outgoingServer type="smtp">
       <outgoingServer type="smtp">
-         <hostname><?= $mailcow_hostname; ?></hostname>
-         <port>587</port>
+         <hostname><?= $autodiscover_config['smtp']['server']; ?></hostname>
+         <port><?= $autodiscover_config['smtp']['tlsport']; ?></port>
          <socketType>STARTTLS</socketType>
          <socketType>STARTTLS</socketType>
          <username>%EMAILADDRESS%</username>
          <username>%EMAILADDRESS%</username>
          <authentication>password-cleartext</authentication>
          <authentication>password-cleartext</authentication>
       </outgoingServer>
       </outgoingServer>
 
 
-      <enable visiturl="https://<?= $mailcow_hostname; ?>/admin.php">
+      <enable visiturl="https://<?= $mailcow_hostname; ?><?php if ($port != 443) echo ':'.$port; ?>/admin.php">
          <instruction>If you didn't change the password given to you by the administrator or if you didn't change it in a long time, please consider doing that now.</instruction>
          <instruction>If you didn't change the password given to you by the administrator or if you didn't change it in a long time, please consider doing that now.</instruction>
          <instruction lang="de">Sollten Sie das Ihnen durch den Administrator vergebene Passwort noch nicht geändert haben, empfehlen wir dies nun zu tun. Auch ein altes Passwort sollte aus Sicherheitsgründen geändert werden.</instruction>
          <instruction lang="de">Sollten Sie das Ihnen durch den Administrator vergebene Passwort noch nicht geändert haben, empfehlen wir dies nun zu tun. Auch ein altes Passwort sollte aus Sicherheitsgründen geändert werden.</instruction>
       </enable>
       </enable>
@@ -68,6 +85,6 @@ header('Content-Type: application/xml');
     </emailProvider>
     </emailProvider>
 
 
     <webMail>
     <webMail>
-      <loginPage url="https://<?= $mailcow_hostname; ?>/SOGo/" />
+      <loginPage url="https://<?= $mailcow_hostname; ?><?php if ($port != 443) echo ':'.$port; ?>/SOGo/" />
     </webMail>
     </webMail>
 </clientConfig>
 </clientConfig>

+ 30 - 24
data/web/autodiscover.php

@@ -12,13 +12,14 @@ error_reporting(0);
 $data = trim(file_get_contents("php://input"));
 $data = trim(file_get_contents("php://input"));
 
 
 // Desktop client needs IMAP, unless it's Outlook 2013 or higher on Windows
 // Desktop client needs IMAP, unless it's Outlook 2013 or higher on Windows
-if (strpos($data, 'autodiscover/outlook/responseschema')) { // desktop client
+if (strpos($data, 'autodiscover/outlook/responseschema') !== false) { // desktop client
   $configuration['autodiscoverType'] = 'imap';
   $configuration['autodiscoverType'] = 'imap';
   if ($configuration['useEASforOutlook'] == 'yes' &&
   if ($configuration['useEASforOutlook'] == 'yes' &&
-  // Office for macOS does not support EAS
-  strpos($_SERVER['HTTP_USER_AGENT'], 'Mac') === false &&
-  // Outlook 2013 (version 15) or higher
-  preg_match('/(Outlook|Office).+1[5-9]\./', $_SERVER['HTTP_USER_AGENT'])) {
+    // Office for macOS does not support EAS
+    strpos($_SERVER['HTTP_USER_AGENT'], 'Mac') === false &&
+    // Outlook 2013 (version 15) or higher
+    preg_match('/(Outlook|Office).+1[5-9]\./', $_SERVER['HTTP_USER_AGENT'])
+  ) {
     $configuration['autodiscoverType'] = 'activesync';
     $configuration['autodiscoverType'] = 'activesync';
   }
   }
 }
 }
@@ -60,8 +61,28 @@ else {
 <?php
 <?php
         exit(0);
         exit(0);
       }
       }
-      $discover = new SimpleXMLElement($data);
-      $email = $discover->Request->EMailAddress;
+      try {
+        $discover = new SimpleXMLElement($data);
+        $email = $discover->Request->EMailAddress;
+      } catch (Exception $e) {
+        $email = $_SERVER['PHP_AUTH_USER'];
+      }
+
+      $username = trim($email);
+      try {
+        $stmt = $pdo->prepare("SELECT `name` FROM `mailbox` WHERE `username`= :username");
+        $stmt->execute(array(':username' => $username));
+        $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
+      }
+      catch(PDOException $e) {
+        die("Failed to determine name from SQL");
+      }
+      if (!empty($MailboxData['name'])) {
+        $displayname = utf8_encode($MailboxData['name']);
+      }
+      else {
+        $displayname = $email;
+      }
 
 
       if ($configuration['autodiscoverType'] == 'imap') {
       if ($configuration['autodiscoverType'] == 'imap') {
 ?>
 ?>
@@ -96,13 +117,13 @@ else {
       </Protocol>
       </Protocol>
       <Protocol>
       <Protocol>
         <Type>CalDAV</Type>
         <Type>CalDAV</Type>
-        <Server><?=$configuration['caldav']['server'];?>/SOGo/dav/<?=$email;?>/Calendar</Server>
+        <Server>https://<?=$configuration['caldav']['server'];?><?php if ($configuration['caldav']['port'] != 443) echo ':'.$configuration['caldav']['port']; ?>/SOGo/dav/<?=$email;?>/Calendar</Server>
         <DomainRequired>off</DomainRequired>
         <DomainRequired>off</DomainRequired>
         <LoginName><?=$email;?></LoginName>
         <LoginName><?=$email;?></LoginName>
       </Protocol>
       </Protocol>
       <Protocol>
       <Protocol>
         <Type>CardDAV</Type>
         <Type>CardDAV</Type>
-        <Server><?=$configuration['carddav']['server'];?>/SOGo/dav/<?=$email;?>/Contacts</Server>
+        <Server>https://<?=$configuration['carddav']['server'];?><?php if ($configuration['caldav']['port'] != 443) echo ':'.$configuration['carddav']['port']; ?>/SOGo/dav/<?=$email;?>/Contacts</Server>
         <DomainRequired>off</DomainRequired>
         <DomainRequired>off</DomainRequired>
         <LoginName><?=$email;?></LoginName>
         <LoginName><?=$email;?></LoginName>
       </Protocol>
       </Protocol>
@@ -111,21 +132,6 @@ else {
 <?php
 <?php
       }
       }
       else if ($configuration['autodiscoverType'] == 'activesync') {
       else if ($configuration['autodiscoverType'] == 'activesync') {
-        $username = trim($email);
-        try {
-          $stmt = $pdo->prepare("SELECT `name` FROM `mailbox` WHERE `username`= :username");
-          $stmt->execute(array(':username' => $username));
-          $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
-        }
-        catch(PDOException $e) {
-          die("Failed to determine name from SQL");
-        }
-        if (!empty($MailboxData['name'])) {
-          $displayname = utf8_encode($MailboxData['name']);
-        }
-        else {
-          $displayname = $email;
-        }
 ?>
 ?>
   <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006">
   <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006">
     <Culture>en:en</Culture>
     <Culture>en:en</Culture>

+ 14 - 10
data/web/inc/functions.inc.php

@@ -62,17 +62,17 @@ function hasMailboxObjectAccess($username, $role, $object) {
 	}
 	}
 	return false;
 	return false;
 }
 }
+function pem_to_der($pem_key) {
+  // Need to remove BEGIN/END PUBLIC KEY
+  $lines = explode("\n", trim($pem_key));
+  unset($lines[count($lines)-1]);
+  unset($lines[0]);
+  return base64_decode(implode('', $lines));
+}
 function generate_tlsa_digest($hostname, $port, $starttls = null) {
 function generate_tlsa_digest($hostname, $port, $starttls = null) {
   if (!is_valid_domain_name($hostname)) {
   if (!is_valid_domain_name($hostname)) {
     return "Not a valid hostname";
     return "Not a valid hostname";
   }
   }
-  function pem_to_der($pem_key) {
-    // Need to remove BEGIN/END PUBLIC KEY
-    $lines = explode("\n", trim($pem_key));
-    unset($lines[count($lines)-1]);
-    unset($lines[0]);
-    return base64_decode(implode('', $lines));
-  }
 
 
   if (empty($starttls)) {
   if (empty($starttls)) {
     $context = stream_context_create(array("ssl" => array("capture_peer_cert" => true, 'verify_peer' => false, 'allow_self_signed' => true)));
     $context = stream_context_create(array("ssl" => array("capture_peer_cert" => true, 'verify_peer' => false, 'allow_self_signed' => true)));
@@ -88,20 +88,24 @@ function generate_tlsa_digest($hostname, $port, $starttls = null) {
       return $error_nr . ': ' . $error_msg;
       return $error_nr . ': ' . $error_msg;
     }
     }
     $banner = fread($stream, 512 );
     $banner = fread($stream, 512 );
-    if (preg_match("/^220/i", $banner)) {
+    if (preg_match("/^220/i", $banner)) { // SMTP
       fwrite($stream,"HELO tlsa.generator.local\r\n");
       fwrite($stream,"HELO tlsa.generator.local\r\n");
       fread($stream, 512);
       fread($stream, 512);
       fwrite($stream,"STARTTLS\r\n");
       fwrite($stream,"STARTTLS\r\n");
       fread($stream, 512);
       fread($stream, 512);
     }
     }
-    elseif (preg_match("/imap.+starttls/i", $banner)) {
+    elseif (preg_match("/imap.+starttls/i", $banner)) { // IMAP
       fwrite($stream,"A1 STARTTLS\r\n");
       fwrite($stream,"A1 STARTTLS\r\n");
       fread($stream, 512);
       fread($stream, 512);
     }
     }
-    elseif (preg_match("/^\+OK/", $banner)) {
+    elseif (preg_match("/^\+OK/", $banner)) { // POP3
       fwrite($stream,"STLS\r\n");
       fwrite($stream,"STLS\r\n");
       fread($stream, 512);
       fread($stream, 512);
     }
     }
+    elseif (preg_match("/^OK/m", $banner)) { // Sieve
+      fwrite($stream,"STARTTLS\r\n");
+      fread($stream, 512);
+    }
     else {
     else {
       return 'Unknown banner: "' . htmlspecialchars(trim($banner)) . '"';
       return 'Unknown banner: "' . htmlspecialchars(trim($banner)) . '"';
     }
     }

+ 24 - 7
data/web/inc/vars.inc.php

@@ -18,31 +18,48 @@ $database_name = getenv('DBNAME');
 $mailcow_hostname = getenv('MAILCOW_HOSTNAME');
 $mailcow_hostname = getenv('MAILCOW_HOSTNAME');
 
 
 // Autodiscover settings
 // Autodiscover settings
+$https_port = strpos($_SERVER['HTTP_HOST'], ':');
+if ($https_port === FALSE) {
+  $https_port = 443;
+} else {
+  $https_port = substr($_SERVER['HTTP_HOST'], $https_port+1);
+}
 $autodiscover_config = array(
 $autodiscover_config = array(
   // Enable the autodiscover service for Outlook desktop clients
   // Enable the autodiscover service for Outlook desktop clients
   'useEASforOutlook' => 'yes',
   'useEASforOutlook' => 'yes',
   // General autodiscover service type: "activesync" or "imap"
   // General autodiscover service type: "activesync" or "imap"
   'autodiscoverType' => 'activesync',
   'autodiscoverType' => 'activesync',
-  // Please don't use STARTTLS-enabled service ports here.
+  // Please don't use STARTTLS-enabled service ports in the "port" variable.
   // The autodiscover service will always point to SMTPS and IMAPS (TLS-wrapped services).
   // The autodiscover service will always point to SMTPS and IMAPS (TLS-wrapped services).
+  // The autoconfig service will additionally announce the STARTTLS-enabled ports, specified in the "tlsport" variable.
   'imap' => array(
   'imap' => array(
     'server' => $mailcow_hostname,
     'server' => $mailcow_hostname,
-    'port' => getenv('IMAPS_PORT'),
+    'port' => array_pop(explode(':', getenv('IMAPS_PORT'))),
+    'tlsport' => array_pop(explode(':', getenv('IMAP_PORT'))),
+  ),
+  'pop3' => array(
+    'server' => $mailcow_hostname,
+    'port' => array_pop(explode(':', getenv('POPS_PORT'))),
+    'tlsport' => array_pop(explode(':', getenv('POP_PORT'))),
   ),
   ),
   'smtp' => array(
   'smtp' => array(
     'server' => $mailcow_hostname,
     'server' => $mailcow_hostname,
-    'port' => getenv('SMTPS_PORT'),
+    'port' => array_pop(explode(':', getenv('SMTPS_PORT'))),
+    'tlsport' => array_pop(explode(':', getenv('SUBMISSION_PORT'))),
   ),
   ),
   'activesync' => array(
   'activesync' => array(
-    'url' => 'https://'.$mailcow_hostname.'/Microsoft-Server-ActiveSync'
+    'url' => 'https://'.$mailcow_hostname.($https_port == 443 ? '' : ':'.$https_port).'/Microsoft-Server-ActiveSync',
   ),
   ),
   'caldav' => array(
   'caldav' => array(
-    'url' => 'https://'.$mailcow_hostname
+    'server' => $mailcow_hostname,
+    'port' => $https_port,
   ),
   ),
   'carddav' => array(
   'carddav' => array(
-    'url' => 'https://'.$mailcow_hostname
-  )
+    'server' => $mailcow_hostname,
+    'port' => $https_port,
+  ),
 );
 );
+unset($https_port);
 
 
 // Where to go after adding and editing objects
 // Where to go after adding and editing objects
 // Can be "form" or "previous"
 // Can be "form" or "previous"

+ 167 - 0
data/web/mobileconfig.php

@@ -0,0 +1,167 @@
+<?php
+require_once 'inc/prerequisites.inc.php';
+
+if (empty($mailcow_hostname)) {
+  exit();
+}
+if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != 'user') {
+  header("Location: index.php");
+  die("This page is only available to logged-in users, not admins.");
+}
+
+header('Content-Type: application/x-apple-aspen-config');
+header('Content-Disposition: attachment; filename="Mailcow.mobileconfig"');
+
+$email = $_SESSION['mailcow_cc_username'];
+$domain = explode('@', $_SESSION['mailcow_cc_username'])[1];
+$identifier = implode('.', array_reverse(explode('.', $domain))) . '.iphoneprofile.mailcow';
+
+try {
+  $stmt = $pdo->prepare("SELECT `name` FROM `mailbox` WHERE `username`= :username");
+  $stmt->execute(array(':username' => $email));
+  $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
+}
+catch(PDOException $e) {
+  die("Failed to determine name from SQL");
+}
+if (!empty($MailboxData['name'])) {
+  $displayname = utf8_encode($MailboxData['name']);
+}
+else {
+  $displayname = $email;
+}
+
+echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
+?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>PayloadContent</key>
+	<array>
+		<dict>
+			<key>CalDAVAccountDescription</key>
+			<string><?php echo $domain; ?></string>
+			<key>CalDAVHostName</key>
+			<string><?php echo $autodiscover_config['caldav']['server']; ?></string>
+			<key>CalDAVPort</key>
+			<real><?php echo $autodiscover_config['caldav']['port']; ?></real>
+			<key>CalDAVPrincipalURL</key>
+			<string>/SOGo/dav/<?php echo $email; ?></string>
+			<key>CalDAVUseSSL</key>
+			<true/>
+			<key>CalDAVUsername</key>
+			<string><?php echo $email; ?></string>
+			<key>PayloadDescription</key>
+			<string>Configures CalDAV account.</string>
+			<key>PayloadDisplayName</key>
+			<string>CalDAV (<?php echo $domain; ?>)</string>
+			<key>PayloadIdentifier</key>
+			<string><?php echo $identifier; ?>.CalDAV</string>
+			<key>PayloadOrganization</key>
+			<string></string>
+			<key>PayloadType</key>
+			<string>com.apple.caldav.account</string>
+			<key>PayloadUUID</key>
+			<string>FC898573-EBA8-48AF-93BD-BFA0C9778FA7</string>
+			<key>PayloadVersion</key>
+			<integer>1</integer>
+		</dict>
+		<dict>
+			<key>EmailAccountDescription</key>
+			<string><?php echo $domain; ?></string>
+			<key>EmailAccountType</key>
+			<string>EmailTypeIMAP</string>
+			<key>EmailAccountName</key>
+			<string><?php echo $displayname; ?></string>
+			<key>EmailAddress</key>
+			<string><?php echo $email; ?></string>
+			<key>IncomingMailServerAuthentication</key>
+			<string>EmailAuthPassword</string>
+			<key>IncomingMailServerHostName</key>
+			<string><?php echo $autodiscover_config['imap']['server']; ?></string>
+			<key>IncomingMailServerPortNumber</key>
+			<integer><?php echo $autodiscover_config['imap']['port']; ?></integer>
+			<key>IncomingMailServerUseSSL</key>
+			<true/>
+			<key>IncomingMailServerUsername</key>
+			<string><?php echo $email; ?></string>
+			<key>OutgoingMailServerAuthentication</key>
+			<string>EmailAuthPassword</string>
+			<key>OutgoingMailServerHostName</key>
+			<string><?php echo $autodiscover_config['smtp']['server']; ?></string>
+			<key>OutgoingMailServerPortNumber</key>
+			<integer><?php echo $autodiscover_config['smtp']['port']; ?></integer>
+			<key>OutgoingMailServerUseSSL</key>
+			<true/>
+			<key>OutgoingMailServerUsername</key>
+			<string><?php echo $email; ?></string>
+			<key>OutgoingPasswordSameAsIncomingPassword</key>
+			<true/>
+			<key>PayloadDescription</key>
+			<string>Configures email account.</string>
+			<key>PayloadDisplayName</key>
+			<string>IMAP Account (<?php echo $domain; ?>)</string>
+			<key>PayloadIdentifier</key>
+			<string><?php echo $identifier; ?>.email</string>
+			<key>PayloadOrganization</key>
+			<string></string>
+			<key>PayloadType</key>
+			<string>com.apple.mail.managed</string>
+			<key>PayloadUUID</key>
+			<string>00294FBB-1016-413E-87B9-652D856D6875</string>
+			<key>PayloadVersion</key>
+			<integer>1</integer>
+			<key>PreventAppSheet</key>
+			<false/>
+			<key>PreventMove</key>
+			<false/>
+			<key>SMIMEEnabled</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>CardDAVAccountDescription</key>
+			<string><?php echo $domain; ?></string>
+			<key>CardDAVHostName</key>
+			<string><?php echo $autodiscover_config['carddav']['server']; ?></string>
+			<key>CardDAVPort</key>
+			<integer><?php echo $autodiscover_config['carddav']['port']; ?></integer>
+			<key>CardDAVPrincipalURL</key>
+			<string>/SOGo/dav/<?php echo $email; ?></string>
+			<key>CardDAVUseSSL</key>
+			<true/>
+			<key>CardDAVUsername</key>
+			<string><?php echo $email; ?></string>
+			<key>PayloadDescription</key>
+			<string>Configures CardDAV accounts</string>
+			<key>PayloadDisplayName</key>
+			<string>CardDAV (<?php echo $domain; ?>)</string>
+			<key>PayloadIdentifier</key>
+			<string><?php echo $identifier; ?>.carddav</string>
+			<key>PayloadOrganization</key>
+			<string></string>
+			<key>PayloadType</key>
+			<string>com.apple.carddav.account</string>
+			<key>PayloadUUID</key>
+			<string>0797EF2B-B1F1-4BC7-ABCD-4580862252B4</string>
+			<key>PayloadVersion</key>
+			<integer>1</integer>
+		</dict>
+	</array>
+	<key>PayloadDescription</key>
+	<string>IMAP, CalDAV, CardDAV</string>
+	<key>PayloadDisplayName</key>
+	<string><?php echo $domain; ?> Mailcow</string>
+	<key>PayloadIdentifier</key>
+	<string><?php echo $identifier; ?></string>
+	<key>PayloadOrganization</key>
+	<string></string>
+	<key>PayloadRemovalDisallowed</key>
+	<false/>
+	<key>PayloadType</key>
+	<string>Configuration</string>
+	<key>PayloadUUID</key>
+	<string>5EE248C5-ACCB-42D8-9199-8F8ED08D5624</string>
+	<key>PayloadVersion</key>
+	<integer>1</integer>
+</dict>
+</plist>