mirror of
https://github.com/ddCat-main/cursor-auto-register.git
synced 2025-12-24 13:38:01 +08:00
feat: 添加自定义邮箱注册功能,支持手动输入验证码并优化相关逻辑;更新前端界面以支持新功能。
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -52,3 +52,4 @@ temp/
|
||||
*.pem
|
||||
*.key
|
||||
credentials.json
|
||||
.history
|
||||
151
api.py
151
api.py
@@ -1,6 +1,6 @@
|
||||
from fastapi import FastAPI, HTTPException, status, UploadFile, Request
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional, List
|
||||
from typing import Optional, List, Dict
|
||||
from sqlalchemy import select, func, delete, desc
|
||||
from pathlib import Path
|
||||
from database import get_session, AccountModel, AccountUsageRecordModel, init_db
|
||||
@@ -29,6 +29,12 @@ from fastapi.staticfiles import StaticFiles
|
||||
from dotenv import load_dotenv
|
||||
import json
|
||||
import time
|
||||
import uuid
|
||||
|
||||
# 从get_email_code.py导入验证码请求字典
|
||||
from get_email_code import EmailVerificationHandler
|
||||
# 修改为直接访问get_email_code模块
|
||||
import get_email_code
|
||||
|
||||
# 全局状态追踪
|
||||
registration_status = {
|
||||
@@ -48,6 +54,9 @@ static_path.mkdir(exist_ok=True) # 确保目录存在
|
||||
# 全局任务存储
|
||||
background_tasks = {"registration_task": None}
|
||||
|
||||
# 添加用于存储等待验证码的邮箱信息的全局字典
|
||||
# pending_verification_codes = {}
|
||||
|
||||
|
||||
# 添加lifespan管理器,在应用启动时初始化数据库
|
||||
@asynccontextmanager
|
||||
@@ -168,9 +177,9 @@ async def run_registration():
|
||||
info("注册失败")
|
||||
except SystemExit:
|
||||
# 捕获 SystemExit 异常,这是注册脚本正常退出的方式
|
||||
info("注册脚本正常退出")
|
||||
if registration_status["last_status"] != "error":
|
||||
registration_status["last_status"] = "completed"
|
||||
info("注册脚本通过sys.exit退出")
|
||||
registration_status["successful_runs"] += 1
|
||||
registration_status["last_status"] = "completed"
|
||||
except Exception as e:
|
||||
error(f"注册过程执行出错: {str(e)}")
|
||||
error(traceback.format_exc())
|
||||
@@ -1423,7 +1432,141 @@ async def restart_service():
|
||||
return {"success": False, "message": f"重启服务失败: {str(e)}"}
|
||||
|
||||
|
||||
class CustomRegistrationRequest(BaseModel):
|
||||
email: str
|
||||
|
||||
@app.post("/registration/custom", tags=["Registration"])
|
||||
async def register_with_custom_email(request: CustomRegistrationRequest):
|
||||
"""使用自定义邮箱注册Cursor账号"""
|
||||
global registration_status
|
||||
|
||||
if registration_status["is_running"]:
|
||||
return JSONResponse(
|
||||
status_code=400,
|
||||
content={
|
||||
"success": False,
|
||||
"message": "当前有注册任务正在运行,请先停止当前任务"
|
||||
}
|
||||
)
|
||||
|
||||
count = await get_active_account_count()
|
||||
if count >= MAX_ACCOUNTS:
|
||||
return JSONResponse(
|
||||
status_code=400,
|
||||
content={
|
||||
"success": False,
|
||||
"message": f"已达到最大账号数量 ({count}/{MAX_ACCOUNTS})"
|
||||
}
|
||||
)
|
||||
|
||||
# 验证邮箱格式
|
||||
if "@" not in request.email:
|
||||
return JSONResponse(
|
||||
status_code=400,
|
||||
content={
|
||||
"success": False,
|
||||
"message": "邮箱格式不正确,请提供正确的邮箱地址"
|
||||
}
|
||||
)
|
||||
|
||||
try:
|
||||
info(f"开始使用自定义邮箱注册: {request.email}")
|
||||
|
||||
# 调用注册函数,传入自定义邮箱
|
||||
try:
|
||||
success = await asyncio.get_event_loop().run_in_executor(
|
||||
None, lambda: register_account(custom_email=request.email)
|
||||
)
|
||||
|
||||
if success:
|
||||
return JSONResponse(
|
||||
content={
|
||||
"success": True,
|
||||
"message": f"使用邮箱 {request.email} 注册成功"
|
||||
}
|
||||
)
|
||||
else:
|
||||
return JSONResponse(
|
||||
status_code=500,
|
||||
content={
|
||||
"success": False,
|
||||
"message": f"使用邮箱 {request.email} 注册失败"
|
||||
}
|
||||
)
|
||||
except SystemExit:
|
||||
# 处理注册函数通过sys.exit退出的情况
|
||||
info("注册函数通过sys.exit退出,可能已成功注册")
|
||||
return JSONResponse(
|
||||
content={
|
||||
"success": True,
|
||||
"message": f"使用邮箱 {request.email} 注册过程完成,请检查账号列表"
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
error(f"使用自定义邮箱注册过程出错: {str(e)}")
|
||||
error(traceback.format_exc())
|
||||
return JSONResponse(
|
||||
status_code=500,
|
||||
content={
|
||||
"success": False,
|
||||
"message": f"注册过程出错: {str(e)}"
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@app.get("/verification/pending")
|
||||
async def check_pending_verification():
|
||||
"""检查是否有等待验证码输入的请求"""
|
||||
# 返回所有等待验证的邮箱ID及邮箱地址
|
||||
result = []
|
||||
for email_id, email_info in get_email_code.pending_verification_codes.items():
|
||||
if email_info.get("status") == "pending":
|
||||
result.append({
|
||||
"id": email_id,
|
||||
"email": email_info.get("email"),
|
||||
"created_at": email_info.get("created_at")
|
||||
})
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"data": result
|
||||
}
|
||||
|
||||
@app.post("/verification/submit")
|
||||
async def submit_verification_code(code_data: Dict):
|
||||
"""提交验证码"""
|
||||
email_id = code_data.get("id")
|
||||
code = code_data.get("code")
|
||||
|
||||
if not email_id or not code:
|
||||
return {
|
||||
"success": False,
|
||||
"message": "缺少必要参数"
|
||||
}
|
||||
|
||||
if email_id not in get_email_code.pending_verification_codes:
|
||||
return {
|
||||
"success": False,
|
||||
"message": "未找到对应的验证请求"
|
||||
}
|
||||
|
||||
# 更新状态和验证码
|
||||
get_email_code.pending_verification_codes[email_id]["status"] = "submitted"
|
||||
get_email_code.pending_verification_codes[email_id]["code"] = code
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "验证码已提交"
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 设置Web模式环境变量
|
||||
os.environ["CURSOR_AUTO_REGISTER_WEB"] = "true"
|
||||
|
||||
# 启动服务器
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run(
|
||||
"api:app",
|
||||
host=API_HOST,
|
||||
|
||||
@@ -11,7 +11,9 @@ from config import (
|
||||
EMAIL_DOMAINS,
|
||||
REGISTRATION_MAX_RETRIES,
|
||||
EMAIL_TYPE,
|
||||
EMAIL_CODE_TYPE
|
||||
EMAIL_CODE_TYPE,
|
||||
EMAIL_USERNAME,
|
||||
EMAIL_DOMAIN
|
||||
)
|
||||
|
||||
|
||||
@@ -182,7 +184,7 @@ def sign_up_account(browser, tab, account_info):
|
||||
if (
|
||||
tab.ele("verify the user is human. Please try again.")
|
||||
or tab.ele("Can't verify the user is human. Please try again.")
|
||||
or tab.ele("Can‘t verify the user is human. Please try again.")
|
||||
or tab.ele("Can't verify the user is human. Please try again.")
|
||||
):
|
||||
info("检测到turnstile验证失败,(IP问题、UA问题、域名问题)...正在重试...")
|
||||
return "EMAIL_USED"
|
||||
@@ -223,8 +225,8 @@ def sign_up_account(browser, tab, account_info):
|
||||
info("注册限制")
|
||||
return "SIGNUP_RESTRICTED"
|
||||
|
||||
# 创建邮件处理器
|
||||
email_handler = EmailVerificationHandler()
|
||||
# 创建邮件处理器,传入自定义邮箱
|
||||
email_handler = EmailVerificationHandler(custom_email=account_info["email"])
|
||||
i = 0
|
||||
while i < 5:
|
||||
try:
|
||||
@@ -234,10 +236,26 @@ def sign_up_account(browser, tab, account_info):
|
||||
break
|
||||
if tab.ele("@data-index=0"):
|
||||
info("等待输入验证码...")
|
||||
# 切换到邮箱标签页
|
||||
|
||||
# 声明全局变量
|
||||
global EMAIL_CODE_TYPE
|
||||
# 获取当前的EMAIL_CODE_TYPE值
|
||||
local_email_code_type = EMAIL_CODE_TYPE
|
||||
if account_info["email"] != f"{EMAIL_USERNAME}@{EMAIL_DOMAIN}":
|
||||
info(f"检测到使用自定义邮箱 {account_info['email']},确保使用手动输入验证码")
|
||||
# 使用自定义邮箱时确保使用手动输入
|
||||
if EMAIL_CODE_TYPE != "INPUT":
|
||||
EMAIL_CODE_TYPE = "INPUT"
|
||||
|
||||
# 切换到邮箱标签页获取验证码
|
||||
code = email_handler.get_verification_code(
|
||||
source_email=account_info["email"]
|
||||
)
|
||||
|
||||
# 如果临时修改了EMAIL_CODE_TYPE,恢复原值
|
||||
if EMAIL_CODE_TYPE != local_email_code_type:
|
||||
EMAIL_CODE_TYPE = local_email_code_type
|
||||
|
||||
if code is None:
|
||||
info("未获取到验证码...系统异常,正在退出....")
|
||||
return "EMAIL_GET_CODE_FAILED"
|
||||
@@ -329,9 +347,9 @@ class EmailGenerator:
|
||||
domain = random.choice(self.domains)
|
||||
return f"{random_str}@{domain}"
|
||||
|
||||
def get_account_info(self):
|
||||
"""获取账号信息,确保每次调用都生成新的邮箱和密码"""
|
||||
self.email = self.generate_email()
|
||||
def get_account_info(self, email=None):
|
||||
"""获取账号信息,确保每次调用都生成新的邮箱和密码,或使用提供的邮箱"""
|
||||
self.email = email if email else self.generate_email()
|
||||
self.password = self.generate_random_password()
|
||||
return {
|
||||
"email": self.email,
|
||||
@@ -417,19 +435,29 @@ def cleanup_and_exit(browser_manager=None, exit_code=0):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
def main(custom_email=None):
|
||||
browser_manager = None
|
||||
max_retries = REGISTRATION_MAX_RETRIES # 从配置文件获取
|
||||
current_retry = 0
|
||||
|
||||
# 先声明全局变量并保存原始值
|
||||
global EMAIL_CODE_TYPE
|
||||
original_email_code_type = EMAIL_CODE_TYPE
|
||||
|
||||
try:
|
||||
email_handler = EmailVerificationHandler()
|
||||
# 如果使用自定义邮箱,切换验证码获取模式为手动输入
|
||||
if custom_email:
|
||||
info(f"使用自定义邮箱 {custom_email},切换为手动输入验证码模式")
|
||||
EMAIL_CODE_TYPE = "INPUT"
|
||||
|
||||
# 初始化邮箱验证处理器时传入自定义邮箱
|
||||
email_handler = EmailVerificationHandler(custom_email=custom_email)
|
||||
if email_handler.check():
|
||||
info('邮箱服务连接正常,开始注册!')
|
||||
else:
|
||||
if EMAIL_CODE_TYPE == "API":
|
||||
error('邮箱服务连接失败,并且验证码为API获取,结束注册!')
|
||||
return
|
||||
return False
|
||||
else:
|
||||
info('邮箱服务连接失败,并且验证码为手动输入,等待输入验证码...')
|
||||
|
||||
@@ -438,7 +466,8 @@ def main():
|
||||
browser = browser_manager.init_browser()
|
||||
while current_retry < max_retries:
|
||||
try:
|
||||
account_info = email_generator.get_account_info()
|
||||
# 使用自定义邮箱或生成新邮箱
|
||||
account_info = email_generator.get_account_info(email=custom_email)
|
||||
info(
|
||||
f"初始化账号信息成功 => 邮箱: {account_info['email']}, 用户名: {account_info['first_name']}, 密码: {account_info['password']}"
|
||||
)
|
||||
@@ -455,7 +484,10 @@ def main():
|
||||
if token:
|
||||
email_generator._save_account_info(user, token, TOTAL_USAGE)
|
||||
info("注册流程完成")
|
||||
cleanup_and_exit(browser_manager, 0)
|
||||
# 关闭资源但不退出程序,只返回成功状态
|
||||
if browser_manager and hasattr(browser_manager, "browser"):
|
||||
browser_manager.browser.quit()
|
||||
return True
|
||||
else:
|
||||
info("获取Cursor会话Token失败")
|
||||
current_retry += 1
|
||||
@@ -487,9 +519,19 @@ def main():
|
||||
pass
|
||||
|
||||
info(f"达到最大重试次数 {max_retries},注册失败")
|
||||
return False
|
||||
except Exception as e:
|
||||
info(f"主程序错误: {str(e)}")
|
||||
info(f"错误详情: {traceback.format_exc()}")
|
||||
cleanup_and_exit(browser_manager, 1)
|
||||
return False
|
||||
finally:
|
||||
cleanup_and_exit(browser_manager, 1)
|
||||
# 恢复原始的EMAIL_CODE_TYPE
|
||||
EMAIL_CODE_TYPE = original_email_code_type
|
||||
|
||||
# 清理资源
|
||||
if browser_manager:
|
||||
try:
|
||||
if hasattr(browser_manager, "browser"):
|
||||
browser_manager.browser.quit()
|
||||
except Exception as e:
|
||||
error(f"关闭浏览器时发生错误: {str(e)}")
|
||||
|
||||
@@ -7,6 +7,9 @@ def warn(message):
|
||||
import time
|
||||
import re
|
||||
import requests
|
||||
import os
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from config import (
|
||||
EMAIL_USERNAME,
|
||||
EMAIL_DOMAIN,
|
||||
@@ -17,13 +20,22 @@ from config import (
|
||||
EMAIL_PROXY_ADDRESS,
|
||||
EMAIL_PROXY_ENABLED,
|
||||
EMAIL_API,
|
||||
EMAIL_CODE_TYPE
|
||||
EMAIL_CODE_TYPE,
|
||||
EMAIL_DOMAINS
|
||||
)
|
||||
|
||||
# 声明全局变量用于存储验证码请求
|
||||
pending_verification_codes = {}
|
||||
|
||||
class EmailVerificationHandler:
|
||||
def __init__(self, username=None, domain=None, pin=None, use_proxy=False):
|
||||
def __init__(self, username=None, domain=None, pin=None, use_proxy=False, custom_email=None):
|
||||
self.email = EMAIL_TYPE
|
||||
self.custom_email = custom_email
|
||||
|
||||
# 如果提供了自定义邮箱,则解析它
|
||||
if custom_email and '@' in custom_email:
|
||||
username, domain = custom_email.split('@', 1)
|
||||
|
||||
self.username = username or EMAIL_USERNAME
|
||||
self.domain = domain or EMAIL_DOMAIN
|
||||
self.session = requests.Session()
|
||||
@@ -51,7 +63,14 @@ class EmailVerificationHandler:
|
||||
info(f"已启用代理: {EMAIL_PROXY_ADDRESS}")
|
||||
|
||||
def check(self):
|
||||
mail_list_url = f"https://tempmail.plus/api/mails?email={self.username}%40{self.domain}&limit=20&epin={self.pin}"
|
||||
# 如果有自定义邮箱,优先使用它
|
||||
username = self.username
|
||||
domain = self.domain
|
||||
if self.custom_email and '@' in self.custom_email:
|
||||
username, domain = self.custom_email.split('@', 1)
|
||||
info(f"使用自定义邮箱进行连接检查: {username}@{domain}")
|
||||
|
||||
mail_list_url = f"https://tempmail.plus/api/mails?email={username}%40{domain}&limit=20&epin={self.pin}"
|
||||
try:
|
||||
# 增加超时时间并添加错误重试
|
||||
for retry in range(3):
|
||||
@@ -97,11 +116,22 @@ class EmailVerificationHandler:
|
||||
Returns:
|
||||
str: 验证码或None
|
||||
"""
|
||||
# 如果邮箱验证码获取方式为输入,则直接返回输入的验证码
|
||||
# 记录当前的验证码获取模式和邮箱信息
|
||||
info(f"验证码获取模式: {EMAIL_CODE_TYPE}, 使用邮箱: {source_email}")
|
||||
|
||||
# 首先检查是否是自定义邮箱(非系统配置的邮箱)
|
||||
if source_email and '@' in source_email:
|
||||
username, domain = source_email.split('@', 1)
|
||||
if username != EMAIL_USERNAME or domain != EMAIL_DOMAIN:
|
||||
info(f"检测到使用非系统配置邮箱: {source_email},强制使用手动输入模式")
|
||||
return self.prompt_manual_code(source_email)
|
||||
|
||||
# 如果是INPUT模式,始终直接进入手动输入
|
||||
if EMAIL_CODE_TYPE == "INPUT":
|
||||
info("EMAIL_CODE_TYPE设为INPUT,跳过自动获取,直接手动输入")
|
||||
return self.prompt_manual_code()
|
||||
return self.prompt_manual_code(source_email)
|
||||
|
||||
# 以下是自动获取验证码的逻辑,只有在EMAIL_CODE_TYPE不是INPUT且不是自定义邮箱时才会执行
|
||||
max_retries = max_retries or EMAIL_VERIFICATION_RETRIES
|
||||
wait_time = wait_time or EMAIL_VERIFICATION_WAIT
|
||||
info(f"开始获取邮箱验证码=>最大重试次数:{max_retries}, 等待时间:{wait_time}")
|
||||
@@ -110,7 +140,7 @@ class EmailVerificationHandler:
|
||||
if self.email not in ["tempemail", "zmail"]:
|
||||
error(f"不支持的邮箱类型: {self.email},支持的类型为: tempemail, zmail")
|
||||
warn("自动切换到手动输入模式")
|
||||
return self.prompt_manual_code()
|
||||
return self.prompt_manual_code(source_email)
|
||||
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
@@ -142,20 +172,77 @@ class EmailVerificationHandler:
|
||||
# 所有自动尝试都失败后,询问是否手动输入
|
||||
response = input("自动获取验证码失败,是否手动输入? (y/n): ").lower()
|
||||
if response == 'y':
|
||||
return self.prompt_manual_code()
|
||||
return self.prompt_manual_code(source_email)
|
||||
return None
|
||||
|
||||
# 手动输入验证码
|
||||
def prompt_manual_code(self):
|
||||
"""手动输入验证码"""
|
||||
info("自动获取验证码失败,开始手动输入验证码。")
|
||||
code = input("输入6位数字验证码: ").strip()
|
||||
return code
|
||||
# 手动输入验证码 - 添加前端输入支持
|
||||
def prompt_manual_code(self, source_email=None):
|
||||
"""手动输入验证码,支持前端输入"""
|
||||
email_display = source_email if source_email else f"{self.username}@{self.domain}"
|
||||
info("=============手动输入验证码模式=============")
|
||||
info(f"请查看邮箱 [{email_display}] 中的验证码")
|
||||
|
||||
# 检查是否有CURSOR_AUTO_REGISTER_WEB环境变量,表示是否通过Web界面运行
|
||||
web_mode = os.environ.get("CURSOR_AUTO_REGISTER_WEB", "").lower() == "true"
|
||||
|
||||
if web_mode:
|
||||
info("检测到Web模式,使用前端验证码输入")
|
||||
return self.prompt_manual_code_web(email_display)
|
||||
else:
|
||||
info("命令行模式,使用控制台输入验证码")
|
||||
info("通常验证码为6位数字,在邮件正文中")
|
||||
code = input("请输入收到的验证码: ").strip()
|
||||
info(f"已输入验证码: {code}")
|
||||
return code
|
||||
|
||||
# 前端验证码输入方法
|
||||
def prompt_manual_code_web(self, source_email):
|
||||
"""在Web界面请求验证码输入"""
|
||||
# 生成唯一ID
|
||||
email_id = str(uuid.uuid4())
|
||||
|
||||
# 存储到等待字典中
|
||||
global pending_verification_codes
|
||||
pending_verification_codes[email_id] = {
|
||||
"email": source_email,
|
||||
"status": "pending",
|
||||
"created_at": datetime.now().isoformat(),
|
||||
"code": None
|
||||
}
|
||||
|
||||
info(f"已创建验证码请求 ID: {email_id},等待前端输入验证码")
|
||||
|
||||
# 循环等待验证码输入,最多等待180秒
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < 180:
|
||||
# 检查是否已提交验证码
|
||||
if email_id in pending_verification_codes and pending_verification_codes[email_id]["status"] == "submitted":
|
||||
code = pending_verification_codes[email_id]["code"]
|
||||
info(f"前端已提交验证码: {code}")
|
||||
# 删除已使用的记录
|
||||
pending_verification_codes.pop(email_id, None)
|
||||
return code
|
||||
|
||||
# 等待1秒再检查
|
||||
time.sleep(1)
|
||||
|
||||
# 超时,从等待字典中移除
|
||||
pending_verification_codes.pop(email_id, None)
|
||||
info("验证码输入超时")
|
||||
return None
|
||||
|
||||
def get_tempmail_email_code(self, source_email=None):
|
||||
info("开始获取邮件列表")
|
||||
# 获取邮件列表
|
||||
mail_list_url = f"https://tempmail.plus/api/mails?email={self.username}%40{self.domain}&limit=20&epin={self.pin}"
|
||||
|
||||
# 如果提供了source_email,且当前不是使用custom_email,则尝试解析它
|
||||
if source_email and source_email != f"{self.username}@{self.domain}" and '@' in source_email:
|
||||
username, domain = source_email.split('@', 1)
|
||||
mail_list_url = f"https://tempmail.plus/api/mails?email={username}%40{domain}&limit=20&epin={self.pin}"
|
||||
info(f"使用自定义邮箱获取验证码: {source_email}")
|
||||
else:
|
||||
mail_list_url = f"https://tempmail.plus/api/mails?email={self.username}%40{self.domain}&limit=20&epin={self.pin}"
|
||||
info(f"使用配置邮箱获取验证码: {self.username}@{self.domain}")
|
||||
|
||||
try:
|
||||
# 增加错误重试和超时时间
|
||||
for retry in range(3):
|
||||
@@ -188,8 +275,14 @@ class EmailVerificationHandler:
|
||||
if not first_id:
|
||||
return None, None
|
||||
info(f"开始获取邮件详情: {first_id}")
|
||||
# 获取具体邮件内容
|
||||
mail_detail_url = f"https://tempmail.plus/api/mails/{first_id}?email={self.username}%40{self.domain}&epin={self.pin}"
|
||||
|
||||
# 使用相同的用户名和域名获取邮件详情
|
||||
if source_email and source_email != f"{self.username}@{self.domain}" and '@' in source_email:
|
||||
username, domain = source_email.split('@', 1)
|
||||
mail_detail_url = f"https://tempmail.plus/api/mails/{first_id}?email={username}%40{domain}&epin={self.pin}"
|
||||
else:
|
||||
mail_detail_url = f"https://tempmail.plus/api/mails/{first_id}?email={self.username}%40{self.domain}&epin={self.pin}"
|
||||
|
||||
try:
|
||||
mail_detail_response = self.session.get(
|
||||
mail_detail_url, timeout=10
|
||||
@@ -222,7 +315,7 @@ class EmailVerificationHandler:
|
||||
|
||||
if code_match:
|
||||
# 清理邮件
|
||||
self._cleanup_mail(first_id)
|
||||
self._cleanup_mail(first_id, source_email)
|
||||
return code_match.group(), first_id
|
||||
return None, None
|
||||
except requests.exceptions.Timeout:
|
||||
@@ -235,11 +328,18 @@ class EmailVerificationHandler:
|
||||
error(f"获取邮件列表发生错误: {str(e)}")
|
||||
return None, None
|
||||
|
||||
def _cleanup_mail(self, first_id):
|
||||
def _cleanup_mail(self, first_id, source_email=None):
|
||||
# 如果提供了source_email,优先使用它
|
||||
username = self.username
|
||||
domain = self.domain
|
||||
if source_email and '@' in source_email:
|
||||
username, domain = source_email.split('@', 1)
|
||||
info(f"使用自定义邮箱清理邮件: {username}@{domain}")
|
||||
|
||||
# 构造删除请求的URL和数据
|
||||
delete_url = "https://tempmail.plus/api/mails/"
|
||||
payload = {
|
||||
"email": f"{self.username}@{self.domain}",
|
||||
"email": f"{username}@{domain}",
|
||||
"first_id": first_id,
|
||||
"epin": self.pin,
|
||||
}
|
||||
@@ -301,13 +401,24 @@ class EmailVerificationHandler:
|
||||
def get_zmail_email_code(self, source_email=None):
|
||||
info("开始获取邮件列表")
|
||||
# 获取邮件列表
|
||||
username = source_email.split("@")[0]
|
||||
# 优先使用传入的source_email,其次是自定义邮箱,最后才是配置中的邮箱
|
||||
email_to_use = source_email if source_email else (self.custom_email if self.custom_email else f"{self.username}@{self.domain}")
|
||||
|
||||
if '@' not in email_to_use:
|
||||
error(f"邮箱格式错误: {email_to_use}")
|
||||
return None, None
|
||||
|
||||
username = email_to_use.split("@")[0]
|
||||
info(f"使用邮箱获取验证码: {email_to_use}, 用户名: {username}")
|
||||
|
||||
mail_list_url = f"{EMAIL_API}/api/mailboxes/{username}/emails"
|
||||
proxy = {
|
||||
|
||||
if EMAIL_PROXY_ENABLED:
|
||||
proxy = {
|
||||
"http": f"{EMAIL_PROXY_ADDRESS}",
|
||||
"https": f"{EMAIL_PROXY_ADDRESS}",
|
||||
}
|
||||
self.session.proxies.update(proxy)
|
||||
self.session.proxies.update(proxy)
|
||||
try:
|
||||
mail_list_response = self.session.get(
|
||||
mail_list_url, timeout=10000
|
||||
|
||||
81
index.html
81
index.html
@@ -24,6 +24,9 @@
|
||||
|
||||
<!-- 加载中遮罩 -->
|
||||
<div class="loading-overlay" id="loading-overlay">
|
||||
<button type="button" class="close-overlay" aria-label="关闭">
|
||||
<i class="fas fa-times fa-lg"></i>
|
||||
</button>
|
||||
<div class="spinner-container">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="visually-hidden">加载中...</span>
|
||||
@@ -170,6 +173,43 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 自定义邮箱注册卡片 - 移到下方 -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header bg-white">
|
||||
<h5 class="mb-0">自定义邮箱注册</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="mb-3">
|
||||
<label for="custom-email" class="form-label">输入邮箱地址</label>
|
||||
<div class="input-group">
|
||||
<input type="email" class="form-control" id="custom-email"
|
||||
placeholder="例如: your.email@example.com">
|
||||
<button class="btn btn-primary" type="button" id="custom-registration">
|
||||
<i class="fas fa-user-plus me-1"></i> 使用此邮箱注册
|
||||
</button>
|
||||
</div>
|
||||
<small class="text-muted">使用自定义邮箱注册时,需要手动获取验证码</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="alert alert-info" id="custom-registration-status"
|
||||
style="display: none;">
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
<span id="custom-registration-message">准备就绪</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 在搜索栏旁边添加排序控件 -->
|
||||
<div class="row mb-3 align-items-center">
|
||||
<div class="col-md-6">
|
||||
@@ -332,7 +372,8 @@
|
||||
<small class="text-muted">True=无界面运行浏览器,False=显示浏览器界面</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="dynamic-useragent" class="form-label">动态User-Agent(先不要配置)</label>
|
||||
<label for="dynamic-useragent"
|
||||
class="form-label">动态User-Agent(先不要配置)</label>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch"
|
||||
id="dynamic-useragent" disabled>
|
||||
@@ -349,7 +390,8 @@
|
||||
<div class="mb-3">
|
||||
<label for="browser-path" class="form-label">浏览器路径 (可选)</label>
|
||||
<input type="text" id="browser-path" class="form-control" disabled>
|
||||
<small class="text-muted">Windows下浏览器可执行文件的完整路径(示例:C:\Users\Administrator\AppData\Local\Google\Chrome\Bin\chrome.exe)</small>
|
||||
<small
|
||||
class="text-muted">Windows下浏览器可执行文件的完整路径(示例:C:\Users\Administrator\AppData\Local\Google\Chrome\Bin\chrome.exe)</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="accounts-limit" class="form-label">最大账号数量</label>
|
||||
@@ -357,7 +399,7 @@
|
||||
disabled>
|
||||
<small class="text-muted">系统允许创建的最大账号数量</small>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 验证码获取方式 -->
|
||||
<div class="mb-3">
|
||||
<label for="captcha-method" class="form-label">验证码获取方式</label>
|
||||
@@ -549,6 +591,7 @@
|
||||
<p>确定要删除此账号吗?此操作不可恢复。</p>
|
||||
<p class="text-danger fw-bold">邮箱: <span id="deleteEmailConfirm"></span></p>
|
||||
<p class="text-muted">ID: <span id="deleteIdConfirm"></span></p>
|
||||
<input type="hidden" id="deleteAccountId" value="">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||||
@@ -590,7 +633,8 @@
|
||||
</div>
|
||||
|
||||
<!-- 账号使用记录模态框 -->
|
||||
<div class="modal fade" id="usageRecordModal" tabindex="-1" aria-labelledby="usageRecordModalLabel" aria-hidden="true">
|
||||
<div class="modal fade" id="usageRecordModal" tabindex="-1" aria-labelledby="usageRecordModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
@@ -638,6 +682,35 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 验证码输入模态框 -->
|
||||
<div class="modal fade" id="codeInputModal" tabindex="-1" aria-labelledby="codeInputModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="codeInputModalLabel">输入验证码</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>请检查以下邮箱中收到的验证码:</p>
|
||||
<p class="fw-bold text-primary" id="verificationEmailDisplay"></p>
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
<span>通常验证码为6位数字,在邮件正文中</span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="verificationCode" class="form-label">验证码</label>
|
||||
<input type="text" class="form-control" id="verificationCode" placeholder="输入验证码" maxlength="6">
|
||||
</div>
|
||||
<input type="hidden" id="pendingEmailId" value="">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" id="submitCodeBtn">提交验证码</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="static/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- jQuery -->
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
3539
static/js/app.js
3539
static/js/app.js
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user