feat: bot_flag 检测停机、注册间隔与 CLI 参数

注册成功后解析 access_token 的 bot_flag_source,命中则立即停止;
支持 register_interval_sec 与 argparse(count/concurrency/interval/hide-window);
邮箱 local-part 强制 z 起首,并关闭 AutomationControlled 特征。
This commit is contained in:
chaos committed 2026-07-16 21:00:35 +08:00
1 parent 986bc36f04
commit d0f06ac93c
7 files changed
+182 -11

No files matched your search

+1
View File
@@ -0,0 +1 @@
helenramos281@mail.bblbb.com----N9ee81e6c!a7#VCKDb6V6----eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiMWU1OTMzYWEtMTJiYi00YjU5LTg1ZDktOTRiZmFhNDliYzU2In0.gnekLoMUj2B5DscbjE5hyC9FoLqkYjjXP9X3usyyqDQ
+1
View File
@@ -0,0 +1 @@
zoieroberts1869@mail.bblbb.com----Ndf7a20b2!a7#M3gEsHL-----eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiNjRkOWNjNTMtM2Q0YS00MzNlLThhMTctMTIxYmUyODNmZTU4In0.ra0SYJyU146-eMqSQKcG9J63YDVip_tXOxk0SRXp_54
+2 -2
View File
@@ -27,12 +27,12 @@
"proxy_check_interval_sec": 300, "proxy_check_interval_sec": 300,
"proxy_source_disable_after": 3, "proxy_source_disable_after": 3,
"enable_nsfw": true, "enable_nsfw": true,
"register_count": 99999, "register_count": 3,
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
"cpa_export_enabled": true, "cpa_export_enabled": true,
"cpa_auth_dir": "./cpa_auths", "cpa_auth_dir": "./cpa_auths",
"cpa_base_url": "https://cli-chat-proxy.grok.com/v1", "cpa_base_url": "https://cli-chat-proxy.grok.com/v1",
"cpa_push_enabled": true, "cpa_push_enabled": false,
"cpa_remote_base": "https://cpa.nopj.cn", "cpa_remote_base": "https://cpa.nopj.cn",
"cpa_remote_secret": "DNznuRVoBhDT2SpSAyWw", "cpa_remote_secret": "DNznuRVoBhDT2SpSAyWw",
"cpa_remote_verify_tls": true, "cpa_remote_verify_tls": true,
@@ -0,0 +1,26 @@
{
"type": "xai",
"auth_kind": "oauth",
"access_token": "eyJ0eXAiOiJhdCtqd3QiLCJhbGciOiJFUzI1NiIsImtpZCI6Im9hdXRoMi1wcm9kdWN0aW9uLTIwMjYtMDItMTkifQ.eyJpc3MiOiJodHRwczovL2F1dGgueC5haSIsInN1YiI6Ijc3ZTI4MTVlLTE1MjQtNDM0MS1iYWE4LWM5NGVjZjc3MzAzYSIsImF1ZCI6ImIxYTAwNDkyLTA3M2EtNDdlYS04MTZmLTRjMzI5MjY0YTgyOCIsImV4cCI6MTc4NDEwOTU5MywiaWF0IjoxNzg0MDg3OTkzLCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIG9mZmxpbmVfYWNjZXNzIGdyb2stY2xpOmFjY2VzcyBhcGk6YWNjZXNzIGNvbnZlcnNhdGlvbnM6cmVhZCBjb252ZXJzYXRpb25zOndyaXRlIiwicHJpbmNpcGFsX3R5cGUiOiJVc2VyIiwicHJpbmNpcGFsX2lkIjoiNzdlMjgxNWUtMTUyNC00MzQxLWJhYTgtYzk0ZWNmNzczMDNhIiwiY2xpZW50X2lkIjoiYjFhMDA0OTItMDczYS00N2VhLTgxNmYtNGMzMjkyNjRhODI4IiwianRpIjoiZDQ5YWQyMzEtOGRkNy00Zjk1LWE3ZjAtYWQ2N2VjZTNhYWRmIiwidGVhbV9pZCI6Ijc5OWY1OWM1LTJhZGMtNDllYi1iMTQ3LTVjNTY1NzJjMzE5MCIsInJlZmVycmVyIjoiZ3Jvay1idWlsZCJ9.LHoRB8Ze9wPEIbP1OYllw5cmDvMVLbYh7D2dL2AgQ3YPV0V7zpuw7gzQXYAOxbP7UPeuIQQ97qGOfXgJEW--yA",
"refresh_token": "wXTgQRJDSMcyGmC8-krwGpHjkdsDzKHN2KnFwpvtdfnli_jBOqlvDnTSIrl2j90boNMVIO4Dg7UAdgGoTmE7ig",
"token_type": "Bearer",
"expires_in": 21600,
"expired": "2026-07-15T09:59:53Z",
"last_refresh": "2026-07-15T03:59:53Z",
"email": "helenramos281@mail.bblbb.com",
"sub": "77e2815e-1524-4341-baa8-c94ecf77303a",
"base_url": "https://cli-chat-proxy.grok.com/v1",
"token_endpoint": "https://auth.x.ai/oauth2/token",
"redirect_uri": "http://127.0.0.1:56121/callback",
"disabled": false,
"headers": {
"x-grok-client-version": "0.2.93",
"x-xai-token-auth": "xai-grok-cli",
"x-authenticateresponse": "authenticate-response",
"x-grok-client-identifier": "grok-pager",
"User-Agent": "grok-pager/0.2.93 grok-shell/0.2.93 (linux; x86_64)"
},
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Im9hdXRoMi1wcm9kdWN0aW9uLTIwMjYtMDItMTkifQ.eyJpc3MiOiJodHRwczovL2F1dGgueC5haSIsInN1YiI6Ijc3ZTI4MTVlLTE1MjQtNDM0MS1iYWE4LWM5NGVjZjc3MzAzYSIsImF1ZCI6ImIxYTAwNDkyLTA3M2EtNDdlYS04MTZmLTRjMzI5MjY0YTgyOCIsImV4cCI6MTc4NDEwOTU5MywiaWF0IjoxNzg0MDg3OTkzLCJub25jZSI6IkU3dGRabjVEQmRNZmdNc2tQRF9NelEiLCJnaXZlbl9uYW1lIjoiS2FpIiwiZmFtaWx5X25hbWUiOiJIYW4iLCJlbWFpbCI6ImhlbGVucmFtb3MyODFAbWFpbC5iYmxiYi5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZX0.Ok3MSOzASage-BhrkdDfVvttZYFat-yBmbQbsth0ykj-jRD07iyjw5snRfX8__2A3gkZM_pLdkSUAfgEkFJTjw",
"sso": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiMWU1OTMzYWEtMTJiYi00YjU5LTg1ZDktOTRiZmFhNDliYzU2In0.gnekLoMUj2B5DscbjE5hyC9FoLqkYjjXP9X3usyyqDQ",
"referrer": "grok-build"
}
@@ -0,0 +1,26 @@
{
"type": "xai",
"auth_kind": "oauth",
"access_token": "eyJ0eXAiOiJhdCtqd3QiLCJhbGciOiJFUzI1NiIsImtpZCI6Im9hdXRoMi1wcm9kdWN0aW9uLTIwMjYtMDItMTkifQ.eyJpc3MiOiJodHRwczovL2F1dGgueC5haSIsInN1YiI6ImJiYzI0ODVlLTcxM2UtNDU4Ny1iZTI3LTZkZTViZWNmZjhkNCIsImF1ZCI6ImIxYTAwNDkyLTA3M2EtNDdlYS04MTZmLTRjMzI5MjY0YTgyOCIsImV4cCI6MTc4NDIxMTcyNywiaWF0IjoxNzg0MTkwMTI3LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIG9mZmxpbmVfYWNjZXNzIGdyb2stY2xpOmFjY2VzcyBhcGk6YWNjZXNzIGNvbnZlcnNhdGlvbnM6cmVhZCBjb252ZXJzYXRpb25zOndyaXRlIiwicHJpbmNpcGFsX3R5cGUiOiJVc2VyIiwicHJpbmNpcGFsX2lkIjoiYmJjMjQ4NWUtNzEzZS00NTg3LWJlMjctNmRlNWJlY2ZmOGQ0IiwiY2xpZW50X2lkIjoiYjFhMDA0OTItMDczYS00N2VhLTgxNmYtNGMzMjkyNjRhODI4IiwianRpIjoiZTQzNjI0ZmMtMDJmNC00MjhmLWFhMmEtNGM5MTAxMDk2MDY3IiwidGVhbV9pZCI6IjkzZGRiMzg3LWMyMDktNDEwZi1iMDJhLTA5NDZhNWM4ODkwNSIsInJlZmVycmVyIjoiZ3Jvay1idWlsZCJ9.DM0FgR-cvN82OkOpza-vvdj6Y7F-DDqcIgALepE3XR_GFKNKlblf6oa6ZGFLg6EkNELsSGNb5bmka_CDx06Mcg",
"refresh_token": "YCyRNl-D1-OAzfoVs9sAKPEBBLm5kHJvdI9SEx18W8tZmXKHGcQ9yp_N2q4hNqq_dQH4Emy3EPbV3ikEBBuOAA",
"token_type": "Bearer",
"expires_in": 21600,
"expired": "2026-07-16T14:22:07Z",
"last_refresh": "2026-07-16T08:22:07Z",
"email": "zoieroberts1869@mail.bblbb.com",
"sub": "bbc2485e-713e-4587-be27-6de5becff8d4",
"base_url": "https://cli-chat-proxy.grok.com/v1",
"token_endpoint": "https://auth.x.ai/oauth2/token",
"redirect_uri": "http://127.0.0.1:56121/callback",
"disabled": false,
"headers": {
"x-grok-client-version": "0.2.93",
"x-xai-token-auth": "xai-grok-cli",
"x-authenticateresponse": "authenticate-response",
"x-grok-client-identifier": "grok-pager",
"User-Agent": "grok-pager/0.2.93 grok-shell/0.2.93 (linux; x86_64)"
},
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Im9hdXRoMi1wcm9kdWN0aW9uLTIwMjYtMDItMTkifQ.eyJpc3MiOiJodHRwczovL2F1dGgueC5haSIsInN1YiI6ImJiYzI0ODVlLTcxM2UtNDU4Ny1iZTI3LTZkZTViZWNmZjhkNCIsImF1ZCI6ImIxYTAwNDkyLTA3M2EtNDdlYS04MTZmLTRjMzI5MjY0YTgyOCIsImV4cCI6MTc4NDIxMTcyNywiaWF0IjoxNzg0MTkwMTI3LCJub25jZSI6Imoxb0JzWUkzR19WUXRseUxWVTBteVEiLCJnaXZlbl9uYW1lIjoiQ2FsZWIiLCJmYW1pbHlfbmFtZSI6IkxpdSIsImVtYWlsIjoiem9pZXJvYmVydHMxODY5QG1haWwuYmJsYmIuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWV9.y38jxu1nWyO0Yzr4lcxVAqVbVc37880Jz0UGlIoQ8P5HWdD1b-hFleiGJmGbqayQ9AhpoKJMcoWrWIYFGMLc2g",
"sso": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiNjRkOWNjNTMtM2Q0YS00MzNlLThhMTctMTIxYmUyODNmZTU4In0.ra0SYJyU146-eMqSQKcG9J63YDVip_tXOxk0SRXp_54",
"referrer": "grok-build"
}
+122 -9
View File
@@ -17,6 +17,7 @@ import random
import re import re
import string import string
import json import json
import base64
from DrissionPage import Chromium, ChromiumOptions from DrissionPage import Chromium, ChromiumOptions
from DrissionPage.errors import PageDisconnectedError from DrissionPage.errors import PageDisconnectedError
@@ -586,13 +587,17 @@ def create_browser_options(proxy=None):
options.set_argument("--disable-background-timer-throttling") options.set_argument("--disable-background-timer-throttling")
options.set_argument("--disable-backgrounding-occluded-windows") options.set_argument("--disable-backgrounding-occluded-windows")
options.set_argument("--disable-renderer-backgrounding") options.set_argument("--disable-renderer-backgrounding")
# 反 bot:关闭 Blink AutomationControlled(否则 navigator.webdriver 在 JS 前就暴露)
options.set_argument("--disable-blink-features=AutomationControlled")
# 固定窗口尺寸,避免 Turnstile iframe 在 0 尺寸窗口里不渲染 # 固定窗口尺寸,避免 Turnstile iframe 在 0 尺寸窗口里不渲染
# 轻微随机化位置即可,尺寸过大/过小都可能影响验证渲染
options.set_argument("--window-size=1280,900") options.set_argument("--window-size=1280,900")
# 隐藏窗口(可选):仅移出屏幕。注意:部分环境下会让 Turnstile 永远 token=0 # 隐藏窗口(可选):仅移出屏幕。注意:部分环境下会让 Turnstile 永远 token=0
if config.get("hide_window", False): if config.get("hide_window", False):
options.set_argument("--window-position=-32000,-32000") options.set_argument("--window-position=-32000,-32000")
else: else:
options.set_argument("--window-position=40,40") options.set_argument(f"--window-position={random.randint(40, 120)},{random.randint(40, 120)}")
# 代理:线程绑定(代理池)> 入参 > config.proxy # 代理:线程绑定(代理池)> 入参 > config.proxy
use_proxy = "" use_proxy = ""
@@ -1125,13 +1130,25 @@ _LAST_NAMES = (
) )
_NAME_SEPARATORS = ("", ".", "_") _NAME_SEPARATORS = ("", ".", "_")
# z 开头的常见英文名字,用于生成 local-part 全部以 z 起首的邮箱
_Z_FIRST_NAMES = (
"zachary", "zack", "zackary", "zackery", "zane", "zayn", "zayne", "zavier",
"zaid", "zaiden", "zayden", "zaire", "zeke", "zephyr", "zeus", "zion",
"ziggy", "zed", "zeb", "zebulon", "zelig", "zeno", "zenon", "zaki",
"zoe", "zoey", "zoie", "zoya", "zora", "zara", "zaria", "zariah",
"zelda", "zena", "zenia", "zinnia", "ziva", "zola", "zainab", "zaynab",
"zahra", "zaida", "zanna", "zara", "zarah", "zaria", "zia", "zula",
)
def generate_username(length=10): def generate_username(length=10):
"""生成更像正常英文用户的邮箱名:姓名/词根 + 数字结尾。 """生成更像正常英文用户的邮箱名:姓名/词根 + 数字结尾。
length 仅作兼容参数(旧调用传 10),实际长度由名字与数字后缀决定,约 8–18。 length 仅作兼容参数(旧调用传 10),实际长度由名字与数字后缀决定,约 8–18。
强制 local-part 以 'z' 起首(first 从 z 开头姓名池抽取;last+first[0] 风格改为
z + last,仍保证首字符为 z)。
""" """
first = secrets.choice(_FIRST_NAMES) first = secrets.choice(_Z_FIRST_NAMES)
last = secrets.choice(_LAST_NAMES) last = secrets.choice(_LAST_NAMES)
sep = secrets.choice(_NAME_SEPARATORS) sep = secrets.choice(_NAME_SEPARATORS)
# 数字后缀:2–4 位更像真实用户(生日年份、学号尾号等) # 数字后缀:2–4 位更像真实用户(生日年份、学号尾号等)
@@ -1163,8 +1180,8 @@ def generate_username(length=10):
# first 首字母 + last + digits e.g. jwilson87 # first 首字母 + last + digits e.g. jwilson87
base = f"{first[0]}{last}" base = f"{first[0]}{last}"
else: else:
# last + first 首字母 + digits e.g. wilsonj87 # z + last + digits e.g. zwilson87(原 last+first[0] 风格改造以保证 z 起首)
base = f"{last}{first[0]}" base = f"z{last}"
local = f"{base}{digits}".lower() local = f"{base}{digits}".lower()
# 邮箱 local 只保留 [a-z0-9._],去掉连续分隔符 # 邮箱 local 只保留 [a-z0-9._],去掉连续分隔符
@@ -2500,7 +2517,7 @@ def fill_email_and_submit(session, timeout=45, log_callback=None, cancel_callbac
while time.time() < deadline: while time.time() < deadline:
raise_if_cancelled(cancel_callback) raise_if_cancelled(cancel_callback)
filled = page.run_js( filled = page.run_js(
""" r"""
const email = arguments[0]; const email = arguments[0];
function isVisible(node) { function isVisible(node) {
if (!node) return false; if (!node) return false;
@@ -3836,6 +3853,37 @@ def register_one(session, shared, worker_id, slot_no):
return email return email
def _check_bot_flag(email, cfg=None):
"""检查刚注册账号的 access_token 是否带 bot_flag_source。
返回 (is_bot: bool, detail: str)。
"""
cfg = cfg or config
try:
import cpa
out_dir = str(cfg.get("cpa_auth_dir", "./cpa_auths"))
fname = cpa.credential_file_name(email)
path = os.path.join(out_dir, fname)
if not os.path.exists(path):
return False, f"auth file not found: {path}"
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
at = str(data.get("access_token") or "")
if not at:
return False, "no access_token"
parts = at.split(".")
if len(parts) < 2:
return False, "invalid JWT"
seg = parts[1] + "=" * (-len(parts[1]) % 4)
payload = json.loads(base64.urlsafe_b64decode(seg))
bot = payload.get("bot_flag_source")
if bot == 1:
return True, "bot_flag_source=1 → 账号被标记为 bot"
return False, f"bot_flag_source={bot} (OK)"
except Exception as e:
return False, f"check error: {e}"
def register_worker(worker_id, shared): def register_worker(worker_id, shared):
"""单个并发 worker:自建独立浏览器,循环领取名额并注册。""" """单个并发 worker:自建独立浏览器,循环领取名额并注册。"""
@@ -3878,6 +3926,18 @@ def register_worker(worker_id, shared):
except Exception: except Exception:
pass pass
log(f"[+] 注册成功: {email}(累计成功 {total})") log(f"[+] 注册成功: {email}(累计成功 {total})")
# ===== 注册后立即检查 bot 标记 =====
if config.get("stop_on_bot_flag", True):
is_bot, detail = _check_bot_flag(email)
if is_bot:
log(f"[!] ⛔ 检测到 bot 标记: {detail}")
log("[!] 立即停止所有注册(避免继续浪费账号)")
shared.stop()
raise RegistrationCancelled("检测到 bot_flag,停止注册")
else:
log(f"[Debug] bot 检查通过: {detail}")
break break
except RegistrationCancelled: except RegistrationCancelled:
raise raise
@@ -3928,6 +3988,13 @@ def register_worker(worker_id, shared):
break break
if shared.should_stop(): if shared.should_stop():
break break
# 注册间隔:控制注册速率,降低被标记为 bot 的风险
interval = float(config.get("register_interval_sec", 0) or 0)
if interval > 0:
log(f"[*] 等待 {interval:.0f}s 后开始下一个账号(register_interval_sec)")
sleep_with_cancel(interval, shared.should_stop)
if shared.should_stop():
break
# 下一账号:默认轮换出口并重启浏览器 # 下一账号:默认轮换出口并重启浏览器
session.restart() session.restart()
except RegistrationCancelled: except RegistrationCancelled:
@@ -3984,11 +4051,55 @@ def run_registration_concurrent(count, concurrency):
def main(): def main():
import argparse
parser = argparse.ArgumentParser(
description="Grok 注册机 - 批量注册 xAI/Grok 账号",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
示例:
python grok_register_ttk.py # 交互模式
python grok_register_ttk.py --count 10 --concurrency 2 # 注册10个,2并发
python grok_register_ttk.py --count 50 --interval 120 # 每2分钟注册1个
python grok_register_ttk.py --no-stop-on-bot # 不自动停(调试用)
""",
)
parser.add_argument("--count", type=int, default=None,
help="注册数量(默认读取 config.json 或 1)")
parser.add_argument("--concurrency", type=int, default=None,
help="并发浏览器数(默认交互输入)")
parser.add_argument("--interval", type=int, default=None, dest="register_interval_sec",
help="注册间隔秒数(如 120=每2分钟1个,0=无间隔)")
parser.add_argument("--stop-on-bot", action="store_true", default=None, dest="stop_on_bot_flag",
help="检测到 bot_flag 立即停止(默认开启)")
parser.add_argument("--no-stop-on-bot", action="store_false", default=None, dest="stop_on_bot_flag",
help="不自动停止(调试用)")
parser.add_argument("--hide-window", action="store_true", default=None, dest="hide_window",
help="隐藏浏览器窗口(移到屏幕外,非 headless)")
parser.add_argument("--show-window", action="store_false", default=None, dest="hide_window",
help="显示浏览器窗口(默认)")
args = parser.parse_args()
load_config() load_config()
count = int(config.get("register_count", 1) or 1) count = args.count if args.count is not None else int(config.get("register_count", 1) or 1)
# 命令行参数覆盖到 config(后续代码统一读 config)
if args.register_interval_sec is not None:
config["register_interval_sec"] = args.register_interval_sec
if args.stop_on_bot_flag is not None:
config["stop_on_bot_flag"] = args.stop_on_bot_flag
if args.hide_window is not None:
config["hide_window"] = args.hide_window
# 默认值
config.setdefault("register_interval_sec", 0)
config.setdefault("stop_on_bot_flag", True)
cli_log("[*] 已加载配置") cli_log("[*] 已加载配置")
interval = config.get("register_interval_sec", 0)
cli_log( cli_log(
f"[*] 当前邮箱服务商: {config.get('email_provider', 'duckmail')} | 目标注册数: {count}" f"[*] 邮箱: {config.get('email_provider', 'duckmail')} | "
f"目标: {count} | 间隔: {'{}s'.format(interval) if interval else '无'} | "
f"bot检测: {'开' if config.get('stop_on_bot_flag') else '关'} | "
f"窗口: {'隐藏' if config.get('hide_window') else '显示'}"
) )
try: try:
import proxy_pool import proxy_pool
@@ -4005,6 +4116,9 @@ def main():
) )
else: else:
cli_log("[*] CPA 导出: 关闭(仅写 accounts_*.txt)") cli_log("[*] CPA 导出: 关闭(仅写 accounts_*.txt)")
concurrency = args.concurrency
if concurrency is None:
try: try:
raw = input("请输入并发数量(同时开几个浏览器,直接回车=1): ").strip() raw = input("请输入并发数量(同时开几个浏览器,直接回车=1): ").strip()
except (KeyboardInterrupt, EOFError): except (KeyboardInterrupt, EOFError):
@@ -4015,8 +4129,7 @@ def main():
except ValueError: except ValueError:
cli_log("[!] 并发数量无效,使用 1") cli_log("[!] 并发数量无效,使用 1")
concurrency = 1 concurrency = 1
if concurrency < 1: concurrency = max(1, min(concurrency, count))
concurrency = 1
run_registration_concurrent(count, concurrency) run_registration_concurrent(count, concurrency)
+4
View File
@@ -979,3 +979,7 @@ t0rpdza1s0@mail.bblbb.com bblbb:t0rpdza1s0
w5ayintm8r@mail.bblbb.com bblbb:w5ayintm8r w5ayintm8r@mail.bblbb.com bblbb:w5ayintm8r
2in9y6cab4@mail.bblbb.com bblbb:2in9y6cab4 2in9y6cab4@mail.bblbb.com bblbb:2in9y6cab4
5fbu5nq3wj@mail.bblbb.com bblbb:5fbu5nq3wj 5fbu5nq3wj@mail.bblbb.com bblbb:5fbu5nq3wj
cynthia464@mail.bblbb.com bblbb:cynthia464
meganmartinez956@mail.bblbb.com bblbb:meganmartinez956
helenramos281@mail.bblbb.com bblbb:helenramos281
zoieroberts1869@mail.bblbb.com bblbb:zoieroberts1869