3 Commits

Author SHA1 Message Date
huangzhenpc
241b1f2413 feat: 8.0.2.1版本支持QQ邮箱获取验证码 2025-02-10 16:59:21 +08:00
huangzhenpc
d1232d7d3b docs: 添加 8.0.2 版本开发任务说明文档 2025-02-10 11:07:31 +08:00
Your Name
ae07d88b28 feat: 更新版本号到8.0.1 2025-02-09 23:25:21 +08:00
8 changed files with 224 additions and 140 deletions

BIN
README.md

Binary file not shown.

38
VERSION_8.0.2.md Normal file
View File

@@ -0,0 +1,38 @@
# Cursor V8.0.2 版本开发任务
## 分支信息
- 分支名称:`8.0.2`
- 基于分支:`master` (8.0.1)
- 开发状态:进行中
## 主要任务
### 1. 邮箱服务迁移
- 将临时邮箱服务从国外 temp 邮箱迁移至国内邮箱服务
- 优化邮箱验证流程
- 提高邮件送达率和稳定性
### 2. 计费系统优化
- 改进计费触发时机
- 实现脚本执行完成后再进行计费
- 优化计费准确性和可靠性
## 预期改进
- 提高邮箱服务的稳定性和速度
- 更准确的计费统计
- 更好的用户体验
## 测试重点
1. 新邮箱服务的可用性测试
2. 计费系统的准确性验证
3. 脚本执行完成后的计费时机控制
## 注意事项
- 确保邮箱服务迁移过程中的平滑过渡
- 保证计费系统改造不影响现有用户
- 做好版本升级方案
## 相关文件
- `config.py`: 邮箱配置更新
- `cursor_pro_keep_alive.py`: 计费逻辑优化
- `test_mail_api.py`: 新邮箱服务测试

View File

@@ -13,6 +13,23 @@ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class Config:
def __init__(self):
# 默认配置
self.default_config = {
"TEMP_MAIL": "", # 设置为空字符串,表示可选
"TEMP_MAIL_EXT": "@mailto.plus",
"TEMP_MAIL_EPIN": "",
"DOMAIN": "mailto.plus",
"BROWSER_USER_AGENT": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"MAIL_SERVER": "https://tempmail.plus",
# IMAP 相关配置
"USE_IMAP": False, # 是否使用 IMAP
"IMAP_HOST": "",
"IMAP_PORT": 993,
"IMAP_USERNAME": "",
"IMAP_PASSWORD": "",
"IMAP_USE_SSL": True
}
# 获取应用程序的根目录路径
if getattr(sys, "frozen", False):
# 如果是打包后的可执行文件
@@ -23,8 +40,8 @@ class Config:
# 配置重试策略
retry_strategy = Retry(
total=3,
backoff_factor=1,
total=2, # 减少重试次数
backoff_factor=0.5, # 减少等待时间
status_forcelist=[429, 500, 502, 503, 504],
)
@@ -41,39 +58,51 @@ class Config:
# 从API获取配置
try:
# 使用session发送请求
# 使用session发送请求,减少超时时间
response = self.session.get(
"https://cursorapi.nosqli.com/admin/api.mail/getRandom",
timeout=30,
"https://cursorapi.nosqli.com/admin/api.mail/gettestapi",
timeout=10,
allow_redirects=True
)
data = response.json()
if data['code'] != 0:
raise Exception(data['msg'])
if data['code'] == 0:
config = data['data']['env']
else:
logging.warning(f"API返回错误: {data.get('msg', '未知错误')}")
logging.info("使用默认配置继续运行...")
config = self.default_config
config = data['data']['env']
# 设置配置项
self.imap = False
self.temp_mail = config.get("TEMP_MAIL", "").strip()
self.temp_mail_ext = config.get("TEMP_MAIL_EXT", "").strip()
self.temp_mail_epin = config.get("TEMP_MAIL_EPIN", "").strip()
self.domain = config.get("DOMAIN", "").strip()
self.browser_user_agent = config.get("BROWSER_USER_AGENT", "").strip()
self.mail_server = config.get("MAIL_SERVER", "").strip()
# 如果临时邮箱为null则加载IMAP
if self.temp_mail == "null":
self.imap = True
self.imap_server = config.get("IMAP_SERVER", "").strip()
self.imap_port = config.get("IMAP_PORT", "").strip()
self.imap_user = config.get("IMAP_USER", "").strip()
self.imap_pass = config.get("IMAP_PASS", "").strip()
self.imap_dir = config.get("IMAP_DIR", "inbox").strip()
except Exception as e:
logging.error(f"从API获取配置失败: {e}")
raise e
logging.warning(f"从API获取配置失败: {str(e)}")
logging.info("使用默认配置继续运行...")
config = self.default_config
# 设置配置项
self.imap = False
# 处理 TEMP_MAIL如果为 null 则启用 IMAP
temp_mail = config.get("TEMP_MAIL")
if temp_mail is None or temp_mail == "null":
self.imap = True
self.temp_mail = "null"
else:
self.temp_mail = str(temp_mail).strip()
# 设置其他基础配置
self.temp_mail_ext = str(config.get("TEMP_MAIL_EXT", self.default_config["TEMP_MAIL_EXT"])).strip()
self.temp_mail_epin = str(config.get("TEMP_MAIL_EPIN", self.default_config["TEMP_MAIL_EPIN"])).strip()
self.domain = str(config.get("DOMAIN", self.default_config["DOMAIN"])).strip()
self.browser_user_agent = str(config.get("BROWSER_USER_AGENT", self.default_config["BROWSER_USER_AGENT"])).strip()
self.mail_server = str(config.get("MAIL_SERVER", self.default_config["MAIL_SERVER"])).strip()
# 如果启用了 IMAP设置 IMAP 配置
if self.imap:
self.imap_server = str(config.get("IMAP_SERVER", "")).strip()
self.imap_port = str(config.get("IMAP_PORT", "")).strip()
self.imap_user = str(config.get("IMAP_USER", "")).strip()
self.imap_pass = str(config.get("IMAP_PASS", "")).strip()
self.imap_dir = str(config.get("IMAP_DIR", "inbox")).strip()
self.check_config()

