OAuth Setup
Google (Gmail and Calendar)¶
msgvault requires OAuth credentials to access the Gmail API. This section walks through the complete setup.
Step 1: Create a Google Cloud Project¶
- Go to Google Cloud Console
- Create a new project or select an existing one
- Note your project ID
Step 2: Enable Google APIs¶
- Navigate to APIs & Services > Library
- Search for "Gmail API"
- Click Enable
- If you will sync Google Calendar too, also search for "Google Calendar API" and click Enable
Step 3: Configure OAuth Consent Screen¶
- Go to APIs & Services > OAuth consent screen (Google may call this Google Auth Platform)
- Choose External user type (or Internal for Google Workspace)
- Fill in required fields:
- App name:
msgvault - User support email: your email
- Developer contact email: your email
- Click Save and Continue
- On the Data Access page, click Add or Remove Scopes
- Add the scope:
https://www.googleapis.com/auth/gmail.modify - If you will sync Google Calendar too, add
https://www.googleapis.com/auth/calendar.readonly - Save and continue through the remaining screens
- Under Test users, add all Gmail addresses you want to sync
Note
The gmail.modify scope enables deletion features while sync operations remain read-only. When you first run delete-staged, msgvault will prompt you to upgrade to full mail.google.com access for batch deletion.
Step 4: Create OAuth Client Credentials¶
- Go to APIs & Services > Credentials
- Click Create Credentials > OAuth client ID
- Choose Desktop app as the application type
- Name it
msgvault(or similar) - Click Create
- Download the JSON file
- Save it as
client_secret.jsonin a secure location
Warning
Never commit client_secret.json to version control.
Desktop App Only
You must choose Desktop app as the client type. Do not use "TVs and Limited Input devices" as Google's device code flow does not support Gmail scopes.
Step 5: Configure msgvault¶
Create config.toml in your msgvault data directory:
- macOS / Linux:
~/.msgvault/config.toml - Windows:
C:\Users\<you>\.msgvault\config.toml
Tip
The .msgvault directory is created automatically the first time you run any msgvault command. If you're unsure of the exact path, run msgvault add-account [email protected]; the error message may show you where to create the config file.
On Windows, use forward slashes or escaped backslashes for the path:
Step 6: Add Your Account¶
msgvault add-account [email protected]
This opens your browser to Google's OAuth consent page. Sign in, grant access, and tokens are stored locally in ~/.msgvault/tokens/.
Multiple Accounts¶
For personal Gmail accounts, a single client_secret.json works for all of them. Each add-account call creates a separate token file:
msgvault add-account [email protected]
msgvault add-account [email protected]
msgvault sync # syncs all accounts
Tip
Make sure all Gmail addresses you want to sync are listed as Test users in your Google Cloud OAuth consent screen (Step 3 above). This is the most common reason a second account fails to authorize.
Google Workspace Accounts¶
Many Google Workspace organizations restrict OAuth to apps created within their own org. If you get an "access denied" or "app blocked" error when authorizing a Workspace account with your personal OAuth app, the org likely requires its own app.
To handle this, create a separate Google Cloud project inside the Workspace org (Steps 1-4 above), then add it as a named OAuth app in config.toml:
[oauth]
client_secrets = "/path/to/personal_secret.json" # default for personal Gmail
[oauth.apps.acme]
client_secrets = "/path/to/acme_workspace_secret.json"
Then specify the app when adding Workspace accounts:
msgvault add-account [email protected] --oauth-app acme
msgvault add-account [email protected] # uses default
The binding is stored per account, so sync, verify, and serve automatically use the correct credentials. You only need --oauth-app when first adding or rebinding an account.
To switch an existing account to a different OAuth app:
msgvault add-account [email protected] --oauth-app acme # re-authorizes with new app
To move an account back to the default app:
msgvault add-account [email protected] --oauth-app "" # clears the binding
Google Workspace Service Accounts¶
Workspace admins can avoid per-user browser OAuth by using a Google service account with domain-wide delegation.
- Create a Google Cloud service account in the Workspace-owned project.
- Create and download a JSON key for the service account.
- In the Google Admin Console, authorize the service account client ID for:
https://www.googleapis.com/auth/gmail.readonlyhttps://www.googleapis.com/auth/gmail.modifyhttps://www.googleapis.com/auth/calendar.readonlyif you will sync Google Calendarhttps://mail.google.com/if you will rundelete-staged --permanent- Store the key with owner-only permissions, for example
chmod 600 /path/to/workspace-service-account.json.
Configure the key as the default Google credential:
Or bind it to a named app:
Then add accounts normally:
msgvault add-account [email protected]
msgvault add-account [email protected] --oauth-app acme
Service account mode validates the delegated Gmail profile and registers the source, but it does not create per-user token files. Do not combine service-account accounts with --headless or --force; delegated tokens are minted on demand.
For Google Calendar with a service account, enable the Google Calendar API and authorize the calendar.readonly scope above. Then configure a [[gcal]] source and run msgvault sync-calendar [email protected] --oauth-app acme (or let msgvault serve run the schedule). No browser token is created.
Headless Server Setup¶
When running msgvault on a headless server (SSH, VPS, Docker), there is no browser available for OAuth. Google's device code flow does not support Gmail scopes, so you must authorize on a machine with a browser and copy the token to your server.
Run --headless to see the setup instructions:
msgvault add-account [email protected] --headless
This prints:
=== Headless Server Setup ===
Google's OAuth device flow does not support Gmail scopes, so --headless
cannot directly authorize. Instead, authorize on a machine with a browser
and copy the token to your server.
Step 1: On a machine with a browser, run:
msgvault add-account [email protected]
Step 2: Copy the token file to your headless server:
ssh user@server 'mkdir -p ~/.msgvault/tokens'
scp ~/.msgvault/tokens/[email protected] user@server:~/.msgvault/tokens/
Step 3: On the headless server, register the account:
msgvault add-account [email protected]
The token will be detected and the account registered. No browser needed.
Step-by-Step¶
-
On your local machine (with a browser), install msgvault and run:
Complete the OAuth flow in your browser.msgvault add-account [email protected] -
Copy the token to your headless server:
ssh user@server mkdir -p ~/.msgvault/tokens scp ~/.msgvault/tokens/[email protected] user@server:~/.msgvault/tokens/ -
On the headless server, register the account:
msgvault detects the existing token and registers the account. Output:msgvault add-account [email protected]Account [email protected] is ready. You can now run: msgvault sync-full [email protected] -
Sync your email:
msgvault sync-full [email protected]
The token file contains OAuth refresh tokens that are automatically renewed. You only need to copy it once unless you revoke access.
Note
Both machines must use the same OAuth client credentials. The token is tied to the OAuth client that created it. If the account uses a named OAuth app (--oauth-app), configure the same [oauth.apps.<name>] section on both machines.
Microsoft 365 (Outlook / Hotmail)¶
The add-o365 command connects Outlook.com, Hotmail, Live.com, and Microsoft 365 organizational accounts via OAuth2 with XOAUTH2 IMAP authentication. No app password is needed.
Prerequisites: Azure AD App Registration¶
You need to register an application in Microsoft Entra (Azure AD) before using add-o365.
- Go to Azure Portal and navigate to Microsoft Entra ID > App registrations > New registration
- Set the fields:
- Name:
msgvault - Supported account types: "Accounts in any organizational directory and personal Microsoft accounts"
- Redirect URI: Platform = Mobile and desktop applications, URI =
http://localhost:8089/callback/microsoft - Click Register
- Under API permissions, click Add a permission > APIs my organization uses, search for Office 365 Exchange Online, select Delegated permissions, then add
IMAP.AccessAsUser.All - Under Authentication, enable Allow public client flows (required for PKCE)
- Copy the Application (client) ID from the app's Overview page
Configure msgvault¶
Add a [microsoft] section to your config.toml:
To restrict authorization to a specific organization, set tenant_id:
When tenant_id is omitted (or set to "common"), both personal Microsoft accounts and organizational accounts can authorize.
Add Your Account¶
msgvault add-o365 [email protected]
This opens your browser for Microsoft OAuth consent. After you authorize, msgvault:
- Validates the token matches the email you specified
- Auto-detects the correct IMAP host based on account type
- Configures XOAUTH2 authentication automatically
Personal accounts (hotmail.com, outlook.com, live.com, msn.com) connect to outlook.office.com. Organizational accounts (company Microsoft 365) connect to outlook.office365.com. This detection is automatic.
To restrict to a specific tenant at authorization time:
msgvault add-o365 [email protected] --tenant your-org-tenant-id
Microsoft Teams Graph Sync¶
Teams ingestion uses the same [microsoft] client_id and redirect URI, but it
requests Microsoft Graph delegated scopes and stores a separate token file under
tokens/teams_<email>.json. The microsoft_<email>.json token created by
add-o365 is for IMAP and is not reused for Teams.
If you will archive Teams chats and channels, add these Microsoft Graph delegated permissions to the app registration:
Chat.ReadChannelMessage.Read.AllTeam.ReadBasic.AllChannel.ReadBasic.AllUser.ReadUser.ReadBasic.All
Then authorize and sync Teams:
msgvault add-teams [email protected]
msgvault sync-teams [email protected]
Some organizations require administrator consent before delegated channel message permissions can be used. See Microsoft Teams for the full Teams workflow.
Sync Your Email¶
After adding the account, sync it the same way as any other account:
msgvault sync-full [email protected]
Headless Servers¶
On a headless server (SSH, VPS, Docker), authorize on a machine with a browser and copy the token file to the server:
- On your local machine, run
msgvault add-o365 [email protected]and complete the browser flow. - Copy the token to the server:
ssh user@server mkdir -p ~/.msgvault/tokens scp ~/.msgvault/tokens/[email protected] \ user@server:~/.msgvault/tokens/ - On the server, run
msgvault add-o365 [email protected]again. It detects the existing token and registers the account without a browser.
Both machines must use the same client_id in their [microsoft] config.