lijunke commited on
Commit
da3203c
·
1 Parent(s): 18081cf

Fix GPTMail code polling defaults and HF timeout stability

Browse files
.env.example CHANGED
@@ -27,10 +27,14 @@ ADMIN_KEY=your-admin-secret-key
27
  # 配置保存在 data/settings.yaml
28
  # ============================================
29
 
 
 
 
 
30
  # ============================================
31
  # 账户配置
32
  # ============================================
33
  # 使用 accounts.json 文件
34
  # 账户配置保存在 accounts.json 文件中
35
  # 首次启动时会自动创建空配置
36
- # 请在管理面板中添加账户,或直接编辑 accounts.json
 
27
  # 配置保存在 data/settings.yaml
28
  # ============================================
29
 
30
+ # 注册验证码轮询参数(可选,适合云环境/HuggingFace)
31
+ # REGISTER_CODE_TIMEOUT_SECONDS=60
32
+ # REGISTER_CODE_INTERVAL_SECONDS=5
33
+
34
  # ============================================
35
  # 账户配置
36
  # ============================================
37
  # 使用 accounts.json 文件
38
  # 账户配置保存在 accounts.json 文件中
39
  # 首次启动时会自动创建空配置
40
+ # 请在管理面板中添加账户,或直接编辑 accounts.json
core/config.py CHANGED
@@ -231,7 +231,7 @@ class ConfigManager:
231
  freemail_domain=str(basic_data.get("freemail_domain") or "").strip(),
232
  mail_proxy_enabled=_parse_bool(basic_data.get("mail_proxy_enabled"), False),
233
  gptmail_base_url=str(basic_data.get("gptmail_base_url") or "https://mail.chatgpt.org.uk").strip(),
234
- gptmail_api_key=str(basic_data.get("gptmail_api_key") or "").strip(),
235
  gptmail_verify_ssl=_parse_bool(basic_data.get("gptmail_verify_ssl"), True),
236
  gptmail_domain=str(basic_data.get("gptmail_domain") or "").strip(),
237
  cfmail_base_url=str(basic_data.get("cfmail_base_url") or "").strip(),
 
231
  freemail_domain=str(basic_data.get("freemail_domain") or "").strip(),
232
  mail_proxy_enabled=_parse_bool(basic_data.get("mail_proxy_enabled"), False),
233
  gptmail_base_url=str(basic_data.get("gptmail_base_url") or "https://mail.chatgpt.org.uk").strip(),
234
+ gptmail_api_key=str(basic_data.get("gptmail_api_key") or "gpt-test").strip(),
235
  gptmail_verify_ssl=_parse_bool(basic_data.get("gptmail_verify_ssl"), True),
236
  gptmail_domain=str(basic_data.get("gptmail_domain") or "").strip(),
237
  cfmail_base_url=str(basic_data.get("cfmail_base_url") or "").strip(),
core/gemini_automation.py CHANGED
@@ -293,17 +293,28 @@ class GeminiAutomation:
293
  self._save_screenshot(page, "code_input_missing")
294
  return {"success": False, "error": "code input not found"}
295
 
296
- # Step 5: 轮询邮件获取验证码(3次每次5秒间隔
297
- self._log("info", "📬 等待邮箱验证码...")
298
- code = mail_client.poll_for_code(timeout=15, interval=5, since_time=task_start_time)
 
 
 
 
 
 
 
 
 
 
 
299
 
300
  if not code:
301
  self._log("warning", "⚠️ 验证码超时,等待后重新发送...")
302
  time.sleep(random.uniform(12, 18))
303
  # 尝试点击重新发送按钮
304
  if self._click_resend_code_button(page):
305
- # 再次轮询验证码(3次,每次5秒间隔)
306
- code = mail_client.poll_for_code(timeout=15, interval=5, since_time=task_start_time)
307
  if not code:
308
  self._log("error", "❌ 重新发送后仍未收到验证码")
309
  self._save_screenshot(page, "code_timeout_after_resend")
 
293
  self._save_screenshot(page, "code_input_missing")
294
  return {"success": False, "error": "code input not found"}
295
 
296
+ # Step 5: 轮询邮件获取验证码(云环境默认延长支持环境变量覆盖
297
+ try:
298
+ code_timeout = int(str(os.getenv("REGISTER_CODE_TIMEOUT_SECONDS", "60")).strip() or "60")
299
+ except Exception:
300
+ code_timeout = 60
301
+ try:
302
+ code_interval = int(str(os.getenv("REGISTER_CODE_INTERVAL_SECONDS", "5")).strip() or "5")
303
+ except Exception:
304
+ code_interval = 5
305
+ code_timeout = max(15, code_timeout)
306
+ code_interval = max(2, code_interval)
307
+
308
+ self._log("info", f"📬 等待邮箱验证码... (timeout={code_timeout}s, interval={code_interval}s)")
309
+ code = mail_client.poll_for_code(timeout=code_timeout, interval=code_interval, since_time=task_start_time)
310
 
311
  if not code:
312
  self._log("warning", "⚠️ 验证码超时,等待后重新发送...")
313
  time.sleep(random.uniform(12, 18))
