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:
- REST API - Documented in this chapter
- BASIC Keywords -
SEND MAILfor scripts - Email Module - Background processing and IMAP/SMTP integration
Endpoints
Send Email
POST /api/email/send
Send an email message.
Request:
{
"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:
{
"message_id": "msg-abc123",
"status": "sent",
"timestamp": "2024-01-15T10:30:00Z"
}
Body Types:
text- Plain texthtml- 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 offsetunread- Filter unread only (boolean)since- Messages since date (ISO 8601)
Response:
{
"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:
{
"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:
{
"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:
{
"read": true
}
Move Email
PUT /api/email/:id/move
Move email to a different folder.
Request:
{
"folder": "Archive"
}
List Folders
GET /api/email/folders
List available email folders.
Response:
{
"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:
{
"to": ["recipient@example.com"],
"subject": "Draft subject",
"body": "Draft content..."
}
Response:
{
"draft_id": "draft-001",
"status": "saved"
}
Send Draft
POST /api/email/drafts/:id/send
Send a previously saved draft.
Response:
{
"message_id": "msg-abc123",
"status": "sent"
}
Email Accounts
List Accounts
GET /api/email/accounts
List configured email accounts.
Response:
{
"accounts": [
{
"id": "account-001",
"email": "user@example.com",
"provider": "stalwart",
"status": "connected"
}
]
}
Add Account
POST /api/email/accounts
Add a new email account.
Request:
{
"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:
{
"account_id": "account-002",
"status": "connected",
"message": "Account added successfully"
}
BASIC Integration
Use email in your BASIC scripts:
' 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:
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:
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:
name,value
email-read-pixel,true
server-url,https://yourdomain.com
How It Works
- When sending an HTML email, a tracking pixel is automatically injected
- When the recipient opens the email, their email client loads the pixel
- The server records the open event with timestamp and metadata
- 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/gifCache-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:
{
"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:
{
"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:
{
"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
- Never hardcode credentials - Use config.csv
- Use App Passwords - Not main account passwords
- Enable TLS - Always use encrypted connections
- Audit sending - Log all outbound emails
Database Schema
-- 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
-- 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 - BASIC email
- CREATE DRAFT Keyword - Draft creation
- External Services - Service configuration
- Configuration Parameters - email-read-pixel setting