Skip to content

OperationMail 运营邮件查询 ​

OperationMail 是服务端查询运营后台或系统投递邮件的低层 API。它覆盖全服运营邮件和指定玩家邮件,不是玩家互发邮件系统;这个底层 API 本身不管理收件箱 UI、红点、已读、领取、删除状态。若希望直接使用官方界面与状态管理,参阅 GameSystemUI 运营邮件收件箱。

当前适合使用 OperationMail 的场景:

  • 服务端需要读取运营后台配置的全服邮件。
  • 服务端需要读取运营后台投递给某个玩家的个人邮件。
  • 项目要自建收件箱 UI,并自行把已读、已领取、已展示等状态存入 CloudData。

不适合使用 OperationMail 的场景:

  • 玩家之间互发邮件。
  • 游戏脚本主动发邮件。
  • 排行榜结算奖励邮件迁移。
  • 客户端直接查询后台邮件。

服务端查询 ​

OperationMail API 只在服务端可用。

csharp
#if SERVER
using GameCore.OperationMail;

public static async Task LoadOperationMailsAsync(long userId)
{
    await OperationMailApi.WaitUntilReadyAsync();

    var mapName = "my_map";
    var env = Game.RuntimeEnvironment;
    var now = DateTime.UtcNow;

    var globalResult = await OperationMailApi.QueryGlobalOperationMailsAsync(mapName, env, now);
    if (!globalResult.IsSuccess)
    {
        Game.Logger.LogWarning("全服运营邮件查询失败: {Result}", globalResult.Result);
        return;
    }

    var userResult = await OperationMailApi.QueryUserOperationMailsAsync(userId, mapName, env, now);
    if (!userResult.IsSuccess)
    {
        Game.Logger.LogWarning("个人运营邮件查询失败: {Result}", userResult.Result);
        return;
    }

    foreach (var mail in globalResult.Records.Concat(userResult.Records))
    {
        Game.Logger.LogInformation("运营邮件: {Id} {Title}", mail.Id, mail.Title);
    }
}
#endif

查询语义 ​

底层 Host 使用固定查询,不向游戏代码开放 SQL 字符串:

  • 全服运营邮件来自 email.admin_email。
  • 个人运营邮件来自 email.user_email。
  • 查询条件包含 mapName、env、state = 0 和 now 所在时间窗口。
  • 全服邮件还限制 target_type = 0。
  • 个人邮件还限制指定 userId。

推荐传 Game.RuntimeEnvironment(GameRuntimeEnvironment.Debug / Test / Formal),API 会映射为后台的 debug / test / formal。Unknown 或不认识的枚举值会抛出参数异常;原 string 重载仍可使用。这里不是部署环境:不要传 Game.DeploymentEnvironment 或 production。

now 由服务端取当前时间传入,推荐 DateTime.UtcNow。运营后台的邮件生效窗口按北京时间配置,查询层会把 DateTimeKind.Utc / Local 的时间转换为北京墙钟后交给后台比较;DateTimeKind.Unspecified 表示调用方已经提供北京墙钟,不会再转换。WASM 环境的 DateTime.Now 可能是 UTC+0,但带 Local Kind 时也会按实际偏移转换。旧项目若曾用 DateTime.Now.AddHours(8) 绕过时差,升级后必须改为 DateTime.UtcNow,否则会重复转换。不要在客户端构造时间后传给服务端决定邮件可见性。

返回字段 ​

OperationMailRecord 包含后台读取邮件所需的原始信息:

字段说明
Id查询表中的记录 id
AdminEmailId来源 admin mail id;全服邮件通常等于 Id
Uuid后台邮件 uuid
Title / Content标题和正文
SenderName后台配置的发件人显示名
ContentType后台内容类型
Attachment后台附件原始 payload
ReceiveType后台领取类型
StartTime / EndTime生效时间窗口对应的 UTC 时间(DateTimeKind.Utc);展示北京时间时需自行转换,不能再将其当作北京墙钟
IncludeNewPlayer全服邮件是否包含邮件开始后加入的新玩家;后台 include_new_player=1 表示排除新玩家,API 返回时已取反。低层 API 不替调用方过滤
Source后台来源值
Env后台环境

状态存储 ​

OperationMail 只查询运营后台邮件,不保存玩家状态。项目自建 UI 时,推荐用 CloudData 保存状态,例如:

  • operation_mail_read_{mailId}
  • operation_mail_claimed_{mailId}
  • operation_mail_hidden_{mailId}

状态 key 的命名应包含邮件 id 或 uuid,避免全服邮件和个人邮件冲突。附件领取逻辑必须在服务端做幂等检查,不能只依赖客户端 UI 状态。

错误处理 ​

常见结果:

结果含义处理
Success查询成功,结果可以为空列表正常处理
ServiceNotInitialized服务或 provider 尚未 ready等待 OperationMailApi.WaitUntilReadyAsync()
FailedToSendHost 没有接受请求可有限重试并记录日志
QueryMapNameMissing / QueryEnvironmentMissing / QueryUserIdMissing参数错误修正调用参数
TooManyReadOperations / MySqlOperationLimitExceeded后台读限流降低查询频率
ResultParseFailed后台响应无法解析记录后台数据和版本信息
QueryConnectionTimeout查询超时有限重试或降级为空收件箱

与 GameSystemUI 收件箱的关系 ​

GameSystemUI 已基于 OperationMail 提供运营邮件收件箱、红点、CloudData 玩家状态和资源附件领取。需要开箱即用的入口与收件箱时使用 GameSystemUI 邮件系统;仅需原始邮件数据或自定义发放规则时,仍可直接调用此底层 API。不要把底层查询误认为已自动保存玩家的已读或领取状态。