View File

@@ -230,13 +230,16 @@ def handle_verification_code(tab, email_handler):
while retry_count < max_retries:
try:
print(f"\n[调试] 开始第 {retry_count + 1} 次验证码处理")
if tab.ele("Account Settings", timeout=3):
print_status("注册成功 - 已进入账户设置页面", "success")
return True
if tab.ele("@data-index=0", timeout=3):
print_status("正在获取邮箱验证码...")
print(f"[调试] 开始获取验证码{email_handler}")
code = get_verification_code_with_retry(email_handler)
print(f"[调试] 获取到的验证码: {code}")
if not code:
print_status("获取验证码失败", "error")
return False
@@ -246,6 +249,7 @@ def handle_verification_code(tab, email_handler):
# 快速输入验证码
for i, digit in enumerate(code):
print(f"[调试] 输入第 {i+1} 位: {digit}")
tab.ele(f"@data-index={i}").input(digit)
time.sleep(0.1)
@@ -254,10 +258,12 @@ def handle_verification_code(tab, email_handler):
return True
retry_count += 1
print(f"[调试] 未找到验证码输入框,重试次数: {retry_count}")
time.sleep(1)
except Exception as e:
print_status(f"验证码处理过程出错: {str(e)}", "error")
print(f"[调试] 错误详情: {str(e)}")
retry_count += 1
if retry_count < max_retries:
time.sleep(1)
@@ -534,15 +540,20 @@ def print_progress(message, delay=0.03):
def get_user_input(prompt, valid_options=None):
"""获取用户输入的美化版本"""
while True:
try:
print(f"\n{Fore.YELLOW}>>>{Fore.WHITE} {prompt}{Style.RESET_ALL}", end=" ")
user_input = input().strip()
if valid_options and user_input not in valid_options:
print(f"{Fore.RED}✗ 无效的输入,请重试{Style.RESET_ALL}")
continue
if valid_options and user_input and user_input not in valid_options:
print(f"{Fore.YELLOW}[提示] 输入无效,请重试{Style.RESET_ALL}")
return get_user_input(prompt, valid_options)
return user_input
except (KeyboardInterrupt, EOFError):
print(f"\n{Fore.YELLOW}[提示] 程序已取消{Style.RESET_ALL}")
sys.exit(0)
except Exception:
return ""
def load_last_account():
@@ -573,53 +584,76 @@ def save_last_account(email):
def verify_member():
"""验证会员身份"""
checker = MemberChecker()
max_retries = 3
retry_count = 0
while True:
print(f"\n{Fore.CYAN}{'='*30} 会员验证 {'='*30}{Style.RESET_ALL}")
# 加载上次使用的账号
last_email, last_used = load_last_account()
if last_email:
print(f"\n{Fore.CYAN}[提示] 上次使用账号: {last_email}")
print(f" 最后使用时间: {last_used}{Style.RESET_ALL}")
print(f"\n{Fore.YELLOW}直接按回车使用上次账号,或输入新的邮箱/订单号{Style.RESET_ALL}")
while retry_count < max_retries:
try:
print(f"\n{Fore.CYAN}{'='*30} 会员验证 {'='*30}{Style.RESET_ALL}")
keyword = get_user_input("请输入会员邮箱或订单号:")
# 如果直接回车且有上次账号记录,使用上次的账号
if not keyword and last_email:
keyword = last_email
print(f"{Fore.CYAN}[信息] 使用上次账号: {keyword}{Style.RESET_ALL}")
elif not keyword:
print(f"{Fore.RED}✗ 输入不能为空,请重试{Style.RESET_ALL}")
continue
# 加载上次使用的账号
last_email, last_used = load_last_account()
if last_email:
print(f"\n{Fore.CYAN}[提示] 上次使用账号: {last_email}")
print(f" 最后使用时间: {last_used}{Style.RESET_ALL}")
print(f"\n{Fore.YELLOW}直接按回车使用上次账号,或输入新的邮箱/订单号{Style.RESET_ALL}")
keyword = get_user_input("请输入会员邮箱或订单号:")
animate_loading("正在验证会员信息", 2) # 使用动画加载替代进度条
result = checker.check_member(keyword)
if result['is_valid']:
# 保存成功验证的账号
save_last_account(keyword)
# 如果直接回车且有上次账号记录,使用上次的账号
if not keyword and last_email:
keyword = last_email
print(f"{Fore.CYAN}[信息] 使用上次账号: {keyword}{Style.RESET_ALL}")
elif not keyword:
if retry_count < max_retries - 1:
print(f"{Fore.YELLOW}[提示] 输入为空,请重试{Style.RESET_ALL}")
retry_count += 1
continue
else:
print(f"{Fore.YELLOW}[提示] 多次输入为空,程序退出{Style.RESET_ALL}")
sys.exit(0)
animate_loading("正在验证会员信息", 2)
result = checker.check_member(keyword)
print(f"\n{Fore.GREEN}✓ 会员验证通过!{Style.RESET_ALL}")
print(f"\n{Fore.CYAN}会员详细信息:{Style.RESET_ALL}")
print(f"{Fore.WHITE}├─ 邮箱: {result['email']}")
print(f"├─ 订单号: {result['order_id']}")
print(f"├─ 到期时间: {result['expire_time']}")
print(f"├─ 使用限制: {result['usage_limit']}")
print(f"└─ 已使用次数: {result['used_count']}{Style.RESET_ALL}")
if result['is_valid']:
# 保存成功验证的账号
save_last_account(keyword)
print(f"\n{Fore.GREEN}✓ 会员验证通过!{Style.RESET_ALL}")
print(f"\n{Fore.CYAN}会员详细信息:{Style.RESET_ALL}")
print(f"{Fore.WHITE}├─ 邮箱: {result['email']}")
print(f"├─ 订单号: {result['order_id']}")
print(f"├─ 到期时间: {result['expire_time']}")
print(f"├─ 使用限制: {result['usage_limit']}")
print(f"└─ 已使用次数: {result['used_count']}{Style.RESET_ALL}")
if result['expire_time']:
expire_time = datetime.strptime(result['expire_time'], "%Y-%m-%d %H:%M:%S")
if expire_time < datetime.now():
print(f"\n{Fore.YELLOW}[提示] 会员已过期,请续费后重试{Style.RESET_ALL}")
sys.exit(0)
return result
if result['expire_time']:
expire_time = datetime.strptime(result['expire_time'], "%Y-%m-%d %H:%M:%S")
if expire_time < datetime.now():
print(f"\n{Fore.RED}✗ 会员已过期,请续费后重试{Style.RESET_ALL}")
sys.exit(1)
return result
print(f"\n{Fore.RED}✗ 验证失败: {result['msg']}{Style.RESET_ALL}")
retry = get_user_input("是否重试? (y/n):", ['y','n'])
if retry != 'y':
sys.exit(1)
print(f"\n{Fore.YELLOW}[提示] 验证失败: {result['msg']}{Style.RESET_ALL}")
retry = get_user_input("是否重试? (y/n):", ['y','n'])
if retry.lower() != 'y':
print(f"\n{Fore.YELLOW}[提示] 程序已退出{Style.RESET_ALL}")
sys.exit(0)
retry_count += 1
except Exception as e:
if retry_count < max_retries - 1:
print(f"\n{Fore.YELLOW}[提示] 验证过程出现问题,正在重试...{Style.RESET_ALL}")
retry_count += 1
time.sleep(1)
continue
else:
print(f"\n{Fore.YELLOW}[提示] 验证失败次数过多,程序退出{Style.RESET_ALL}")
sys.exit(0)
print(f"\n{Fore.YELLOW}[提示] 验证次数已达上限,程序退出{Style.RESET_ALL}")
sys.exit(0)
def print_status(message, status="info"):
@@ -732,8 +766,8 @@ if __name__ == "__main__":
print_status("浏览器初始化完成", "success")
print_status("正在初始化邮箱验证模块...")
email_handler = EmailVerificationHandler()
print_step_header("配置信息")
login_url = "https://authenticator.cursor.sh"
@@ -751,6 +785,11 @@ if __name__ == "__main__":
print_status(f"生成的邮箱账号: {account}")
auto_update_cursor_auth = True
print_status("正在初始化邮箱验证模块...")
# 使用生成的account初始化email_handler
email_handler = EmailVerificationHandler(account=account)
print_status("初始化邮箱验证模块成功", "success")
tab = browser.latest_tab
tab.run_js("try { turnstile.reset() } catch(e) { }")
@@ -764,19 +803,31 @@ if __name__ == "__main__":
email=account, access_token=token, refresh_token=token
)
print_status("执行完整重置...")
# 关闭浏览器以释放文件锁
# 先关闭浏览器以释放文件锁
if browser_manager:
browser_manager.quit()
print_status("正在关闭 Cursor...", "info")
if ExitCursor():
print_status("Cursor 已关闭", "success")
else:
print_status("Cursor 关闭失败,继续执行...", "warning")
time.sleep(2) # 等待进程完全退出
# 执行完整重置
from full_reset import full_system_reset
if full_system_reset():
print_status("执行完整重置...")
# 以管理员权限执行完整重置
try:
subprocess.run([
"powershell",
"-Command",
"Start-Process python -ArgumentList 'full_reset.py' -Verb RunAs -Wait"
])
print_status("完整重置成功", "success")
print_status("所有操作已完成", "success")
print(f"\n{Fore.GREEN}✓ 重置完成!下次启动 Cursor 将使用新的配置。{Style.RESET_ALL}")
else:
print_status("完整重置失败", "error")
except Exception as e:
print_status(f"完整重置失败: {str(e)}", "error")
else:
print_status("获取会话令牌失败,注册流程未完成", "error")

