feat: auto-fetch codex login otp from mailbox
This commit is contained in:
@@ -198,12 +198,14 @@ class CodexOAuthHTTPFlow:
|
||||
otp: str = "",
|
||||
workspace_id: str = "",
|
||||
use_browser: bool = False,
|
||||
mailbox: dict | None = None,
|
||||
) -> None:
|
||||
self.authorize_url = authorize_url
|
||||
self.email = email
|
||||
self.password = password
|
||||
self.otp = otp
|
||||
self.workspace_id = workspace_id
|
||||
self.mailbox = mailbox
|
||||
self.auth_base = "https://auth.openai.com"
|
||||
self.proxy = load_proxy()
|
||||
self.http = HTTPClient(self.proxy)
|
||||
@@ -304,13 +306,36 @@ class CodexOAuthHTTPFlow:
|
||||
print(f"[otp] sending email code via {send_url}")
|
||||
return self._api_json("GET", send_url, referer=referer)
|
||||
|
||||
def _fetch_otp_from_mailbox(self) -> str:
|
||||
"""Try to fetch OTP from mailbox automatically."""
|
||||
if not self.mailbox:
|
||||
return ""
|
||||
from vmail_client import MailClient
|
||||
mail = MailClient()
|
||||
print("[otp] auto-fetching OTP from mailbox...")
|
||||
try:
|
||||
code = mail.wait_for_otp(self.mailbox, timeout=120, poll=3.0)
|
||||
print(f" OTP: {code}")
|
||||
return code
|
||||
except Exception as e:
|
||||
print(f"[otp] auto-fetch failed: {e}")
|
||||
return ""
|
||||
|
||||
def _validate_email_otp(self, referer: str) -> dict[str, Any]:
|
||||
validate_url = f"{self.auth_base}/api/accounts/email-otp/validate"
|
||||
resend_url = f"{self.auth_base}/api/accounts/email-otp/resend"
|
||||
|
||||
while True:
|
||||
code = (self.otp or input("Email OTP (or type 'resend'): ").strip()).strip()
|
||||
self.otp = ""
|
||||
if self.otp:
|
||||
code = self.otp.strip()
|
||||
self.otp = ""
|
||||
elif self.mailbox:
|
||||
code = self._fetch_otp_from_mailbox()
|
||||
if not code:
|
||||
raise FlowError("Failed to auto-fetch OTP from mailbox")
|
||||
else:
|
||||
code = input("Email OTP (or type 'resend'): ").strip()
|
||||
|
||||
if not code:
|
||||
continue
|
||||
|
||||
|
||||
22
src/main.py
22
src/main.py
@@ -103,6 +103,26 @@ def cmd_codex_login(args):
|
||||
|
||||
authorize_url = args.authorize_url or DEFAULT_AUTHORIZE_URL
|
||||
|
||||
# Try to get mailbox token for auto OTP fetching
|
||||
mailbox = None
|
||||
if args.mailbox_password:
|
||||
import httpx
|
||||
try:
|
||||
token_resp = httpx.post(
|
||||
"https://api.mail.tm/token",
|
||||
json={"address": email, "password": args.mailbox_password},
|
||||
timeout=30,
|
||||
)
|
||||
if token_resp.status_code == 200:
|
||||
mailbox = {
|
||||
"address": email,
|
||||
"password": args.mailbox_password,
|
||||
"token": token_resp.json()["token"],
|
||||
}
|
||||
print(f"Mailbox token obtained, will auto-fetch OTP if needed")
|
||||
except Exception as e:
|
||||
print(f"Warning: Failed to get mailbox token: {e}")
|
||||
|
||||
print(f"Starting Codex OAuth flow for {email}")
|
||||
flow = CodexOAuthHTTPFlow(
|
||||
authorize_url=authorize_url,
|
||||
@@ -110,6 +130,7 @@ def cmd_codex_login(args):
|
||||
password=password,
|
||||
otp=args.otp or "",
|
||||
workspace_id=args.workspace_id or "",
|
||||
mailbox=mailbox,
|
||||
)
|
||||
try:
|
||||
callback_url = flow.run()
|
||||
@@ -153,6 +174,7 @@ Examples:
|
||||
p_codex.add_argument("--otp", default="", help="Email OTP code (if already known)")
|
||||
p_codex.add_argument("--workspace-id", dest="workspace_id", default="", help="Workspace ID to select")
|
||||
p_codex.add_argument("--authorize-url", dest="authorize_url", default="", help="Custom authorize URL")
|
||||
p_codex.add_argument("--mailbox-password", dest="mailbox_password", default="", help="Mailbox password for auto OTP fetching")
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
Reference in New Issue
Block a user