# Email Briefing — setup guide The Companion can greet students with a spoken summary of their recent school email ("Hi Denis, Ms. Uwase sent the Entrepreneurship assignment due Friday…"). Students opt in from **Settings → Email Briefing**, choose what the briefing should mention, and the chat page reads it aloud when they arrive. Code map: | Piece | File | |---|---| | Backend routes (`/api/email/*`) | `backend_hf/email_briefing.py` | | Router mount | `backend_hf/app.py` | | Frontend API client | `frontend/src/services/emailBriefingService.ts` | | Settings card | `frontend/src/components/settings/EmailBriefingSettings.tsx` | | Chat greeting banner + voice | `frontend/src/components/chat/EmailBriefingGreeting.tsx` | | Browser text-to-speech helper | `frontend/src/utils/speech.ts` | ## 1. Create the Google OAuth client (one-time, admin) ALU student email runs on Google Workspace, so this uses the Gmail API. 1. Go to https://console.cloud.google.com/ and create (or reuse) a project, e.g. `alu-student-companion`. 2. **APIs & Services → Library** → enable **Gmail API**. 3. **APIs & Services → OAuth consent screen**: - User type: **Internal** if the project lives in the `alustudent.com` / `alueducation.com` Workspace (best — no Google verification needed and only school accounts can connect). Otherwise **External** + add test users while developing. - Scopes: add `.../auth/gmail.readonly` (read-only; we never send or delete mail). 4. **APIs & Services → Credentials → Create credentials → OAuth client ID**: - Application type: **Web application** - Authorized redirect URI: `https://studentcompanion-alu-chatbot.hf.space/api/email/oauth/callback` (and `http://localhost:8080/api/email/oauth/callback` for local dev) 5. Copy the **Client ID** and **Client secret**. ## 2. Configure the backend (HF Space secrets) | Secret | Required | Value | |---|---|---| | `GOOGLE_OAUTH_CLIENT_ID` | yes | from step 1 | | `GOOGLE_OAUTH_CLIENT_SECRET` | yes | from step 1 | | `BACKEND_PUBLIC_URL` | no | defaults to `https://studentcompanion-alu-chatbot.hf.space` | | `FRONTEND_URL` | no | defaults to `https://alustudentcompanion.vercel.app` | | `EMAIL_TOKEN_KEY` | recommended | Fernet key so Gmail refresh tokens are encrypted at rest. Generate with `python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"` | Storage: when the Aurora data layer is configured (`DB_HOST` etc., see `db.py`), tokens and preferences live in the `email_accounts` table (created automatically). Without a database they're kept in process memory — fine for local testing, lost on restart. ## 3. How it works 1. `POST /api/email/connect` (Firebase-authed) returns a Google consent URL. The student's identity is baked into a signed, 10-minute `state` value. 2. Google redirects to `GET /api/email/oauth/callback`; the backend exchanges the code for a **refresh token**, checks the Google account matches the student's ALU login email, stores it, and redirects back to `/settings?email_briefing=connected`. 3. `GET /api/email/briefing` mints a short-lived access token, pulls recent inbox messages (subject/sender/snippet only), and asks the LLM chain (Claude → NVIDIA → Groq — same as chat) to write a ≤120-word spoken greeting honoring the student's category filters. Briefings are cached for 10 minutes per student. 4. The frontend shows the text in a banner and reads it aloud with the browser's built-in speech synthesis. Browsers block audio before the first user interaction with a page, so on a cold reload the banner shows a play button instead of speaking automatically. ## 4. Endpoints | Route | Auth | Purpose | |---|---|---| | `GET /api/email/status` | Firebase | configured? connected? current prefs | | `POST /api/email/connect` | Firebase | returns Google consent URL | | `GET /api/email/oauth/callback` | signed state | Google redirect target | | `PUT /api/email/preferences` | Firebase | save category/voice prefs | | `GET /api/email/briefing?refresh=` | Firebase | the generated briefing | | `POST /api/email/disconnect` | Firebase | delete + revoke the grant | ## 5. Privacy notes - Scope is **read-only** (`gmail.readonly`); the app cannot send, modify or delete mail. - Only message *metadata + snippet* (sender, subject, first ~200 chars) is read — never full bodies or attachments. - Nothing from the inbox is persisted; only the refresh token and the student's preferences are stored, and disconnecting revokes the grant at Google.