- Add comprehensive documentation in botbook/ with 12 chapters - Add botapp/ Tauri desktop application - Add botdevice/ IoT device support - Add botlib/ shared library crate - Add botmodels/ Python ML models service - Add botplugin/ browser extension - Add botserver/ reorganized server code - Add bottemplates/ bot templates - Add bottest/ integration tests - Add botui/ web UI server - Add CI/CD workflows in .forgejo/workflows/ - Add AGENTS.md and PROD.md documentation - Add dependency management scripts (DEPENDENCIES.sh/ps1) - Remove legacy src/ structure and migrations - Clean up temporary and backup files
599 lines
No EOL
12 KiB
Markdown
599 lines
No EOL
12 KiB
Markdown
# Email API
|
|
|
|
The Email API provides endpoints for email operations including sending, receiving, and managing email accounts through the Stalwart mail server integration.
|
|
|
|
## Overview
|
|
|
|
Email functionality in General Bots is available through:
|
|
|
|
1. **REST API** - Documented in this chapter
|
|
2. **BASIC Keywords** - `SEND MAIL` for scripts
|
|
3. **Email Module** - Background processing and IMAP/SMTP integration
|
|
|
|
## Endpoints
|
|
|
|
### Send Email
|
|
|
|
**POST** `/api/email/send`
|
|
|
|
Send an email message.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"to": ["recipient@example.com"],
|
|
"cc": ["cc@example.com"],
|
|
"bcc": [],
|
|
"subject": "Meeting Tomorrow",
|
|
"body": "Hi, just a reminder about our meeting.",
|
|
"body_type": "text",
|
|
"attachments": []
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"message_id": "msg-abc123",
|
|
"status": "sent",
|
|
"timestamp": "2024-01-15T10:30:00Z"
|
|
}
|
|
```
|
|
|
|
**Body Types:**
|
|
- `text` - Plain text
|
|
- `html` - HTML formatted
|
|
|
|
### List Emails
|
|
|
|
**GET** `/api/email/inbox`
|
|
|
|
Retrieve inbox messages.
|
|
|
|
**Query Parameters:**
|
|
- `folder` - Folder name (default: INBOX)
|
|
- `limit` - Number of messages (default: 50)
|
|
- `offset` - Pagination offset
|
|
- `unread` - Filter unread only (boolean)
|
|
- `since` - Messages since date (ISO 8601)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"messages": [
|
|
{
|
|
"id": "email-001",
|
|
"from": "sender@example.com",
|
|
"subject": "Hello",
|
|
"preview": "Just wanted to say hi...",
|
|
"date": "2024-01-15T09:00:00Z",
|
|
"read": false,
|
|
"has_attachments": false
|
|
}
|
|
],
|
|
"total": 142,
|
|
"unread_count": 5
|
|
}
|
|
```
|
|
|
|
### Get Email
|
|
|
|
**GET** `/api/email/:id`
|
|
|
|
Get specific email details.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"id": "email-001",
|
|
"from": {
|
|
"name": "John Doe",
|
|
"email": "john@example.com"
|
|
},
|
|
"to": [
|
|
{
|
|
"name": "You",
|
|
"email": "you@example.com"
|
|
}
|
|
],
|
|
"cc": [],
|
|
"subject": "Meeting Notes",
|
|
"body": "Here are the notes from today's meeting...",
|
|
"body_html": "<p>Here are the notes from today's meeting...</p>",
|
|
"date": "2024-01-15T09:00:00Z",
|
|
"read": true,
|
|
"attachments": [
|
|
{
|
|
"id": "att-001",
|
|
"filename": "notes.pdf",
|
|
"size": 102400,
|
|
"content_type": "application/pdf"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Delete Email
|
|
|
|
**DELETE** `/api/email/:id`
|
|
|
|
Delete an email message.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "deleted",
|
|
"message_id": "email-001"
|
|
}
|
|
```
|
|
|
|
### Get Attachment
|
|
|
|
**GET** `/api/email/:id/attachments/:attachment_id`
|
|
|
|
Download an email attachment.
|
|
|
|
**Response:** Binary file with appropriate Content-Type header.
|
|
|
|
### Mark as Read
|
|
|
|
**PUT** `/api/email/:id/read`
|
|
|
|
Mark email as read.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"read": true
|
|
}
|
|
```
|
|
|
|
### Move Email
|
|
|
|
**PUT** `/api/email/:id/move`
|
|
|
|
Move email to a different folder.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"folder": "Archive"
|
|
}
|
|
```
|
|
|
|
### List Folders
|
|
|
|
**GET** `/api/email/folders`
|
|
|
|
List available email folders.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"folders": [
|
|
{
|
|
"name": "INBOX",
|
|
"path": "INBOX",
|
|
"unread_count": 5,
|
|
"total_count": 142
|
|
},
|
|
{
|
|
"name": "Sent",
|
|
"path": "Sent",
|
|
"unread_count": 0,
|
|
"total_count": 89
|
|
},
|
|
{
|
|
"name": "Drafts",
|
|
"path": "Drafts",
|
|
"unread_count": 0,
|
|
"total_count": 3
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Create Draft
|
|
|
|
**POST** `/api/email/drafts`
|
|
|
|
Create an email draft.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"to": ["recipient@example.com"],
|
|
"subject": "Draft subject",
|
|
"body": "Draft content..."
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"draft_id": "draft-001",
|
|
"status": "saved"
|
|
}
|
|
```
|
|
|
|
### Send Draft
|
|
|
|
**POST** `/api/email/drafts/:id/send`
|
|
|
|
Send a previously saved draft.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"message_id": "msg-abc123",
|
|
"status": "sent"
|
|
}
|
|
```
|
|
|
|
## Email Accounts
|
|
|
|
### List Accounts
|
|
|
|
**GET** `/api/email/accounts`
|
|
|
|
List configured email accounts.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"accounts": [
|
|
{
|
|
"id": "account-001",
|
|
"email": "user@example.com",
|
|
"provider": "stalwart",
|
|
"status": "connected"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Add Account
|
|
|
|
**POST** `/api/email/accounts`
|
|
|
|
Add a new email account.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"email": "user@example.com",
|
|
"imap_server": "imap.example.com",
|
|
"imap_port": 993,
|
|
"smtp_server": "smtp.example.com",
|
|
"smtp_port": 587,
|
|
"username": "user@example.com",
|
|
"password": "app-specific-password"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"account_id": "account-002",
|
|
"status": "connected",
|
|
"message": "Account added successfully"
|
|
}
|
|
```
|
|
|
|
## BASIC Integration
|
|
|
|
Use email in your BASIC scripts:
|
|
|
|
```basic
|
|
' Simple email
|
|
SEND MAIL "recipient@example.com", "Subject", "Body"
|
|
|
|
' With variables
|
|
TALK "Who should I email?"
|
|
recipient = HEAR
|
|
|
|
TALK "What's the subject?"
|
|
subject = HEAR
|
|
|
|
TALK "What's the message?"
|
|
body = HEAR
|
|
|
|
SEND MAIL recipient, subject, body
|
|
TALK "Email sent!"
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Configure email in `config.csv`:
|
|
|
|
```csv
|
|
key,value
|
|
smtp-server,smtp.gmail.com
|
|
smtp-port,587
|
|
imap-server,imap.gmail.com
|
|
imap-port,993
|
|
email-username,your-email@gmail.com
|
|
email-password,your-app-password
|
|
email-from,Your Name <your-email@gmail.com>
|
|
```
|
|
|
|
**Gmail Configuration:**
|
|
- Use App Passwords (not your main password)
|
|
- Enable IMAP in Gmail settings
|
|
- Allow less secure apps or use OAuth
|
|
|
|
## Stalwart Mail Server
|
|
|
|
When using the built-in Stalwart mail server:
|
|
|
|
**Automatic Configuration:**
|
|
- Server runs on standard ports (25, 993, 587)
|
|
- Accounts created through Zitadel integration
|
|
- TLS certificates auto-managed
|
|
|
|
**Manual Configuration:**
|
|
```csv
|
|
key,value
|
|
stalwart-enabled,true
|
|
stalwart-domain,mail.yourdomain.com
|
|
stalwart-admin-password,secure-password
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
| Status Code | Error | Description |
|
|
|-------------|-------|-------------|
|
|
| 400 | `invalid_recipient` | Invalid email address |
|
|
| 401 | `unauthorized` | Authentication required |
|
|
| 403 | `forbidden` | No access to mailbox |
|
|
| 404 | `not_found` | Email not found |
|
|
| 422 | `send_failed` | SMTP delivery failed |
|
|
| 503 | `service_unavailable` | Mail server offline |
|
|
|
|
## Rate Limits
|
|
|
|
| Endpoint | Limit |
|
|
|----------|-------|
|
|
| Send | 100/hour per user |
|
|
| Inbox | 300/hour per user |
|
|
| Attachments | 50/hour per user |
|
|
|
|
## Email Read Tracking
|
|
|
|
General Bots supports email read tracking via an invisible 1x1 pixel embedded in HTML emails. When enabled, you can track when recipients open your emails.
|
|
|
|
### Configuration
|
|
|
|
Enable tracking in `config.csv`:
|
|
|
|
```csv
|
|
name,value
|
|
email-read-pixel,true
|
|
server-url,https://yourdomain.com
|
|
```
|
|
|
|
### How It Works
|
|
|
|
1. When sending an HTML email, a tracking pixel is automatically injected
|
|
2. When the recipient opens the email, their email client loads the pixel
|
|
3. The server records the open event with timestamp and metadata
|
|
4. You can query the tracking status via API or view in the Suite UI
|
|
|
|
### Tracking Endpoints
|
|
|
|
#### Serve Tracking Pixel
|
|
|
|
**GET** `/api/email/tracking/pixel/:tracking_id`
|
|
|
|
This endpoint is called automatically by email clients when loading the tracking pixel. It returns a 1x1 transparent GIF and records the read event.
|
|
|
|
**Response:** Binary GIF image (1x1 pixel)
|
|
|
|
**Headers Set:**
|
|
- `Content-Type: image/gif`
|
|
- `Cache-Control: no-store, no-cache, must-revalidate, max-age=0`
|
|
|
|
#### Get Tracking Status
|
|
|
|
**GET** `/api/email/tracking/status/:tracking_id`
|
|
|
|
Get the read status for a specific sent email.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"tracking_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"to_email": "recipient@example.com",
|
|
"subject": "Meeting Tomorrow",
|
|
"sent_at": "2024-01-15T10:30:00Z",
|
|
"is_read": true,
|
|
"read_at": "2024-01-15T14:22:00Z",
|
|
"read_count": 3
|
|
}
|
|
}
|
|
```
|
|
|
|
#### List Tracked Emails
|
|
|
|
**GET** `/api/email/tracking/list`
|
|
|
|
List all sent emails with their tracking status.
|
|
|
|
**Query Parameters:**
|
|
- `account_id` - Filter by email account (optional)
|
|
- `limit` - Number of results (default: 50)
|
|
- `offset` - Pagination offset (default: 0)
|
|
- `filter` - Filter by status: `all`, `read`, `unread` (default: all)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"tracking_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"to_email": "recipient@example.com",
|
|
"subject": "Meeting Tomorrow",
|
|
"sent_at": "2024-01-15T10:30:00Z",
|
|
"is_read": true,
|
|
"read_at": "2024-01-15T14:22:00Z",
|
|
"read_count": 3
|
|
},
|
|
{
|
|
"tracking_id": "661e8400-e29b-41d4-a716-446655440001",
|
|
"to_email": "another@example.com",
|
|
"subject": "Project Update",
|
|
"sent_at": "2024-01-15T11:00:00Z",
|
|
"is_read": false,
|
|
"read_at": null,
|
|
"read_count": 0
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### Get Tracking Statistics
|
|
|
|
**GET** `/api/email/tracking/stats`
|
|
|
|
Get aggregate statistics for email tracking.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"total_sent": 150,
|
|
"total_read": 98,
|
|
"read_rate": 65.33,
|
|
"avg_time_to_read_hours": 4.5
|
|
}
|
|
}
|
|
```
|
|
|
|
### Tracking Data Stored
|
|
|
|
For each tracked email, the following data is recorded:
|
|
|
|
| Field | Description |
|
|
|-------|-------------|
|
|
| `tracking_id` | Unique ID embedded in the pixel URL |
|
|
| `to_email` | Recipient email address |
|
|
| `subject` | Email subject line |
|
|
| `sent_at` | Timestamp when email was sent |
|
|
| `is_read` | Whether email has been opened |
|
|
| `read_at` | Timestamp of first open |
|
|
| `read_count` | Number of times opened |
|
|
| `first_read_ip` | IP address of first open |
|
|
| `last_read_ip` | IP address of most recent open |
|
|
| `user_agent` | Browser/client user agent string |
|
|
|
|
### Privacy Considerations
|
|
|
|
- Email tracking should be used responsibly
|
|
- Consider disclosing tracking in your email footer
|
|
- Some email clients block tracking pixels by default
|
|
- Users may have images disabled, preventing tracking
|
|
- GDPR/LGPD may require consent for tracking
|
|
|
|
### Suite UI Integration
|
|
|
|
The Suite email interface shows tracking status:
|
|
|
|
- **📊 Tracking** folder shows all tracked emails
|
|
- Green checkmarks (✓✓) indicate opened emails
|
|
- Gray checkmarks indicate sent but unread
|
|
- Hover over emails to see open timestamp
|
|
- Statistics panel shows open rates
|
|
|
|
## Security Notes
|
|
|
|
1. **Never hardcode credentials** - Use config.csv
|
|
2. **Use App Passwords** - Not main account passwords
|
|
3. **Enable TLS** - Always use encrypted connections
|
|
4. **Audit sending** - Log all outbound emails
|
|
|
|
## Database Schema
|
|
|
|
```sql
|
|
-- user_email_accounts
|
|
CREATE TABLE user_email_accounts (
|
|
id UUID PRIMARY KEY,
|
|
user_id UUID REFERENCES users(id),
|
|
email TEXT NOT NULL,
|
|
imap_server TEXT,
|
|
smtp_server TEXT,
|
|
encrypted_password TEXT,
|
|
created_at TIMESTAMPTZ
|
|
);
|
|
|
|
-- email_drafts
|
|
CREATE TABLE email_drafts (
|
|
id UUID PRIMARY KEY,
|
|
user_id UUID REFERENCES users(id),
|
|
recipients JSONB,
|
|
subject TEXT,
|
|
body TEXT,
|
|
attachments JSONB,
|
|
created_at TIMESTAMPTZ,
|
|
updated_at TIMESTAMPTZ
|
|
);
|
|
```
|
|
|
|
## Database Schema
|
|
|
|
```sql
|
|
-- user_email_accounts
|
|
CREATE TABLE user_email_accounts (
|
|
id UUID PRIMARY KEY,
|
|
user_id UUID REFERENCES users(id),
|
|
email TEXT NOT NULL,
|
|
imap_server TEXT,
|
|
smtp_server TEXT,
|
|
encrypted_password TEXT,
|
|
created_at TIMESTAMPTZ
|
|
);
|
|
|
|
-- email_drafts
|
|
CREATE TABLE email_drafts (
|
|
id UUID PRIMARY KEY,
|
|
user_id UUID REFERENCES users(id),
|
|
recipients JSONB,
|
|
subject TEXT,
|
|
body TEXT,
|
|
attachments JSONB,
|
|
created_at TIMESTAMPTZ,
|
|
updated_at TIMESTAMPTZ
|
|
);
|
|
|
|
-- sent_email_tracking (for read receipts)
|
|
CREATE TABLE sent_email_tracking (
|
|
id UUID PRIMARY KEY,
|
|
tracking_id UUID NOT NULL UNIQUE,
|
|
bot_id UUID NOT NULL,
|
|
account_id UUID NOT NULL,
|
|
from_email VARCHAR(255) NOT NULL,
|
|
to_email VARCHAR(255) NOT NULL,
|
|
cc TEXT,
|
|
bcc TEXT,
|
|
subject TEXT NOT NULL,
|
|
sent_at TIMESTAMPTZ NOT NULL,
|
|
is_read BOOLEAN NOT NULL DEFAULT FALSE,
|
|
read_at TIMESTAMPTZ,
|
|
read_count INTEGER NOT NULL DEFAULT 0,
|
|
first_read_ip VARCHAR(45),
|
|
last_read_ip VARCHAR(45),
|
|
user_agent TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL,
|
|
updated_at TIMESTAMPTZ NOT NULL
|
|
);
|
|
```
|
|
|
|
## See Also
|
|
|
|
- [SEND MAIL Keyword](../04-basic-scripting/keyword-send-mail.md) - BASIC email
|
|
- [CREATE DRAFT Keyword](../04-basic-scripting/keyword-create-draft.md) - Draft creation
|
|
- [External Services](../appendix-external-services/README.md) - Service configuration
|
|
- [Configuration Parameters](../10-configuration-deployment/parameters.md) - email-read-pixel setting |