ForcePilot/backend/package/yuxi/channel/extensions/email_smtp/streaming.py
Kris 59c6caaa64 feat(email-smtp): 新增SMTP/IMAP邮件渠道插件
实现完整的邮件收发渠道,支持IMAP IDLE实时收信、SMTP发信,包含附件校验、重复消息去重、OAuth2认证、邮件内容解析与引用剥离、邮件发送限流与连接池等功能
2026-05-21 10:45:56 +08:00

67 lines
2.2 KiB
Python

from __future__ import annotations
from .outbound import EmailSmtpOutboundAdapter
class EmailSmtpStreamingAdapter:
streaming_mode = "block"
preview_stream_throttle_ms = 160
preview_min_initial_chars = 18
block_streaming_enabled = True
block_streaming_break = "text_end"
block_streaming_chunk_min_chars = 800
block_streaming_chunk_max_chars = 1200
block_streaming_chunk_break_preference = "paragraph"
block_streaming_coalesce_defaults = None
def __init__(self, outbound: EmailSmtpOutboundAdapter | None = None):
self._outbound = outbound or EmailSmtpOutboundAdapter()
self._idle_ms = 800
def create_block_chunker(self) -> BlockChunker:
return BlockChunker(
min_chars=self.block_streaming_chunk_min_chars,
max_chars=self.block_streaming_chunk_max_chars,
break_preference=self.block_streaming_chunk_break_preference,
)
def create_draft_stream_session(self, target_id: str) -> dict:
return {
"target_id": target_id,
"accumulated": "",
"chunks_sent": 0,
}
class BlockChunker:
def __init__(self, min_chars: int = 800, max_chars: int = 1200, break_preference: str = "paragraph"):
self._min_chars = min_chars
self._max_chars = max_chars
self._break_preference = break_preference
def chunk(self, text: str) -> list[str]:
if len(text) <= self._max_chars:
return [text] if text else []
chunks = []
remaining = text
while len(remaining) > self._max_chars:
split_at = self._max_chars
if self._break_preference == "paragraph":
para_break = remaining.rfind("\n\n", 0, self._max_chars)
if para_break > self._min_chars:
split_at = para_break + 2
else:
line_break = remaining.rfind("\n", 0, self._max_chars)
if line_break > self._min_chars:
split_at = line_break + 1
chunks.append(remaining[:split_at].strip())
remaining = remaining[split_at:].strip()
if remaining:
chunks.append(remaining)
return chunks