3.5 KiB
2925 account pool integration notes — 2026-05-11
Decision: abandon POP3/SMTP/IMAP forwarding to ClawEmail. Use the original extension's 2925 webmail/account-pool model directly.
Account pool
Secret file:
~/.hermes/secrets/mail2925_accounts.txt
Format:
邮箱----密码
user@2925.com----password
BOSS provided 20 accounts (chickliu2021@2925.com through chickliu2040@2925.com). Passwords are stored only in the local secret file with mode 0600; never print or commit raw passwords.
State file:
~/.hermes/state/mail2925_accounts_state.json
State fields per account:
{
"lastUsedAt": 0,
"lastLoginAt": 0,
"lastLimitAt": 0,
"disabledUntil": 0,
"lastError": ""
}
Hard invariant: alias/account binding
A generated 2925 registration address must be derived from the same 2925 account used to read mail.
Example:
selected account: chickliu2021@2925.com
allowed alias: chickliu2021rl9sxh@2925.com
mail reader: logged in as chickliu2021@2925.com
Forbidden:
alias from chickliu2021*, but mailbox logged in as chickliu2022@2925.com
Gate before reading any code:
displayedMailboxEmail == selectedAccount.email
alias.localPart startsWith selectedAccount.localPart
If the displayed mailbox email differs, clear 2925 cookies and force-login the selected account before continuing.
Alias generation
Use original extension rule, not Gmail-style plus tags:
baseLocal + randomSuffix(6) + @2925.com
Example:
chickliu2021@2925.com -> chickliu2021a8k2mz@2925.com
Do not generate chickliu2021+tag@2925.com.
Account selection
Pick among accounts that are:
enabled != false
have password
disabledUntil <= now
Sort by:
lastUsedAt ascending, then email ascending
This rotates accounts and avoids overusing one mailbox.
Limit handling
Detect 2925 limit messages:
子邮箱已达上限
已达上限邮箱
子邮箱上限
邮箱已达上限
On hit:
currentAccount.disabledUntil = now + 24h
currentAccount.lastLimitAt = now
currentAccount.lastError = reason
switch to next available account
terminate current OpenAI attempt and restart next round with a fresh alias
Do not continue the same OpenAI page after switching 2925 account; it risks mixing alias/account state.
Local helper
python3 scripts/mail2925_pool.py selftest
python3 scripts/mail2925_pool.py list
python3 scripts/mail2925_pool.py pick
python3 scripts/mail2925_pool.py mark-limit chickliu2021@2925.com --reason '子邮箱已达上限邮箱'
python3 scripts/mail2925_pool.py mark-login chickliu2021@2925.com
pick prints only email + generated alias; never prints passwords.
Verified locally on 2026-05-11:
{"accounts":20,"aliasFailures":[],"secretMode":"0o600","ok":true}
Webmail flow to implement/use
- Pick account and generate alias in one operation.
- Open/login
https://2925.com/login/orhttps://2925.com/#/mailList. - Verify displayed mailbox email equals picked account email.
- Clear inbox before triggering OpenAI code.
- Submit generated alias to OpenAI.
- Poll 2925 inbox: 15 attempts, 15s interval.
- Match OpenAI/auth/verify/code/login sender/subject/body; extract 6-digit code.
- Open matching mail, extract body code, delete mail, return inbox.
- Submit code; if invalid, add to rejectedCodes, resend, and continue polling.
- On 2925 limit, mark current account cooldown and restart with next account.