View File

@@ -9,11 +9,12 @@ import json
class EmailVerificationHandler:
def __init__(self):
def __init__(self, account=None):
config = Config()
self.imap = config.get_imap()
self.username = config.get_temp_mail()
self.epin = config.get_temp_mail_epin()
self.account = account # 添加account属性用于存储随机生成的邮箱
# 创建新的session并设置基本配置
self.session = requests.Session()
@@ -56,25 +57,38 @@ class EmailVerificationHandler:
mail.login(self.imap['imap_user'], self.imap['imap_pass'])
mail.select(self.imap['imap_dir'])
status, messages = mail.search(None, 'FROM', '"no-reply@cursor.sh"')
# 使用分开的参数方式搜索,更准确
status, messages = mail.search(None, 'TO', f'"{self.account}"', 'FROM', '"no-reply@cursor.sh"')
if status != 'OK':
return None
mail_ids = messages[0].split()
if not mail_ids:
# 没有获取到,就获取一次
# 没有获取到,就获取一次
return self._get_mail_code_by_imap(retry=retry + 1)
latest_mail_id = mail_ids[-1]
latest_id = mail_ids[-1]
# 获取邮件内容
status, msg_data = mail.fetch(latest_mail_id, '(RFC822)')
status, msg_data = mail.fetch(latest_id, '(RFC822)')
if status != 'OK':
return None
raw_email = msg_data[0][1]
email_message = email.message_from_bytes(raw_email)
# 严格验证收件人
to_addresses = email_message.get_all('to', [])
found_match = False
for addr in to_addresses:
if self.account.lower() in addr.lower():
found_match = True
break
if not found_match:
return self._get_mail_code_by_imap(retry=retry + 1)
# 提取邮件正文
body = self._extract_imap_body(email_message)
if body:
@@ -83,16 +97,13 @@ class EmailVerificationHandler:
if code_match:
code = code_match.group()
# 删除邮件
mail.store(latest_mail_id, '+FLAGS', '\\Deleted')
mail.store(latest_id, '+FLAGS', '\\Deleted')
mail.expunge()
mail.logout()
# print(f"找到的验证码: {code}")
return code
# print("未找到验证码")
mail.logout()
return None
except Exception as e:
print(f"发生错误: {e}")
return None
def _extract_imap_body(self, email_message):
@@ -177,6 +188,4 @@ class EmailVerificationHandler:
if __name__ == "__main__":
email_handler = EmailVerificationHandler()
code = email_handler.get_verification_code()
print(code)
pass

