/api/qmail/db/messages/search
GETFull-text search across email subjects and bodies.
Description
The /api/qmail/db/messages/search endpoint performs a full-text search across the subject lines and body content of all emails in the mailbox. It returns matching emails with metadata and a short body preview, making it ideal for building search interfaces and filtering large mailboxes.
Search Scope
The search text is matched against both the subject and body fields of every email. Results are returned in reverse chronological order (newest first) and include a 200-character body preview for each match.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | Yes | The search text to find in email subjects and bodies. |
limit |
integer | No | Maximum number of results to return. Range: 1-200. Default: 50. |
Response
Returns a JSON object containing the search query, result count, and an array of matching email objects.
Response Properties
success
boolean
Indicates whether the search completed successfully.
query
string
The original search query echoed back.
count
integer
Number of matching results returned.
results
array<object>
Array of email objects matching the search query.
results[].email_id
string
Unique email identifier (hex string).
results[].subject
string
The email subject line.
results[].sender_sn
integer (int64)
Serial number of the party. For incoming folders this is the sender; for Sent/Drafts results it is the primary recipient.
results[].sender_denomination_code
integer
Denomination code of the party's address,
0–4 (0=bit, 1=byte, 2=kilo, 3=mega, 4=giga).
results[].sender_denomination
number
Human-readable denomination value derived from
sender_denomination_code.
results[].sender_address
string
Canonical dotted-decimal QMail address of the party (e.g.
6.197@bit).
results[].sender_name
string
Display name of the sender, resolved from the saved contacts database by serial number. Empty string when the sender is not a saved contact. Prefer this over
sender_address when non-empty.
results[].sender_is_favorite
boolean
Whether the resolved sender contact is a favorite.
false when not a saved contact.
results[].sender_trust_level
integer
Trust level of the resolved sender contact.
0 when not a saved contact.
results[].sender_class_name
string
Optional class/category label on the resolved sender contact. Empty string when unset or not a saved contact.
results[].sender_description
string
Optional description on the resolved sender contact. Empty string when unset or not a saved contact.
results[].sender_user_notes
string
Optional private notes on the resolved sender contact. Empty string when unset or not a saved contact.
results[].recipient_count
integer
Number of recipients on this email.
0 for incoming mail with no stored recipients. The recipient_* fields describe the primary (first TO) recipient.
results[].recipient_sn
integer (int64)
Serial number of the primary recipient. Present when
recipient_count > 0.
results[].recipient_denomination_code
integer
Denomination code (
0–4) of the primary recipient. May be -1 when unresolved.
results[].recipient_denomination
number
Human-readable denomination value of the primary recipient.
results[].recipient_address
string
Canonical dotted-decimal QMail address of the primary recipient. Present when its serial number and denomination are known.
results[].recipient_name
string
Display name of the primary recipient, resolved from saved contacts. Empty string when not a saved contact. For Sent/Drafts results, prefer this over
recipient_address when non-empty.
results[].recipient_is_favorite
boolean
Whether the resolved recipient contact is a favorite.
false when not a saved contact.
results[].recipient_trust_level
integer
Trust level of the resolved recipient contact.
0 when not a saved contact.
results[].recipient_class_name
string
Optional class/category label on the resolved recipient contact. Empty string when unset or not a saved contact.
results[].recipient_description
string
Optional description on the resolved recipient contact. Empty string when unset or not a saved contact.
results[].recipient_user_notes
string
Optional private notes on the resolved recipient contact. Empty string when unset or not a saved contact.
results[].received_timestamp
integer (int64)
Unix timestamp (in seconds) when the email was received.
results[].sent_timestamp
integer (int64)
Unix timestamp (in seconds) when the sender sent the email. May be
0 for older mail; fall back to received_timestamp.
results[].is_read
boolean
Whether the email has been read.
results[].folder
integer
Numeric folder identifier where the email resides.
results[].attachment_count
integer
Number of attachments stored with this email.
0 when none.
results[].body_preview
string
Preview of the email body (first 200 characters).
Success Response (200 OK)
{
"success": true,
"query": "meeting",
"count": 2,
"results": [
{
"email_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"subject": "Team Meeting Tomorrow",
"sender_sn": 1048576,
"sender_denomination_code": 2,
"sender_denomination": 100,
"sender_address": "16.0.0@kilo",
"sender_name": "Alice Johnson",
"sender_is_favorite": true,
"sender_trust_level": 1,
"sender_class_name": "Work",
"sender_description": "Finance team lead",
"sender_user_notes": "Prefers replies before noon.",
"recipient_count": 0,
"recipient_name": "",
"recipient_is_favorite": false,
"recipient_trust_level": 0,
"recipient_class_name": "",
"recipient_description": "",
"recipient_user_notes": "",
"received_timestamp": 1736952600,
"sent_timestamp": 1736952480,
"is_read": false,
"folder": 0,
"attachment_count": 0,
"body_preview": "Hi team, just a reminder that we have our weekly meeting tomorrow at 10am. Please bring your status updates and any blockers you want to discuss. The agenda includes project timeline review and..."
},
{
"email_id": "b2c3d4e5f6071829304b5c6d7e8f90a1",
"subject": "Re: Meeting Notes",
"sender_sn": 197,
"sender_denomination_code": 0,
"sender_denomination": 1,
"sender_address": "197@bit",
"sender_name": "",
"sender_is_favorite": false,
"sender_trust_level": 0,
"sender_class_name": "",
"sender_description": "",
"sender_user_notes": "",
"recipient_count": 0,
"recipient_name": "",
"recipient_is_favorite": false,
"recipient_trust_level": 0,
"recipient_class_name": "",
"recipient_description": "",
"recipient_user_notes": "",
"received_timestamp": 1736847300,
"sent_timestamp": 1736847180,
"is_read": true,
"folder": 0,
"attachment_count": 0,
"body_preview": "Here are the notes from yesterday's meeting as discussed. Action items have been assigned and deadlines are listed below. Please review and confirm your tasks by end of day Friday."
}
]
}
Error Response (400 Bad Request)
{
"error": true,
"message": "Missing required parameter: query",
"code": 400
}
Error Response (500 Internal Server Error)
{
"error": true,
"message": "Search failed",
"code": 500,
"detail": "database_error"
}
Try It Out
Examples
cURL
# Basic search
curl "http://localhost:8082/api/qmail/db/messages/search?query=meeting"
# Search with custom limit
curl "http://localhost:8082/api/qmail/db/messages/search?query=invoice&limit=10"
# URL-encode spaces in the query
curl "http://localhost:8082/api/qmail/db/messages/search?query=project%20update&limit=25"
# Pretty print the JSON response
curl "http://localhost:8082/api/qmail/db/messages/search?query=meeting" | jq
JavaScript (async/await)
const API_BASE = 'http://localhost:8082/api';
async function searchEmails(query, limit = 50) {
try {
const params = new URLSearchParams({
query: query,
limit: limit.toString()
});
const response = await fetch(`${API_BASE}/qmail/db/messages/search?${params}`);
if (!response.ok) {
throw new Error(`HTTP error ${response.status}`);
}
const data = await response.json();
console.log(`Search for "${data.query}" returned ${data.count} result(s)`);
data.results.forEach(email => {
const status = email.is_read ? 'Read' : 'Unread';
// Prefer the resolved contact name; fall back to the address, then the SN.
const who = email.sender_name || email.sender_address || `SN ${email.sender_sn}`;
console.log(`[${status}] ${email.subject}`);
console.log(` From: ${who}${email.sender_is_favorite ? ' [FAV]' : ''}`);
console.log(` ID: ${email.email_id}`);
console.log(` Preview: ${email.body_preview}`);
});
return data;
} catch (error) {
console.error('Search failed:', error);
throw error;
}
}
// Example usage
searchEmails('meeting', 20);
Python
import requests
API_BASE = 'http://localhost:8082/api'
def search_emails(query, limit=50):
"""
Search for emails by subject and body content.
Args:
query: Search text to match against subjects and bodies
limit: Maximum results to return (1-200, default 50)
Returns:
Dictionary with success, query, count, and results
"""
params = {
'query': query,
'limit': limit
}
response = requests.get(f'{API_BASE}/qmail/db/messages/search', params=params)
response.raise_for_status()
data = response.json()
print(f"Search for '{data['query']}' returned {data['count']} result(s)\n")
for email in data['results']:
status = 'Read' if email['is_read'] else 'Unread'
# Prefer the resolved contact name; fall back to the address, then the SN.
who = email.get('sender_name') or email.get('sender_address') or f"SN {email['sender_sn']}"
fav = ' [FAV]' if email.get('sender_is_favorite') else ''
print(f"[{status}] {email['subject']}")
print(f" From: {who}{fav}")
print(f" ID: {email['email_id']}")
print(f" Folder: {email['folder']}")
print(f" Preview: {email['body_preview']}\n")
return data
# Example usage
if __name__ == '__main__':
results = search_emails('meeting', limit=20)