#outlook #mapi #winapi #api-bindings

outlook-mapi

Rust bindings for the Outlook MAPI interface

24 releases (12 breaking)

0.13.2 Apr 13, 2024
0.13.0 Mar 21, 2024

#39 in Windows APIs

Download history 21/week @ 2024-02-18 1247/week @ 2024-02-25 181/week @ 2024-03-03 649/week @ 2024-03-10 764/week @ 2024-03-17 15/week @ 2024-03-24 128/week @ 2024-03-31 206/week @ 2024-04-07 21/week @ 2024-04-14

426 downloads per month

MIT license

2.5MB
48K SLoC

outlook-mapi

This crate implements Rust bindings for the Outlook MAPI COM APIs. The bindings are generated by the Windows crate in outlook-mapi-sys.

Getting Started

Include a reference to the latest version of outlook-mapi in your Cargo.toml.

See the docs for more details.

Safety

Most of the bindings are re-exported transparently from outlook-mapi-sys as the outlook-mapi::sys module, and they are still marked unsafe. Unlike typical idiomatic Rust crates wrapped around a -sys crate, the emphasis of this crate is on writing as little manual wrapper code as possible. This way, outlook-mapi can project 100% of the Outlook MAPI COM API, but the downside is you will need to wrap most uses in an unsafe block or function.

Convenience Types

This crate does add several Rust structs and macro definitions to make it easier to work with MAPI types, and to add some lifetime guarantees when used in place of the raw MAPI API. For instance, the typical sequence of MAPI calls in C++ looks something like this:

MAPIInitialize(...);

// Logon with a new session.
MAPILogonEx(..., &session);

// Do stuff with the session...

// This should be the last reference to the session!
session->Release();

MAPIUninitialize();

The convenience types ensure that you have a matching pair of MAPIInitialize and MAPIUninitialize calls, and they live at least as long as the session is in use. They also constrain which flags you can pass to each of these calls:

println!("Initializing MAPI...");
let initialized = Initialize::new(Default::default()).expect("failed to initialize MAPI");
println!("Trying to logon to the default profile...");
let logon = Logon::new(
    initialized,
    Default::default(),
    None,
    None,
    LogonFlags {
        extended: true,
        unicode: true,
        logon_ui: true,
        use_default: true,
        ..Default::default()
    },
)
.expect("should be able to logon to the default MAPI profile");
println!("Success!");

Dependencies

~140MB
~2.5M SLoC