\documentclass{article}
\usepackage{ulem}
\usepackage{graphicx}
\usepackage{hyperref}
\pagestyle{headings}
\begin{document}
\part{ActiveSync}
Exchange ActiveSync (EAS) is a protocol for synchronizing email, contacts, calendar, tasks, and notes between mobile clients and a groupware server. EAS uses <a href="http://en.wikipedia.org/wiki/WBXML">WAP Binary XML (WBXML)</a> over HTTP/HTTPS. It was originally developed by Microsoft for Exchange, but is now supported by iOS Mail, Android, Outlook 2013+, Windows Mail, and many third-party clients.

In addition to synchronization, the protocol provides device management and security features (provisioning, remote wipe, PIN policies).

\section{People}
<a href="https://wiki.horde.org/MichaelRubinsky">Michael Rubinsky</a><br />
Torben Dannhauer

\section{Bugs}
See the <a href="http://bugs.horde.org/queue/sync">bug tracker</a>, the list of <a href="https://wiki.horde.org/ActiveSync/KnownIssues">known issues</a>, and <a href="https://wiki.horde.org/ActiveSync/BrokenClientBehavior">broken client behavior</a>.

\section{Description}
The Horde\_ActiveSync library provides the protocol engine for synchronizing a Horde groupware stack with EAS clients. In a typical Horde 6 deployment the data backend is \texttt{Horde\_Core\_ActiveSync\_Driver} in \texttt{horde/core}, which talks to IMP (mail), Kronolith (calendar), Turba (contacts), Nag (tasks), and Mnemo (notes).

For the feature matrix by EAS version, see <a href="https://wiki.horde.org/ActiveSync/FeatureGrid">ActiveSync Feature Grid</a>. For developer-oriented protocol documentation, see the <a href="https://github.com/horde/activesync/blob/FRAMEWORK_6_0/README.md">horde/activesync README</a> and the <a href="http://dev.horde.org/api/master/lib/ActiveSync">API documentation</a>.

Horde 6 ActiveSync passes <a href="https://www.testexchangeconnectivity.com">Microsoft's Remote Connectivity Analyzer</a> when provisioning is disabled for the test account (the analyzer does not respond to the HTTP 449 header sent when provisioning is required).

\section{Server Setup}
\subsection{Enable ActiveSync in Horde}
Activate ActiveSync in Horde administration -> ActiveSync tab (or \texttt{var/config/horde/conf.php}). Create the SQL state tables from the Horde configuration screen when prompted.

Minimum configuration:

<pre><code class="language-php">\$conf['activesync']['enabled'] = true;
\$conf['activesync']['version'] = '16.1';   // global EAS ceiling
\$conf['activesync']['storage'] = 'Sql';
\$conf['activesync']['emailsync'] = true;
\$conf['activesync']['auth']['type'] = 'basic';
</code></pre>
History (\texttt{\$conf['history']['enabled']}) must be enabled -- ActiveSync relies on it for change tracking.

\subsection{Web server}
Clients expect two URL paths to reach Horde's RPC endpoint:

\begin{itemize}
\item \texttt{/Microsoft-Server-ActiveSync} -- sync traffic


\item \texttt{/autodiscover/autodiscover.xml} and \texttt{/autodiscover/autodiscover.json} -- Autodiscover (see below)


\end{itemize}
In a Composer-based Horde 6 deployment, the web-readable entry point is \texttt{web/horde/rpc.php} (symlinked from the package tree). Your web server document root should point at the deployment's \texttt{web/} directory.

\subsubsection{Apache}
Recommended rewrite rules (case-insensitive Autodiscover, v1 and v2):

