feat: add cloud-mail service support

This commit is contained in:
zhoukailian
2026-03-26 20:07:21 +08:00
parent ae089ee707
commit a890bc7f2b
14 changed files with 801 additions and 9 deletions

View File

@@ -1540,6 +1540,7 @@ def _build_inbox_config(db, service_type, email: str) -> dict:
EST.DUCK_MAIL: "duck_mail",
EST.FREEMAIL: "freemail",
EST.IMAP_MAIL: "imap_mail",
EST.CLOUD_MAIL: "cloud_mail",
EST.OUTLOOK: "outlook",
}
db_type = type_map.get(service_type)

View File

@@ -84,7 +84,7 @@ class OutlookBatchImportResponse(BaseModel):
# ============== Helper Functions ==============
# 敏感字段列表,返回响应时需要过滤
SENSITIVE_FIELDS = {'password', 'api_key', 'refresh_token', 'access_token', 'admin_token'}
SENSITIVE_FIELDS = {'password', 'api_key', 'refresh_token', 'access_token', 'admin_token', 'admin_password'}
def filter_sensitive_config(config: Dict[str, Any]) -> Dict[str, Any]:
"""过滤敏感配置信息"""
@@ -147,6 +147,7 @@ async def get_email_services_stats():
'duck_mail_count': 0,
'freemail_count': 0,
'imap_mail_count': 0,
'cloud_mail_count': 0,
'tempmail_available': True, # 临时邮箱始终可用
'enabled_count': enabled_count
}
@@ -164,6 +165,8 @@ async def get_email_services_stats():
stats['freemail_count'] = count
elif service_type == 'imap_mail':
stats['imap_mail_count'] = count
elif service_type == 'cloud_mail':
stats['cloud_mail_count'] = count
return stats
@@ -235,6 +238,17 @@ async def get_service_types():
{"name": "domain", "label": "邮箱域名", "required": False, "placeholder": "example.com"},
]
},
{
"value": "cloud_mail",
"label": "Cloud Mail",
"description": "cloud-mail 自部署邮箱服务,使用公开 API",
"config_fields": [
{"name": "base_url", "label": "站点地址", "required": True, "placeholder": "https://mail.example.com"},
{"name": "admin_email", "label": "管理员邮箱", "required": True, "placeholder": "admin@example.com"},
{"name": "admin_password", "label": "管理员密码", "required": True, "secret": True},
{"name": "default_domain", "label": "默认域名", "required": True, "placeholder": "mail.example.com"},
]
},
{
"value": "imap_mail",
"label": "IMAP 邮箱",

View File

@@ -285,6 +285,9 @@ def _normalize_email_service_config(
elif service_type == EmailServiceType.DUCK_MAIL:
if 'domain' in normalized and 'default_domain' not in normalized:
normalized['default_domain'] = normalized.pop('domain')
elif service_type == EmailServiceType.CLOUD_MAIL:
if 'domain' in normalized and 'default_domain' not in normalized:
normalized['default_domain'] = normalized.pop('domain')
if proxy_url and 'proxy_url' not in normalized:
normalized['proxy_url'] = proxy_url
@@ -527,6 +530,10 @@ def _build_email_service_candidates(
append_database_candidates("imap_mail")
if not candidates:
raise ValueError("没有可用的 IMAP 邮箱服务,请先在邮箱服务中添加")
elif service_type == EmailServiceType.CLOUD_MAIL:
append_database_candidates("cloud_mail")
if not candidates:
raise ValueError("没有可用的 Cloud Mail 邮箱服务,请先在邮箱服务页面添加服务")
else:
append_candidate(service_type, email_service_config or {})
@@ -1783,6 +1790,11 @@ async def get_available_email_services():
"available": False,
"count": 0,
"services": []
},
"cloud_mail": {
"available": False,
"count": 0,
"services": []
}
}
@@ -1911,6 +1923,24 @@ async def get_available_email_services():
result["imap_mail"]["count"] = len(imap_mail_services)
result["imap_mail"]["available"] = len(imap_mail_services) > 0
cloud_mail_services = db.query(EmailServiceModel).filter(
EmailServiceModel.service_type == "cloud_mail",
EmailServiceModel.enabled == True
).order_by(EmailServiceModel.priority.asc()).all()
for service in cloud_mail_services:
config = service.config or {}
result["cloud_mail"]["services"].append({
"id": service.id,
"name": service.name,
"type": "cloud_mail",
"default_domain": config.get("default_domain"),
"priority": service.priority
})
result["cloud_mail"]["count"] = len(cloud_mail_services)
result["cloud_mail"]["available"] = len(cloud_mail_services) > 0
return result