refactor: 更新URL哈希处理逻辑 feat: 添加聊天消息存储支持 docs: 更新API控制器基类文档 chore: 删除无用脚本文件 fix: 修复分类模型返回类型问题 feat: 添加回执登录功能 build: 更新依赖项配置 style: 统一HTML模板中的哈希ID引用格式 ci: 添加部署和检查脚本
120 lines
4.0 KiB
Dart
120 lines
4.0 KiB
Dart
/// ============================================================
|
||
/// 闲言APP — 邮箱验证码服务
|
||
/// 创建时间: 2026-04-30
|
||
/// 更新时间: 2026-04-30
|
||
/// 作用: 本地SMTP发送验证码邮件,配合回执验证机制
|
||
/// 上次更新: 初始创建,使用mailer库通过SMTP发送验证码
|
||
/// ============================================================
|
||
|
||
import 'dart:math';
|
||
|
||
import 'package:mailer/mailer.dart';
|
||
import 'package:mailer/smtp_server.dart';
|
||
|
||
import '../../../core/utils/logger.dart';
|
||
|
||
class EmailService {
|
||
EmailService._();
|
||
|
||
static const String _smtpHost = 'free.mboxhosting.com';
|
||
static const int _smtpPort = 465;
|
||
static const String _username = 'gg@0gg.cc';
|
||
static const String _password = '520kiss123';
|
||
static const String _fromEmail = 'gg@0gg.cc';
|
||
static const String _fromName = '闲言APP';
|
||
|
||
static String? _pendingCode;
|
||
static String? _pendingEmail;
|
||
static DateTime? _codeExpireTime;
|
||
|
||
static String generateCode() {
|
||
final random = Random.secure();
|
||
return List.generate(6, (_) => random.nextInt(10)).join();
|
||
}
|
||
|
||
static Future<bool> sendVerificationCode({
|
||
required String toEmail,
|
||
required String code,
|
||
}) async {
|
||
try {
|
||
final smtpServer = SmtpServer(
|
||
_smtpHost,
|
||
port: _smtpPort,
|
||
username: _username,
|
||
password: _password,
|
||
ssl: true,
|
||
);
|
||
|
||
final message = Message()
|
||
..from = const Address(_fromEmail, _fromName)
|
||
..recipients.add(Address(toEmail))
|
||
..subject = '闲言APP 验证码'
|
||
..html = _buildEmailHtml(code);
|
||
|
||
final sendReport = await send(message, smtpServer);
|
||
Log.i('验证码邮件发送成功: ${sendReport.toString()}');
|
||
|
||
_pendingCode = code;
|
||
_pendingEmail = toEmail;
|
||
_codeExpireTime = DateTime.now().add(const Duration(minutes: 5));
|
||
|
||
return true;
|
||
} catch (e) {
|
||
Log.e('验证码邮件发送失败', e);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
static bool verifyCode({required String email, required String code}) {
|
||
if (_pendingCode == null || _pendingEmail == null) return false;
|
||
if (_codeExpireTime != null && DateTime.now().isAfter(_codeExpireTime!)) {
|
||
_clear();
|
||
return false;
|
||
}
|
||
if (_pendingEmail != email || _pendingCode != code) return false;
|
||
_clear();
|
||
return true;
|
||
}
|
||
|
||
static void _clear() {
|
||
_pendingCode = null;
|
||
_pendingEmail = null;
|
||
_codeExpireTime = null;
|
||
}
|
||
|
||
static String _buildEmailHtml(String code) {
|
||
return '''
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
</head>
|
||
<body style="margin:0;padding:0;background:#f5f5f7;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
|
||
<table width="100%" cellpadding="0" cellspacing="0" style="background:#f5f5f7;padding:40px 0;">
|
||
<tr><td align="center">
|
||
<table width="480" cellpadding="0" cellspacing="0" style="background:#fff;border-radius:16px;overflow:hidden;box-shadow:0 2px 12px rgba(0,0,0,0.08);">
|
||
<tr><td style="background:linear-gradient(135deg,#007AFF,#5856D6);padding:32px;text-align:center;">
|
||
<h1 style="margin:0;color:#fff;font-size:24px;font-weight:700;">✨ 闲言APP</h1>
|
||
</td></tr>
|
||
<tr><td style="padding:32px;">
|
||
<p style="margin:0 0 8px;font-size:16px;color:#1d1d1f;font-weight:600;">验证你的邮箱</p>
|
||
<p style="margin:0 0 24px;font-size:14px;color:#86868b;">请使用以下验证码完成操作,5分钟内有效:</p>
|
||
<table cellpadding="0" cellspacing="0" style="margin:0 auto 24px;"><tr>
|
||
<td style="background:#f5f5f7;border-radius:12px;padding:16px 32px;text-align:center;">
|
||
<span style="font-size:36px;font-weight:700;letter-spacing:8px;color:#007AFF;">$code</span>
|
||
</td></tr></table>
|
||
<p style="margin:0;font-size:12px;color:#86868b;text-align:center;">如非本人操作,请忽略此邮件</p>
|
||
</td></tr>
|
||
<tr><td style="padding:16px 32px;background:#f5f5f7;text-align:center;">
|
||
<p style="margin:0;font-size:11px;color:#86868b;">© 闲言APP · 安全验证</p>
|
||
</td></tr>
|
||
</table>
|
||
</td></tr>
|
||
</table>
|
||
</body>
|
||
</html>
|
||
''';
|
||
}
|
||
}
|