# How Macro's Email Service Integrates with Gmail Using OAuth and the Google API

> Learn how Macro's email service integrates with Gmail using OAuth and Google API for secure, sustained access and real-time mailbox updates. Discover the technical details.

- Repository: [Macro/macro](https://github.com/macro-inc/macro)
- Tags: integration-guide
- Published: 2026-08-18

---

**Macro's email service connects to Gmail through an OAuth 2.0 identity provider that requests specific Google API scopes, utilizes refresh tokens for sustained access, and processes real-time mailbox updates via a Pub/Sub webhook forwarder.**

The Macro repository implements a comprehensive Gmail integration that synchronizes user emails, manages contacts, and handles calendar data using Google's standard OAuth 2.0 protocol. This architecture combines Rust-based identity configuration, a dedicated REST API client, and containerized webhook forwarding to maintain secure, low-latency synchronization with Google Workspace accounts.

## OAuth 2.0 Configuration and Gmail API Scopes

The integration begins in [`tooling/xtask/crates/xtask_local/src/local/kickstart.rs`](https://github.com/macro-inc/macro/blob/main/tooling/xtask/crates/xtask_local/src/local/kickstart.rs), where the Google-Gmail identity provider is initialized using the `oauth2_base` function. This configuration defines the **OAuth 2.0 scopes** required for mailbox modification, contact access, and calendar synchronization.

Macro requests the following Gmail-specific scopes during the authorization flow:

- `https://www.googleapis.com/auth/gmail.modify` – Read, compose, send, and permanently delete emails
- `https://www.googleapis.com/auth/contacts.readonly` – Access the user's contacts
- `https://www.googleapis.com/auth/contacts.other.readonly` – Access the user's "Other contacts"
- `https://www.googleapis.com/auth/gmail.settings.basic` – Manage basic mail settings
- `https://www.googleapis.com/auth/calendar` – Access calendar data

```rust
// tooling/xtask/crates/xtask_local/src/local/kickstart.rs
let oauth2 = oauth2_base(
    "openid profile email \
     https://www.googleapis.com/auth/gmail.modify \
     https://www.googleapis.com/auth/contacts.readonly \
     https://www.googleapis.com/auth/contacts.other.readonly \
     https://www.googleapis.com/auth/gmail.settings.basic \
     https://www.googleapis.com/auth/calendar",
);

```

Local development environments inject credentials through specific environment variables read by the **xtask_local** tooling:
- `GOOGLE_CLIENT_ID` – The OAuth client identifier
- `GOOGLE_CLIENT_SECRET_KEY` – The confidential client secret
- `GMAIL_TEST_ACCOUNT_TOKENS` – A mapping of refresh tokens for test accounts

## Gmail API Client and Token Management

The HTTP communication layer resides in [`tooling/seed_cli/src/entity/gmail/mod.rs`](https://github.com/macro-inc/macro/blob/main/tooling/seed_cli/src/entity/gmail/mod.rs). This **Gmail entity** constructs requests against the base URL `https://gmail.googleapis.com/gmail/v1/users/me` and handles **bearer token authentication** using access tokens obtained from the stored refresh tokens.

```rust
// tooling/seed_cli/src/entity/gmail/mod.rs
let url = format!("{}/gmail/v1/users/me/messages", GMAIL_BASE);
let resp = client
    .get(&url)
    .bearer_auth(access_token)   // Token derived from refresh token flow
    .send()
    .await?
    .json::<serde_json::Value>()
    .await?;

```

The client implements retry logic and quota-throttling to handle Gmail API rate limits. All mailbox operations—including listing messages, sending mail, applying labels, and modifying thread states—route through this centralized module rather than using direct HTTP calls elsewhere in the codebase.

## Real-Time Synchronization with Pub/Sub and Webhooks

To eliminate polling overhead, Macro leverages the **Gmail watch API** combined with Google Cloud Pub/Sub. When a user enables syncing, the service registers a watch that pushes change notifications to a configured Pub/Sub topic. The [`tooling/xtask/crates/xtask_local/src/local/gen_compose.rs`](https://github.com/macro-inc/macro/blob/main/tooling/xtask/crates/xtask_local/src/local/gen_compose.rs) file defines a **gmail-forwarder** sidecar container that subscribes to this topic and forwards validated events to the internal email service.

```rust
// tooling/xtask/crates/xtask_local/src/local/gen_compose.rs
services.insert(
    "gmail_forwarder".to_string(),
    Service {
        image: "gmail-forwarder:latest".into(),
        env: hashmap! {
            "GMAIL_GCP_QUEUE".into() => "gmail-gcp-queue-local".into(),
            "TARGET_WEBHOOK".into() => "http://email-service:8080/gmail/webhook".into(),
        },
        // ... additional configuration
    },
);

```

Upon receiving a notification at `http://email-service:8080/gmail/webhook`, the email service validates the payload and emits internal domain events declared in [`crates/email/src/domain/events.rs`](https://github.com/macro-inc/macro/blob/main/crates/email/src/domain/events.rs) to trigger downstream processing pipelines.

## Secure Credential Management in Production

Production deployments use **Doppler** for secret management rather than flat environment files. The OAuth client secrets and service account keys are accessed through the `macro_env_var` crate, which provides type-safe secret retrieval that avoids `std::env` directly. The gmail-forwarder sidecar authenticates with Pub/Sub using the `GMAIL_FORWARDER_SA_KEY` environment variable, injected via the local environment configuration in [`tooling/xtask/crates/xtask_local/src/local/local_env.rs`](https://github.com/macro-inc/macro/blob/main/tooling/xtask/crates/xtask_local/src/local/local_env.rs).

## Summary

- **OAuth Configuration**: [`kickstart.rs`](https://github.com/macro-inc/macro/blob/main/kickstart.rs) defines the Google identity provider with comprehensive Gmail, Contacts, and Calendar scopes using the `oauth2_base` function and environment variables like `GOOGLE_CLIENT_ID`.
- **API Client**: The `seed_cli` `gmail` entity manages all REST communication with `https://gmail.googleapis.com/gmail/v1/users/me`, handling bearer token injection and retry logic.
- **Real-Time Delivery**: A `gmail-forwarder` sidecar container consumes Pub/Sub messages and pushes Gmail watch notifications to the internal webhook endpoint at `/gmail/webhook`.
- **Security Architecture**: Credentials are stored in Doppler for production and accessed via the `macro_env_var` crate, with local development supported through `xtask_local` environment injection.

## Frequently Asked Questions

### What specific OAuth scopes does Macro request for Gmail access?

Macro requests the `gmail.modify` scope for full mailbox read/write access, `contacts.readonly` and `contacts.other.readonly` for contact synchronization, `gmail.settings.basic` for mail settings, and `calendar` for calendar integration. These are declared in the `oauth2_base` function within [`tooling/xtask/crates/xtask_local/src/local/kickstart.rs`](https://github.com/macro-inc/macro/blob/main/tooling/xtask/crates/xtask_local/src/local/kickstart.rs).

### How does Macro receive email notifications without polling the Gmail API?

The service calls the Gmail **watch API** to register for push notifications, which Google delivers to a Cloud Pub/Sub topic. The `gmail-forwarder` sidecar defined in [`gen_compose.rs`](https://github.com/macro-inc/macro/blob/main/gen_compose.rs) subscribes to this topic and forwards events to the internal webhook at `http://email-service:8080/gmail/webhook`, enabling near real-time synchronization without API polling.

### Where are the Gmail OAuth credentials stored in Macro's architecture?

Production environments store credentials in **Doppler**, accessed at runtime through the `macro_env_var` crate. For local development, the `xtask_local` tooling reads `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET_KEY`, and `GMAIL_TEST_ACCOUNT_TOKENS` from the host environment and injects them into containers via [`tooling/xtask/crates/xtask_local/src/local/local_env.rs`](https://github.com/macro-inc/macro/blob/main/tooling/xtask/crates/xtask_local/src/local/local_env.rs).

### Which component executes HTTP requests to the Gmail REST API?

The **seed_cli** `gmail` entity in [`tooling/seed_cli/src/entity/gmail/mod.rs`](https://github.com/macro-inc/macro/blob/main/tooling/seed_cli/src/entity/gmail/mod.rs) executes all Gmail API calls. It builds requests against `https://gmail.googleapis.com/gmail/v1/users/me`, attaches bearer tokens obtained from refresh tokens, and manages response parsing and error handling.