fix(email): complete mail settings and templates

This commit is contained in:
2026-09-04 12:06:42 +08:00
parent 4f8ab94fac
commit 4833053a5c
29 changed files with 716 additions and 426 deletions
@@ -0,0 +1,67 @@
const test = require('node:test')
const assert = require('node:assert/strict')
const fs = require('node:fs')
const path = require('node:path')
const root = path.resolve(__dirname, '..', '..')
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8')
const templates = read('src/Settings/MailTemplates.php')
const mail = read('src/Settings/Mail.php')
const notifications = read('src/Settings/MailNotifications.php')
const globalController = read('src/Admin/GlobalController.php')
const userController = read('src/Admin/UserController.php')
const settings = read('src/Settings/Settings.php')
test('email catalog includes required non-forum and financial events', () => {
const required = [
'reg_verify_code', 'reg_success', 'login_code', 'password_reset', 'change_code', 'change_notice',
'order_paid', 'order_status', 'withdraw_submitted', 'withdraw_completed', 'affiliate_commission',
'creator_income', 'transfer_received', 'comment_approved', 'comment_reply', 'post_result',
'phone_changed', 'auth_apply_result', 'user_ban', 'report_result',
'order_paid_admin', 'withdraw_submitted_admin',
]
for (const event of required) {
assert.match(templates, new RegExp(`'${event}'\\s*=>\\s*self::event`), event)
}
})
test('forum-only events stay out of the email catalog', () => {
for (const forbidden of ['bbs', 'moderator', 'answer_adopted', 'answer-adopted']) {
assert.doesNotMatch(templates, new RegExp(forbidden, 'i'))
assert.doesNotMatch(notifications, new RegExp(forbidden, 'i'))
}
})
test('email templates and SMTP use one aksrt_settings schema', () => {
assert.match(templates, /'option_key'\s*=>\s*'aksrt_settings'/)
assert.match(templates, /'mail_passwd'.*'secret'\s*=>\s*true/)
assert.match(mail, /Settings::get_all\(\)/)
assert.doesNotMatch(settings, /aksrt_mail_smtp/)
assert.doesNotMatch(globalController, /aksrt_mail_config|\/settings\/mail'/)
assert.doesNotMatch(userController, /aksrt_mail_templates|mail-templates/)
})
test('only the canonical mail service calls wp_mail', () => {
const phpFiles = []
const walk = (dir) => {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name)
if (entry.isDirectory()) walk(full)
else if (entry.name.endsWith('.php')) phpFiles.push(full)
}
}
walk(root)
const callers = phpFiles.filter((file) => /wp_mail\s*\(/.test(fs.readFileSync(file, 'utf8')))
assert.deepEqual(callers.map((file) => path.relative(root, file).replaceAll('\\', '/')), ['src/Settings/Mail.php'])
})
test('financial and account hooks are wired to the notification service', () => {
for (const hook of [
'aksrt_order_paid', 'aksrt_order_status_changed', 'aksrt_asset_transaction_committed',
'aksrt_withdrawal_submitted', 'aksrt_withdrawal_status_changed',
'aksrt_user_phone_changed',
]) {
assert.match(notifications, new RegExp(`add_action\\('${hook}'`), hook)
}
})