diff --git a/README.md b/README.md
index 9791cf7..a14a1a0 100644
--- a/README.md
+++ b/README.md
@@ -7,10 +7,10 @@
-[](https://github.com/yeongpin/cursor-free-vip/releases/latest)
+[](https://github.com/yeongpin/cursor-free-vip/releases/latest)
[](https://creativecommons.org/licenses/by-nc-nd/4.0/)
-[](https://github.com/yeongpin/cursor-free-vip/stargazers)
-[](https://github.com/yeongpin/cursor-free-vip/releases/latest)
+[](https://github.com/yeongpin/cursor-free-vip/stargazers)
+[](https://github.com/yeongpin/cursor-free-vip/releases/latest)
diff --git a/config.py b/config.py
index 1d59a21..f59f384 100644
--- a/config.py
+++ b/config.py
@@ -249,6 +249,13 @@ def setup_config(translator=None):
'product_json_path': os.path.join(cursor_dir, "resources/app/product.json") if cursor_dir else ""
}
+ # Add tempmail_plus configuration
+ default_config['TempMailPlus'] = {
+ 'enabled': 'false',
+ 'email': '',
+ 'epin': ''
+ }
+
# Read existing configuration and merge
if os.path.exists(config_file):
config.read(config_file, encoding='utf-8')
diff --git a/cursor_register_manual.py b/cursor_register_manual.py
index ca63813..bf3cf83 100644
--- a/cursor_register_manual.py
+++ b/cursor_register_manual.py
@@ -6,6 +6,7 @@ from faker import Faker
from cursor_auth import CursorAuth
from reset_machine_manual import MachineIDResetter
from get_user_token import get_token_from_cookie
+from config import get_config
os.environ["PYTHONVERBOSE"] = "0"
os.environ["PYINSTALLER_VERBOSE"] = "0"
@@ -102,6 +103,18 @@ class CursorRegistration:
try:
print(f"{Fore.CYAN}{EMOJI['START']} {self.translator.get('register.register_start')}...{Style.RESET_ALL}")
+ # Check if tempmail_plus is enabled
+ config = get_config(self.translator)
+ email_tab = None
+ if config and config.has_section('TempMailPlus'):
+ if config.getboolean('TempMailPlus', 'enabled'):
+ email = config.get('TempMailPlus', 'email')
+ epin = config.get('TempMailPlus', 'epin')
+ if email and epin:
+ from email_tabs.tempmail_plus_tab import TempMailPlusTab
+ email_tab = TempMailPlusTab(email, epin)
+ print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('register.using_tempmail_plus')}{Style.RESET_ALL}")
+
# Use new_signup.py directly for registration
from new_signup import main as new_signup_main
@@ -111,7 +124,7 @@ class CursorRegistration:
password=self.password,
first_name=self.first_name,
last_name=self.last_name,
- email_tab=None, # No email tab needed
+ email_tab=email_tab, # Pass email_tab if tempmail_plus is enabled
controller=self, # Pass self instead of self.controller
translator=self.translator
)
diff --git a/email_tabs/email_tab_interface.py b/email_tabs/email_tab_interface.py
new file mode 100644
index 0000000..d80f0a1
--- /dev/null
+++ b/email_tabs/email_tab_interface.py
@@ -0,0 +1,27 @@
+from abc import ABC, abstractmethod
+
+class EmailTabInterface(ABC):
+ """Email tab interface for handling email verification"""
+
+ @abstractmethod
+ def refresh_inbox(self) -> None:
+ """Refresh the email inbox"""
+ pass
+
+ @abstractmethod
+ def check_for_cursor_email(self) -> bool:
+ """Check if there is a verification email from Cursor
+
+ Returns:
+ bool: True if verification email exists, False otherwise
+ """
+ pass
+
+ @abstractmethod
+ def get_verification_code(self) -> str:
+ """Get the verification code from the email
+
+ Returns:
+ str: The verification code if found, empty string otherwise
+ """
+ pass
diff --git a/email_tabs/tempmail_plus_tab.py b/email_tabs/tempmail_plus_tab.py
new file mode 100644
index 0000000..4fbea0d
--- /dev/null
+++ b/email_tabs/tempmail_plus_tab.py
@@ -0,0 +1,109 @@
+import requests
+import re
+from typing import Optional
+from .email_tab_interface import EmailTabInterface
+
+class TempMailPlusTab(EmailTabInterface):
+ """Implementation of EmailTabInterface for tempmail.plus"""
+
+ def __init__(self, email: str, epin: str):
+ """Initialize TempMailPlusTab
+
+ Args:
+ email: The email address to check
+ epin: The epin token for authentication
+ """
+ self.email = email
+ self.epin = epin
+ self.base_url = "https://tempmail.plus/api"
+ self.headers = {
+ 'accept': 'application/json',
+ 'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6',
+ 'cache-control': 'no-cache',
+ 'pragma': 'no-cache',
+ 'referer': 'https://tempmail.plus/zh/',
+ 'sec-ch-ua': '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
+ 'sec-ch-ua-mobile': '?0',
+ 'sec-ch-ua-platform': '"macOS"',
+ 'sec-fetch-dest': 'empty',
+ 'sec-fetch-mode': 'cors',
+ 'sec-fetch-site': 'same-origin',
+ 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36',
+ 'x-requested-with': 'XMLHttpRequest'
+ }
+ self.cookies = {'email': email}
+ self._cached_mail_id = None # 缓存mail_id
+
+ def refresh_inbox(self) -> None:
+ """Refresh the email inbox"""
+ pass
+
+ def check_for_cursor_email(self) -> bool:
+ """Check if there is a verification email from Cursor
+
+ Returns:
+ bool: True if verification email exists, False otherwise
+ """
+ try:
+ params = {
+ 'email': self.email,
+ 'epin': self.epin
+ }
+ response = requests.get(
+ f"{self.base_url}/mails",
+ params=params,
+ headers=self.headers,
+ cookies=self.cookies
+ )
+ response.raise_for_status()
+
+ data = response.json()
+ if data.get('result') and data.get('mail_list'):
+ for mail in data['mail_list']:
+ if 'cursor.sh' in mail.get('from_mail', '') and mail.get('is_new') == True:
+ self._cached_mail_id = mail.get('mail_id') # 缓存mail_id
+ return True
+ return False
+ except Exception as e:
+ print(f"检查Cursor邮件失败: {str(e)}")
+ return False
+
+ def get_verification_code(self) -> str:
+ """Get the verification code from the email
+
+ Returns:
+ str: The verification code if found, empty string otherwise
+ """
+ try:
+ # 如果没有缓存的mail_id,先检查是否有新邮件
+ if not self._cached_mail_id:
+ if not self.check_for_cursor_email():
+ return ""
+
+ # 使用缓存的mail_id获取邮件内容
+ params = {
+ 'email': self.email,
+ 'epin': self.epin
+ }
+ response = requests.get(
+ f"{self.base_url}/mails/{self._cached_mail_id}",
+ params=params,
+ headers=self.headers,
+ cookies=self.cookies
+ )
+ response.raise_for_status()
+
+ data = response.json()
+ if not data.get('result'):
+ return ""
+
+ # Extract verification code from text content using regex
+ text = data.get('text', '')
+ match = re.search(r'\n\n(\d{6})\n\n', text)
+ if match:
+ return match.group(1)
+
+ return ""
+ except Exception as e:
+ print(f"获取验证码失败: {str(e)}")
+ return ""
\ No newline at end of file
diff --git a/locales/en.json b/locales/en.json
index ef4711b..a0977db 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -211,7 +211,18 @@
"try_install_browser": "Try installing the browser with your package manager",
"tracking_processes": "Tracking {count} {browser} processes",
"no_new_processes_detected": "No new {browser} processes detected to track",
- "could_not_track_processes": "Could not track {browser} processes: {error}"
+ "could_not_track_processes": "Could not track {browser} processes: {error}",
+ "using_tempmail_plus": "Using TempMailPlus for email verification",
+ "tempmail_plus_enabled": "TempMailPlus is enabled",
+ "tempmail_plus_disabled": "TempMailPlus is disabled",
+ "tempmail_plus_config_missing": "TempMailPlus configuration is missing",
+ "tempmail_plus_email_missing": "TempMailPlus email is not configured",
+ "tempmail_plus_epin_missing": "TempMailPlus epin is not configured",
+ "tempmail_plus_initialized": "TempMailPlus initialized successfully",
+ "tempmail_plus_init_failed": "Failed to initialize TempMailPlus: {error}",
+ "tempmail_plus_verification_started": "Starting TempMailPlus verification process",
+ "tempmail_plus_verification_completed": "TempMailPlus verification completed successfully",
+ "tempmail_plus_verification_failed": "TempMailPlus verification failed: {error}"
},
"auth": {
"title": "Cursor Auth Manager",
diff --git a/locales/zh_cn.json b/locales/zh_cn.json
index bba962e..4221f5e 100644
--- a/locales/zh_cn.json
+++ b/locales/zh_cn.json
@@ -211,7 +211,18 @@
"no_new_processes_detected": "未检测到新的 {browser} 进程",
"could_not_track_processes": "无法跟踪 {browser} 进程: {error}",
"human_verify_error": "无法验证用户是人类,正在重试...",
- "max_retries_reached": "已达到最大重试次数,注册失败。"
+ "max_retries_reached": "已达到最大重试次数,注册失败。",
+ "using_tempmail_plus": "使用TempMailPlus进行邮箱验证",
+ "tempmail_plus_enabled": "TempMailPlus已启用",
+ "tempmail_plus_disabled": "TempMailPlus已禁用",
+ "tempmail_plus_config_missing": "TempMailPlus配置缺失",
+ "tempmail_plus_email_missing": "未配置TempMailPlus邮箱",
+ "tempmail_plus_epin_missing": "未配置TempMailPlus epin",
+ "tempmail_plus_initialized": "TempMailPlus初始化成功",
+ "tempmail_plus_init_failed": "TempMailPlus初始化失败:{error}",
+ "tempmail_plus_verification_started": "开始TempMailPlus验证流程",
+ "tempmail_plus_verification_completed": "TempMailPlus验证成功完成",
+ "tempmail_plus_verification_failed": "TempMailPlus验证失败:{error}"
},
"auth": {
"title": "Cursor 认证管理器",
@@ -649,7 +660,9 @@
"found_chrome_at": "找到 Chrome: {path}",
"found_browser_user_data_dir": "找到 {browser} 用户数据目录: {path}",
"select_profile": "选择要使用的 {browser} 配置文件:",
- "profile_list": "可用 {browser} 配置文件:"
+ "profile_list": "可用 {browser} 配置文件:",
+ "chrome_permissions_fixed": "已修复 Chrome 用户数据目录权限",
+ "chrome_permissions_fix_failed": "修复 Chrome 权限失败: {error}"
},
"browser_profile": {
"title": "浏览器配置文件选择",
diff --git a/locales/zh_tw.json b/locales/zh_tw.json
index 3e8bf28..ecd8fa4 100644
--- a/locales/zh_tw.json
+++ b/locales/zh_tw.json
@@ -212,6 +212,17 @@
"could_not_track_processes": "無法跟踪{瀏覽器}進程:{error}",
"human_verify_error": "無法驗證用戶是人類。重試...",
"tracking_processes": "跟踪{count} {瀏覽器}進程"
+ "using_tempmail_plus": "使用TempMailPlus進行郵箱驗證",
+ "tempmail_plus_enabled": "TempMailPlus已啟用",
+ "tempmail_plus_disabled": "TempMailPlus已禁用",
+ "tempmail_plus_config_missing": "TempMailPlus配置缺失",
+ "tempmail_plus_email_missing": "未配置TempMailPlus郵箱",
+ "tempmail_plus_epin_missing": "未配置TempMailPlus epin",
+ "tempmail_plus_initialized": "TempMailPlus初始化成功",
+ "tempmail_plus_init_failed": "TempMailPlus初始化失敗:{error}",
+ "tempmail_plus_verification_started": "開始TempMailPlus驗證流程",
+ "tempmail_plus_verification_completed": "TempMailPlus驗證成功完成",
+ "tempmail_plus_verification_failed": "TempMailPlus驗證失敗:{error}"
},
"auth": {
"title": "Cursor 認證管理器",
diff --git a/oauth_auth.py b/oauth_auth.py
index c30c198..0dcc891 100644
--- a/oauth_auth.py
+++ b/oauth_auth.py
@@ -483,6 +483,25 @@ class OAuthHandler:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.error_configuring_browser_options', error=str(e)) if self.translator else f'Error configuring browser options: {e}'}{Style.RESET_ALL}")
raise
+ def _fix_chrome_permissions(self, user_data_dir):
+ """Fix permissions for Chrome user data directory"""
+ try:
+ if sys.platform == 'darwin': # macOS
+ import subprocess
+ import pwd
+
+ # Get current user
+ current_user = pwd.getpwuid(os.getuid()).pw_name
+
+ # Fix permissions for Chrome directory
+ chrome_dir = os.path.expanduser('~/Library/Application Support/Google/Chrome')
+ if os.path.exists(chrome_dir):
+ subprocess.run(['chmod', '-R', 'u+rwX', chrome_dir])
+ subprocess.run(['chown', '-R', f'{current_user}:staff', chrome_dir])
+ print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('oauth.chrome_permissions_fixed') if self.translator else 'Fixed Chrome user data directory permissions'}{Style.RESET_ALL}")
+ except Exception as e:
+ print(f"{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('oauth.chrome_permissions_fix_failed', error=str(e)) if self.translator else f'Failed to fix Chrome permissions: {str(e)}'}{Style.RESET_ALL}")
+
def handle_google_auth(self):
"""Handle Google OAuth authentication"""
try:
@@ -493,6 +512,9 @@ class OAuthHandler:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.browser_failed') if self.translator else 'Browser failed to initialize'}{Style.RESET_ALL}")
return False, None
+ # Get user data directory for later use
+ user_data_dir = self._get_user_data_directory()
+
# Navigate to auth URL
try:
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.navigating_to_authentication_page') if self.translator else 'Navigating to authentication page...'}{Style.RESET_ALL}")
@@ -556,6 +578,8 @@ class OAuthHandler:
try:
if self.browser:
self.browser.quit()
+ # Fix Chrome permissions after browser is closed
+ self._fix_chrome_permissions(user_data_dir)
except:
pass