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.
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.
Pre-flight
- Google account. The deployer's, not the end user's. Free tier is fine.
- Project in Google Cloud Console. Reasonable name:
mailslothor<your-domain>-mailsloth. - 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 · Open the consent screen
Console search bar →
OAuth consent screen→ open. - 2 · User Type
Select External.
- 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 · Save and continue.
Chunk B · Audience / Test users
While your app is in Testing publishing status:
- 1 · Add test users
The deployer's own Gmail address, plus any other emails to test with. Max ~100.
Chunk C · Data Access / Scopes
The MailSloth-canonical minimal scope set is six scopes:
| Scope | Tier |
|---|---|
https://www.googleapis.com/auth/userinfo.email | Non-sensitive |
https://www.googleapis.com/auth/userinfo.profile | Non-sensitive |
openid | Non-sensitive |
https://www.googleapis.com/auth/gmail.send | Sensitive |
https://www.googleapis.com/auth/gmail.readonly | Restricted |
https://www.googleapis.com/auth/gmail.modify | Restricted |
https://mail.google.com/— full mailbox access including delete-all. Massive overreach for MailSloth.gmail.compose— duplicative withsend+modify.gmail.metadata— subset ofgmail.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.
Chunk D · Create OAuth Client
- 1 · Open Clients
Left sidebar → Clients → + Create client.
- 2 · Application type
Web application.
- 3 · Name
MailSloth backend. - 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 · Create
Modal pops with Client ID (
.apps.googleusercontent.comsuffix) + Client secret (GOCSPX-prefix). Both shown together. Download the JSON or copy both values.
These map to:
| Env var | Source |
|---|---|
GOOGLE_CLIENT_ID | The *.apps.googleusercontent.com string |
GOOGLE_CLIENT_SECRET | The GOCSPX-… string |
Pre-flight
- Microsoft account. The deployer's; Hotmail, Live, or any Microsoft account works.
- Sign in to Microsoft Entra admin center at
https://entra.microsoft.com(cleaner than the classic Azure portal). - Verify you have a tenant. If not, sign-up creates one (
<random>.onmicrosoft.com).
Chunk A · App Registration
- 1 · New registration
Left sidebar → Entra ID → App registrations → + New registration.
- 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 · 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 · Create the secret
Left sidebar → Certificates & secrets → + New client secret.
Description:mailsloth-prod. Expires: 24 months. Add. - 2 · Copy the Value
Copy the Value column of the new secret immediately. ⚠ Only shown once. That's
MICROSOFT_CLIENT_SECRET. - 3 · Open API permissions
Left sidebar → API permissions → + Add a permission → Microsoft Graph → Delegated permissions.
- 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.
| Permission | Section | Purpose |
|---|---|---|
Mail.Read | Read messages for triage | |
Mail.ReadWrite | Apply labels, archive, modify (superset of Read; can use alone instead of also-Read) | |
Mail.Send | Send mail | |
offline_access | OpenId permissions | REQUIRED — refresh tokens; without this, tokens expire in 1 hour |
User.Read | User | Identify connected account (the plain one, NOT User.Read.All or other variants) |
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.
- 5 · Add permissions
Click Add permissions.
- 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 · Open Authentication
Left sidebar → Authentication (or "Authentication (Preview)").
- 2 · Add a Web platform
+ Add a platform → Web (if no Web platform already exists).
- 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 · Implicit grant + hybrid flows
Leave both unchecked. MailSloth uses authorization-code flow with PKCE.
- 5 · Front-channel logout URL
Leave empty.
- 6 · Save / Configure
/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 var | Source |
|---|---|
MICROSOFT_CLIENT_ID | Application (client) ID GUID from the Overview page |
MICROSOFT_CLIENT_SECRET | The Value column of the secret you created in Chunk B |
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 · SSH into the deployed mailsloth-server host.
- 2 · Create or extend
/opt/aimanac/mailsloth.envwith 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 · Lock the file
chmod 600 /opt/aimanac/mailsloth.env
- 4 · Recreate with compose (preferred) or
docker run --env-fileAfter 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-rsis the maintainer's; yours will mirror your deploy convention). - 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).
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.
-
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. -
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.comunless it's tied to a Workspace group. Use the deployer's actual Gmail. -
NO
O3 — Granting
https://mail.google.com/orgmail.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. -
NO
O4 — Missing
offline_accesson MicrosoftThe Microsoft permission picker shows
Mail.*by default scroll position;offline_accesslives 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 forUser.Read(in User section). -
NO
O5 — Granting
User.Read.AllorUser.ReadWrite.AllYou only need plain
User.Read— identifying the one account that just connected. The.Allvariants 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. -
NO
O6 — Using
docker run -e GOOGLE_CLIENT_SECRET=…Secrets on the command line land in
psoutput, shell history, and the docker daemon's audit log. Use--env-file /opt/aimanac/mailsloth.envinstead. The push-deploy pattern preserves this on redeploy;-edoesn't. -
NO
O7 — Skipping
chmod 600on the env fileAn env file with default permissions (often 644) is world-readable on a shared host. Any process on the box can
catyour OAuth secrets.chmod 600after every write. -
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.
/opt/aimanac/mailsloth.env path.
- MailSloth manualApp overview, why server, what MailSloth does, identity + versions.
- Self-deploy specLLM-readable AiMANAC backend setup — paste into Claude / ChatGPT for the full backend walkthrough.
- Why backend mattersThe architectural posture — why running your own server is the whole point.
- BROILR · Railway deployCompanion per-sibling deploy page — Railway path, env vars, /ready gate.