ReasonFlow connects to Gmail via OAuth2 to fetch, classify, and respond to emails automatically.
User clicks "Connect Gmail"
→ GET /auth/gmail/url → redirect to Google consent screen
→ User grants permissions
→ Google redirects to /auth/gmail/callback with code
→ Backend exchanges code for access + refresh tokens
→ Tokens encrypted and stored in users table
https://www.googleapis.com/auth/gmail.readonly— Read emailshttps://www.googleapis.com/auth/gmail.send— Send emailshttps://www.googleapis.com/auth/gmail.compose— Create drafts
class GmailClient:
async def fetch_emails(max_results=50) -> list[dict]
async def get_email(gmail_id: str) -> dict
async def send_email(to: str, subject: str, body: str) -> str
async def create_draft(to: str, subject: str, body: str) -> strAll calls use httpx.AsyncClient with the Google Gmail REST API v1.
- Access tokens: short-lived (~1 hour), auto-refreshed on expiry
- Refresh tokens: stored encrypted (Fernet symmetric encryption)
- Token refresh: automatic via
refresh_token()before API calls
GET /emails/sync triggers:
- Fetch latest emails from Gmail API
- Deduplicate by
gmail_id - Store new emails in database with
status=pending - Return count of new emails
- OAuth tokens encrypted at rest using
cryptography.fernet - Client secret stored only in environment variables
- Redirect URI validated against configured value
- Token auto-revocation on user disconnect