Thanks to visit codestin.com
Credit goes to pkg.go.dev

activesync

package module
v0.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 27, 2026 License: MIT Imports: 0 Imported by: 0

README

go-activesync

CI Latest release Go Reference Go Report Card Go Version

A pure-Go client library for the Microsoft Exchange ActiveSync (EAS) protocol, version 14.1.

The library is built spec-first (TDD): every requirement of the underlying Microsoft Open Specifications is backed by a concrete test before any implementation lands. See docs/spec-coverage.md for the traceability matrix.


Quick examples

Discover the EAS endpoint and provision a device
import (
    "context"
    "net/http"

    "github.com/remdev/go-activesync/autodiscover"
    "github.com/remdev/go-activesync/client"
)

ctx := context.Background()

ad, err := autodiscover.New(http.DefaultClient).Discover(ctx, "[email protected]",
    &autodiscover.Credentials{Username: "[email protected]", Password: "pass"})
if err != nil { /* handle */ }

c, _ := client.New(client.Config{
    BaseURL:    ad.URL,
    Auth:       &client.BasicAuth{Username: "[email protected]", Password: "pass"},
    DeviceID:   "stable-device-id",
    DeviceType: "SmartPhone",
    UserAgent:  "my-app/1.0",
})

if _, err := c.Provision(ctx, "[email protected]"); err != nil { /* handle */ }
Sync new e-mails from the inbox
import (
    "log"

    "github.com/remdev/go-activesync/client"
    "github.com/remdev/go-activesync/eas"
)

initial, _ := c.Sync(ctx, user, &eas.SyncRequest{
    Collections: eas.SyncCollections{
        Collection: []eas.SyncCollection{{SyncKey: "0", CollectionID: inboxID}},
    },
})
syncKey := initial.Collections.Collection[0].SyncKey

resp, _ := client.SyncTyped[eas.Email](ctx, c, user, &eas.SyncRequest{
    Collections: eas.SyncCollections{
        Collection: []eas.SyncCollection{{
            SyncKey:      syncKey,
            CollectionID: inboxID,
            GetChanges:   1,
            WindowSize:   25,
        }},
    },
})

for _, col := range resp.Collections {
    for _, add := range col.Add {
        if add.ApplicationData == nil {
            continue
        }
        log.Printf("new mail %s: %s", add.ServerID, add.ApplicationData.Subject)
    }
}

For mixed-class collections, call c.Sync directly and use the SyncAdd.Email() / Appointment() / Contact() / Task() helpers, or project a single collection with eas.NewTypedSyncResponse[T].

Long-poll for changes with Ping
resp, _ := c.Ping(ctx, user, &eas.PingRequest{
    HeartbeatInterval: 480,
    Folders: eas.PingFolders{
        Folder: []eas.PingFolder{{ID: inboxID, Class: "Email"}},
    },
})
if eas.PingHasChanges(resp.Status) {
    // pull the changed folders with Sync
}
Outlook-like client profile

Many servers key off the request query shape and Outlook-style device metadata. Use QueryEncoding: client.QueryEncodingPlain to send Cmd=...&User=...&DeviceId=...&DeviceType=..., DeviceType: "Outlook" when emulating Outlook, and Locale: 0x0419 with AcceptLanguage: "ru-RU" for ru-RU. Header-backed profile fields are sent as X-MS-Device* headers and, when any profile field is set, in the Provision DeviceInformation body; DeviceFriendlyName and DeviceIMEI are body-only. Keep ExtraHeaders for integration-specific headers that are not modeled directly. If you must avoid HTTP/2 to match an older appliance or proxy, pass ForceHTTP11: true with HTTPClient: nil; if you inject your own HTTPClient, tune its transport yourself (ForceHTTP11 is ignored).

_, err := client.New(client.Config{
    BaseURL:          ad.URL,
    Auth:             &client.BasicAuth{Username: "[email protected]", Password: "pass"},
    DeviceID:         "stable-device-id",
    QueryEncoding:    client.QueryEncodingPlain,
    DeviceType:       "Outlook",
    DeviceModel:      "Outlook for iOS and Android",
    DeviceOS:         "iOS 17.5",
    DeviceOSLanguage: "ru",
    Carrier:          "Apple",
    DeviceUserAgent:  "Outlook-iOS-Android/1.0",
    UserAgent:        "Outlook-iOS-Android/1.0 (iCloud, Exchange ActiveSync)",
    AcceptLanguage:   "ru-RU",
    Locale:           0x0419,
    ForceHTTP11:      true,
})

Runnable end-to-end programs live under examples/: login, inbox-sync, calendar-sync, ping.


Install

go get github.com/remdev/go-activesync@latest

Requires Go 1.26 or newer.


Status (v0.x)

Implemented and covered by the test suite:

Area Detail
Transport MS-ASHTTP — base64-encoded query, plain query fallback, mandatory headers
Codec MS-ASWBXML — WBXML 1.3 encoder/decoder, all 25 EAS 14.1 code pages
Reflection wbxml.Marshal / wbxml.Unmarshal driven by wbxml:"Page.Tag" tags
Autodiscover MS-OXDISCO + MS-ASAB POX (mobilesync schema, SRV fallback, redirects)
Auth HTTP Basic; pluggable Authenticator interface
Provisioning Two-pass MS-ASPROV with auto re-provision on Status 142/143
Commands Provision, FolderSync, Sync, Ping
Typed Sync client.SyncTyped[T], eas.UnmarshalApplicationData[T], four helpers
PIM data models MS-ASEMAIL, MS-ASCAL, MS-ASCNTC, MS-ASTASK
Stores In-memory PolicyStore and SyncStateStore; pluggable interfaces
Hardening Bounded decoder allocations + FuzzDecode over the WBXML reader