<pre><code><IfModule mod\_rewrite.c>
    RewriteEngine On

    \# Pass MS headers through mod\_proxy\_fcgi to PHP-FPM when needed:
    RewriteRule .* - [E=HTTP\_AUTHORIZATION:\%\{HTTP:Authorization\}]
    RewriteRule .* - [E=HTTP\_MS\_ASPROTOCOLVERSION:\%\{HTTP:Ms-Asprotocolversion\}]
    RewriteRule .* - [E=HTTP\_X\_MS\_POLICYKEY:\%\{HTTP:X-Ms-Policykey\}]

    \# Autodiscover v1 (POX/XML) -- [NC] is required; iOS sends /Autodiscover/Autodiscover.xml
    RewriteRule "\^{}/autodiscover/autodiscover\textbackslash\{\}.xml\$" "/horde/rpc.php" [NC,L]

    \# Autodiscover v2 (JSON) -- no \$ anchor; path continues with /v1.0/<email>
    RewriteRule "\^{}/autodiscover/autodiscover\textbackslash\{\}.json" "/horde/rpc.php" [NC,L,QSA]

    \# ActiveSync
    RewriteRule "\^{}/Microsoft-Server-ActiveSync" "/horde/rpc.php" [L,QSA]
</IfModule>
</code></pre>
\textit{Note:} An \texttt{Alias} to \texttt{rpc.php} also works when PHP runs as mod\_php in the same vhost. With \texttt{mod\_proxy\_fcgi}, prefer \texttt{RewriteRule} as shown. If Authorization headers are not passed to PHP, the \texttt{E=HTTP\_AUTHORIZATION} rule above usually fixes it.

\textit{Note:} Horde 6 uses symlinks under \texttt{web/} into \texttt{vendor/}. Make sure rewrites target \texttt{/horde/rpc.php} relative to the vhost document root that serves Horde.

\subsubsection{nginx}
<pre><code>location /Microsoft-Server-ActiveSync \{
    rewrite \^{} /horde/rpc.php last;
\}
location \textasciitilde{}* \^{}/autodiscover/autodiscover\textbackslash\{\}.xml\$ \{
    rewrite \^{} /horde/rpc.php last;
\}
location \textasciitilde{}* \^{}/autodiscover/autodiscover\textbackslash\{\}.json \{
    rewrite \^{} /horde/rpc.php last;
\}
</code></pre>
Pass \texttt{Authorization}, \texttt{Ms-Asprotocolversion}, and \texttt{X-Ms-Policykey} headers to PHP-FPM. Increase \texttt{fastcgi\_read\_timeout} (or equivalent) for long-poll \texttt{Ping} requests -- see \textit{Reverse proxy} below.

\subsubsection{lighttpd}
<pre><code>alias.url = (
    "/Microsoft-Server-ActiveSync" => "/var/www/horde/web/horde/rpc.php",
    "/autodiscover/autodiscover.xml" => "/var/www/horde/web/horde/rpc.php",
    "/autodiscover/autodiscover.json" => "/var/www/horde/web/horde/rpc.php"
)
</code></pre>
Use case-insensitive matching or multiple alias entries if your clients vary path casing.

\subsection{Autodiscover}
Autodiscover tells the device where the ActiveSync server lives. Horde supports \textbf{both} Autodiscover protocols:

<table class="horde-table">Protocol & Request & Auth & Response \\
\hline
\textbf{v2 JSON} & \texttt{GET /autodiscover/autodiscover.json/v1.0/<email>?Protocol=ActiveSync} & None & \texttt{\{"Protocol":"ActiveSync","Url":"https://.../Microsoft-Server-ActiveSync"\}} \\
\hline
\textbf{v1 POX/XML} & \texttt{POST /autodiscover/autodiscover.xml} & HTTP Basic & XML with ActiveSync and optional IMAP/SMTP settings \\
\hline
</table>
Modern clients (recent iOS, Outlook) try \textbf{v2 first}, then fall back to v1. Both must reach \texttt{rpc.php} via the web server rules above. A v2 \texttt{404} alone is harmless (clients fall back), but routing v2 is recommended for faster account setup.

SSL is required for production Autodiscover. Self-signed certificates require the device to trust the CA.

