Skip to content

user00265/imap-activesync

Repository files navigation

imap-activesync

A Go single-binary daemon that bridges mobile devices (Android / iOS) speaking the Exchange ActiveSync (EAS) 16.1 protocol to a plain IMAP backend. It has no web UI and is meant to sit behind a reverse proxy.

The roles are fixed:

  • IMAP is the source of truth — the daemon never owns mail state; it reflects what the IMAP server holds.
  • The daemon is the translation layer — it speaks EAS to devices and IMAP/SMTP/DAV to the server, reconciling the two models.
  • ActiveSync is the transport lane to and from the devices.

There is a single backend for every user (like Z-Push — no per-tenant or per-domain routing). A device authenticates with whatever username its owner typed, and that string is sent to the backend verbatim. Mail is always on; Contacts (CardDAV), Calendar/Reminders (CalDAV), and Notes (IMAP) are optional modules. Device passwords arrive at runtime and live only in an in-memory vault — they never touch disk.

References

The implementation is written to be faithful to primary specifications rather than reverse-engineered behavior:

  • Exchange ActiveSync — the Microsoft Open Specifications: [MS-ASWBXML] (WBXML), [MS-ASHTTP] (transport), [MS-ASCMD] (commands), [MS-ASEMAIL], [MS-ASPROV] (provisioning), [MS-ASDTYPE] (base types), and the module specs [MS-ASCNTC], [MS-ASCAL], [MS-ASTASK], [MS-ASNOTE].
  • IMAP — RFC 3501 / RFC 9051 (IMAP4rev1/rev2), RFC 7162 (CONDSTORE/QRESYNC), RFC 5465 (NOTIFY), RFC 2177 (IDLE), RFC 6154 (SPECIAL-USE), RFC 6203 (SEARCH=FUZZY).
  • SMTP / DAV / MIME — RFC 5321 / RFC 6409 (SMTP submission), RFC 5322 (IMF), RFC 6352 (CardDAV), RFC 4791 (CalDAV), RFC 5545 (iCalendar), RFC 6350 (vCard).

The MS-AS* specs are published in the Microsoft Open Specifications, and the RFCs by the RFC Editor. Microsoft's Remote Connectivity Analyzer (O365 EAS test) is the external acceptance check.

Configuration

Config layers in increasing precedence:

defaults  <  process env (IMAP_ACTIVESYNC_*)  <  .env file  <  config file

Every scalar setting, the module toggles, and the backend are all env-overridable, so a container needs no config file at all. To use a file, copy imap-activesync.example.yaml to /etc/imap-activesync.yaml (the default path) or pass -config <path>. The file holds no secrets.

Minimum to get running — point it at your IMAP (and optionally SMTP) backend:

listen: "127.0.0.1:9000"               # behind a reverse proxy (plain HTTP)
data_dir: "/var/lib/imap-activesync/state.db"
backend:
  imap_address: "imap.example.com:993" # implicit TLS
  imap_starttls: false
  smtp_address: "smtp.example.com:465" # outbound (optional)
  smtp_starttls: false

The equivalent environment variables are IMAP_ACTIVESYNC_LISTEN, IMAP_ACTIVESYNC_DATA_DIR, IMAP_ACTIVESYNC_IMAP_ADDRESS, IMAP_ACTIVESYNC_IMAP_STARTTLS, IMAP_ACTIVESYNC_SMTP_ADDRESS, etc. See the example file for the full set, including the optional modules, garbage collection, Ping heartbeat bounds, and provisioning.

Running

Docker

Multi-arch images (linux/amd64, linux/arm64) are published to the GitHub Container Registry on each release. The image is built on Chainguard's distroless static base and runs nonroot (uid 65532).

docker run -d --name imap-activesync \
  -p 9000:9000 \
  -v imap-activesync-data:/data \
  -e IMAP_ACTIVESYNC_IMAP_ADDRESS=imap.example.com:993 \
  -e IMAP_ACTIVESYNC_SMTP_ADDRESS=smtp.example.com:465 \
  ghcr.io/user00265/imap-activesync:latest

A compose.yaml is included. The container writes its bbolt state to /data; use a named volume (as shown) so the mount inherits the nonroot ownership automatically.

systemd

For a host install, drop the binary in place and use one of the provided units in deploy/systemd/ — a hardened system-wide unit (DynamicUser, StateDirectory=/var/lib/imap-activesync) or a per-user unit. Each unit's header documents the exact install steps. In short:

install -Dm755 imap-activesync /usr/local/bin/imap-activesync
install -Dm644 imap-activesync.example.yaml /etc/imap-activesync.yaml   # then edit
install -Dm644 deploy/systemd/imap-activesync.service \
               /etc/systemd/system/imap-activesync.service
systemctl daemon-reload && systemctl enable --now imap-activesync

AI assistance

This project was developed with the assistance of AI large language models (LLMs). What that means in practice: an LLM was used as a coding and drafting aid — generating, refactoring, and reviewing code, and helping cross-check behavior against the specifications listed above. It does not mean the output is unreviewed or authoritative: every change is subject to human review, the test suite is spec-first (the spec is the ground truth, never the model's output), and the specifications and RFCs remain the final word wherever the two disagree.

License

Released under the MIT License.

Copyright (c) 2026 Elisamuel "Sam" Resto Donate sam@samresto.dev

About

A Go implementation of Exchange EAS with an IMAP backend.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages