PHPackages                             horde/mapi - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. horde/mapi

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

horde/mapi
==========

MAPI utility library

v2.0.0alpha5(1y ago)193942LGPL-2.1-onlyPHPPHP ^8.1

Since Jan 18Pushed 2w ago5 watchersCompare

[ Source](https://github.com/horde/Mapi)[ Packagist](https://packagist.org/packages/horde/mapi)[ Docs](https://www.horde.org)[ RSS](/packages/horde-mapi/feed)WikiDiscussions FRAMEWORK\_6\_0 Synced 1mo ago

READMEChangelog (2)Dependencies (3)Versions (17)Used By (2)

Horde MAPI
==========

[](#horde-mapi)

**MAPI utility library** – helper library for Microsoft MAPI data structures in the Horde Framework.

**Package**`horde/mapi`**Upstream**[github.com/horde/mapi](https://github.com/horde/mapi)**License**LGPL-2.1**Author**Michael J Rubinsky**PHP**^8.1**Dependencies**`horde/date`, `horde/exception`, PHP extension `bcmath`What is MAPI?
-------------

[](#what-is-mapi)

**MAPI** (Messaging Application Programming Interface) is Microsoft's API for messaging, calendars, and contacts—primarily in Exchange and Outlook. In Horde, this library is **not** a full MAPI client or Exchange connector. It provides **binary format helpers** used by Microsoft protocols, especially **Exchange ActiveSync**.

Typical use cases in Horde:

- Encode/decode timezones as MAPI `TIME_ZONE_INFORMATION` blobs (ActiveSync)
- Convert **Global Object Identifier (GOID)** ↔ iCalendar UID (appointments, meeting requests)
- Convert **Windows FILETIME** to Unix timestamps

Architecture
------------

[](#architecture)

The library is intentionally small and consists of three classes:

```
lib/Horde/
├── Mapi.php              → Horde_Mapi (static helpers)
└── Mapi/
    ├── Timezone.php      → Horde_Mapi_Timezone
    └── Exception.php     → Horde_Mapi_Exception

```

### `Horde_Mapi`

[](#horde_mapi)

General MAPI helper functions (all static):

MethodDescription`isLittleEndian()`Checks the system's byte order`chbo($num)`Reverses the byte order of an integer (for big-endian systems)`getUidFromGoid($goid)`Extracts a UID from a Base64-encoded GOID`createGoid($uid)`Creates a Base64-encoded GOID from a UID`filetimeToUnixtime($ft)`Converts binary Windows FILETIME to a Unix timestampMAPI structures are encoded in **little-endian** order. On big-endian systems, values are adjusted with `chbo()` before packing/unpacking.

`filetimeToUnixtime()` requires the PHP **bcmath** extension because FILETIME uses 64-bit values that PHP cannot represent natively. Without `bcmath`, it returns `-1`.

### `Horde_Mapi_Timezone`

[](#horde_mapi_timezone)

Converts between Microsoft's timezone blob and PHP/IANA timezones.

Microsoft defines timezones as a binary `TIME_ZONE_INFORMATION` structure (bias, standard/daylight names, `SYSTEMTIME` transitions, etc.). ActiveSync transmits this structure **Base64-encoded** in the WBXML protocol.

MethodDirectionDescription`getOffsetsFromSyncTZ($data)`MAPI blob → arrayDecodes an ActiveSync timezone blob into an offset hash`getSyncTZFromOffsets($offsets)`array → MAPI blobBuilds an ActiveSync-compatible timezone blob`getOffsetsFromDate(Horde_Date $date)`IANA TZ → arrayDerives offsets from a `Horde_Date`/timezone`getTimezone($offsets, $expectedTimezone)`MAPI blob/array → IANAGuesses the matching Olson timezone`getListOfTimezones($offsets, $expectedTimezone)`MAPI blob/array → arrayAll matching IANA identifiersReverse mapping (MAPI offsets → IANA timezone) is **ambiguous**: multiple timezones can share the same offsets. You can pass `$expectedTimezone` to prefer a specific match; otherwise `Horde_Date::getTimezoneAlias()` picks an alias.

Logic for detecting the nth weekday occurrence in a month (e.g. "second Sunday in March") is partly inspired by the [Tine 2.0](http://tine20.org) project.

### `Horde_Mapi_Exception`

[](#horde_mapi_exception)

Base exception class (extends `Horde_Exception_Wrapped`), e.g. for missing `bcmath` extension or no matching timezone.

How it works
------------

[](#how-it-works)

### 1. Timezone blob (ActiveSync)

[](#1-timezone-blob-activesync)

```
Horde_Date / IANA timezone
        │
        ▼
getOffsetsFromDate()          ← reads DST/STD transitions via DateTimeZone
        │
        ▼
getSyncTZFromOffsets()        ← pack() into TIME_ZONE_INFORMATION, base64_encode()
        │
        ▼
ActiveSync WBXML (Appointment.timezone)

```

Reverse direction when receiving:

```
Base64 timezone blob from client
        │
        ▼
getOffsetsFromSyncTZ()        ← base64_decode(), unpack()
        │
        ▼
getTimezone() / getListOfTimezones()   ← match against all IANA zones
        │
        ▼
e.g. "Europe/Berlin"

```

### 2. Global Object Identifier (GOID)

[](#2-global-object-identifier-goid)

GOIDs uniquely identify appointments across Exchange/Outlook. The library supports two formats:

- **Outlook style**: hex representation of the entire GOID, bytes 17–20 set to zero
- **vCal style**: `vCal-Uid` marker in the blob, UID as plain text after it

```
iCalendar UID  ←→  createGoid() / getUidFromGoid()  ←→  Base64 GOID

```

### 3. FILETIME

[](#3-filetime)

Windows stores timestamps as 64-bit counters in 100-ns ticks since 1 Jan 1601 UTC. Conversion steps:

1. Hex string from binary data
2. Flip endianness (`_flipEndian`)
3. Hex → bcmath integer (`_hexToBcint`)
4. Subtract epoch offset and divide by 10,000,000 (`_win64ToUnix`)

Usage in a Horde installation
-----------------------------

[](#usage-in-a-horde-installation)

`horde/mapi` is used mainly indirectly via **ActiveSync**:

ModuleFileUsage**ActiveSync**`Horde/ActiveSync/Message/Appointment.php``setTimezone()` / `getTimezone()` for appointment sync**ActiveSync**`Horde/ActiveSync/Message/MeetingRequest.php``createGoid()` for meeting UIDs, timezone parsing**Kronolith**`lib/Event.php``_handleEas16Exception()` – resolve timezone from ActiveSync messageThese functions previously lived in `Horde_ActiveSync_Utils` and `Horde_ActiveSync_Timezone`; since Horde 6 they were moved into `horde/mapi` (the old classes are marked `@deprecated`).

Examples
--------

[](#examples)

### Create a timezone blob

[](#create-a-timezone-blob)

```
$date = new Horde_Date(time(), 'Europe/Berlin');
$offsets = Horde_Mapi_Timezone::getOffsetsFromDate($date);
$blob = Horde_Mapi_Timezone::getSyncTZFromOffsets($offsets);
// $blob → Base64 string for ActiveSync
```

### Parse a timezone blob

[](#parse-a-timezone-blob)

```
$parser = new Horde_Mapi_Timezone();
$tz = $parser->getTimezone($blob, 'Europe/Berlin');
// $tz → e.g. "Europe/Berlin"
```

### GOID ↔ UID

[](#goid--uid)

```
$goid = Horde_Mapi::createGoid('{81412D3C-2A24-4E9D-B20E-11F7BBE92799}');
$uid  = Horde_Mapi::getUidFromGoid($goid);
```

### Convert FILETIME

[](#convert-filetime)

```
$binaryFiletime = /* from MAPI pTypDate property */;
$unix = Horde_Mapi::filetimeToUnixtime($binaryFiletime);
```

Installation
------------

[](#installation)

Via Composer (in Horde, typically as a framework dependency):

```
composer require horde/mapi
```

In this installation: `dev-FRAMEWORK_6_0` (Horde Framework 6).

Tests
-----

[](#tests)

```
cd vendor/horde/mapi
vendor/bin/phpunit
```

Tests live under `test/Unnamespaced/` (`MapiTest.php`, `TimezoneTest.php`) with fixtures for GOIDs and FILETIME.

Further reading
---------------

[](#further-reading)

- [MSDN: TIME\_ZONE\_INFORMATION](https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/ns-timezoneapi-time_zone_information)
- [MSDN: Global Object IDs](https://learn.microsoft.com/en-us/previous-versions/office/developer/exchange-server-2010/ee157690(v=exchg.80))
- [Horde Libraries: Horde\_Mapi](https://www.horde.org/libraries/Horde_Mapi)

###  Health Score

50

—

FairBetter than 95% of packages

Maintenance75

Regular maintenance activity

Popularity23

Limited adoption so far

Community27

Small or concentrated contributor base

Maturity66

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~297 days

Recently: every ~390 days

Total

15

Last Release

395d ago

Major Versions

1.0.10 → 2.0.0alpha22021-02-24

PHP version history (7 changes)1.0.1PHP &gt;=5.3.0

1.0.3PHP &gt;=5.3.0,&lt;=6.0.0alpha1

1.0.6PHP &gt;=5.3.0,&lt;=8.0.0alpha1

1.0.9PHP ^5.3 || ^7

2.0.0alpha2PHP ^7

v2.0.0alpha4PHP ^7.4 || ^8

v2.0.0alpha5PHP ^8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/c943a083635c28520599075eaea7ede2d743b7697b76e84d6bdc37e52cc8249b?d=identicon)[yunosh](/maintainers/yunosh)

![](https://www.gravatar.com/avatar/c931cd02664859360478593450d6c473a05bb12b209dfacfc534cd13257cc7ef?d=identicon)[ralflang](/maintainers/ralflang)

![](https://www.gravatar.com/avatar/e4f6c6771993db2ed500959b42353f6cf6a2ca0406d9617f7ae680f4504faa4a?d=identicon)[horde](/maintainers/horde)

![](https://www.gravatar.com/avatar/a7767adb66b45f2f05bcd44d49bc4e67efacd9ce05b161ce2d481d5dd6af025c?d=identicon)[mrubinsk](/maintainers/mrubinsk)

---

Top Contributors

[![yunosh](https://avatars.githubusercontent.com/u/379318?v=4)](https://github.com/yunosh "yunosh (48 commits)")[![mrubinsk](https://avatars.githubusercontent.com/u/66822?v=4)](https://github.com/mrubinsk "mrubinsk (39 commits)")[![ralflang](https://avatars.githubusercontent.com/u/646976?v=4)](https://github.com/ralflang "ralflang (8 commits)")[![slusarz](https://avatars.githubusercontent.com/u/381003?v=4)](https://github.com/slusarz "slusarz (3 commits)")[![TDannhauer](https://avatars.githubusercontent.com/u/6716033?v=4)](https://github.com/TDannhauer "TDannhauer (3 commits)")[![remicollet](https://avatars.githubusercontent.com/u/270445?v=4)](https://github.com/remicollet "remicollet (1 commits)")

### Embed Badge

![Health badge](/badges/horde-mapi/health.svg)

```
[![Health](https://phpackages.com/badges/horde-mapi/health.svg)](https://phpackages.com/packages/horde-mapi)
```

###  Alternatives

[horde/horde

Horde base application

583.0k62](/packages/horde-horde)[horde/kronolith

Calendar and scheduling application

101.3k4](/packages/horde-kronolith)[horde/imp

Webmail application

261.1k](/packages/horde-imp)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