\subsubsection{Email domain vs Horde hostname}
Autodiscover is driven by the \textbf{email domain} -- the part after \texttt{@}. For \texttt{user@example.com}, the device queries \texttt{example.com} and \texttt{autodiscover.example.com}. It does \textbf{not} know that Horde might live on \texttt{mail.example.com} or \texttt{webmail.example.com} unless discovery succeeds and returns that URL.

This matters when Horde runs on a different host than the email domain (very common).

\subsubsection{Discovery sequence}
For \texttt{user@example.com}, a typical iOS/Outlook client tries, in order:

\begin{itemize}
\item \texttt{GET https://example.com/autodiscover/autodiscover.json/v1.0/user@example.com?Protocol=ActiveSync} (v2)


\item \texttt{POST https://example.com/autodiscover/autodiscover.xml} (v1)


\item \texttt{POST https://autodiscover.example.com/autodiscover/autodiscover.xml} (v1)


\item \texttt{GET http://autodiscover.example.com/autodiscover/autodiscover.xml} -- expects a \textbf{302 redirect} to HTTPS, then POST


\item DNS SRV lookup \texttt{\_autodiscover.\_tcp.example.com} -> POST to the target host


\end{itemize}
DNS is used in two ways: \textbf{A/AAAA} records for each hostname in steps 1-4, and an optional \textbf{SRV} record in step 5:

<pre><code>\_autodiscover.\_tcp.example.com.  3600  IN  SRV  0 1 443 mail.example.com.
</code></pre>
Point the SRV target at the host that actually serves Horde Autodiscover.

\subsubsection{Path case sensitivity}
Microsoft documentation uses mixed case (\texttt{AutoDiscover/AutoDiscover.xml}). Real clients often send \texttt{/Autodiscover/Autodiscover.xml} or \texttt{/autodiscover/autodiscover.xml} -- the difference is the \textbf{\texttt{d}} in the middle of the word. Apache \texttt{RewriteRule} is case-sensitive unless \texttt{[NC]} is set. Use \texttt{[NC]} on all Autodiscover rewrite rules.

\subsubsection{Single-host setup}
When Horde and the email domain are the same host (e.g. \texttt{https://example.com/horde} for \texttt{user@example.com}), the Apache/nginx rules in \textit{Web server} above are sufficient. No redirect is needed.

\subsubsection{Multi-host / central Horde setup}
When email addresses use \texttt{@example.com} but Horde runs on \texttt{https://mail.example.com}, configure \textbf{each email-domain vhost} to forward Autodiscover to the Horde host.

On the \textbf{email-domain} vhost (e.g. \texttt{example.com}, \texttt{autodiscover.example.com}) -- \textbf{not} the Horde host:

<pre><code>RedirectMatch 302 (?i)/autodiscover/autodiscover.xml https://mail.example.com/autodiscover/autodiscover.xml
RedirectMatch 302 (?i)\^{}(/autodiscover/autodiscover\textbackslash\{\}.json.*)\$ https://mail.example.com\$1
</code></pre>
Autodiscover clients follow the redirect and re-send the request. If a client drops the POST body on \texttt{302}, use \texttt{Redirect 307} instead.

Port 80 redirect for step 4 above:

<pre><code><VirtualHost *:80>
    ServerName autodiscover.example.com
    RedirectMatch 302 (?i)/autodiscover/autodiscover.xml https://mail.example.com/autodiscover/autodiscover.xml
</VirtualHost>
</code></pre>
\textbf{Important:} Do \textbf{not} install ActiveSync rewrite rules on vhosts that are \textbf{not} the Horde document root. If a non-Horde vhost rewrites Autodiscover to \texttt{/horde/rpc.php} but has no \texttt{horde/} directory, requests return \textbf{404} and any \texttt{RedirectMatch} on the same vhost will not run (\texttt{mod\_rewrite} is evaluated before \texttt{mod\_alias}). Email-domain vhosts should only \textbf{redirect} to the Horde host; the Horde host vhost carries the \texttt{rpc.php} rewrites.

\subsubsection{Horde Autodiscover configuration}
Horde must map the email address from the Autodiscover request to a Horde username. Configure this on the ActiveSync tab (\texttt{autodiscovery} settings). Hooks are available for custom logic -- see \texttt{horde/config/hooks.php.dist} (\texttt{activesync\_get\_autodiscover\_username}, \texttt{activesync\_autodiscover\_xml}, \texttt{activesync\_autodiscover\_parameters}).

If Autodiscover authentication fails, the device falls back to manual setup.

\subsubsection{Verifying Autodiscover}
<table class="horde-table">Test & Expected result \\
\hline
\texttt{POST https://mail.example.com/autodiscover/autodiscover.xml} (no credentials) & \textbf{401} -- Horde asks for auth; routing works \\
\hline
Same request & \textbf{404} -- routing broken (check rewrite rules and vhost) \\
\hline
\texttt{GET .../autodiscover.json/v1.0/user@example.com?Protocol=ActiveSync} & **200** JSON with ActiveSync URL (if v2 routed) \\
\hline
Valid credentials on v1 POST & **200** XML with server URLs \\
\hline
</table>
Example:

<pre><code>curl -ks -o /dev/null -w "\%\{http\_code\}\textbackslash\{\}n" \textbackslash\{\}
  -X POST -H "Content-Type: text/xml" --data "<x/>" \textbackslash\{\}
  https://mail.example.com/autodiscover/autodiscover.xml
</code></pre>
A \texttt{401} response with realm "Horde ActiveSync" means the request reached \texttt{rpc.php} correctly.

\subsection{Reverse proxy}
ActiveSync \texttt{Ping} holds connections open for up to 3540 seconds (depending on client and \texttt{\$conf['activesync']['ping']['heartbeatmax']}). Reverse proxies must not time out sooner.

Apache backend example:

<pre><code>ProxyPass        / https://192.168.1.230/ connectiontimeout=600 timeout=4000
ProxyPassReverse / https://192.168.1.230/
ProxyTimeout 5400
</code></pre>
Adjust timeouts for your environment. Similar \texttt{proxy\_read\_timeout} / \texttt{fastcgi\_read\_timeout} settings apply for nginx.

\subsection{PHP execution time}
Set \texttt{max\_execution\_time} to \texttt{0} or at least \textbf{twice} the maximum heartbeat interval. Configure this in Horde's general configuration tab or in \texttt{php.ini} / the PHP-FPM pool.

\section{Administration}
Administrators manage ActiveSync under Horde administration -> \textbf{ActiveSync} and \textbf{ActiveSync Devices}.

Key options on the ActiveSync tab:

<table class="horde-table">Setting & Purpose \\
\hline
Enable ActiveSync & Master switch \\
\hline
Storage backend & \texttt{Sql} or \texttt{Nosql} (MongoDB) for device state \\
\hline
Highest EAS version & Global protocol ceiling (\texttt{2.5} ... \texttt{16.1}) \\
\hline
Email sync & Enable/disable mail collections \\
\hline
Autodiscovery & Username mapping from email address \\
\hline
Logging & Path, level, per-device log files \\
\hline
Ping heartbeat min/max & Long-poll interval bounds \\
\hline
</table>
Per-user EAS version limits are set under \textbf{Permissions} -> ActiveSync -> \textit{Maximum ActiveSync protocol version} -- not in user preferences. Per-device limits use the \texttt{activesync\_device\_version} hook with \texttt{version\_mode = device} in \texttt{conf.php}.

Provisioning mode: \textbf{None}, \textbf{Allow}, or \textbf{Force} -- see \textit{Provisioning/Remote Wipe} below.

Device management: administrators can view all paired devices, request remote wipe, force re-provisioning, and block devices. Per-device protocol log \textbf{files} are supported (\texttt{logging.type = perdevice}); a per-device log toggle in the admin GUI is still on the roadmap.

<a href="https://learn.microsoft.com/en-us/previous-versions/office/exchange-server-2010/bb123484(v=exchg.141)">Microsoft documentation on EAS security policies.</a>

\section{Application Configuration}
No additional steps are normally required for synchronization of the supported applications. Each application has user preferences for which shares are synchronized. For example, in Kronolith the user's default calendar is \textbf{always} synchronized; additional owned calendars can be selected.

\subsection{Multiple sources in the same collection}
Starting with Horde 5.2, applications can expose discrete calendars, address books, task lists, and note pads on the client instead of multiplexing them into a single collection. Not all EAS clients support this.

\begin{itemize}
\item Enable or disable the discrete-sources preference per application (affects all of a user's devices).


\item Implement the \texttt{activesync\_device\_modify} hook (\texttt{horde/config/hooks.php.dist}) for device-specific overrides.


\end{itemize}
All sync-able sources \textbf{must} be writable by the user.

Users manage paired devices under \textbf{Global Preferences} -> \textit{ActiveSync Devices} (force re-sync, remote wipe).

\section{Email Support}
Email synchronization can be disabled on the ActiveSync tab. ActiveSync email requires IMAP; POP3 is not supported. In the Horde stack, IMP's configured IMAP server is used.

QRESYNC and per-mailbox MODSEQ on the IMAP server greatly improve performance. An IMAP proxy can also help.

Supported mail flags: \textit{seen} and \textit{flagged for follow up}. Flag-only changes trigger a sync when MODSEQ is available; otherwise a new message arrival triggers sync and flag changes are picked up in the same pass.

ActiveSync does not support the IMAP \texttt{\textbackslash\{\}Deleted} flag. Messages flagged deleted in a desktop MUA are not removed on the device until expunged. Configure a Trash folder in IMP for device-side deletes to move messages instead of immediate expunge.

\section{S/MIME Support}
S/MIME signing and encryption work when IMP S/MIME is configured. Native iOS and Outlook clients generally support S/MIME over ActiveSync. Most Android native mail clients do \textbf{not} support S/MIME; third-party clients may.

\section{ActiveSync Versions}
Horde 6 supports EAS \textbf{2.5} through \textbf{16.1}. See <a href="https://wiki.horde.org/ActiveSync/FeatureGrid">Supported ActiveSync Features</a> for the full matrix.

Notable version milestones:

<table class="horde-table">EAS version & Exchange equivalent & Highlights \\
\hline
12.0 / 12.1 & 2007 & HTML mail, follow-up flags, WBXML provisioning \\
\hline
14.0 / 14.1 & 2010 & Outlook 2013+ sync, extended search \\
\hline
16.0 & 2016 & Calendar instance model, draft sync, mailbox Find/KQL \\
\hline
16.1 & 2016+ & Propose-new-time (COUNTER), account-only remote wipe \\
\hline
</table>
Version negotiation: the server advertises a ceiling (\texttt{conf['activesync']['version']}); the client sends \texttt{MS-ASProtocolVersion} per request. Per-user permissions and per-device hooks can lower (or in some cases raise) the ceiling for individual accounts or devices.

\section{Provisioning / Remote Wipe}
Provisioning registers devices with the server and enables policy enforcement (PIN, complexity, failed-attempt limits) and remote wipe.

Enable provisioning via the permissions tree: \textit{Horde} -> \textit{ActiveSync} -> \textit{Provisioning} -> individual policies.

<table class="horde-table">Mode & Behavior \\
\hline
\textbf{None} & No provisioning; remote wipe disabled \\
\hline
\textbf{Allow} & Provision devices that support it; others may still connect \\
\hline
\textbf{Force} & Only provisioned devices may connect \\
\hline
</table>
EAS 16.1 adds \textbf{account-only remote wipe} for devices negotiating >= 16.1.

Users and administrators initiate wipe from the device management UI. The wipe command is sent on the device's next non-PING request. Status \textit{Pending} can be cancelled; status \textit{Wiped} requires removing the device entry before it can pair again.

\section{Client Compatibility}
Contacts, calendar, tasks, notes, and email all sync through Horde ActiveSync. Current iOS Mail, Android (Gmail, Samsung), Outlook 2013+, and Windows Mail generally work with EAS 14.1+. EAS 16.x features require clients and server configuration that negotiate 16.0 or 16.1.

Not all devices support tasks or notes natively. Check <a href="https://wiki.horde.org/ActiveSync/KnownIssues">known issues</a> and <a href="https://wiki.horde.org/ActiveSync/BrokenClientBehavior">broken client behavior</a> before troubleshooting a specific client.

For the complete feature set by protocol version, see <a href="https://wiki.horde.org/ActiveSync/FeatureGrid">Supported ActiveSync Features</a>.

\section{Setting up the device}
Create a new account of type \textit{Microsoft Exchange}, \textit{Exchange}, or \textit{Corporate}. Enter the Horde username and password.

With Autodiscover configured, enter only the email address and password -- the device discovers the server. Without Autodiscover, set the server to the hostname of the vhost that serves Horde (e.g. \texttt{mail.example.com}), not the full URL path. The ActiveSync path \texttt{/Microsoft-Server-ActiveSync} is implied.

SSL should be enabled for production. Self-signed certificates must be trusted on the device.

After setup, select which folders/collections to synchronize. Some clients require a manual folder refresh after the initial sync.

\section{Outlook Connectivity}
Outlook 2013 and later can sync via ActiveSync (requires EAS >= 14.0). ActiveSync does not provide full Exchange functionality in Outlook.

With Autodiscover working, use the standard email account wizard. For manual setup, choose \textit{Outlook.com or Exchange ActiveSync compatible service} -- \textbf{not} \textit{Microsoft Exchange Server or compatible service}.

Outlook does not use EAS for Free/Busy lookup. Provide Kronolith's Free/Busy URL under \textit{File -> Options -> Calendar -> Free/Busy Options}:

<pre><code>https://example.com/horde/kronolith/fb.php?u=\%NAME\%
</code></pre>
\texttt{\%NAME\%} is replaced with the mailbox user portion of the meeting address.

\section{Troubleshooting}
\textbf{First}, check <a href="https://wiki.horde.org/ActiveSync/KnownIssues">known issues</a> and the <a href="http://bugs.horde.org/queue/sync">bug tracker</a>.

\textbf{Autodiscover fails / account setup loops:}

\begin{itemize}
\item Verify Autodiscover routing (\texttt{POST .../autodiscover.xml} -> 401 without credentials).


\item Confirm the email-domain vhost redirects to the Horde host when Horde is on a separate hostname.


\item Check that non-Horde vhosts do not rewrite Autodiscover to a non-existent \texttt{/horde/rpc.php}.


\item Verify \texttt{[NC]} on Autodiscover rewrite rules (path case).


\item Check DNS: A/AAAA for \texttt{example.com} / \texttt{autodiscover.example.com}, optional SRV record.


\end{itemize}
\textbf{Setup succeeds but no data appears:}

\begin{itemize}
\item Some clients need a manual folder selection after setup.


\item Confirm the user has the ActiveSync permission.


\item Check provisioning mode -- some clients require \textit{Allow} or \textit{Force}.


\end{itemize}
\textbf{Collecting diagnostics:}

\begin{itemize}
\item Web server and PHP error logs.


\item ActiveSync log file -- configured on the ActiveSync tab; per-device log files when \texttt{logging.type = perdevice}.


\item WBXML protocol log at higher verbosity for command-level detail.


\end{itemize}
\subsubsection{tshark capture}
For unencrypted HTTP debugging:

<pre><code>tshark 'tcp port 80 and (((ip[2:2] - ((ip[0]\&0xf)<<2)) - ((tcp[12]\&0xf0)>>2)) != 0)' -w /path/to/capture.pcap
</code></pre>
SSL capture requires the server's RSA private key and non-forward-secret ciphers -- use only on test systems.

\section{Roadmap}
Historical milestones and current Horde 6 work. For protocol-level detail on EAS 16, see the <a href="https://github.com/horde/activesync/blob/FRAMEWORK_6_0/README.md">horde/activesync README</a>. Open library refactor items are tracked in the package \texttt{doc/todo.md}.

\subsection{Horde 5.1}
<table class="horde-table">Feature & Status \\
\hline
EAS 14(.1) support. & Complete. \\
\hline
Improved device management via hooks. & Complete. \\
\hline
Support for SOFTDELETE. & Complete. \\
\hline
</table>
\subsection{Horde 5.2}
<table class="horde-table">Feature & Status \\
\hline
Improved email identity support. & Complete. \\
\hline
Support for multiple sources per collection. E.g., multiple calendars, addressbooks etc... & Complete. \\
\hline
Improved device management GUI. & Complete. \\
\hline
</table>
\subsection{Horde 6.0}
\subsubsection{Protocol and core stack}
<table class="horde-table">Feature & Status \\
\hline
EAS 16.0 support in applications. & \textbf{Complete} (calendar instance model, draft sync, Find/KQL, \texttt{ClientUid}, \texttt{Location}, SmartForward \texttt{Forwardee}). \\
\hline
EAS 16.1 support. & \textbf{Complete} (propose-new-time / \texttt{METHOD=COUNTER}, \texttt{DisallowNewTimeProposal}, account-only remote wipe). \\
\hline
Per-user EAS version ceiling via permissions. & \textbf{Complete} (\texttt{horde:activesync:version}). \\
\hline
Per-device EAS version ceiling via hook. & \textbf{Complete} (\texttt{activesync\_device\_version} with \texttt{version\_mode = device}). \\
\hline
EAS 16.0 \textbf{Find} command (mailbox/GAL search). & \textbf{Complete} -- KQL parser in \texttt{horde/activesync}, IMP search backend in \texttt{horde/core}. \\
\hline
Autodiscover v2 JSON (\texttt{autodiscover.json}). & \textbf{Complete} in PHP; requires web server routing (see \textit{Autodiscover} above). \\
\hline
Autodiscover v2 JSON response hardening. & \textbf{Complete} (Protocol default, \texttt{json\_encode}). \\
\hline
Multiplexed PIM folders (multiple calendars, address books, task lists, note pads). & \textbf{Complete}. \\
\hline
</table>
\subsubsection{Calendar, mail, and invitations (2026)}
<table class="horde-table">Feature & Status \\
\hline
EAS 16.0 recurring calendar instance sync. & \textbf{Complete} -- bound/modified instances, exception deletion (\texttt{horde/kronolith}). \\
\hline
Meeting invitations in mail (recurring RRULE / \texttt{RECURRENCE-ID} in \texttt{MeetingRequest}). & \textbf{Complete}. \\
\hline
\texttt{MeetingResponse} RSVP and propose-new-time from device. & \textbf{Complete} -- includes \texttt{InstanceId} -> \texttt{RECURRENCE-ID} mapping. \\
\hline
IMP iTip RSVP UI above invitation mail body. & \textbf{Complete}. \\
\hline
EAS 16.0 draft mail sync (create/edit/send drafts on device). & \textbf{Complete}. \\
\hline
\texttt{FILTERTYPE\_INCOMPLETETASKS} for task collections. & \textbf{Complete} (\texttt{horde/core} / \texttt{horde/nag}). \\
\hline
</table>
\subsubsection{Stability and client compatibility (2026)}
<table class="horde-table">Feature & Status \\
\hline
SQL/Mongo row locks for parallel device state access. & \textbf{Complete}. \\
\hline
Reject and repair corrupt collection \texttt{sync\_data}. & \textbf{Complete}. \\
\hline
Separate PING watermark from SYNC modseq (iOS mail loop fix). & \textbf{Complete}. \\
\hline
\texttt{FOLDERSYNC\_REQUIRED} loop guard for broken clients. & \textbf{Complete}. \\
\hline
Modern iOS Notes multiplexing behaviour. & \textbf{Complete}. \\
\hline
PING orphan-collection and hierarchy-sync recovery. & \textbf{Complete}. \\
\hline
\texttt{ItemOperations} fetch fixes (deleted messages, folder type). & \textbf{Complete}. \\
\hline
</table>
\subsubsection{Administration and operations}
<table class="horde-table">Feature & Status \\
\hline
Improved device management GUI (grouped by user, collection details, account wipe). & \textbf{Complete}. \\
\hline
Per-device protocol log \textbf{files} (\texttt{logging.type = perdevice}). & \textbf{Complete}. \\
\hline
Ability for admin to toggle sync log on/off \textbf{per device from GUI} and view via GUI. & Planned. \\
\hline
CLI admin tool. & If sponsored. \\
\hline
EAS usage dashboard / live operator monitor. & Planned (separate admin tool; not in protocol library). \\
\hline
</table>
\subsubsection{Still open or deferred}
<table class="horde-table">Feature & Status \\
\hline
SMS synchronization. & Planned -- today SMS collections are stubbed so broken clients do not break mail sync; full backend support targeted for Horde 6 refactor. \\
\hline
\texttt{ItemOperations:Schema} requests. & Deferred -- no known client requires this. \\
\hline
HTTP 503 throttling (\texttt{X-MS-Throttle}). & Deferred -- relevant only at high load. \\
\hline
Task \texttt{Regenerate=1} (Outlook post-completion regeneration). & Not supported -- Nag uses \texttt{completions[]}, not regenerated due dates. \\
\hline
Horde 6 library refactor (PSR-4 class names, \texttt{horde/http} request/response, pluggable driver subsystems, storage layer rename). & Planned -- breaking changes; see \texttt{horde/activesync} \texttt{doc/todo.md}. \\
\hline
</table>
\textit{EAS 16.0/16.1 application support shipped in the Horde 6 / ActiveSync 3.x line on \texttt{FRAMEWORK\_6\_0}. See <a href="https://wiki.horde.org/ActiveSync/FeatureGrid">Supported ActiveSync Features</a> for the version matrix.}

\section{Horde\_ActiveSync vs. Z-Push}
Horde\_ActiveSync protocol handling was originally based on Z-Push but has been heavily refactored. Key advantages of Horde's stack:

\begin{itemize}
\item \textbf{Modularity} -- pluggable \texttt{Horde\_ActiveSync\_Driver\_Base} backends; state and diff logic are separate.


\item \textbf{Efficiency} -- Horde History-based change tracking instead of Z-Push file-based UID polling.


\item \textbf{Integrated groupware} -- calendar recurrence, timezone handling, and appointment logic built in.


\item \textbf{IMAP} -- uses \texttt{Horde\_Imap\_Client} with QRESYNC instead of the PHP c-client extension.


\item \textbf{Configuration} -- heartbeat, security policies, and provisioning via Horde admin UI and permissions.


\item \textbf{Protocol coverage} -- EAS 16.0/16.1 in Horde 6 vs Z-Push's more limited Exchange-version support.


\end{itemize}
\section{Resources}
\subsection{Protocol documentation}
\begin{itemize}
\item <a href="https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-ascntc30">Microsoft Exchange ActiveSync protocol docs</a>


\item <a href="http://en.wikipedia.org/wiki/Exchange_ActiveSync">Exchange ActiveSync (Wikipedia)</a>


\item <a href="https://github.com/horde/activesync/blob/FRAMEWORK_6_0/README.md">horde/activesync README</a>


\end{itemize}
\subsection{Horde wiki}
\begin{itemize}
\item <a href="https://wiki.horde.org/ActiveSync/FeatureGrid">ActiveSync Feature Grid</a>


\item <a href="https://wiki.horde.org/ActiveSync/KnownIssues">Known Issues</a>


\item <a href="https://wiki.horde.org/ActiveSync/BrokenClientBehavior">Broken Client Behavior</a>


\end{itemize}
\subsection{Other implementations}
\begin{itemize}
\item <a href="https://github.com/Z-Hubo/Z-Push">Z-Push</a>


\item <a href="http://z-push.sourceforge.net">z-push</a> (legacy)


\end{itemize}
\end{document}
