Email Platform Feature Documentation
EmailAdapter is an email adapter based on the SMTP/IMAP protocol, supporting email sending, receiving, and processing.
Document Information
- Corresponding Module Version: 4.2.0
- Maintainer: ErisPulse
Basic Information
- Platform Overview: A general-purpose adapter for sending and receiving emails via standard SMTP/IMAP protocols
- Adapter Name: EmailAdapter
- Multi-account Support: Supports configuring multiple email accounts simultaneously
- Connection Method: IMAP long-polling for receiving + SMTP for sending
- Authentication Method: Email address + password/authorization code
- OneBot12 Compatibility: Supports sending OneBot12 formatted messages
Configuration Guide
Global Configuration (EmailAdapter)
| Configuration Item | Type | Default Value | Description |
|---|---|---|---|
imap_server |
str | imap.example.com |
Default IMAP server address |
imap_port |
int | 993 |
Default IMAP port |
smtp_server |
str | smtp.example.com |
Default SMTP server address |
smtp_port |
int | 465 |
Default SMTP port |
ssl |
bool | true |
Whether to enable SSL by default |
timeout |
int | 30 |
Default connection timeout (seconds) |
poll_interval |
int | 60 |
IMAP polling interval (seconds) |
max_retries |
int | 3 |
Maximum number of retry attempts on connection failure |
Account Configuration (EmailAdapter.accounts)
Each account corresponds to an independent email. Account-level configurations take precedence over global configurations.
[EmailAdapter.accounts.default]
email = "[email protected]"
password = "your-password-or-auth-code"
imap_server = "imap.example.com" # Optional, leave empty to use global default
imap_port = 993 # Optional
smtp_server = "smtp.example.com" # Optional
smtp_port = 465 # Optional
ssl = true # Optional
timeout = 30 # Optional
enabled = true
[EmailAdapter.accounts.backup]
email = "[email protected]"
password = "another-password"
enabled = true
v5 Paradigm Update (4.2.0)
- Api DSL Minimal Set: get_self_info (email address) / get_status / get_version / get_supported_actions
- spawn_background Task Ownership: IMAP polling tasks now use runtime.spawn_background
- Framework Soft Dependency: Runtime checks for ErisPulse>=2.7.1 and prompts; version logs are output on startup
- Import paths updated to Core.Bases; _load_accounts retained (global default values merged into adapter-specific logic)
Platform Capabilities Already Integrated
- Receiving: IMAP polling for receiving messages (body/HTML/attachments parsed into message segments), incremental unread detection
- Sending: SMTP sending (Subject/Text/Html/Cc/Bcc/ReplyTo/Attachment), supports multiple accounts
- API: Account information and runtime status (minimal set); concepts like email recall/group are not applicable
Supported Message Sending Types
All sending methods are implemented using a chainable syntax:
from ErisPulse.Core import adapter
mail = adapter.get("email")
# Simple text email
await mail.Send.To("private", "[email protected]").Subject("Test").Text("Content")
# HTML email with attachments
await mail.Send.To("private", "[email protected]") \
.Subject("HTML Email") \
.Cc(["[email protected]", "[email protected]"]) \
.Attachment("report.pdf") \
.Html("<h1>HTML Content</h1>")
# Use Raw_ob12 to send standard OB12 messages
await mail.Send.To("private", "[email protected]").Raw_ob12([
{"type": "text", "data": {"text": "Email body"}},
{"type": "file", "data": {"file": "/path/to/attachment.pdf"}},
])
# Specify sending account (multi-account)
await mail.Send.Using("default").To("private", "[email protected]").Text("Content")
Note: When using chainable syntax, parameter methods (Subject / Cc / Attachment, etc.) must be called before the sending method (Text / Html / Raw_ob12).
Basic Sending Methods
| Method | Description |
|---|---|
.Text(text: str) |
Send a plain text email |
.Html(html: str) |
Send an HTML formatted email |
.Raw_ob12(message, **kwargs) |
Send a OneBot12 formatted message |
Chainable Modifier Methods (Return self, can be combined)
| Method | Description |
|---|---|
.Subject(subject: str) |
Set the email subject |
.Cc(emails: Union[str, List[str]]) |
Set the CC addresses |
.Bcc(emails: Union[str, List[str]]) |
Set the BCC addresses |
.ReplyTo(email: str) |
Set the reply-to address |
.Attachment(file, filename: str = None) |
Add an attachment |
OB12 Message Segment Reverse Conversion (Raw_ob12)
| OB12 Message Segment | Converted to Email Content |
|---|---|
text |
Plain text body |
image |
Image attachment |
video |
Video attachment |
file |
File attachment |
audio |
Audio attachment |
markdown |
Converted to HTML body |
Unique Event Types
Core Differences
- All email events are of
messagetype, withdetail_typefixed asprivate user_idis the sender's pure email address,user_nicknameis the sender's display namemessagemessage segments are in standard OB12 format (text segment + file segment)- The email subject is obtained via the
email_subjectextension field - The complete original data is preserved in the
email_rawfield
New Email Event (email_new)
{
"id": "<[email protected]>",
"time": 1751990446,
"type": "message",
"detail_type": "private",
"platform": "email",
"self": {
"platform": "email",
"user_id": "[email protected]"
},
"message": [
{
"type": "text",
"data": {
"text": "Email body content"
}
}
],
"alt_message": "Email Subject",
"user_id": "[email protected]",
"user_nickname": "Saber"
}
Email with Attachments
{
"message": [
{
"type": "text",
"data": {
"text": "Please check the attachment"
}
},
{
"type": "file",
"data": {
"file_id": "document.pdf",
"file_name": "document.pdf",
"size": 102400
}
}
]
}
Reply Email Event (email_reply)
When the email contains References or In-Reply-To headers, email_raw_type is email_reply:
{
"email_raw_type": "email_reply",
"email_raw": {
"references": "<[email protected]>",
"in_reply_to": "<[email protected]>"
}
}
Extension Field Descriptions
| Field | Type | Description |
|---|---|---|
email_raw |
dict | Complete original email data (subject/from/to/date/cc/bcc/text_content/html_content/attachments, etc.) |
email_raw_type |
str | Original event type: email_new (new email) or email_reply (reply email) |
email_subject |
str | Email subject (convenient access) |
email_from |
str | Sender's pure email address (convenient access) |
attachments |
list | List of attachment data (including binary data field, backward compatible) |
Standard Event Examples
Complete Email Event
{
"id": "<[email protected]>",
"time": 1751990446,
"type": "message",
"detail_type": "private",
"platform": "email",
"self": {
"platform": "email",
"user_id": "[email protected]"
},
"message": [
{
"type": "text",
"data": {
"text": "Please check the attachment"
}
},
{
"type": "file",
"data": {
"file_id": "document.pdf",
"file_name": "document.pdf",
"size": 102400
}
}
],
"alt_message": "Meeting Notice",
"user_id": "[email protected]",
"user_nickname": "Sender",
"email_subject": "Meeting Notice",
"email_from": "[email protected]",
"email_raw": {
"subject": "Meeting Notice",
"from": "\"Sender\" <[email protected]>",
"to": "<[email protected]>",
"date": "Wed, 9 Jul 2026 02:00:46 +0800",
"message_id": "<[email protected]>",
"references": "",
"in_reply_to": "",
"cc": "",
"bcc": "",
"text_content": "Please check the attachment",
"html_content": "<p>Please check the attachment</p>",
"attachments": ["document.pdf"]
},
"email_raw_type": "email_new",
"attachments": [
{
"filename": "document.pdf",
"content_type": "application/pdf",
"size": 102400,
"data": "..."
}
]
}
Sending Method Return Values
{
"status": "ok",
"retcode": 0,
"data": {
"message_id": "<[email protected]>",
"time": 1751990446
},
"message_id": "<[email protected]>",
"message": "",
"email_raw": {
"success": true,
"message": "Email sent successfully"
}
}
Event Handling Example
from ErisPulse.Core.Event import message
@message.on_message()
async def handle_email(event):
if event.get("platform") != "email":
return
# Pure email address of sender
sender = event["user_id"] # [email protected]
# Sender's display name
nickname = event.get("user_nickname") # Sender
# Email subject
subject = event.get("email_subject") # Meeting Notice
# Plain text body (first text segment)
text = event.get_text()
# Complete original data
raw = event.get("email_raw", {})
html = raw.get("html_content", "")
# Process attachments
for seg in event.get("message", []):
if seg["type"] == "file":
filename = seg["data"]["file_name"]
size = seg["data"]["size"]
# Reply to email
await event.reply(f"Received: {subject}")