mirror of
https://github.com/ddCat-main/cursor-auto-register.git
synced 2025-12-24 13:38:01 +08:00
feat:新增开源无限邮箱类型zmail、动态配置选择邮箱类型
This commit is contained in:
11
.env.example
11
.env.example
@@ -17,6 +17,9 @@ PROXY_PORT=7897
|
||||
# 代理超时时间
|
||||
PROXY_TIMEOUT=10
|
||||
|
||||
|
||||
# 临时邮箱类型 可选值:tempemail, zmail
|
||||
EMAIL_TYPE=tempemail
|
||||
# 多个域名使用逗号分隔
|
||||
EMAIL_DOMAINS=xxx.xx
|
||||
|
||||
@@ -25,6 +28,14 @@ EMAIL_USERNAME=xxx
|
||||
# 临时邮箱PIN码(如果需要)
|
||||
EMAIL_PIN=
|
||||
|
||||
# ===== ZMail配置 =====
|
||||
# ZMail API地址
|
||||
EMAIL_API=https://xxxxxxxxxxxxxxx
|
||||
# 是否启用邮箱API代理
|
||||
EMAIL_PROXY_ENABLED=True
|
||||
# 邮箱API代理地址
|
||||
EMAIL_PROXY_ADDRESS=http://ip:port
|
||||
|
||||
# ===== 账号管理配置 =====
|
||||
# 系统最大已激活的账号数量,如果达到这个数量,则停止注册
|
||||
# so 要么在页面维护好当前已激活的账号,要么在页面删除账号,或者直接增大该值
|
||||
|
||||
4
api.py
4
api.py
@@ -1216,6 +1216,10 @@ async def get_config():
|
||||
"BROWSER_HEADLESS": os.getenv("BROWSER_HEADLESS", "True").lower() == "true",
|
||||
"BROWSER_USER_AGENT": os.getenv("BROWSER_USER_AGENT", ""),
|
||||
"MAX_ACCOUNTS": int(os.getenv("MAX_ACCOUNTS", "10")),
|
||||
"EMAIL_TYPE": os.getenv("EMAIL_TYPE", "tempemail"),
|
||||
"EMAIL_PROXY_ENABLED": os.getenv("EMAIL_PROXY_ENABLED", "False").lower() == "true",
|
||||
"EMAIL_PROXY_ADDRESS": os.getenv("EMAIL_PROXY_ADDRESS", ""),
|
||||
"EMAIL_API": os.getenv("EMAIL_API", ""),
|
||||
"EMAIL_DOMAINS": os.getenv("EMAIL_DOMAINS", ""),
|
||||
"EMAIL_USERNAME": os.getenv("EMAIL_USERNAME", ""),
|
||||
"EMAIL_DOMAIN": os.getenv("EMAIL_DOMAIN", ""),
|
||||
|
||||
@@ -53,6 +53,8 @@ SIGN_UP_URL = "https://authenticator.cursor.sh/sign-up"
|
||||
SETTINGS_URL = "https://www.cursor.com/settings"
|
||||
|
||||
# ===== 邮箱配置 =====
|
||||
# 邮箱类型
|
||||
EMAIL_TYPE = os.getenv("EMAIL_TYPE", "tempemail")
|
||||
# 临时邮箱用户名
|
||||
EMAIL_USERNAME = os.getenv("EMAIL_USERNAME", "xxx")
|
||||
# 临时邮箱域名
|
||||
@@ -63,6 +65,12 @@ EMAIL_PIN = os.getenv("EMAIL_PIN", "")
|
||||
EMAIL_DOMAINS = [
|
||||
domain.strip() for domain in os.getenv("EMAIL_DOMAINS", "xxx.xx").split(",")
|
||||
]
|
||||
# ZMail API地址
|
||||
EMAIL_API = os.getenv("EMAIL_API", "")
|
||||
# 是否启用邮箱API代理
|
||||
EMAIL_PROXY_ENABLED = os.getenv("EMAIL_PROXY_ENABLED", "false").lower() == "true"
|
||||
# 邮箱API代理地址
|
||||
EMAIL_PROXY_ADDRESS = os.getenv("EMAIL_PROXY_ADDRESS", "")
|
||||
# 邮件验证码获取最大重试次数
|
||||
EMAIL_VERIFICATION_RETRIES = int(os.getenv("EMAIL_VERIFICATION_RETRIES", 5))
|
||||
# 邮件验证码获取重试间隔(秒)
|
||||
|
||||
@@ -10,6 +10,7 @@ from config import (
|
||||
SETTINGS_URL,
|
||||
EMAIL_DOMAINS,
|
||||
REGISTRATION_MAX_RETRIES,
|
||||
EMAIL_TYPE
|
||||
)
|
||||
|
||||
|
||||
@@ -150,6 +151,8 @@ def sign_up_account(browser, tab, account_info):
|
||||
info(
|
||||
f"账号信息: 邮箱: {account_info['email']}, 密码: {account_info['password']}, 姓名: {account_info['first_name']} {account_info['last_name']}"
|
||||
)
|
||||
if EMAIL_TYPE == "zmail":
|
||||
EmailVerificationHandler.create_zmail_email(account_info)
|
||||
tab.get(SIGN_UP_URL)
|
||||
try:
|
||||
if tab.ele("@name=first_name"):
|
||||
|
||||
@@ -8,20 +8,30 @@ from config import (
|
||||
EMAIL_PIN,
|
||||
EMAIL_VERIFICATION_RETRIES,
|
||||
EMAIL_VERIFICATION_WAIT,
|
||||
EMAIL_TYPE,
|
||||
EMAIL_PROXY_ADDRESS,
|
||||
EMAIL_PROXY_ENABLED,
|
||||
EMAIL_API
|
||||
)
|
||||
|
||||
|
||||
class EmailVerificationHandler:
|
||||
def __init__(self, username=None, domain=None, pin=None):
|
||||
self.email = EMAIL_TYPE
|
||||
self.username = username or EMAIL_USERNAME
|
||||
self.domain = domain or EMAIL_DOMAIN
|
||||
self.session = requests.Session()
|
||||
self.emailApi = EMAIL_API
|
||||
self.emailExtension = f"@{self.domain}"
|
||||
self.pin = pin or EMAIL_PIN
|
||||
info(
|
||||
f"初始化邮箱验证器成功: {self.username}{self.emailExtension} pin: {self.pin}"
|
||||
)
|
||||
|
||||
if self.email == "tempemail":
|
||||
info(
|
||||
f"初始化邮箱验证器成功: {self.username}{self.emailExtension} pin: {self.pin}"
|
||||
)
|
||||
elif self.email == "zmail":
|
||||
info(
|
||||
f"初始化邮箱验证器成功: {self.emailApi}"
|
||||
)
|
||||
def get_verification_code(
|
||||
self, source_email=None, max_retries=None, wait_time=None
|
||||
):
|
||||
@@ -40,7 +50,11 @@ class EmailVerificationHandler:
|
||||
info(f"开始获取邮箱验证码=>最大重试次数:{max_retries}, 等待时间:{wait_time}")
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
code, mail_id = self._get_latest_mail_code(source_email)
|
||||
info(f"当前EMail类型为: {EMAIL_TYPE}")
|
||||
if self.email == "tempemail":
|
||||
code, mail_id = self.get_tempmail_email_code(source_email)
|
||||
elif self.email == "zmail":
|
||||
code, mail_id = self.get_zmail_email_code(source_email)
|
||||
if code:
|
||||
info(f"成功获取验证码: {code}")
|
||||
return code
|
||||
@@ -58,7 +72,7 @@ class EmailVerificationHandler:
|
||||
return None
|
||||
|
||||
# 手动输入验证码
|
||||
def _get_latest_mail_code(self, source_email=None):
|
||||
def get_tempmail_email_code(self, source_email=None):
|
||||
info("开始获取邮件列表")
|
||||
# 获取邮件列表
|
||||
mail_list_url = f"https://tempmail.plus/api/mails?email={self.username}{self.emailExtension}&limit=20&epin={self.pin}"
|
||||
@@ -145,3 +159,116 @@ class EmailVerificationHandler:
|
||||
time.sleep(0.2)
|
||||
|
||||
return False
|
||||
|
||||
# 如果是zmail 需要先创建邮箱
|
||||
def create_zmail_email(account_info):
|
||||
# 如果邮箱类型是zmail 需要先创建邮箱
|
||||
session = requests.Session()
|
||||
if EMAIL_PROXY_ENABLED:
|
||||
proxy = {
|
||||
"http": f"{EMAIL_PROXY_ADDRESS}",
|
||||
"https": f"{EMAIL_PROXY_ADDRESS}",
|
||||
}
|
||||
session.proxies.update(proxy)
|
||||
# 创建临时邮箱URL
|
||||
create_url = f"{EMAIL_API}/api/mailboxes"
|
||||
username = account_info["email"].split("@")[0]
|
||||
# 生成临时邮箱地址
|
||||
payload = {
|
||||
"address": f"{username}",
|
||||
"expiresInHours": 24,
|
||||
}
|
||||
# 发送POST请求创建临时邮箱
|
||||
try:
|
||||
create_response = session.post(
|
||||
create_url, json=payload, timeout=100
|
||||
) # 添加超时参数
|
||||
info(f"创建临时邮箱成功: {create_response.status_code}")
|
||||
create_data = create_response.json()
|
||||
info(f"创建临时邮箱返回数据: {create_data}")
|
||||
# 检查创建邮箱是否成功
|
||||
time.sleep(0.5)
|
||||
if create_data.get("success") is True or create_data.get('error') == '邮箱地址已存在':
|
||||
info(f"邮箱创建成功: {create_data}")
|
||||
else:
|
||||
error(f"邮箱创建失败: {create_data}")
|
||||
return None, None
|
||||
except requests.exceptions.Timeout:
|
||||
error("创建临时邮箱超时", create_url)
|
||||
return None, None
|
||||
info(f"创建临时邮箱成功: {create_data}, 返回值: {create_data}")
|
||||
|
||||
# 获取zmail邮箱验证码
|
||||
def get_zmail_email_code(self, source_email=None):
|
||||
info("开始获取邮件列表")
|
||||
# 获取邮件列表
|
||||
username = source_email.split("@")[0]
|
||||
mail_list_url = f"{EMAIL_API}/api/mailboxes/{username}/emails"
|
||||
proxy = {
|
||||
"http": f"{EMAIL_PROXY_ADDRESS}",
|
||||
"https": f"{EMAIL_PROXY_ADDRESS}",
|
||||
}
|
||||
self.session.proxies.update(proxy)
|
||||
try:
|
||||
mail_list_response = self.session.get(
|
||||
mail_list_url, timeout=10000
|
||||
) # 添加超时参数
|
||||
mail_list_data = mail_list_response.json()
|
||||
time.sleep(2)
|
||||
if not mail_list_data.get("emails"):
|
||||
return None, None
|
||||
except requests.exceptions.Timeout:
|
||||
error("获取邮件列表超时")
|
||||
return None, None
|
||||
except requests.exceptions.ConnectionError:
|
||||
error("获取邮件列表连接错误")
|
||||
return None, None
|
||||
except Exception as e:
|
||||
error(f"获取邮件列表发生错误: {str(e)}")
|
||||
return None, None
|
||||
|
||||
# 获取最新邮件的ID、
|
||||
mail_detail_data_len = len(mail_list_data["emails"])
|
||||
if mail_detail_data_len == 0:
|
||||
return None, None
|
||||
mail_list_data = mail_list_data["emails"][0]
|
||||
# 获取最新邮件的ID
|
||||
mail_id = mail_list_data.get("id")
|
||||
if not mail_id:
|
||||
return None, None
|
||||
# 获取具体邮件内容
|
||||
mail_detail_url = f"{EMAIL_API}/api/emails/{mail_id}"
|
||||
returnData = ''
|
||||
try:
|
||||
mail_detail_response = self.session.get(
|
||||
mail_detail_url, timeout=10
|
||||
) # 添加超时参数
|
||||
returnData = mail_detail_response.json()
|
||||
time.sleep(2)
|
||||
except requests.exceptions.Timeout:
|
||||
error("获取邮件详情超时")
|
||||
return None, None
|
||||
except requests.exceptions.ConnectionError:
|
||||
error("获取邮件详情连接错误")
|
||||
return None, None
|
||||
except Exception as e:
|
||||
error(f"获取邮件详情发生错误: {str(e)}")
|
||||
return None, None
|
||||
|
||||
# 从邮件文本中提取6位数字验证码\
|
||||
mail_text = returnData.get("email")
|
||||
mail_text = mail_text.get("textContent")
|
||||
# 如果提供了source_email,确保邮件内容中包含该邮箱地址
|
||||
if source_email and source_email.lower() not in mail_text.lower():
|
||||
error(f"邮件内容不包含指定的邮箱地址: {source_email}")
|
||||
else:
|
||||
info(f"邮件内容包含指定的邮箱地址: {source_email}")
|
||||
|
||||
code_match = re.search(r"(?<![a-zA-Z@.])\b\d{6}\b", mail_text)
|
||||
info(f"验证码匹配结果: {code_match}")
|
||||
# 如果找到验证码, 返回验证码和邮件ID
|
||||
if code_match:
|
||||
return code_match.group(), mail_id
|
||||
else:
|
||||
error("未找到验证码")
|
||||
return None, None
|
||||
|
||||
52
index.html
52
index.html
@@ -344,21 +344,56 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="email-type" class="form-label">邮箱类型</label>
|
||||
<select id="email-type" class="form-control" disabled>
|
||||
<option value="tempemail">TempEmail</option>
|
||||
<option value="zmail">ZMail</option>
|
||||
</select>
|
||||
<small class="text-muted">选择用于注册的临时邮箱服务类型</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="email-domains" class="form-label">邮箱域名</label>
|
||||
<input type="text" id="email-domains" class="form-control" disabled>
|
||||
<small class="text-muted">用于注册的邮箱域名,多个域名用逗号分隔</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="email-username" class="form-label">临时邮箱用户名</label>
|
||||
<input type="text" id="email-username" class="form-control" placeholder="加载中...">
|
||||
<small class="text-muted">用于接收验证码的临时邮箱用户名(不需要输入@及后面的部分)</small>
|
||||
|
||||
<!-- TempEmail相关字段 -->
|
||||
<div id="tempemail-fields">
|
||||
<div class="mb-3">
|
||||
<label for="email-username" class="form-label">临时邮箱用户名</label>
|
||||
<input type="text" id="email-username" class="form-control" placeholder="加载中...">
|
||||
<small class="text-muted">用于接收验证码的临时邮箱用户名(不需要输入@及后面的部分)</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="email-pin" class="form-label">临时邮箱PIN</label>
|
||||
<input type="text" id="email-pin" class="form-control" disabled>
|
||||
<small class="text-muted">临时邮箱PIN码(如果需要)</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="email-pin" class="form-label">临时邮箱PIN</label>
|
||||
<input type="text" id="email-pin" class="form-control" disabled>
|
||||
<small class="text-muted">临时邮箱PIN码(如果需要)</small>
|
||||
|
||||
<!-- ZMail相关字段 -->
|
||||
<div id="zmail-fields" style="display: none;">
|
||||
<div class="mb-3">
|
||||
<label for="email-api" class="form-label">邮箱API</label>
|
||||
<input type="text" id="email-api" class="form-control" disabled>
|
||||
<small class="text-muted">ZMail API地址</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="email-proxy-enabled" class="form-label">邮箱代理</label>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="email-proxy-enabled" disabled>
|
||||
<label class="form-check-label" for="email-proxy-enabled">启用邮箱代理</label>
|
||||
</div>
|
||||
<small class="text-muted">是否启用邮箱API代理</small>
|
||||
</div>
|
||||
<div class="mb-3" id="email-proxy-address-container">
|
||||
<label for="email-proxy-address" class="form-label">邮箱代理地址</label>
|
||||
<input type="text" id="email-proxy-address" class="form-control" disabled>
|
||||
<small class="text-muted">邮箱API代理服务器地址</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="browser-path" class="form-label">浏览器路径 (可选)</label>
|
||||
<input type="text" id="browser-path" class="form-control" disabled>
|
||||
@@ -369,7 +404,6 @@
|
||||
<input type="text" id="cursor-path" class="form-control" disabled>
|
||||
<small class="text-muted">Cursor安装目录的完整路径</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 在系统配置表单中添加代理设置部分 -->
|
||||
<div class="config-section card mb-3">
|
||||
|
||||
@@ -1196,7 +1196,22 @@ function loadConfig() {
|
||||
}
|
||||
}
|
||||
|
||||
$("#email-type").val(config.EMAIL_TYPE);
|
||||
$("#email-proxy-enabled").prop('checked', config.EMAIL_PROXY_ENABLED || false);
|
||||
if (config.EMAIL_PROXY_ENABLED) {
|
||||
$("#email-proxy-address").val(config.EMAIL_PROXY_ADDRESS);
|
||||
$("#email-api").val(config.EMAIL_API);
|
||||
}
|
||||
if (config.EMAIL_TYPE == "tempemail") {
|
||||
$("#tempemail-fields").show();
|
||||
$("#zmail-fields").hide();
|
||||
} else if (config.EMAIL_TYPE == "zmail") {
|
||||
$("#tempemail-fields").hide();
|
||||
$("#zmail-fields").show();
|
||||
}
|
||||
|
||||
hideLoading();
|
||||
|
||||
} else {
|
||||
showAlert('danger', '加载配置失败: ' + response.message);
|
||||
hideLoading();
|
||||
|
||||
@@ -66,4 +66,14 @@ $(window).resize(function() {
|
||||
if ($(window).width() > 576) {
|
||||
$('body').removeClass('sidebar-open');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#email-type").change(function() {
|
||||
if ($(this).val() === "tempemail") {
|
||||
$("#tempemail-fields").show();
|
||||
$("#zmail-fields").hide();
|
||||
} else if ($(this).val() === "zmail") {
|
||||
$("#tempemail-fields").hide();
|
||||
$("#zmail-fields").show();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user