00
Provider OAuth Setup
Gmail (Google Cloud) + Outlook (Microsoft Entra ID)
Validated 2026-05-19 · maintainer's own deploy

OAuth credentials, your own.

mailsloth-server needs OAuth 2.0 client credentials from each provider you connect — Google for Gmail, Microsoft for Outlook / Hotmail / Live. The credentials are yours: you register your own apps in Google Cloud + Microsoft Entra, you hold your own client secrets, and the iOS app connects through them. Everplay-Tech never mints or holds these. This page mirrors the live walkthrough the maintainer ran on the reference deployment 2026-05-19 — what you click here is what they clicked there.

Time estimate (maintainer's pace 2026-05-19): Google ~15–20 min · Microsoft ~10–15 min · apply-to-backend ~30 sec per provider. Total ~30–40 min, mostly cloud-console clicking.

01
Why each deployer holds their own client secrets
Family rule · No phone home

The whole MailSloth posture is customer-owned backend. To make that real at the OAuth layer, each deployer registers their own app inside each provider's developer console. The end users your deployment serves see your app on the Google / Microsoft consent screen — not Everplay-Tech's. Tokens are exchanged between your server and the provider directly. Cipher / Everplay-Tech is not in the path.

What you register

A Google Cloud project + OAuth client; a Microsoft Entra app registration. Both free. Both tied to your deployer account.

What you receive

Four secret values: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET. They land on your mailsloth-server as env vars.

What the end user sees

The provider's hosted consent screen — branded with the app name you chose ("MailSloth" or whatever), under your support email. Then back into the iOS app.

What Everplay-Tech sees

Nothing. No tokens, no audit log, no metadata. The OAuth flow runs entirely between the end user, the provider, and your server.

Reading order. You only need the provider you actually use. Run Google if you want Gmail support; Microsoft if you want Outlook / Hotmail / Live. Most deployers do both. Section ordering below matches the maintainer's walkthrough sequence on 2026-05-19.
02
Google Cloud — Gmail OAuth
Four chunks · ~15–20 min

Pre-flight

  1. Google account. The deployer's, not the end user's. Free tier is fine.
  2. Project in Google Cloud Console. Reasonable name: mailsloth or <your-domain>-mailsloth.
  3. Enable Gmail API. Open https://console.cloud.google.com/apis/library/gmail.googleapis.com?project=<project> and click Enable. Free; not a billing change for OAuth-scoped reads/writes. Without this, OAuth scopes won't appear in the picker.

Chunk A · OAuth Consent Screen / Branding

The new Google Cloud "Google Auth Platform" UI calls this Branding.

  1. 1 · Open the consent screen

    Console search bar → OAuth consent screen → open.

  2. 2 · User Type

    Select External.

  3. 3 · Fill

    App name: MailSloth (whatever the deployer wants users to see).
    User support email: deployer's Gmail. Google restricts this to your current-account email OR Workspace-managed groups; you cannot type an arbitrary address.
    App logo: skip for now.
    App home page: any reachable URL (e.g. https://your-domain.com).
    Authorized domains: the parent domain only (e.g. your-domain.com, not subdomains).
    Developer contact email: deployer's email.

  4. 4 · Save and continue.

Chunk B · Audience / Test users

While your app is in Testing publishing status:

  1. 1 · Add test users

    The deployer's own Gmail address, plus any other emails to test with. Max ~100.

Operational expectation. While in Testing, only listed test users can complete OAuth. Production verification is a separate Google process — can take days, and any restricted scope you request may trigger a CASA security audit (third-party assessor, $15k–75k). See Chunk C for the minimal-scope discipline that keeps this manageable.

Chunk C · Data Access / Scopes

The MailSloth-canonical minimal scope set is six scopes:

ScopeTier
https://www.googleapis.com/auth/userinfo.emailNon-sensitive
https://www.googleapis.com/auth/userinfo.profileNon-sensitive
openidNon-sensitive
https://www.googleapis.com/auth/gmail.sendSensitive
https://www.googleapis.com/auth/gmail.readonlyRestricted
https://www.googleapis.com/auth/gmail.modifyRestricted
Anti-pattern surfaced during walkthrough. The consent-screen UI offers a tempting "select all Gmail scopes" experience. AVOID. Specifically REMOVE:
  • https://mail.google.com/ — full mailbox access including delete-all. Massive overreach for MailSloth.
  • gmail.compose — duplicative with send + modify.
  • gmail.metadata — subset of gmail.readonly; redundant.
  • gmail.insert — inserting emails into a mailbox (migration tools); not needed.
  • gmail.settings.basic / gmail.settings.sharing — manage user's filters / sharing; not your job.
  • All gmail.addons.* — for Gmail browser-extension add-ons, not backend servers.
Why: every restricted scope you request triggers Google's app verification process for production launch (potentially that $15k–75k CASA audit). Fewer scopes = simpler verification. Plus, the OAuth consent screen shows users every scope — "permanently delete all your email" reads as malware; users hit Cancel.

Chunk D · Create OAuth Client

  1. 1 · Open Clients

    Left sidebar → Clients+ Create client.

  2. 2 · Application type

    Web application.

  3. 3 · Name

    MailSloth backend.

  4. 4 · Authorized redirect URIs

    Add both:

    https://<your-mailsloth-domain>/api/v1/mailsloth/oauth/google/callback
    http://localhost:3010/api/v1/mailsloth/oauth/google/callback

    The localhost URI is for local dev; you can drop it once you're production-only.

  5. 5 · Create

    Modal pops with Client ID (.apps.googleusercontent.com suffix) + Client secret (GOCSPX- prefix). Both shown together. Download the JSON or copy both values.

These map to:

Env varSource
GOOGLE_CLIENT_IDThe *.apps.googleusercontent.com string
GOOGLE_CLIENT_SECRETThe GOCSPX-… string
03
Microsoft Entra ID — Outlook OAuth
Three chunks · ~10–15 min

Pre-flight

  1. Microsoft account. The deployer's; Hotmail, Live, or any Microsoft account works.
  2. Sign in to Microsoft Entra admin center at https://entra.microsoft.com (cleaner than the classic Azure portal).
  3. Verify you have a tenant. If not, sign-up creates one (<random>.onmicrosoft.com).

Chunk A · App Registration

  1. 1 · New registration

    Left sidebar → Entra IDApp registrations+ New registration.

  2. 2 · Fill

    Name: MailSloth backend.
    Supported account types: Accounts in any organizational directory (Any Microsoft Entra ID tenant — Multitenant) and personal Microsoft accounts. Critical for allowing any Outlook / Hotmail user to connect, not just deployer's tenant.
    Redirect URI: leave empty for now (chunk C below).

  3. 3 · Register

    On the new app's Overview page, copy Application (client) ID (a GUID). That's MICROSOFT_CLIENT_ID.

Chunk B · Client Secret + API Permissions

  1. 1 · Create the secret

    Left sidebar → Certificates & secrets+ New client secret.
    Description: mailsloth-prod. Expires: 24 months. Add.

  2. 2 · Copy the Value

    Copy the Value column of the new secret immediately. ⚠ Only shown once. That's MICROSOFT_CLIENT_SECRET.

  3. 3 · Open API permissions

    Left sidebar → API permissions+ Add a permissionMicrosoft GraphDelegated permissions.

  4. 4 · Add the five required permissions

    Use the search box at the top of the permission picker — they're in DIFFERENT sections of the alphabetized list. Scrolling will miss them.

PermissionSectionPurpose
Mail.ReadMailRead messages for triage
Mail.ReadWriteMailApply labels, archive, modify (superset of Read; can use alone instead of also-Read)
Mail.SendMailSend mail
offline_accessOpenId permissionsREQUIRED — refresh tokens; without this, tokens expire in 1 hour
User.ReadUserIdentify connected account (the plain one, NOT User.Read.All or other variants)
Anti-pattern surfaced during walkthrough. The permission picker defaults to showing Mail.* by alphabetical scroll position. offline_access and User.Read live in other sections — easy to miss. Always use the search box at the top, not the scroll view.
  1. 5 · Add permissions

    Click Add permissions.

  2. 6 · (Optional) Grant admin consent

    Click Grant admin consent for <tenant> — only applies to deployer's own tenant; external users consent themselves on first OAuth.

Chunk C · Redirect URIs

  1. 1 · Open Authentication

    Left sidebar → Authentication (or "Authentication (Preview)").

  2. 2 · Add a Web platform

    + Add a platformWeb (if no Web platform already exists).

  3. 3 · Add redirect URIs

    Add one at a time:

    https://<your-mailsloth-domain>/api/v1/mailsloth/oauth/complete
    http://localhost:3010/api/v1/mailsloth/oauth/complete
  4. 4 · Implicit grant + hybrid flows

    Leave both unchecked. MailSloth uses authorization-code flow with PKCE.

  5. 5 · Front-channel logout URL

    Leave empty.

  6. 6 · Save / Configure
Path differs from Google. Microsoft's mailsloth-server callback is /oauth/complete (provider-agnostic). Google's specific callback is /oauth/google/callback (provider-specific). Server-side routing detail you don't need to think about as long as you use the URIs documented per provider above.

These map to:

Env varSource
MICROSOFT_CLIENT_IDApplication (client) ID GUID from the Overview page
MICROSOFT_CLIENT_SECRETThe Value column of the secret you created in Chunk B
04
Apply to deployed mailsloth-server
/opt/aimanac/mailsloth.env + container recreate

mailsloth-server reads OAuth credentials from environment variables at process start. Customer path: run the pulled image from /apps/mailsloth/setup/deploy/ (docker compose pull, not docker compose build). Persist secrets in mailsloth.env and recreate the container — same hygiene as below.

Setup (one-time per deployer)

  1. 1 · SSH into the deployed mailsloth-server host.
  2. 2 · Create or extend /opt/aimanac/mailsloth.env with the four OAuth values:
    GOOGLE_CLIENT_ID=<your Google client ID>.apps.googleusercontent.com
    GOOGLE_CLIENT_SECRET=GOCSPX-<your Google secret>
    MICROSOFT_CLIENT_ID=<your Microsoft client GUID>
    MICROSOFT_CLIENT_SECRET=<your Microsoft secret>
  3. 3 · Lock the file
    chmod 600 /opt/aimanac/mailsloth.env
  4. 4 · Recreate with compose (preferred) or docker run --env-file

    After editing mailsloth.env, pull the pinned tag and recreate — do not rebuild on the host:

    export MS_IMAGE_TAG=rust-cutover-20260520-ghcr-pipeline
    cd /opt/aimanac   # or your DEPLOY_DIR from the deploy page
    docker compose pull
    docker compose up -d --force-recreate mailsloth-server

    Single-container alternative (maintainer fleet):

    IMAGE=ghcr.io/everplay-tech/mailsloth-server:${MS_IMAGE_TAG}
    docker pull "$IMAGE"
    docker stop mailsloth-magus-rs && docker rm mailsloth-magus-rs
    docker run -d --name mailsloth-magus-rs --restart unless-stopped \
      --network fleet_default -p 127.0.0.1:3010:3010 \
      --env-file /opt/aimanac/mailsloth.env "$IMAGE"

    Substitute your own container name (mailsloth-magus-rs is the maintainer's; yours will mirror your deploy convention).

  5. 5 · Verify
    docker exec mailsloth-magus-rs printenv \
      | grep -E "^(GOOGLE|MICROSOFT)_CLIENT" \
      | awk -F= '{print $1"=<set>"}'
    docker logs --tail 10 mailsloth-magus-rs
    # Expect: "listening on 0.0.0.0:3010" + scheduler/queue_drain/imap_poll workers spawned

Rollback

The old container is preserved as mailsloth-magus-rs-prev-<TS>. If the new container fails to boot:

docker stop mailsloth-magus-rs
docker rm mailsloth-magus-rs
docker rename mailsloth-magus-rs-prev-<TS> mailsloth-magus-rs
docker start mailsloth-magus-rs

Why --env-file and not docker run -e

Persistence

Survives redeploys — push-deploy scripts capture --env-file from the current container's launch config.

Secret hygiene

Values never appear in ps output or shell history. docker run -e GOOGLE_CLIENT_SECRET=… writes the secret to both.

Filesystem ACL

chmod 600 limits read to root + container runtime. No other user / process gets the file.

Atomic update

Single file = single edit when adding a new env var (e.g. when a third provider like ProtonMail lands later).

05
Anti-patterns · What NOT to do
Eight gaps named explicitly (O1–O8)

Each item below corresponds to a customer-doc gap the maintainer hit on 2026-05-19. Show this list to your AI assistant if it tries to suggest any of these — they all look like the assistant is being helpful, and they all cost you something later.

  1. NO

    O1 — Skipping the Gmail API enable step

    Until you click Enable on console.cloud.google.com/apis/library/gmail.googleapis.com?project=<project>, the scope picker won't surface Gmail scopes at all. No error — just an empty list and a confused operator.

  2. NO

    O2 — Typing an arbitrary "User support email"

    Google restricts the User support email field to your current-account email OR a Workspace-managed group you own. You cannot type support@your-domain.com unless it's tied to a Workspace group. Use the deployer's actual Gmail.

  3. NO

    O3 — Granting https://mail.google.com/ or gmail.addons.*

    The full-mailbox scope (delete-all included) is massive overreach. gmail.addons.* is for Gmail browser extensions, not backend servers. Both balloon your CASA-audit exposure for production verification. Use the six-scope canonical set in Chunk C.

  4. NO

    O4 — Missing offline_access on Microsoft

    The Microsoft permission picker shows Mail.* by default scroll position; offline_access lives in the OpenId permissions section. Miss it and your tokens expire in 1 hour with no refresh-token path. Use the search box at the top, don't scroll. Same trap for User.Read (in User section).

  5. NO

    O5 — Granting User.Read.All or User.ReadWrite.All

    You only need plain User.Read — identifying the one account that just connected. The .All variants are tenant-wide admin reads; consent goes through admin-grant rails and lights up red flags. Plus Supported account types on the app registration MUST be multitenant + personal — otherwise non-tenant Outlook / Hotmail users can't connect at all.

  6. NO

    O6 — Using docker run -e GOOGLE_CLIENT_SECRET=…

    Secrets on the command line land in ps output, shell history, and the docker daemon's audit log. Use --env-file /opt/aimanac/mailsloth.env instead. The push-deploy pattern preserves this on redeploy; -e doesn't.

  7. NO

    O7 — Skipping chmod 600 on the env file

    An env file with default permissions (often 644) is world-readable on a shared host. Any process on the box can cat your OAuth secrets. chmod 600 after every write.

  8. NO

    O8 — Pasting secrets into Slack / committing them / leaving downloads

    Secrets sent to chat or committed to git enter audit trails you can't easily redact. Move the Google JSON + Microsoft secret out of ~/Downloads/ into a chmod-700 directory like ~/Documents/aimanac-secrets/, chmod 600 the files, and never paste the values into a chat. Treat them like a database password.

Bonus operational note (O8 continued). The Microsoft secret is also subject to a 24-month expiry; Google secrets have an implicit indefinite lifetime. Rotate periodically — document the rotation in your customer-recovery runbook so the next deploy of mailsloth-server picks up the new values via the same /opt/aimanac/mailsloth.env path.
06
See also
Related setup paths