View File

@@ -1,4 +1,4 @@
{
"email": "12132ed@qq.com",
"last_used": "2025-02-09 18:55:32"
"last_used": "2025-02-10 16:52:55"
}

View File

@@ -30,7 +30,7 @@ def print_logo():
██║ ╚████║╚██████╔╝███████║╚██████╔╝███████╗██║
╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚══▀▀═╝ ╚══════╝╚═╝{Fore.CYAN}
{Fore.YELLOW}CURSOR PROFESSIONAL TOOLS - ENTERPRISE EDITION V8.0{Fore.CYAN}
{Fore.YELLOW}CURSOR PROFESSIONAL TOOLS - ENTERPRISE EDITION V8.0.2{Fore.CYAN}
════════════════════════════════════════════════════════════════════════════

View File

@@ -1,43 +0,0 @@
import requests
import json
import urllib3
# 禁用SSL警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def test_specific_email():
print("开始测试指定邮箱API...")
# 创建session并配置
session = requests.Session()
session.verify = False
session.trust_env = False
# 测试URL
test_url = "https://tempmail.plus/api/mails?email=ademyyk@mailto.plus&limit=20&epin="
try:
# 不使用代理直接测试
print("\n1. 直接连接测试...")
response = session.get(test_url)
print(f"状态码: {response.status_code}")
print(f"响应内容: {json.dumps(response.json(), indent=2, ensure_ascii=False)}")
except Exception as e:
print(f"\n直接连接出错: {e}")
# 如果直接连接失败,尝试使用代理
try:
print("\n2. 尝试使用代理...")
proxies = {
'http': 'http://127.0.0.1:7890',
'https': 'http://127.0.0.1:7890'
}
response = session.get(test_url, proxies=proxies)
print(f"状态码: {response.status_code}")
print(f"响应内容: {json.dumps(response.json(), indent=2, ensure_ascii=False)}")
except Exception as e:
print(f"\n代理连接也出错: {e}")
if __name__ == "__main__":
test_specific_email()