
以前提到验证码注册登录自动化问题就堵死,也确实是,问题不是在于技术难度,代码难写,而是在于没有验证码接口呀,巧妇难为无米之炊!
现在我自己手搓了一个邮件服务接口,直接提供验证码查询 API 出来。
当前的思路是这样,我下面直接输出接口代码:
第一步:随机一个 https://www.nimai.cn 的临时邮箱(如:x2sd332@nimail.cn),调用业务接口,发送验证码:
第二步 1:查询邮件服务接口,用上面随机生成的邮箱(x2sd332@nimail.cn)去循环查询邮件。
关键在这里,需要用邮箱去查邮件,这里可能返回多个邮件,拿最新的一个就行:
curl 'https://www.nimail.cn/api/getmails' \
-H 'accept: application/json, text/javascript, /; q=0.01' \
-H 'accept-language: zh-CN,zh;q=0.9' \
-H 'origin: https://www.nimail.cn' \
--data-raw 'mail=ohgim96m%40nimail.cn'
第二步 2:上面查询到数据后,使用字段 id 的值,请求这个接口获取邮件内容。
curl 'https://www.nimail.cn/api/raw-html/ohgim96m@nimail.cn/1761577116655'
第三步:查询到的邮件后,对邮件进行正则匹配,匹配到你的验证码,提取出来。
第四步:用验证码和第一步调用业务接口获取到的随机字符串一起,请求验证接口或者注册接口
第五步:验证完成。
代码示例如下:
import requests
import random
import string
import time
import re
import json
import urllib.parse
class EmailVerification:
def __init__(self):
self.base_url = "http://localhost:8888/v1/user"
self.nimail_api = "https://www.nimail.cn/api"
def generate_random_email(self):
"""生成随机nimail邮箱"""
# 生成随机用户名(6-10位字母数字)
username_length = random.randint(6, 10)
username = ''.join(random.choices(string.ascii_lowercase + string.digits, k=username_length))
return f"{username}@nimail.cn"
def send_verification_code(self, email):
"""第一步:发送验证码"""
url = f"{self.base_url}/sendEmailCode"
headers = {
'Accept-Language': 'en-US',
'Content-Type': 'text/plain'
}
data = {
"email": email
}
try:
response = requests.post(url, headers=headers, data=json.dumps(data))
print(f"发送验证码响应状态: {response.status_code}")
print(f"发送验证码响应内容: {response.text}")
if response.status_code == 200:
# 假设响应中包含codeid,根据实际接口调整
response_data = response.json()
codeid = response_data.get('codeid', 'default_codeid')
return True, codeid
else:
return False, None
except Exception as e:
print(f"发送验证码时出错: {e}")
return False, None
def get_emails_list(self, email, max_attempts=30, delay=2):
"""第二步1:查询邮件列表"""
print(f"开始查询邮箱 {email} 的邮件列表...")
for attempt in range(max_attempts):
try:
headers = {
'accept': 'application/json, text/javascript, */*; q=0.01',
'accept-language': 'zh-CN,zh;q=0.9',
'origin': 'https://www.nimail.cn'
}
# 构建请求数据
data = {
'mail': email
}
response = requests.post(f"{self.nimail_api}/getmails", headers=headers, data=data)
if response.status_code == 200:
emails_data = response.json()
# 根据实际API响应结构调整
if isinstance(emails_data, list) and len(emails_data) > 0:
print(f"第 {attempt + 1} 次查询: 找到 {len(emails_data)} 封邮件")
# 返回最新的邮件(假设列表是按时间顺序的,第一个或最后一个是最新的)
latest_email = emails_data[0] # 根据实际情况调整索引
return latest_email
else:
print(f"第 {attempt + 1} 次查询: 未找到邮件,继续等待...")
else:
print(f"第 {attempt + 1} 次查询: API响应异常,状态码: {response.status_code}")
except Exception as e:
print(f"第 {attempt + 1} 次查询时出错: {e}")
time.sleep(delay)
print("达到最大查询次数,未找到验证码邮件")
return None
def get_email_content(self, email, email_id):
"""第二步2:根据邮件ID获取邮件内容"""
try:
# 构建获取邮件内容的URL
url = f"{self.nimail_api}/raw-html/{urllib.parse.quote(email)}/{email_id}"
headers = {
'accept': 'application/json, text/javascript, */*; q=0.01',
'accept-language': 'zh-CN,zh;q=0.9',
'origin': 'https://www.nimail.cn'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
print("成功获取邮件内容")
return response.text
else:
print(f"获取邮件内容失败,状态码: {response.status_code}")
return None
except Exception as e:
print(f"获取邮件内容时出错: {e}")
return None
def extract_verification_code(self, email_content):
"""第三步:从邮件内容中提取验证码"""
if not email_content:
return None
# 使用正则表达式匹配验证码(6位数字)
code_patterns = [
r'\b\d{6}\b', # 6位数字
r'验证码.*?(\d{6})', # 包含"验证码"的6位数字
r'code.*?(\d{6})', # 包含"code"的6位数字
r'verification.*?(\d{6})', # 包含"verification"的6位数字
r'【.*?】.*?(\d{6})', # 中文格式的验证码
r'<strong>(\d{6})</strong>', # HTML中的验证码
r'<td[^>]*>(\d{6})</td>' # 表格中的验证码
]
for pattern in code_patterns:
matches = re.search(pattern, email_content, re.IGNORECASE)
if matches:
verification_code = matches.group(1) if matches.groups() else matches.group(0)
print(f"找到验证码: {verification_code}")
return verification_code
# 如果没有匹配到,尝试打印部分内容用于调试
print("邮件内容预览(前500字符):", email_content[:500])
print("未在邮件中找到验证码")
return None
def register_user(self, email, codeid, verification_code, password="123456"):
"""第四步:注册用户"""
url = f"{self.base_url}/register"
headers = {
'Content-Type': 'text/plain'
}
data = {
"username": email,
"account": "",
"password": password,
"codeid": codeid,
"code": int(verification_code)
}
try:
response = requests.post(url, headers=headers, data=json.dumps(data))
print(f"注册响应状态: {response.status_code}")
print(f"注册响应内容: {response.text}")
if response.status_code == 200:
print("注册成功!")
return True
else:
print("注册失败!")
return False
except Exception as e:
print(f"注册时出错: {e}")
return False
def run_complete_verification(self):
"""执行完整的验证流程"""
print("=== 开始邮箱验证流程 ===")
# 第一步:生成随机邮箱并发送验证码
email = self.generate_random_email()
print(f"生成的随机邮箱: {email}")
success, codeid = self.send_verification_code(email)
if not success:
print("发送验证码失败,终止流程")
return False
print(f"验证码发送成功,codeid: {codeid}")
# 第二步1:查询邮件列表,获取最新邮件
latest_email = self.get_emails_list(email)
if not latest_email:
print("未找到邮件,终止流程")
return False
# 获取邮件ID(根据实际API响应结构调整)
email_id = latest_email.get('id')
if not email_id:
print("未找到邮件ID,终止流程")
return False
print(f"找到最新邮件,ID: {email_id}")
# 第二步2:获取邮件内容
email_content = self.get_email_content(email, email_id)
if not email_content:
print("获取邮件内容失败,终止流程")
return False
# 第三步:提取验证码
verification_code = self.extract_verification_code(email_content)
if not verification_code:
print("未找到验证码,终止流程")
return False
# 第四步:注册用户
success = self.register_user(email, codeid, verification_code)
# 第五步:完成验证
if success:
print("=== 验证完成 ===")
else:
print("=== 验证失败 ===")
return success
# 使用示例
if __name__ == "__main__":
verifier = EmailVerification()
# 执行一次完整的验证流程
verifier.run_complete_verification()
# 如果需要批量执行,可以使用循环
# for i in range(5): # 执行5次
# print(f"\n=== 第 {i+1} 次执行 ===")
# verifier.run_complete_verification()
# time.sleep(5) # 每次执行间隔5秒