314
  # 尝试点击重新发送按钮
315
  if self._click_resend_code_button(page):
316
+ # 再次轮询验证码
317
+ code = mail_client.poll_for_code(timeout=code_timeout, interval=code_interval, since_time=task_start_time)
318
  if not code:
319
  self._log("error", "❌ 重新发送后仍未收到验证码")
320
  self._save_screenshot(page, "code_timeout_after_resend")
core/gptmail_client.py CHANGED
@@ -74,6 +74,22 @@ class GPTMailClient:
74
  pass
75
  return res
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  def generate_email(self, domain: Optional[str] = None) -> Optional[str]:
78
  """生成一个新的邮箱地址。"""
79
  if not self.base_url:
@@ -151,7 +167,11 @@ class GPTMailClient:
151
  self._log("info", "📭 邮箱为空,暂无邮件")
152
  return None
153
 
154
- emails = sorted(emails, key=lambda item: int(item.get("timestamp") or 0), reverse=True)
 
 
 
 
155
  self._log("info", f"📨 收到 {len(emails)} 封邮件,开始检查验证码...")
156
 
157
  for msg in emails:
@@ -161,12 +181,14 @@ class GPTMailClient:
161
 
162
  ts = msg.get("timestamp")
163
  if since_time and ts:
164
- try:
165
- msg_time = datetime.fromtimestamp(int(ts)).astimezone().replace(tzinfo=None)
166
- if msg_time < since_time:
167
- continue
168
- except Exception:
169
- pass
 
 
170
 
171
  content = (msg.get("content") or "") + (msg.get("html_content") or "")
172
  code = extract_verification_code(content)
@@ -203,17 +225,24 @@ class GPTMailClient:
203
  if not self.email:
204
  return None
205
 
206
- max_retries = max(1, timeout // interval)
 
 
207
  self._log("info", f"⏱️ 开始轮询验证码 (超时 {timeout}秒, 间隔 {interval}秒, 最多 {max_retries} 次)")
208
 
209
- for i in range(1, max_retries + 1):
210
- self._log("info", f"🔄 第 {i}/{max_retries} 次轮询...")
 
 
 
211
  code = self.fetch_verification_code(since_time=since_time)
212
  if code:
213
  self._log("info", f"🎉 验证码获取成功: {code}")
214
  return code
215
- if i < max_retries:
216
- time.sleep(interval)
 
 
217
 
218
- self._log("error", "❌ 验证码获取超时")
219
  return None
 
74
  pass
75
  return res
76
 
77
+ @staticmethod
78
+ def _normalize_unix_ts(value: Any) -> Optional[float]:
79
+ """兼容秒/毫秒时间戳,统一转换为秒。"""
80
+ if value in (None, ""):
81
+ return None
82
+ try:
83
+ ts = float(str(value).strip())
84
+ except Exception:
85
+ return None
86
+ # 毫秒时间戳降级为秒
87
+ if ts > 1e12:
88
+ ts /= 1000.0
89
+ if ts <= 0:
90
+ return None
91
+ return ts
92
+
93
  def generate_email(self, domain: Optional[str] = None) -> Optional[str]:
94
  """生成一个新的邮箱地址。"""
95
  if not self.base_url:
 
167
  self._log("info", "📭 邮箱为空,暂无邮件")
168
  return None
169
 
170
+ emails = sorted(
171
+ emails,
172
+ key=lambda item: self._normalize_unix_ts(item.get("timestamp")) or 0,
173
+ reverse=True,
174
+ )
175
  self._log("info", f"📨 收到 {len(emails)} 封邮件,开始检查验证码...")
176
 
177
  for msg in emails:
 
181
 
182
  ts = msg.get("timestamp")
183
  if since_time and ts:
184
+ ts_value = self._normalize_unix_ts(ts)
185
+ if ts_value:
186
+ try:
187
+ msg_time = datetime.fromtimestamp(ts_value)
188
+ if msg_time < since_time:
189
+ continue
190
+ except Exception:
191
+ pass
192
 
193
  content = (msg.get("content") or "") + (msg.get("html_content") or "")
194
  code = extract_verification_code(content)
 
225
  if not self.email:
226
  return None
227
 
228
+ timeout = max(1, int(timeout))
229
+ interval = max(1, int(interval))
230
+ max_retries = max(1, timeout // interval + 1)
231
  self._log("info", f"⏱️ 开始轮询验证码 (超时 {timeout}秒, 间隔 {interval}秒, 最多 {max_retries} 次)")
232
 
233
+ deadline = time.monotonic() + timeout
234
+ attempt = 0
235
+ while True:
236
+ attempt += 1
237
+ self._log("info", f"🔄 第 {attempt}/{max_retries} 次轮询...")
238
  code = self.fetch_verification_code(since_time=since_time)
239
  if code:
240
  self._log("info", f"🎉 验证码获取成功: {code}")
241
  return code
242
+ now = time.monotonic()
243
+ if now >= deadline:
244
+ break
245
+ time.sleep(min(interval, max(0.0, deadline - now)))
246
 
247
+ self._log("error", f"❌ 验证码获取超时 ({timeout}秒)")
248
  return None