Skip to content
This repository was archived by the owner on Apr 22, 2026. It is now read-only.

Commit fd7ecaa

Browse files
committed
release(v1.0.5): 集成Luckyous邮箱API并补全配置与提示
1 parent b5b4536 commit fd7ecaa

12 files changed

Lines changed: 811 additions & 4 deletions

README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ CodeX Register 是一个本地桌面化控制台,用于统一执行注册流
1111
## 1. 核心能力
1212

1313
- 工作台:启动/停止任务、实时日志、成功率、重试原因、SMS 消耗与余额统计。
14-
- 邮箱体系:支持 `Cloudflare Temp Email`[`MailFree`](https://github.com/Msg-Lbo/mailfree)`CloudMail``Mail-Curl``Gmail IMAP``Microsoft Graph`
14+
- 邮箱体系:支持 `Cloudflare Temp Email`[`MailFree`](https://github.com/Msg-Lbo/mailfree)`CloudMail``Mail-Curl`[`Luckyous API`](https://mails.luckyous.com/user/api-doc)`Gmail IMAP``Microsoft Graph`
1515
- MailFree 域名配置:可在 UI 内读取 Cloudflare Zone、管理 CNAME、并将 DNS 子域名批量同步到 MailFree 域名池(`/api/domains`)。
1616
- 代理能力:支持单代理或多代理轮换(逗号/空格/换行分隔);支持 [`FlClash`](https://github.com/chen08209/FlClash) 动态切节点、延迟探测、自动跳过香港节点。
1717
- 本地账号管理:SQLite(`local_accounts.db`)作为本地账号真源,支持导入、筛选、状态展示、导出与同步。
@@ -97,6 +97,7 @@ python gui.py --mode browser --no-auto-open
9797

9898
- 先选择 `mail_service_provider`
9999
- MailFree / Cloudflare Temp / CloudMail 可配置域名策略(随机域名、白名单、自定义 local-part)。
100+
- Luckyous API 支持按项目编码自动下单邮箱并轮询验证码。
100101
- Graph 模式需提供账号文件,支持启动前预刷新 token。
101102
- Gmail 模式需使用应用专用密码(非登录密码)。
102103

@@ -172,7 +173,7 @@ Cloudflare Token 要求(用于域名配置页读取 Zone 和管理 CNAME):
172173

173174
| 键名 | 类型 | 默认值 | 说明 |
174175
|---|---|---:|---|
175-
| `mail_service_provider` | string | `mailfree` | `cloudflare_temp_email` / `mailfree` / `cloudmail` / `mail_curl` / `gmail` / `graph` |
176+
| `mail_service_provider` | string | `mailfree` | `cloudflare_temp_email` / `mailfree` / `cloudmail` / `mail_curl` / `luckyous` / `gmail` / `graph` |
176177
| `mail_domains` | string | `""` | 通用域名池(主要用于 Cloudflare Temp / CloudMail) |
177178
| `mail_domain_allowlist` | array | `[]` | 注册域白名单 |
178179
| `mailfree_random_domain` | bool | `true` | 是否随机域名 |
@@ -196,7 +197,7 @@ Cloudflare Token 要求(用于域名配置页读取 Zone 和管理 CNAME):
196197
| `cf_dns_target_domain` | string | `""` | CNAME 目标域名默认值 |
197198
| `cf_temp_admin_auth` | string | `""` | Cloudflare Temp Email 管理员认证 |
198199

199-
### 6.5 CloudMail / Mail-Curl
200+
### 6.5 CloudMail / Mail-Curl / Luckyous
200201

201202
| 键名 | 类型 | 默认值 | 说明 |
202203
|---|---|---:|---|
@@ -205,6 +206,13 @@ Cloudflare Token 要求(用于域名配置页读取 Zone 和管理 CNAME):
205206
| `cloudmail_admin_password` | string | `""` | CloudMail 管理员密码 |
206207
| `mail_curl_api_base` | string | `""` | Mail-Curl API 地址 |
207208
| `mail_curl_key` | string | `""` | Mail-Curl Key |
209+
| `luckyous_api_base` | string | `https://mails.luckyous.com` | Luckyous API 地址 |
210+
| `luckyous_api_key` | string | `""` | Luckyous API Key(X-API-Key) |
211+
| `luckyous_project_code` | string | `""` | Luckyous 项目编码(必填) |
212+
| `luckyous_email_type` | string | `ms_graph` | Luckyous 邮箱类型(如 `ms_graph`|
213+
| `luckyous_domain` | string | `""` | Luckyous 指定域名(可选) |
214+
| `luckyous_variant_mode` | string | `""` | Luckyous 变种模式(可选:`dot/plus/mixed/all`|
215+
| `luckyous_specified_email` | string | `""` | Luckyous 指定邮箱(可选,优先于 domain) |
208216

209217
### 6.6 Gmail / Graph
210218

@@ -287,6 +295,7 @@ bob@outlook.com----pass456----yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy----0.AXEA...
287295
- 多代理请使用逗号/空格/换行分隔;
288296
- FlClash 仅有 1 个可用非香港节点时无法切换。
289297
- MailFree 域名同步失败:确认是严格管理员账号,且 MailFree 服务已升级到动态域名版本。
298+
- Luckyous 下单失败:检查 API Key、项目编码与账户余额是否可用。
290299
- `invalid_auth_step` 频繁:降低并发、提高代理质量、开启随机指纹。
291300
- Gmail 登录失败:必须用应用专用密码。
292301
- HeroSMS `NO_BALANCE`:充值或降低余额下限策略。

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.0.4
1+
1.0.5

codex_register/gui_config_store.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@
5151
"cloudmail_admin_password": "",
5252
"mail_curl_api_base": "",
5353
"mail_curl_key": "",
54+
"luckyous_api_base": "https://mails.luckyous.com",
55+
"luckyous_api_key": "",
56+
"luckyous_project_code": "",
57+
"luckyous_email_type": "ms_graph",
58+
"luckyous_domain": "",
59+
"luckyous_variant_mode": "",
60+
"luckyous_specified_email": "",
5461
"mail_service_provider": "mailfree",
5562
"graph_accounts_file": "",
5663
"graph_tenant": "common",
@@ -158,6 +165,13 @@ def load_config() -> dict[str, Any]:
158165
cfg["cloudmail_admin_password"] = env.get("CLOUDMAIL_ADMIN_PASSWORD", env.get("CM_ADMIN_PASS", ""))
159166
cfg["mail_curl_api_base"] = env.get("MAIL_CURL_API_BASE", env.get("MC_API_BASE", ""))
160167
cfg["mail_curl_key"] = env.get("MAIL_CURL_KEY", env.get("MC_KEY", ""))
168+
cfg["luckyous_api_base"] = env.get("LUCKYOUS_API_BASE", "https://mails.luckyous.com")
169+
cfg["luckyous_api_key"] = env.get("LUCKYOUS_API_KEY", "")
170+
cfg["luckyous_project_code"] = env.get("LUCKYOUS_PROJECT_CODE", "")
171+
cfg["luckyous_email_type"] = env.get("LUCKYOUS_EMAIL_TYPE", "ms_graph")
172+
cfg["luckyous_domain"] = env.get("LUCKYOUS_DOMAIN", "")
173+
cfg["luckyous_variant_mode"] = env.get("LUCKYOUS_VARIANT_MODE", "")
174+
cfg["luckyous_specified_email"] = env.get("LUCKYOUS_SPECIFIED_EMAIL", "")
161175
cfg["mail_service_provider"] = mode
162176
cfg["remote_account_provider"] = env.get("REMOTE_ACCOUNT_PROVIDER", cfg.get("remote_account_provider", "sub2api"))
163177
cfg["cliproxy_api_base"] = env.get("CLIPROXY_API_BASE", env.get("CLIPROXY_MANAGEMENT_API", ""))

codex_register/gui_frontend_app_setup.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@
113113
cloudmail_admin_password: "",
114114
mail_curl_api_base: "",
115115
mail_curl_key: "",
116+
luckyous_api_base: "https://mails.luckyous.com",
117+
luckyous_api_key: "",
118+
luckyous_project_code: "",
119+
luckyous_email_type: "ms_graph",
120+
luckyous_domain: "",
121+
luckyous_variant_mode: "",
122+
luckyous_specified_email: "",
116123
graph_accounts_file: "",
117124
graph_tenant: "common",
118125
graph_fetch_mode: "graph_api",
@@ -950,6 +957,7 @@
950957
}
951958
if (["cloudmail", "cloud_mail"].includes(val)) return "cloudmail";
952959
if (["mail_curl", "mailcurl", "curl_mail"].includes(val)) return "mail_curl";
960+
if (["luckyous", "luckyous_api", "luckymail", "lucky_mail", "luckyous_openapi"].includes(val)) return "luckyous";
953961
if (val === "graph") return "graph";
954962
if (val === "gmail" || val === "imap") return "gmail";
955963
return "mailfree";
@@ -1505,6 +1513,13 @@
15051513
settingsForm.cloudmail_admin_password = String(cfg.cloudmail_admin_password || "");
15061514
settingsForm.mail_curl_api_base = String(cfg.mail_curl_api_base || "");
15071515
settingsForm.mail_curl_key = String(cfg.mail_curl_key || "");
1516+
settingsForm.luckyous_api_base = String(cfg.luckyous_api_base || "https://mails.luckyous.com");
1517+
settingsForm.luckyous_api_key = String(cfg.luckyous_api_key || "");
1518+
settingsForm.luckyous_project_code = String(cfg.luckyous_project_code || "");
1519+
settingsForm.luckyous_email_type = String(cfg.luckyous_email_type || "ms_graph");
1520+
settingsForm.luckyous_domain = String(cfg.luckyous_domain || "");
1521+
settingsForm.luckyous_variant_mode = String(cfg.luckyous_variant_mode || "");
1522+
settingsForm.luckyous_specified_email = String(cfg.luckyous_specified_email || "");
15081523
settingsForm.graph_accounts_file = String(cfg.graph_accounts_file || "");
15091524
settingsForm.graph_tenant = String(cfg.graph_tenant || "common");
15101525
settingsForm.graph_fetch_mode = String(cfg.graph_fetch_mode || "graph_api");
@@ -1588,6 +1603,13 @@
15881603
cloudmail_admin_password: String(settingsForm.cloudmail_admin_password || "").trim(),
15891604
mail_curl_api_base: String(settingsForm.mail_curl_api_base || "").trim(),
15901605
mail_curl_key: String(settingsForm.mail_curl_key || "").trim(),
1606+
luckyous_api_base: String(settingsForm.luckyous_api_base || "https://mails.luckyous.com").trim(),
1607+
luckyous_api_key: String(settingsForm.luckyous_api_key || "").trim(),
1608+
luckyous_project_code: String(settingsForm.luckyous_project_code || "").trim(),
1609+
luckyous_email_type: String(settingsForm.luckyous_email_type || "ms_graph").trim(),
1610+
luckyous_domain: String(settingsForm.luckyous_domain || "").trim(),
1611+
luckyous_variant_mode: String(settingsForm.luckyous_variant_mode || "").trim(),
1612+
luckyous_specified_email: String(settingsForm.luckyous_specified_email || "").trim(),
15911613
graph_accounts_file: String(settingsForm.graph_accounts_file || "").trim(),
15921614
graph_tenant: String(settingsForm.graph_tenant || "common").trim(),
15931615
graph_fetch_mode: String(settingsForm.graph_fetch_mode || "graph_api").trim(),

codex_register/gui_frontend_app_template.html

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,9 @@ <h1>注册任务面板</h1>
369369
<n-tab-pane name="mail_curl" tab="Mail-Curl">
370370
<span style="display:none"></span>
371371
</n-tab-pane>
372+
<n-tab-pane name="luckyous" tab="Luckyous API">
373+
<span style="display:none"></span>
374+
</n-tab-pane>
372375
<n-tab-pane name="gmail" tab="Gmail IMAP">
373376
<span style="display:none"></span>
374377
</n-tab-pane>
@@ -541,6 +544,15 @@ <h1>注册任务面板</h1>
541544
<n-input class="toolbar-path" v-model:value="settingsForm.mail_curl_api_base" placeholder="Mail-Curl API 地址" />
542545
<n-input class="toolbar-path" v-model:value="settingsForm.mail_curl_key" type="password" show-password-on="click" placeholder="Mail-Curl Key" />
543546
</div>
547+
<div v-else-if="mailProviderTab === 'luckyous'" class="toolbar" style="margin-top: 10px">
548+
<n-input class="toolbar-path" v-model:value="settingsForm.luckyous_api_base" placeholder="Luckyous API 地址(默认 https://mails.luckyous.com)" />
549+
<n-input class="toolbar-path" v-model:value="settingsForm.luckyous_api_key" type="password" show-password-on="click" placeholder="Luckyous API Key(X-API-Key)" />
550+
<n-input class="toolbar-path" v-model:value="settingsForm.luckyous_project_code" placeholder="项目编码(例如 twitter)" />
551+
<n-input class="toolbar-path" v-model:value="settingsForm.luckyous_email_type" placeholder="邮箱类型(默认 ms_graph)" />
552+
<n-input class="toolbar-path" v-model:value="settingsForm.luckyous_domain" placeholder="指定域名(可选,如 outlook.com)" />
553+
<n-input class="toolbar-path" v-model:value="settingsForm.luckyous_variant_mode" placeholder="变种模式(可选:dot/plus/mixed/all)" />
554+
<n-input class="toolbar-path" v-model:value="settingsForm.luckyous_specified_email" placeholder="指定邮箱(可选,优先于 domain)" />
555+
</div>
544556
<div v-else-if="mailProviderTab === 'gmail'" class="toolbar" style="margin-top: 10px">
545557
<n-input
546558
class="toolbar-path"
@@ -635,6 +647,9 @@ <h1>注册任务面板</h1>
635647
<div v-if="mailProviderTab === 'mail_curl'" class="meta" style="margin-top: 6px">
636648
Mail-Curl 通过 <code>/api/remail</code> 创建邮箱,邮件读取依赖本地邮箱-ID 映射。
637649
</div>
650+
<div v-if="mailProviderTab === 'luckyous'" class="meta" style="margin-top: 6px">
651+
Luckyous API 使用 <code>/api/v1/openapi/order/create</code> 下单并通过 <code>/order/{order_no}/code</code> 轮询验证码。
652+
</div>
638653
<div v-if="mailProviderTab === 'graph'" class="meta" style="margin-top: 6px">
639654
文件格式要求:每行必须为 <code>邮箱----密码----client_id----令牌</code>(共 4 段,使用四个中划线分隔)。
640655
</div>

codex_register/gui_service.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,9 @@ def _config_health_locked(self) -> tuple[list[str], list[str]]:
10411041
cloudmail_admin_password = str(cfg.get("cloudmail_admin_password") or "").strip()
10421042
mail_curl_api_base = str(cfg.get("mail_curl_api_base") or "").strip()
10431043
mail_curl_key = str(cfg.get("mail_curl_key") or "").strip()
1044+
luckyous_api_base = str(cfg.get("luckyous_api_base") or "").strip()
1045+
luckyous_api_key = str(cfg.get("luckyous_api_key") or "").strip()
1046+
luckyous_project_code = str(cfg.get("luckyous_project_code") or "").strip()
10441047
graph_file = str(cfg.get("graph_accounts_file") or "").strip()
10451048
gmail_user = str(cfg.get("gmail_imap_user") or "").strip()
10461049
gmail_pass = str(cfg.get("gmail_imap_pass") or "").strip()
@@ -1080,6 +1083,13 @@ def _config_health_locked(self) -> tuple[list[str], list[str]]:
10801083
blockers.append("Mail-Curl API 地址未填写(mail_curl_api_base)")
10811084
if not mail_curl_key:
10821085
blockers.append("Mail-Curl Key 未填写(mail_curl_key)")
1086+
elif provider == "luckyous":
1087+
if not luckyous_api_base:
1088+
blockers.append("Luckyous API 地址未填写(luckyous_api_base)")
1089+
if not luckyous_api_key:
1090+
blockers.append("Luckyous API Key 未填写(luckyous_api_key)")
1091+
if not luckyous_project_code:
1092+
blockers.append("Luckyous 项目编码未填写(luckyous_project_code)")
10831093
elif provider == "gmail":
10841094
if not gmail_user:
10851095
blockers.append("Gmail IMAP 账号未填写(gmail_imap_user)")
@@ -1454,6 +1464,13 @@ def update_config(self, data: dict[str, Any], emit_log: bool = True) -> dict[str
14541464
"cloudmail_admin_password",
14551465
"mail_curl_api_base",
14561466
"mail_curl_key",
1467+
"luckyous_api_base",
1468+
"luckyous_api_key",
1469+
"luckyous_project_code",
1470+
"luckyous_email_type",
1471+
"luckyous_domain",
1472+
"luckyous_variant_mode",
1473+
"luckyous_specified_email",
14571474
"graph_accounts_file",
14581475
"graph_tenant",
14591476
"graph_fetch_mode",
@@ -1604,6 +1621,16 @@ def update_config(self, data: dict[str, Any], emit_log: bool = True) -> dict[str
16041621
str(cfg.get("cf_worker_mail_domain_binding") or "MAIL_DOMAIN").strip() or "MAIL_DOMAIN"
16051622
)
16061623
cfg["cf_dns_target_domain"] = str(cfg.get("cf_dns_target_domain") or "").strip().lower()
1624+
cfg["luckyous_api_base"] = (
1625+
str(cfg.get("luckyous_api_base") or "https://mails.luckyous.com").strip()
1626+
or "https://mails.luckyous.com"
1627+
)
1628+
cfg["luckyous_api_key"] = str(cfg.get("luckyous_api_key") or "").strip()
1629+
cfg["luckyous_project_code"] = str(cfg.get("luckyous_project_code") or "").strip()
1630+
cfg["luckyous_email_type"] = str(cfg.get("luckyous_email_type") or "ms_graph").strip().lower()
1631+
cfg["luckyous_domain"] = str(cfg.get("luckyous_domain") or "").strip().lower()
1632+
cfg["luckyous_variant_mode"] = str(cfg.get("luckyous_variant_mode") or "").strip().lower()
1633+
cfg["luckyous_specified_email"] = str(cfg.get("luckyous_specified_email") or "").strip().lower()
16071634
graph_mode = str(cfg.get("graph_fetch_mode") or "graph_api").strip().lower()
16081635
if graph_mode not in {"graph_api", "imap_xoauth2"}:
16091636
graph_mode = "graph_api"
@@ -1715,6 +1742,17 @@ def _apply_to_env(self) -> None:
17151742
os.environ["CLOUDMAIL_ADMIN_PASSWORD"] = str(self.cfg.get("cloudmail_admin_password") or "")
17161743
os.environ["MAIL_CURL_API_BASE"] = str(self.cfg.get("mail_curl_api_base") or "").strip()
17171744
os.environ["MAIL_CURL_KEY"] = str(self.cfg.get("mail_curl_key") or "")
1745+
os.environ["LUCKYOUS_API_BASE"] = str(
1746+
self.cfg.get("luckyous_api_base") or "https://mails.luckyous.com"
1747+
).strip()
1748+
os.environ["LUCKYOUS_API_KEY"] = str(self.cfg.get("luckyous_api_key") or "").strip()
1749+
os.environ["LUCKYOUS_PROJECT_CODE"] = str(self.cfg.get("luckyous_project_code") or "").strip()
1750+
os.environ["LUCKYOUS_EMAIL_TYPE"] = str(self.cfg.get("luckyous_email_type") or "ms_graph").strip().lower()
1751+
os.environ["LUCKYOUS_DOMAIN"] = str(self.cfg.get("luckyous_domain") or "").strip().lower()
1752+
os.environ["LUCKYOUS_VARIANT_MODE"] = str(self.cfg.get("luckyous_variant_mode") or "").strip().lower()
1753+
os.environ["LUCKYOUS_SPECIFIED_EMAIL"] = str(
1754+
self.cfg.get("luckyous_specified_email") or ""
1755+
).strip().lower()
17181756
os.environ["MAIL_SERVICE_PROVIDER"] = normalize_mail_provider(
17191757
self.cfg.get("mail_service_provider") or "mailfree"
17201758
)
@@ -2543,6 +2581,12 @@ def _worker(self) -> None:
25432581
domain = cf_domain
25442582
if cf_domains_raw:
25452583
mail_domains_raw = cf_domains_raw
2584+
elif mail_provider == "luckyous":
2585+
lucky_base = str(
2586+
self.cfg.get("luckyous_api_base") or "https://mails.luckyous.com"
2587+
).strip()
2588+
if lucky_base:
2589+
domain = lucky_base
25462590
if domain and not domain.startswith("http"):
25472591
domain = f"https://{domain}"
25482592

@@ -2623,6 +2667,26 @@ def _worker(self) -> None:
26232667
"配置 -> "
26242668
f"mail={mail_provider}, api={mc_api}, key={mc_mask}"
26252669
)
2670+
elif mail_provider == "luckyous":
2671+
lucky_api = str(
2672+
self.cfg.get("luckyous_api_base") or "https://mails.luckyous.com"
2673+
).strip()
2674+
lucky_key = str(self.cfg.get("luckyous_api_key") or "")
2675+
lucky_key_mask = (
2676+
lucky_key[:4] + "***"
2677+
if len(lucky_key) >= 4
2678+
else ("***" if lucky_key else "")
2679+
)
2680+
lucky_project = str(self.cfg.get("luckyous_project_code") or "").strip()
2681+
lucky_type = str(self.cfg.get("luckyous_email_type") or "ms_graph").strip().lower()
2682+
lucky_domain = str(self.cfg.get("luckyous_domain") or "").strip().lower()
2683+
lucky_mode = str(self.cfg.get("luckyous_variant_mode") or "").strip().lower()
2684+
self.log(
2685+
"配置 -> "
2686+
f"mail={mail_provider}, api={lucky_api}, key={lucky_key_mask}, "
2687+
f"project={lucky_project or '-'}, type={lucky_type or '-'}, "
2688+
f"domain={lucky_domain or '-'}, variant={lucky_mode or '-'}"
2689+
)
26262690
else:
26272691
gmail_user = str(self.cfg.get("gmail_imap_user") or "").strip().lower()
26282692
gmail_server = (

0 commit comments

Comments
 (0)