Email Integration for Aitana Assistants
This document describes the email integration system that allows users to interact with Aitana assistants via email.
Overview
The email integration enables users to:
- Send emails to specific assistants using structured email addresses
- Receive AI-generated responses back via email
- Use existing permission and rate limiting systems
- Have conversations logged for tracking and auditing
Architecture
Components
- Frontend Webhook Proxy (
src/app/api/email/webhook/route.ts) - Backend Email Processing (
backend/email_integration.py) - Mailgun Signature Validation (Frontend)
- User Permission System (Frontend integration)
- Rate Limiting & AI Processing (Backend)
Email Flow
User Email → Mailgun → Frontend Webhook → Permission Check → Backend API → AI Processing → Email Response
New Architecture Benefits:
- Security: Mailgun webhooks can reach unauthenticated endpoint
- Validation: User permissions checked using existing frontend system
- Authentication: Backend stays protected behind OAuth2
Shared Processing Architecture
The email integration leverages a centralized assistant processing system to ensure consistency across all channels:
Core Components
process_assistant_request()inassistant_utils.py: Centralized processing functioncreate_emissary_config(): Consistent emissaryConfig creation- Unified chat history management: Automatic reading/saving with configurable options
- Standard configuration handling: Same assistant config, tools, and permissions
Benefits
- Consistency: Email behavior matches API behavior exactly
- Maintainability: Single source of truth for assistant processing logic
- Future-proof: New integrations (Twilio, etc.) can use the same functions
- Configuration completeness: Includes
initialInstructions, user details, tool configs, etc.
Integration Pattern
# All integrations use this pattern:
result = await process_assistant_request(
assistant_id=assistant_id,
user_input=message,
current_user=user_info,
documents=attachments,
save_to_history=True,
read_from_history=True
)
Setup and Configuration
1. Mailgun Configuration
Frontend Environment Variables:
For local development (.env.local):
MAILGUN_WEBHOOK_SECRET=webhook_signing_key_from_mailgun
NEXT_PUBLIC_BACKEND_URL=https://your-backend.com
For production deployment, these variables must be added to GCP Secret Manager:
- Download current secrets:
gcloud secrets versions access latest --secret=FIREBASE_ENV --project YOUR_PROJECT_ID > .env.local - Add the new variables to
.env.local - Upload back to Secret Manager:
gcloud secrets versions add FIREBASE_ENV --data-file=.env.local --project YOUR_PROJECT_ID
The get-firebase-config.sh script automatically downloads these during Cloud Build deployment.
Backend Environment Variables (Cloud Run):
MAILGUN_API_KEY=your_mailgun_api_key
MAILGUN_DOMAIN=yourdomain.com
MAILGUN_ENDPOINT=https://api.eu.mailgun.net # Optional: EU endpoint (default: https://api.eu.mailgun.net)
NEXT_PUBLIC_FRONTEND_URL=https://ai.aitana.chat # Production: https://ai.aitana.chat, Test: https://ai2.aitana.chat
Mailgun Setup Steps:
- Create a Mailgun account and verify your domain
- Configure DNS records for your domain
- Set up webhook URL:
https://your-frontend.com/api/email/webhook - Configure webhook events:
delivered(required for email processing) - Enable webhook signing for security
- Copy webhook signing key to
MAILGUN_WEBHOOK_SECRET - Configure email routing (see Mailgun Route Configuration section below)
2. Email Address Format
Users send emails to assistants using this format:
[env-]assistant-{assistantId}@email.aitana.chat
Examples:
assistant-123@email.aitana.chat→ Routes to assistant with ID “123” (production)dev-assistant-123@email.aitana.chat→ Routes to assistant with ID “123” (development)test-assistant-123@email.aitana.chat→ Routes to assistant with ID “123” (testing)assistant-gpt-helper@email.aitana.chat→ Routes to assistant with ID “gpt-helper” (production)
2.1 Special Assistant List Feature
Users can get a list of available assistants by emailing the special “list” assistant:
List Request Format:
[env-]assistant-list@email.aitana.chat
Examples:
assistant-list@email.aitana.chat→ Get list of assistants in productiondev-assistant-list@email.aitana.chat→ Get list of assistants in developmenttest-assistant-list@email.aitana.chat→ Get list of assistants in testing
Features:
- Returns only assistants the user has access to (respects access control)
- Includes email addresses and web URLs for each assistant
- Shows assistant names, descriptions, and avatars
- Provides usage instructions and tips
- Bypasses rate limiting (lightweight operation)
- Automatically detects environment for correct email formatting
Technical Implementation:
- Frontend validation specifically allows “list” as a valid assistant ID (despite being shorter than the usual 10-character minimum)
- Backend processing handles “list” as a special case to generate assistant directory responses
- Rate limiting is bypassed for list requests since they are lightweight operations
3. Mailgun Route Configuration
Important: After setting up your Mailgun domain and webhook, you must configure email routing to forward assistant emails to your webhook endpoint.
3.1 Create a Route in Mailgun Dashboard
Navigate to Mailgun Dashboard > Routes and create the following routes (in order of priority):
Production Route (Priority: 10)
Route Filter:
match_recipient("^assistant-(.*)@email\.aitana\.chat$")
Route Actions:
forward("https://ai.aitana.chat/api/email/webhook")
stop()
Development Route (Priority: 11)
Route Filter:
match_recipient("^dev-assistant-(.*)@email\.aitana\.chat$")
Route Actions:
forward("https://frontend-556246783252.europe-west1.run.app/api/email/webhook")
stop()
Test Route (Priority: 12)
Route Filter:
match_recipient("^test-assistant-(.*)@email\.aitana\.chat$")
Route Actions:
forward("https://ai2.aitana.chat/api/email/webhook")
stop()
3.2 Route Configuration Explanation
Environment-Specific Routing:
Production Pattern: ^assistant-(.*)@email\.aitana\.chat$
^- Start of stringassistant-- Literal text “assistant-“ (no environment prefix)(.*)- Capture group for assistant ID (any characters)@email\.aitana\.chat- The email domain (escape the dots)$- End of string
Development Pattern: ^dev-assistant-(.*)@email\.aitana\.chat$
dev-- Environment prefix for developmentassistant-- Literal text “assistant-“(.*)- Capture group for assistant ID
Test Pattern: ^test-assistant-(.*)@email\.aitana\.chat$
test-- Environment prefix for testingassistant-- Literal text “assistant-“(.*)- Capture group for assistant ID
Actions:
forward()- Sends email data to environment-specific webhook endpointstop()- Prevents further route processing
Route Priority: Lower numbers = higher priority. Development and test routes have higher priority numbers so production route doesn’t accidentally catch prefixed emails.
3.3 Advanced Route Examples
Combined environment routing (single route for all environments):
Filter: match_recipient("^(dev-|test-)?assistant-(.*)@email\.aitana\.chat$")
Action: forward("https://ai.aitana.chat/api/email/webhook")
Note: This approach requires backend logic to handle environment detection
Route with captured environment and assistant ID:
Filter: match_recipient("^(?P<env>dev-|test-)?assistant-(?P<assistant_id>.*)@email\.aitana\.chat$")
Action: forward("https://ai.aitana.chat/api/email/webhook?env=\g<env>&aid=\g<assistant_id>")
Multiple domain support with environments:
Filter: match_recipient("^(dev-|test-)?assistant-(.*)@(email\.aitana\.chat|email\.aitana\.ai)$")
Action: forward("https://ai.aitana.chat/api/email/webhook")
Staging environment route:
Filter: match_recipient("^staging-assistant-(.*)@email\.aitana\.chat$")
Action: forward("https://ai2.aitana.chat/api/email/webhook")
3.4 Route Priority and Ordering
- Routes are processed in priority order (lower number = higher priority)
- Set assistant route priority to 10 to ensure it processes before catch-all routes
- Always include
stop()action to prevent emails from being processed by subsequent routes
3.5 Testing Your Route
Test via Mailgun Dashboard:
- Go to Mailgun Dashboard > Routes
- Find your route and click Test
- Enter test emails:
- Production:
assistant-test123@email.aitana.chat - Development:
dev-assistant-test123@email.aitana.chat - Testing:
test-assistant-test123@email.aitana.chat
- Production:
- Verify it matches your route pattern
Test via email:
# Test production
echo "Test message" | mail -s "Test Subject" assistant-test123@email.aitana.chat
# Test development
echo "Test dev message" | mail -s "Test Dev Subject" dev-assistant-test123@email.aitana.chat
# Test testing environment
echo "Test message" | mail -s "Test Subject" test-assistant-test123@email.aitana.chat
4. DNS Configuration
Configure MX records to point to Mailgun:
MX 10 mxa.mailgun.org
MX 10 mxb.mailgun.org
Security Features
1. Rate Limiting
- Limit: 1 email per minute per user email address
- Storage: Rate limits stored in Firestore
email_rate_limitscollection - Behavior: Returns 429 status with wait time if limit exceeded
- Special Exception: Assistant list requests (
assistant-list@email.aitana.chat) bypass rate limiting as they are lightweight operations
2. Webhook Validation
- HMAC Signature Verification: Validates incoming webhooks using Mailgun’s signing key
- IP Validation: Only accepts webhooks from Mailgun’s IP ranges
- Timestamp Checking: Prevents replay attacks
3. Permission System Integration
- Existing Permissions: Uses the same permission system as web interface
- Email-based Access: Validates user access based on sender email address
- Tool Filtering: Only allows tools that the user has permission to use
4. Input Validation
- Email Format Validation: Ensures sender email is properly formatted
- Content Cleaning: Removes email signatures, headers, and quoted content
- Assistant ID Extraction: Validates assistant exists before processing
API Endpoints
Frontend Webhook Proxy
POST /api/email/webhook
Purpose: Receives incoming emails from Mailgun, validates permissions, forwards to backend
Request Format (from Mailgun):
{
"timestamp": "1234567890",
"token": "webhook_token",
"signature": "hmac_signature",
"sender": "user@example.com",
"recipient": "assistant-123@yourdomain.com",
"cc": "colleague1@example.com, colleague2@example.com",
"subject": "My question",
"body-plain": "Email content here..."
}
Processing Flow:
- Validate Mailgun signature using
MAILGUN_WEBHOOK_SECRET - Extract assistant ID from recipient email format
- Parse CC recipients from webhook payload
- Check user permissions using existing access control system
- Forward to backend with authentication headers and CC information if authorized
Response:
{
"status": "processed",
"assistant_id": "123",
"sender": "user@example.com",
"response": "AI generated response",
"email_sent": true,
"message": "Email processed and response sent"
}
Error Responses:
401: Invalid webhook signature400: Invalid email format or missing assistant403: Access denied (insufficient permissions)500: Internal server error
GET /api/email/webhook
Purpose: Health check for frontend webhook system
Response:
{
"status": "healthy",
"timestamp": "2025-06-13T12:00:00Z",
"webhook_secret_configured": true,
"backend_url": "https://your-backend.com"
}
Backend Processing
POST /api/email/webhook (Backend)
Purpose: Processes validated email requests from frontend proxy
Headers (from frontend):
X-Validated-User: user@example.com
X-Assistant-ID: 123
X-Request-ID: req_abc123
Request Body:
timestamp=1234567890&token=webhook_token&signature=hmac_signature&sender=user@example.com&recipient=assistant-123@yourdomain.com&subject=My+question&body-plain=Email+content&validated=true
GET /api/email/status (Backend)
Purpose: Health check for backend email processing system
Response:
{
"status": "healthy",
"timestamp": "2025-06-13T12:00:00Z",
"webhook_secret_configured": true
}
Email Content Processing
Content Cleaning
The system automatically removes:
- Email headers (
From:,To:,Date:, etc.) - Common signatures (
Sent from my iPhone,--,___) - Quoted content (lines starting with
>) - Unsubscribe links and marketing content
CC Recipient Handling
The email integration fully supports CC’d recipients on incoming emails:
Automatic CC Detection
- Mailgun provides CC recipient information in the
ccfield of webhook payloads - The system automatically parses CC recipients from comma-separated strings
- Supports both simple email formats (
user@example.com) and display name formats (John Doe <user@example.com>)
Reply-All Functionality
When an assistant responds to an email with CC recipients:
- Original sender receives the response as the primary recipient (
tofield) - All CC recipients are automatically included in the reply (
ccfield) - This maintains email thread continuity for team conversations
CC Parsing Examples
# Simple CC list
cc = "user1@example.com, user2@example.com"
# With display names
cc = "John Doe <john@example.com>, Jane Smith <jane@example.com>"
# Mixed formats
cc = "john@example.com, Jane Smith <jane@example.com>"
Email Thread Example
Original Email:
- To:
assistant-123@email.aitana.chat - CC:
colleague1@company.com, colleague2@company.com - From:
sender@company.com
Assistant Reply:
- To:
sender@company.com - CC:
colleague1@company.com, colleague2@company.com - From:
assistant-123@email.aitana.chat
This ensures all team members stay in the loop when collaborating with AI assistants via email.
BCC Limitations
- BCC recipients are not supported - this is a fundamental email privacy feature
- BCC information is never visible in received emails (applies to all email systems)
- The system only handles visible recipients (To and CC fields)
Message Format
Emails are formatted for the AI assistant as:
Email Subject: [Original Subject]
[Cleaned email content]
Data Storage
Firestore Collections
email_rate_limits/{userEmail}{ "last_email_time": "2025-06-06T12:00:00Z", "total_emails": 5 }email_interactions/{documentId}{ "sender_email": "user@example.com", "assistant_id": "123", "subject": "My question", "content": "Email content", "ai_response": "AI response", "timestamp": "2025-06-06T12:00:00Z", "processed": true }
Usage Examples
Basic Email Interaction
User sends email to: assistant-123@email.aitana.chat (production)
Subject: Help with my project
Hi Aitana,
I need help with setting up a new React component.
Can you provide some guidance on best practices?
Thanks!
John
AI Response sent back to user:
Subject: Re: Help with my project
Hello,
Thank you for your email. Here's the response from the Aitana assistant:
To create a new React component following best practices, here are the key steps:
1. Use functional components with hooks
2. Follow proper naming conventions (PascalCase)
3. Implement proper prop validation with TypeScript
4. Use composition over inheritance
5. Keep components small and focused
[Detailed explanation continues...]
---
This response was generated by an AI assistant. If you have any questions or need further assistance, please reply to this email.
Best regards,
Aitana Team
Assistant List Request
User sends email to: assistant-list@email.aitana.chat
Subject: What assistants are available?
Hi,
Can you send me a list of assistants I can interact with via email?
Thanks!
Sarah
AI Response with assistant list:
Subject: Re: What assistants are available?
# Your Available Assistants (3 found)
Here are the assistants you can access:
## ✦ Data Analyst
*I help analyze data and create insights from your datasets*
**✉ Email:** assistant-data-analyst@email.aitana.chat
**⌐ Web:** https://ai.aitana.chat/assistant/data-analyst
---
## ✦ Code Helper
*I assist with programming questions and code reviews*
**✉ Email:** assistant-code-helper@email.aitana.chat
**⌐ Web:** https://ai.aitana.chat/assistant/code-helper
---
## ✦ Marketing Assistant
*I help create marketing content and strategies*
**✉ Email:** assistant-marketing@email.aitana.chat
**⌐ Web:** https://ai.aitana.chat/assistant/marketing
---
## How to Use
**Via Email:** Send your questions directly to any assistant's email address above.
**Via Web:** Click the web links to use the full interface with file uploads and interactive features.
**Tips:**
- Add `(export:pdf)` or `(export:docx)` to your email subject to receive formatted documents
- You can CC others in your emails - they'll see the response even if they don't have access
**Need the list again?** Email: `assistant-list@email.aitana.chat`
---
Assistant Directory
AI Assistant
Continue this conversation: https://ai.aitana.chat/assistant/list
You can also reply directly to this email to continue our conversation.
Tip: Add (export:pdf) or (export:docx) to your email subject to receive formatted documents
### Team Collaboration with CC
**User sends email with CC recipients:**
To: assistant-data-analyst@email.aitana.chat CC: colleague1@company.com, colleague2@company.com Subject: Q3 Sales Analysis Request
Hi Data Analyst,
Can you help analyze our Q3 sales data and identify key trends? The team would like to understand regional performance differences.
Thanks, Sarah
**AI Response sent to all recipients:**
To: sarah@company.com CC: colleague1@company.com, colleague2@company.com Subject: Re: Q3 Sales Analysis Request
Hello Sarah,
Thank you for your email. Here’s the Q3 sales analysis you requested:
Key Findings:
- Regional Performance: West Coast showed 23% growth vs 8% for East Coast
- Product Categories: SaaS products outperformed hardware by 34%
- Seasonal Trends: September spike of 41% attributed to back-to-school campaigns
Detailed Analysis:
[Analysis continues…]
All team members can continue this conversation by replying to this email.
This response was generated by an AI assistant.
Best regards, Data Analyst Assistant
**Benefits of CC Support:**
- ✅ **Team continuity** - All colleagues stay informed of AI insights
- ✅ **Collaborative decisions** - Team can build on AI analysis together
- ✅ **Email thread integrity** - Natural email workflow maintained
- ✅ **Knowledge sharing** - AI responses visible to entire team
### Environment-Specific Examples
#### Development Environment Testing
**User sends email to**: `dev-assistant-123@email.aitana.chat`
Subject: Testing new feature
Hi Aitana,
I’m testing the new document analysis feature. Can you help me analyze this report?
Thanks! Developer
**AI Response sent back** (from frontend-556246783252.europe-west1.run.app):
Subject: Re: Testing new feature
Hello,
Thank you for your email. Here’s the response from the Aitana assistant (Development Environment):
I’d be happy to help you test the document analysis feature! To analyze your report, I’ll need you to…
[Development-specific response with debug information]
Continue this conversation: https://frontend-556246783252.europe-west1.run.app/assistant/123
This response was generated by an AI assistant in the DEVELOPMENT environment.
#### Test Environment Example
**User sends email to**: `test-assistant-qa-bot@email.aitana.chat`
Subject: QA Test - Bug Report Analysis
Testing the bug report analysis workflow for QA purposes.
Test case: #QA-001 Expected behavior: Parse bug report and suggest fixes
**AI Response** (from ai2.aitana.chat):
Subject: Re: QA Test - Bug Report Analysis
Hello,
Thank you for your email. Here’s the response from the Aitana assistant (Test Environment):
Test case #QA-001 processed successfully. The bug report analysis indicates…
[Test-specific response with QA markers]
Continue this conversation: https://ai2.aitana.chat/assistant/qa-bot
This response was generated by an AI assistant in the TEST environment.
## Error Handling
### Common Error Scenarios
1. **Invalid Assistant ID**
- Production: `assistant-nonexistent@email.aitana.chat` → "Assistant nonexistent not found"
- Development: `dev-assistant-nonexistent@email.aitana.chat` → "Assistant nonexistent not found"
- Testing: `test-assistant-nonexistent@email.aitana.chat` → "Assistant nonexistent not found"
2. **Rate Limiting**
- User sends multiple emails within 1 minute
- Response: "Rate limit exceeded. Please wait 45 seconds."
3. **Permission Denied**
- User email not in allowed domains/users
- Response: "Access denied - insufficient permissions"
4. **Invalid Email Format**
- Email doesn't match `assistant-{id}@domain` pattern
- Response: "Invalid recipient format"
## Monitoring and Logging
### Logs Generated
- Email reception and processing attempts
- Rate limiting violations
- Permission check results
- AI response generation
- Email sending status
### Metrics to Monitor
- Email processing success rate
- Average response time
- Rate limiting triggers
- Permission denials
- Email delivery failures
## Testing
### Unit Tests
**Backend tests**:
```bash
cd backend
python -m pytest tests/test_email_integration.py -v
Frontend tests (if available):
npm test src/app/api/email/webhook/
Manual Testing
- Test frontend webhook endpoint:
curl -X POST https://your-frontend.com/api/email/webhook \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "timestamp=1234567890&token=test&signature=test&sender=test@example.com&recipient=assistant-123@yourdomain.com&subject=Test&body-plain=Test message" - Test frontend health check:
curl https://your-frontend.com/api/email/webhook - Test backend status (via proxy):
curl -X POST https://your-frontend.com/api/proxy \ -H "Content-Type: application/json" \ -d '{"endpoint": "/api/email/status", "method": "GET"}'
Integration Testing
With Mailgun:
- Use Mailgun’s webhook testing tools in their dashboard
- Send test emails to
assistant-{id}@yourdomain.com - Monitor logs in both frontend (Vercel/Cloud Run) and backend (Cloud Run)
Permission Testing:
- Test with authorized user emails
- Test with unauthorized user emails
- Test with different assistant access control settings
- Verify rate limiting behavior
Deployment Considerations
Frontend Deployment (Cloud Run)
Environment Variables (managed via GCP Secret Manager):
Add to the FIREBASE_ENV secret in Secret Manager:
MAILGUN_WEBHOOK_SECRET=webhook_secret_from_mailgun
NEXT_PUBLIC_BACKEND_URL=https://your-backend.run.app
To update production secrets:
gcloud secrets versions access latest --secret=FIREBASE_ENV --project YOUR_PROJECT_ID > .env.local- Edit
.env.localto add/update the variables above gcloud secrets versions add FIREBASE_ENV --data-file=.env.local --project YOUR_PROJECT_ID- Redeploy frontend to pick up new secrets
Resource Requirements:
- Memory: 512MB (lightweight proxy)
- CPU: 0.5 vCPU
- Timeout: 60 seconds (webhook validation + forwarding)
Backend Deployment (Cloud Run)
Environment Variables:
MAILGUN_API_KEY=key_from_mailgun
MAILGUN_DOMAIN=yourdomain.com
GOOGLE_CLOUD_PROJECT=your-project-id
Resource Requirements:
- Memory: 1GB minimum (for AI processing)
- CPU: 1 vCPU minimum
- Timeout: 3600 seconds (60 minutes for Cloud Run maximum)
Timeout Configuration
The email integration uses context-aware timeout configuration that automatically applies extended timeouts optimized for email processing. This ensures complex operations can complete successfully without user waiting for immediate responses.
Email Context Timeouts
Email processing automatically uses extended timeouts compared to UI interactions:
| Operation | UI Context | Email Context | Improvement |
|---|---|---|---|
| Stream processing | 2 minutes | 30 minutes | 15x longer |
| HTTP requests | 30 seconds | 5 minutes | 10x longer |
| AI model calls | 60 seconds | 5 minutes | 5x longer |
| Tool execution | 10 minutes | 50 minutes | 5x longer |
| Document export | N/A | 10 minutes | New capability |
| File downloads | N/A | 5 minutes | New capability |
| Email API calls | N/A | 2 minutes | New capability |
Automatic Context Detection
The system automatically detects email processing context via environment variables:
# Automatically set during email processing
os.environ["EMAIL_PROCESSING_MODE"] = "true"
Benefits for Email Operations
- Complex document generation: Quarto exports can take up to 10 minutes
- Large file processing: Extended timeouts for attachment downloads
- Multi-tool operations: Tool orchestration can run for up to 50 minutes
- AI processing: Complex reasoning tasks get extended time limits
- Retry strategies: More patient retry behavior with longer waits between attempts
Cloud Run Compliance
- Maximum timeout: 60 minutes (Cloud Run limit)
- Recommended timeout: 50 minutes (allows cleanup time)
- Email operations stay well within limits
- Automatic resource optimization based on operation complexity
Monitoring Timeouts
Email processing logs timeout configurations for debugging:
INFO: EmailProcessor initialized with context 'email' and timeouts: {...}
INFO: Using tool orchestrator timeouts for context 'email': heartbeat=300s, hard_timeout=3000s
INFO: Using GenAI timeout for context 'email': 300000ms
For more details, see Timeout Configuration Documentation.
Scaling Considerations
- Rate Limiting: Scales automatically with Firestore
- Email Processing: Each email is processed independently
- Memory Usage: Monitor for large email attachments
- API Limits: Consider Mailgun API rate limits
Troubleshooting
Common Issues
- Emails not being received
- Check MX record configuration pointing to Mailgun
- Verify Mailgun domain setup and verification
- Check Mailgun route configuration (see route troubleshooting below)
- Check frontend webhook URL accessibility:
https://your-frontend.com/api/email/webhook - Ensure webhook is configured in Mailgun dashboard
- Webhook signature validation failing
- Verify
MAILGUN_WEBHOOK_SECRETin frontend environment variables - Check webhook signing key in Mailgun dashboard matches environment variable
- Ensure webhook signing is enabled in Mailgun
- Verify
- Permission errors
- Verify sender email has access to the target assistant
- Check assistant access control configuration (public/private/domain/specific)
- Review assistant ownership and sharing settings
- Test with assistant owner email first
- Backend forwarding issues
- Check
NEXT_PUBLIC_BACKEND_URLis correctly configured - Verify backend is accessible from frontend
- Monitor frontend logs for forwarding errors
- Check backend logs for processing errors
- Check
- Rate limiting issues
- Check Firestore
email_rate_limitscollection for user entries - Verify 1-minute rate limit behavior
- Consider temporary rate limit adjustments for testing
- Check Firestore
Mailgun Route Troubleshooting
6. Emails not reaching webhook (routing issues)
Symptoms:
- Emails are delivered to Mailgun but webhook never receives them
- Mailgun logs show successful receipt but no webhook calls
- Assistant emails work for some addresses but not others
Debugging Steps:
- Check Mailgun Route Configuration:
# Via Mailgun API curl -s --user "api:YOUR_MAILGUN_API_KEY" \ https://api.mailgun.net/v3/routes \ | jq '.items[] | {priority: .priority, description: .description, expression: .expression, actions: .actions}' - Test Route Pattern Matching:
- Go to Mailgun Dashboard > Routes
- Find your assistant route
- Click “Test” and enter:
assistant-test123@yourdomain.com - Verify it matches your route filter
-
Common Route Configuration Errors:
❌ Wrong pattern (missing escape):
match_recipient("assistant-(.*)@email.aitana.chat") # Missing escape for dots✅ Correct patterns:
# Production match_recipient("^assistant-(.*)@email\.aitana\.chat$") # Development match_recipient("^dev-assistant-(.*)@email\.aitana\.chat$") # Testing match_recipient("^test-assistant-(.*)@email\.aitana\.chat$")❌ Wrong action (missing stop):
forward("https://your-frontend.com/api/email/webhook") # Missing stop()✅ Correct action:
forward("https://ai.aitana.chat/api/email/webhook") stop() - Check Route Priority:
- Assistant route should have priority 10 or lower
- Routes with higher priority numbers run after lower ones
- Ensure no catch-all routes (priority 0-9) intercept assistant emails
- Verify Route is Active:
- Route status should be “active” in Mailgun dashboard
- Inactive routes won’t process emails
7. Route testing and validation
Test route via Mailgun logs:
- Send test emails to different environments:
- Production:
assistant-test123@email.aitana.chat - Development:
dev-assistant-test123@email.aitana.chat - Testing:
test-assistant-test123@email.aitana.chat
- Production:
- Check Mailgun Dashboard > Logs
- Look for route processing information in email details
- Verify route actions were executed
Manual route testing:
# Test specific email address against your routes
curl -s --user "api:YOUR_MAILGUN_API_KEY" \
"https://api.mailgun.net/v3/routes" \
-G -d "match_recipient=dev-assistant-test123@email.aitana.chat"
Debug Endpoints
Frontend Health Check:
curl https://your-frontend.com/api/email/webhook
Verifies:
- Frontend webhook system is healthy
MAILGUN_WEBHOOK_SECRETis configured- Backend URL is set
Backend Health Check (via proxy):
curl -X POST https://your-frontend.com/api/proxy \
-H "Content-Type: application/json" \
-d '{"endpoint": "/api/email/status", "method": "GET"}'
Verifies:
- Backend email processing system is healthy
- Backend Mailgun configuration is set
Advanced Features
HTML Email Formatting
The email integration provides rich HTML formatting for assistant responses:
Markdown to HTML Conversion
- Automatic conversion: Markdown content is converted to HTML with proper styling
- Code blocks: Syntax highlighting with proper
<pre>and<code>formatting - Tables: Full table support with borders and styling
- Blockquotes: Styled with accent borders matching the design system
- Lists: Proper bullet and numbered list formatting
Dynamic Domain Configuration
- Configurable frontend URL: The
NEXT_PUBLIC_FRONTEND_URLenvironment variable controls:- Assistant links in email signatures (e.g., “Continue this conversation”)
- Avatar image URLs (when using relative paths)
- Font asset URLs for custom fonts
- Multi-environment support:
- Production:
https://ai.aitana.chat - Test:
https://ai2.aitana.chat - Development: Custom URLs as needed
- Production:
- Automatic fallback: Defaults to production URL if not configured
Custom Component Handling
The system intelligently handles custom React components in email contexts:
Email-Compatible Components:
<img>and<image>tags → Converted to standard HTML<img>with responsive styling<svg>elements → Small SVGs (< 2KB) are preserved with email-safe styling
Interactive Components (graceful degradation):
<plot>,<networkgraph>,<googlesearch>→ Replaced with “View online” messages<dynamicui>,<artifact>,<preview>→ Professional “Interactive component” notices<toolconfirmation>,<assistantresponse>→ Styled notification boxes
Example of component replacement:
<div style="background-color: #fef3c7; padding: 16px; border-radius: 8px;
margin: 16px 0; text-align: center; border-left: 4px solid #f59e0b;">
<strong>Interactive Plot Component</strong><br>
<span style="color: #92400e;">View online for full interactive experience</span>
</div>
Design System Consistency
All email styling matches the web application’s design system:
Typography:
- Primary font: ‘Euclid Circular A’ with web font fallbacks
- Headings use ‘Crimson Pro’ for consistency
- Monospace code uses Menlo, Monaco, Consolas for code blocks
Colors:
- Background:
hsl(0, 0%, 100%)(white) - Text:
hsl(222.2, 84%, 4.9%)(dark slate) - Accent:
hsl(20, 100%, 70%)(orange accent) - Borders:
hsl(214.3, 31.8%, 91.4%)(light gray) - Code background:
#f8f9fcwith dark text
Layout:
- Maximum width: 600px for optimal email client compatibility
- Responsive padding and margins
- Border radius: 0.5rem for modern appearance
- Professional spacing with 24px padding
Email Attachments
Supported File Types
The system supports the same file types as the web interface:
Documents:
- PDF files (
application/pdf) - Plain text files (
text/plain,text/html,text/css,text/md,text/csv) - Code files (
text/javascript,text/x-python) - Data files (
application/json,text/xml,text/rtf)
Media:
- Images: PNG, JPEG, GIF, WebP
- Audio: WAV, MP3, MPEG
- Video: MP4, MPEG, MOV, AVI, WMV, FLV
Storage Architecture
Attachments are stored in Firebase Storage following the UI upload structure:
Storage Path:
users/{userId}/shares/{assistantId}/documents/{uniqueFilename}
Process:
- User lookup: Find user ID by sender email address
- Download: Fetch attachment from Mailgun with authentication
- Validation: Check file type and size (30MB limit)
- Upload: Store in Firebase Storage with metadata
- Integration: Include in assistant context as documents
Metadata stored:
{
"original_filename": "report.pdf",
"sender_email": "user@example.com",
"uploaded_at": "2025-06-14T12:00:00Z",
"assistant_id": "abc123"
}
Professional Email Signatures
Each email response includes a professional signature with:
HTML Signature Features
- Assistant avatar: 48px circular avatar image
- Assistant name: Prominently displayed with proper typography
- Role identification: “AI Assistant” subtitle
- Call-to-action button: “Continue this conversation” with brand styling
- Reply instructions: Clear guidance on email replies
- Export tips: Help text about document export flags
Signature Styling
<div style="margin-top: 24px; padding-top: 16px;
border-top: 2px solid hsl(20, 100%, 70%);
font-family: 'Euclid Circular A', sans-serif;">
<!-- Avatar and name section -->
<!-- CTA button with brand colors -->
<!-- Help text and tips -->
</div>
Plain Text Fallback
A clean text-only version is provided for email clients that don’t support HTML:
---
Assistant Name
AI Assistant
Continue this conversation: https://ai.aitana.chat/assistant/123
You can also reply directly to this email to continue our conversation.
Tip: Add (export:pdf) or (export:docx) to your email subject to receive formatted documents
Quarto Document Export
The email integration supports generating and attaching formatted documents to responses.
Export Triggers
Users can request document exports by adding flags to their email subject:
Supported formats:
(export:pdf)→ PDF document(export:docx)→ Word document(export:html)→ HTML document(export:pptx)→ PowerPoint presentation
Example subjects:
- “Analysis request (export:pdf)”
- “Report generation (export:docx) (export:pdf)”
- “Presentation needed (export:pptx)”
Export Process
- Flag detection: Extract export format requests from email subject
- Content preparation: Format AI response for document generation
- API call: Send formatted content to Quarto API endpoint
- Document generation: Quarto processes content into requested format
- File download: Retrieve generated document from API
- Email attachment: Attach document to email response
Document Formatting
Generated documents include:
- Title: “Email Response: [Original Subject]”
- Author: Assistant name
- Date: Current date
- Content: AI response with proper formatting
- Metadata: Export timestamp and format information
Error Handling
- Individual export failures don’t prevent email sending
- Failed exports are logged but don’t block other formats
- Users receive the email response even if exports fail
- Export status is tracked for debugging
Rate Limiting and Security
Enhanced Rate Limiting
- Timezone-aware: All datetime operations use
timezone.utc - Firestore integration: Rate limits stored in
email_rate_limitscollection - Per-user tracking: 1 email per minute per user email address
- Graceful degradation: Clear error messages with wait times
Security Measures
- Webhook validation: HMAC signature verification with Mailgun
- Input sanitization: Email content cleaning and validation
- Permission checking: Same access control as web interface
- Attachment validation: File type and size restrictions
- User verification: Email sender must be registered user
Chat History Integration
Email interactions are fully integrated with assistant chat history:
Message Storage
Each email creates two chat messages:
User message:
{
"sender": "user",
"content": "Email content with subject context",
"userName": "User Name (from email)",
"userEmail": "user@example.com",
"source": "email",
"read": false,
"traceId": "langfuse_trace_id"
}
Assistant response:
{
"sender": "assistant",
"content": "AI generated response",
"userName": "Assistant (from email)",
"source": "email",
"read": true,
"traceId": "langfuse_trace_id"
}
Context Continuity
- Email responses consider recent chat history (last 20 messages)
- Existing conversation context informs email responses
- Web and email conversations are seamlessly integrated
- Users can switch between email and web interface mid-conversation
Future Enhancements
Planned Features
- Email Threading: Link related emails to conversation threads with improved subject parsing
- Template Customization: Per-assistant email templates and signature customization
- Advanced Export Options: Custom export templates and styling options
- Email Scheduling: Delayed response sending and scheduled summaries
- Multi-language Support: Detect email language and respond accordingly
- Rich Media: Inline image processing and media attachment handling
- Email Analytics: Track open rates, response times, and engagement metrics
Configuration Extensions
- Per-Assistant Rate Limits: Configurable limits based on assistant type
- Custom Email Domains: Support for multiple branded domains
- Advanced Routing: Content-based routing and smart assistant selection
- Integration APIs: REST APIs for email management and monitoring
- Webhook Extensions: Support for additional email providers
- Export Customization: Custom Quarto templates and branding options
Security Best Practices
- Webhook Security: Always validate webhook signatures
- Input Sanitization: Clean and validate all email content
- Rate Limiting: Implement aggressive rate limiting for email endpoints
- Permission Checking: Verify user access before processing
- Logging: Log all email interactions for audit trails
- Error Handling: Don’t expose internal system details in error messages
Support and Maintenance
For issues with email integration:
- Check system logs in Cloud Run
- Verify Firestore collections for rate limiting and interactions
- Test webhook endpoints manually
- Contact Mailgun support for delivery issues
- Review permission configurations for access problems