Documentation
¶
Overview ¶
Package activesync provides an embeddable Microsoft Exchange ActiveSync server built on Echo v5. Implement the Backend interface and call NewServer to start.
Index ¶
- func GeneratePolicyKey() (string, error)
- func GenerateSyncKey() (string, error)
- type Backend
- type BackendFactory
- type DeviceState
- type DeviceStore
- type Dispatcher
- type Handler
- func (h *Handler) HandleAutodiscover(c *echo.Context) error
- func (h *Handler) HandleFolderSync(c *echo.Context, backend Backend, deviceState *DeviceState) error
- func (h *Handler) HandleGetItemEstimate(c *echo.Context, backend Backend, _ *DeviceState) error
- func (h *Handler) HandleMeetingResponse(c *echo.Context, backend Backend, _ *DeviceState) error
- func (h *Handler) HandleMoveItems(c *echo.Context, backend Backend, _ *DeviceState) error
- func (h *Handler) HandlePing(c *echo.Context, backend Backend, _ *DeviceState) error
- func (h *Handler) HandleProvision(c *echo.Context, backend Backend, deviceState *DeviceState) error
- func (h *Handler) HandleSearch(c *echo.Context, backend Backend, _ *DeviceState) error
- func (h *Handler) HandleSendMail(c *echo.Context, backend Backend, _ *DeviceState) error
- func (h *Handler) HandleSettings(c *echo.Context, backend Backend, deviceState *DeviceState) error
- func (h *Handler) HandleSmartForward(c *echo.Context, backend Backend, _ *DeviceState) error
- func (h *Handler) HandleSmartReply(c *echo.Context, backend Backend, _ *DeviceState) error
- func (h *Handler) HandleSync(c *echo.Context, backend Backend, deviceState *DeviceState) error
- type Options
- type SearchQuery
- type Server
- type SyncOptions
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GeneratePolicyKey ¶
GeneratePolicyKey creates a new random policy key.
func GenerateSyncKey ¶
GenerateSyncKey creates a new random sync key.
Types ¶
type Backend ¶
type Backend interface {
// Logon authenticates the user. Returns false on failure.
Logon(ctx context.Context, username, domain, password string) bool
// Logoff is called after the request is complete. Should release resources.
Logoff(ctx context.Context) error
// Setup prepares the backend for the given user (and optional impersonated user).
// This is called after Logon succeeds.
Setup(ctx context.Context, username, impersonatedUser string) error
// GetFolderList returns the complete folder hierarchy for the authenticated user.
GetFolderList(ctx context.Context) ([]protocol.Folder, error)
// GetFolderSyncKey returns the current sync key for the folder hierarchy.
// An empty string or "0" means full sync is required.
GetFolderSyncKey(ctx context.Context) (string, error)
// SetFolderSyncKey saves a new folder hierarchy sync key.
SetFolderSyncKey(ctx context.Context, key string) error
// GetChanges returns items that have changed since the last sync.
// syncKey "0" means a full sync; a non-zero key returns only deltas.
// Returns the new sync key and a slice of changes.
GetChanges(ctx context.Context, folderID, syncKey string, options *SyncOptions) (newKey string, changes []protocol.Change, err error)
// ApplyChange applies a client-originated change (add/modify/delete) to the backend.
ApplyChange(ctx context.Context, folderID string, change protocol.Change) (serverID string, err error)
// GetItemCount returns the estimated number of items to sync for a folder.
GetItemCount(ctx context.Context, folderID, syncKey string) (int, error)
// SendMail sends an email message (raw MIME data).
SendMail(ctx context.Context, mime []byte, saveInSentItems bool) error
// SmartForward forwards an existing message with additional content.
SmartForward(ctx context.Context, itemID, folderID string, mime []byte) error
// SmartReply replies to an existing message.
SmartReply(ctx context.Context, itemID, folderID string, mime []byte) error
// GetAttachment fetches an attachment by its file reference.
GetAttachment(ctx context.Context, fileRef string) (data []byte, contentType string, err error)
// MoveItems moves one or more items between folders.
MoveItems(ctx context.Context, moves []protocol.MoveRequest) ([]protocol.MoveResult, error)
// MeetingResponse processes a meeting accept/decline/tentative response.
MeetingResponse(ctx context.Context, requestID, folderID string, userResponse protocol.MeetingResponseStatus) (calendarID string, err error)
// Search performs a search across the mailbox or GAL.
Search(ctx context.Context, query *SearchQuery) ([]protocol.SearchResult, int, error)
// GetDevicePolicy returns the device security policy for this user/device.
// Returning nil means no policy enforcement.
GetDevicePolicy(ctx context.Context) (*protocol.Policy, error)
// AcknowledgePolicy acknowledges that the device accepted the policy.
AcknowledgePolicy(ctx context.Context, policyKey string) error
// GetDeviceInfo returns stored device info for this device, if any.
GetDeviceInfo(ctx context.Context, deviceID string) (*protocol.DeviceInfo, error)
// SaveDeviceInfo stores updated device information from a Settings request.
SaveDeviceInfo(ctx context.Context, info *protocol.DeviceInfo) error
}
Backend is the interface that backends must implement to provide data to the ActiveSync server. Each method corresponds to one or more AS commands.
A new Backend instance is created per-request via BackendFactory. Logon is always the first call; Logoff is always the last.
type BackendFactory ¶
type BackendFactory func() Backend
BackendFactory creates a new Backend instance for each incoming request.
type DeviceState ¶
type DeviceState struct {
DeviceID string
DeviceType string
UserAgent string
Username string
PolicyKey string
PolicyAcked bool
FolderSyncKey string
ItemSyncKeys map[string]string // folderID → syncKey
LastSyncTime map[string]time.Time
CreatedAt time.Time
UpdatedAt time.Time
// contains filtered or unexported fields
}
DeviceState holds per-device synchronization state. In production, persist this via a StateMachine implementation.
func NewDeviceState ¶
func NewDeviceState(deviceID, deviceType, username string) *DeviceState
NewDeviceState creates an empty DeviceState for the given device.
func (*DeviceState) GetSyncKey ¶
func (d *DeviceState) GetSyncKey(folderID string) string
GetSyncKey returns the current sync key for a folder. Returns "0" if no key has been assigned yet.
func (*DeviceState) SetSyncKey ¶
func (d *DeviceState) SetSyncKey(folderID, key string)
SetSyncKey updates the sync key for a folder.
type DeviceStore ¶
type DeviceStore struct {
// contains filtered or unexported fields
}
DeviceStore is a thread-safe in-memory store for DeviceState objects. Replace with a persistent implementation for production use.
func NewDeviceStore ¶
func NewDeviceStore() *DeviceStore
NewDeviceStore creates an empty in-memory device store.
func (*DeviceStore) Get ¶
func (s *DeviceStore) Get(deviceID, deviceType, username string) *DeviceState
Get retrieves or creates a DeviceState for the given device/user pair.
func (*DeviceStore) Save ¶
func (s *DeviceStore) Save(d *DeviceState) error
Save persists an updated DeviceState (no-op in the in-memory implementation).
type Dispatcher ¶
type Dispatcher struct {
// contains filtered or unexported fields
}
Dispatcher routes ActiveSync POST requests to the correct handler.
func NewDispatcher ¶
func NewDispatcher(h *Handler) *Dispatcher
NewDispatcher creates a Dispatcher from a Handler.
func (*Dispatcher) HandleActiveSyncPost ¶
func (d *Dispatcher) HandleActiveSyncPost(c *echo.Context) error
HandleActiveSyncPost is the main Echo handler for POST /Microsoft-Server-ActiveSync.
func (*Dispatcher) HandleOptions ¶
func (d *Dispatcher) HandleOptions(c *echo.Context) error
HandleOptions handles HTTP OPTIONS requests (capability discovery).
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler holds shared dependencies for all AS command handlers. It lives inside pkg/activesync so it can reference Backend, DeviceStore, Options directly.
func NewHandler ¶
func NewHandler(factory BackendFactory, deviceStore *DeviceStore, opts *Options, logger *zap.Logger) *Handler
NewHandler creates a Handler instance.
func (*Handler) HandleAutodiscover ¶
HandleAutodiscover responds to Exchange Autodiscover requests. It returns the server URL for ActiveSync configuration.
func (*Handler) HandleFolderSync ¶
func (h *Handler) HandleFolderSync(c *echo.Context, backend Backend, deviceState *DeviceState) error
HandleFolderSync processes a FolderSync command. The client sends its current folder sync key; the server returns any changes to the folder hierarchy since that key.
func (*Handler) HandleGetItemEstimate ¶
HandleGetItemEstimate processes a GetItemEstimate command. Returns the estimated number of items to sync for each requested collection.
func (*Handler) HandleMeetingResponse ¶
HandleMeetingResponse processes a MeetingResponse command.
func (*Handler) HandleMoveItems ¶
HandleMoveItems processes a MoveItems command.
func (*Handler) HandlePing ¶
HandlePing processes a Ping command (long-poll for server-side changes). The server holds the connection open until changes arrive or the heartbeat interval expires.
func (*Handler) HandleProvision ¶
HandleProvision processes a Provision command. Phase 1: client requests policy → server sends policy + temp key. Phase 2: client acknowledges policy → server sends permanent key.
func (*Handler) HandleSearch ¶
HandleSearch processes a Search command.
func (*Handler) HandleSendMail ¶
HandleSendMail processes a SendMail command. The request body contains raw MIME data (not WBXML).
func (*Handler) HandleSettings ¶
HandleSettings processes a Settings command.
func (*Handler) HandleSmartForward ¶
HandleSmartForward processes a SmartForward command.
func (*Handler) HandleSmartReply ¶
HandleSmartReply processes a SmartReply command.
func (*Handler) HandleSync ¶
HandleSync processes a Sync command. The client sends collection sync keys; the server returns changes.
type Options ¶
type Options struct {
// Addr is the listen address, e.g. ":8080" or ":443".
Addr string
// TLSCert and TLSKey are paths to the TLS certificate and key files.
// If empty, the server starts without TLS (not suitable for production).
TLSCert string
TLSKey string
// Logger is the zap logger. If nil, a production logger is created.
Logger *zap.Logger
// MaxPingInterval is the maximum heartbeat interval for Ping commands (seconds).
// Default: 540 (9 minutes).
MaxPingInterval int
// MinPingInterval is the minimum heartbeat interval (seconds).
// Default: 60.
MinPingInterval int
// MaxPingFolders is the maximum number of folders a Ping command may monitor.
// Default: 100.
MaxPingFolders int
// EnforceProvisioning requires clients to exchange a policy before syncing.
// Default: false (permissive for testing).
EnforceProvisioning bool
// ServerHeader overrides the X-MS-Server-ActiveSync header value.
ServerHeader string
}
Options configures the ActiveSync server.
type SearchQuery ¶
type SearchQuery struct {
StoreName string
Query string
FreeText string
RangeStart int
RangeEnd int
DeepTraversal bool
}
SearchQuery encapsulates a Search command request.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the ActiveSync server. It wraps an Echo instance and routes all AS protocol requests through the registered Backend.
func NewServer ¶
NewServer creates a new ActiveSync server with the given options. Call SetBackendFactory before Start.
func (*Server) SetBackendFactory ¶
func (s *Server) SetBackendFactory(f BackendFactory)
SetBackendFactory registers the factory that creates a Backend per request.
type SyncOptions ¶
type SyncOptions struct {
FilterType protocol.FilterType
WindowSize int
BodyType protocol.BodyType
TruncationSize int
MIMESupport int
}
SyncOptions holds per-collection sync options from the client.
Source Files
¶
- backend.go
- device.go
- dispatcher.go
- handler_autodiscover.go
- handler_base.go
- handler_foldersync.go
- handler_getitemestimate.go
- handler_meetingresponse.go
- handler_moveitems.go
- handler_ping.go
- handler_provision.go
- handler_search.go
- handler_sendmail.go
- handler_settings.go
- handler_sync.go
- middleware.go
- options.go
- server.go