Roadmap

Out of scope for v0.x; tracked for future releases.

  • Commands: SendMail, SmartReply, SmartForward, MeetingResponse, MoveItems, ItemOperations (Fetch/EmptyFolderContents), GetItemEstimate, Search, ResolveRecipients, ValidateCert, Settings, ResolveRecipients, Find.
  • Protocol versions: negotiation of EAS 12.1, 14.0, 16.0, 16.1 in addition to the current hard-coded 14.1.
  • Code pages: per-version code-page selection (the current set is pinned to 14.1).
  • Auth: OAuth 2.0 bearer (Microsoft 365 / EWS-style), client-certificate / mutual-TLS authenticator, NTLM/Negotiate.
  • Body: MIME body type round-tripping, BodyPartPreference + Rights Management (MS-ASRM).
  • Search & Document Library: GAL Search, MS-ASDOC document fetch.
  • Notes class: typed MS-ASNOTE model.
  • Persistence: SQLite/Bolt-backed PolicyStore and SyncStateStore alongside the in-memory implementations.
  • Server side: there is no server skeleton; this is purely a client library.
  • Observability: structured logging hooks, OpenTelemetry spans on command boundaries.

Repository layout

wbxml/             WBXML 1.3 codec + EAS code page tables, fuzz harness
eas/               typed request/response/domain models (one file per spec)
autodiscover/      POX Autodiscover client
client/            high-level EAS client (transport, auth, command methods, stores)
examples/          runnable demos (login, inbox-sync, calendar-sync, ping)
internal/spec/     traceability-matrix linter + coverage gate tool
docs/              spec-coverage.md and other design notes

Development

make test       # go test -race ./...
make vet        # go vet ./...
make lint       # golangci-lint run ./...   (auto-installs golangci-lint if absent)
make lint-fix   # golangci-lint run --fix
make spec-lint  # verify the traceability matrix is fully covered
make cover      # go test -race -coverprofile=cover.out
make cover-gate # enforce per-package coverage thresholds
make fuzz       # short FuzzDecode smoke run
make all        # vet + lint + test + cover-gate
make ci         # run the exact CI pipeline locally (mod verify, vet, lint,
                # race tests, cover-gate, spec-lint, fuzz smoke)

Always run make ci before pushing or opening a PR — it mirrors .github/workflows/ci.yml step-for-step. See AGENTS.md for the full contributor checklist.

The configured linter set (see .golangci.yml) bundles staticcheck, govet, errcheck, revive, gosec, gocritic, bodyclose, errorlint, unparam, unconvert, usestdlibvars, usetesting, formatters gofmt and goimports, and a handful of others. Test files relax the noisier rules; see the exclusions block for the exact list.

CI enforces per-package coverage thresholds (covergate):

Package Threshold
wbxml/ 90%
eas/ 90%
client/ 80%
autodiscover/ 80%

License

MIT. See LICENSE.

Documentation

Overview

Package activesync is the umbrella documentation entry point for the go-activesync library, a pure-Go client for the Microsoft Exchange ActiveSync (EAS) protocol, revision 14.1.

The library is split into focused subpackages:

Implementation references the following Microsoft Open Specifications: MS-ASHTTP, MS-ASWBXML, MS-ASCMD, MS-ASEMAIL, MS-ASCAL, MS-ASCNTC, MS-ASTASK, MS-ASPROV, MS-OXDISCO, MS-ASAB.

Directories

Path Synopsis
Package autodiscover implements MS-OXDISCO/MS-ASAB POX Autodiscover for Exchange ActiveSync mobile clients.
Package autodiscover implements MS-OXDISCO/MS-ASAB POX Autodiscover for Exchange ActiveSync mobile clients.
Package client provides the high-level Exchange ActiveSync client used to talk to a 14.1 server.
Package client provides the high-level Exchange ActiveSync client used to talk to a 14.1 server.
Package eas defines the typed Exchange ActiveSync 14.1 commands and domain objects used by the client.
Package eas defines the typed Exchange ActiveSync 14.1 commands and domain objects used by the client.
examples
calendar-sync command
Command calendar-sync runs an initial calendar Sync.
Command calendar-sync runs an initial calendar Sync.
inbox-sync command
Command inbox-sync demonstrates an initial Sync against the inbox folder.
Command inbox-sync demonstrates an initial Sync against the inbox folder.
login command
Command login demonstrates the discovery + Provision exchange against an EAS 14.1 server.
Command login demonstrates the discovery + Provision exchange against an EAS 14.1 server.
ping command
Command ping demonstrates a long-poll Ping that waits for changes on the inbox folder and exits as soon as the server signals Status=2 or the context deadline expires.
Command ping demonstrates a long-poll Ping that waits for changes on the inbox folder and exits as soon as the server signals Status=2 or the context deadline expires.
internal
spec
Package spec parses the spec-coverage matrix and the // SPEC: markers emitted by tests across the module, then reports any required spec requirement that is not covered by at least one test.
Package spec parses the spec-coverage matrix and the // SPEC: markers emitted by tests across the module, then reports any required spec requirement that is not covered by at least one test.
spec/cmd/covergate command
Command covergate fails when per-package coverage falls below the thresholds defined in the project plan:
Command covergate fails when per-package coverage falls below the thresholds defined in the project plan:
spec/cmd/speclint command
speclint validates the spec-coverage matrix against // SPEC: markers in every *_test.go file under the module root.
speclint validates the spec-coverage matrix against // SPEC: markers in every *_test.go file under the module root.
Package wbxml implements the WAP Binary XML 1.3 codec used by the Microsoft Exchange ActiveSync wire protocol.
Package wbxml implements the WAP Binary XML 1.3 codec used by the Microsoft Exchange ActiveSync wire protocol.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL