{"components":{"responses":{"BadRequest":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Bad request"},"InternalError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"L\u1ed7i server"},"NotFound":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Kh\u00f4ng t\u00ecm th\u1ea5y"},"RateLimited":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Qu\u00e1 nhi\u1ec1u request - \u0111\u1ee3i 1 ph\u00fat"},"Success":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateResponse"}}},"description":"Th\u00e0nh c\u00f4ng"},"Unauthorized":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Phi\u00ean h\u1ebft h\u1ea1n ho\u1eb7c ch\u01b0a \u0111\u0103ng nh\u1eadp"},"UnsupportedMediaType":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Content-Type ph\u1ea3i l\u00e0 application/json"}},"schemas":{"AdminStats":{"properties":{"active_sessions":{"type":"integer"},"db_virtual_users":{"type":"integer"},"total_messages":{"type":"integer"},"total_sessions":{"type":"integer"}},"type":"object"},"EmailDetail":{"properties":{"attachments":{"items":{"properties":{"filename":{"type":"string"},"id":{"type":"string"}},"type":"object"},"type":"array"},"body":{"description":"Plain text body (HTML-escaped)","type":"string"},"date":{"type":"string"},"from":{"type":"string"},"html_body":{"description":"HTML \u0111\u00e3 \u0111\u01b0\u1ee3c sanitize (XSS-clean)","type":"string"},"id":{"type":"string"},"subject":{"type":"string"}},"type":"object"},"EmailSummary":{"properties":{"date":{"format":"date-time","type":"string"},"from":{"example":"noreply@byteplus.com","type":"string"},"id":{"example":"<abc@byteplus.com>","type":"string"},"read":{"type":"boolean"},"subject":{"example":"Verification code","type":"string"}},"type":"object"},"Error":{"properties":{"detail":{"description":"Chi ti\u1ebft (optional)","type":"string"},"error":{"description":"M\u00f4 t\u1ea3 l\u1ed7i","type":"string"}},"type":"object"},"GenerateResponse":{"properties":{"domain":{"example":"rionfashion.com","type":"string"},"email":{"example":"myuser@rionfashion.com","type":"string"},"expires_in":{"description":"Gi\u00e2y cho t\u1edbi khi h\u1ebft h\u1ea1n","example":3600,"type":"integer"},"is_resync":{"description":"True n\u1ebfu email \u0111\u00e3 t\u1ed3n t\u1ea1i (resync). False n\u1ebfu t\u1ea1o m\u1edbi.","type":"boolean"},"note":{"type":"string"},"password":{"description":"Password c\u1ee7a email - L\u01afU L\u1ea0I, ch\u1ec9 tr\u1ea3 v\u1ec1 1 l\u1ea7n","example":"xK9mP3nQ","type":"string"},"provider":{"example":"custom","type":"string"},"session_id":{"description":"ID phi\u00ean, d\u00f9ng \u0111\u1ec3 qu\u1ea3n l\u00fd session","type":"string"},"success":{"type":"boolean"}},"type":"object"},"SessionInfo":{"properties":{"active":{"type":"boolean"},"email":{"type":"string"},"expires_in":{"type":"integer"},"password":{"description":"Ch\u1ec9 tr\u1ea3 v\u1ec1 khi active=true","type":"string"},"provider":{"type":"string"},"reason":{"description":"L\u00fd do kh\u00f4ng active (vd: 'expired')","type":"string"},"session_id":{"type":"string"}},"type":"object"}},"securitySchemes":{"adminCookie":{"description":"Admin session cookie. L\u1ea5y qua `/admin/login`.","in":"cookie","name":"admin_sid","type":"apiKey"},"sessionCookie":{"description":"Flask session cookie (HttpOnly). Set t\u1ef1 \u0111\u1ed9ng sau khi g\u1ecdi `/api/generate`.","in":"cookie","name":"session","type":"apiKey"}}},"info":{"contact":{"name":"HomicMail Support","url":"https://tempmail.rionfashion.com"},"description":"\n# HomicMail - API t\u1ea1o email t\u1ea1m th\u1eddi\n\nAPI cho ph\u00e9p b\u1ea1n t\u00edch h\u1ee3p email t\u1ea1m v\u00e0o tool/script c\u1ee7a m\u00ecnh.\n\n## \ud83c\udfaf Use cases\n- \u0110\u0103ng k\u00fd t\u00e0i kho\u1ea3n c\u1ea7n email verification\n- Nh\u1eadn OTP, confirm code t\u1eeb website\n- Test form t\u1ef1 \u0111\u1ed9ng\n- Bypass y\u00eau c\u1ea7u email khi scrape\n\n## \u26a1 Quick start\n\n**1. T\u1ea1o email m\u1edbi:**\n```bash\ncurl -X POST https://tempmail.rionfashion.com/api/generate \\\n    -H \"Content-Type: application/json\" -c cookies.txt \\\n    -d '{\"username\": \"myuser\"}'\n```\n\n**2. Check inbox (d\u00f9ng cookie t\u1eeb step 1):**\n```bash\ncurl -b cookies.txt https://tempmail.rionfashion.com/api/inbox\n```\n\n**3. \u0110\u1ecdc mail:**\n```bash\ncurl -b cookies.txt https://tempmail.rionfashion.com/api/message/{mail_id}\n```\n\n## \ud83d\udd12 B\u1ea3o m\u1eadt\n- M\u1ecdi endpoint \u0111\u1ec1u tr\u1ea3 JSON\n- Session qu\u1ea3n l\u00fd qua cookie Flask (HttpOnly, SameSite=Lax)\n- Email m\u1eb7c \u0111\u1ecbnh h\u1ebft h\u1ea1n sau 60 ph\u00fat\n- Rate limit: 30 requests/min/IP (cho API public)\n\n## \ud83d\udce6 Response format\nM\u1ecdi response \u0111\u1ec1u l\u00e0 JSON. L\u1ed7i tr\u1ea3 v\u1ec1:\n```json\n{\"error\": \"M\u00f4 t\u1ea3 l\u1ed7i\"}\n```\nStatus codes:\n- `200` - Th\u00e0nh c\u00f4ng\n- `400` - Bad request (validation fail)\n- `401` - Unauthorized (session h\u1ebft h\u1ea1n ho\u1eb7c ch\u01b0a login)\n- `404` - Not found\n- `415` - Content-Type ph\u1ea3i l\u00e0 `application/json`\n- `429` - Rate limit\n- `500` - Internal server error\n        ","license":{"name":"MIT"},"title":"HomicMail API","version":"1.2.0","x-generated-at":1793466518},"openapi":"3.0.3","paths":{"/admin/login":{"post":{"description":"D\u00f9ng `ADMIN_USER` / `ADMIN_PASS` env var \u0111\u1ec3 login.","operationId":"adminLogin","requestBody":{"content":{"application/json":{"schema":{"properties":{"password":{"type":"string"},"username":{"type":"string"}},"required":["username","password"],"type":"object"}}},"required":true},"responses":{"200":{"description":"Login th\u00e0nh c\u00f4ng - set cookie `admin_sid`"},"401":{"description":"Sai th\u00f4ng tin \u0111\u0103ng nh\u1eadp"}},"summary":"\u0110\u0103ng nh\u1eadp admin","tags":["admin"]}},"/admin/logout":{"post":{"operationId":"adminLogout","responses":{"200":{"description":"\u0110\u00e3 logout"}},"security":[{"adminCookie":[]}],"summary":"\u0110\u0103ng xu\u1ea5t admin","tags":["admin"]}},"/api/admin/sessions":{"get":{"operationId":"adminSessions","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SessionInfo"},"type":"array"}}},"description":"Sessions"},"401":{"description":"Unauthorized"}},"security":[{"adminCookie":[]}],"summary":"Li\u1ec7t k\u00ea 50 session g\u1ea7n nh\u1ea5t","tags":["admin"]}},"/api/admin/stats":{"get":{"description":"T\u1ed5ng s\u1ed1 session, message, virtual users tr\u00ean MariaDB.","operationId":"adminStats","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminStats"}}},"description":"Stats"},"401":{"description":"Unauthorized"}},"security":[{"adminCookie":[]}],"summary":"Th\u1ed1ng k\u00ea h\u1ec7 th\u1ed1ng","tags":["admin"]}},"/api/delete":{"post":{"description":"X\u00f3a v\u0129nh vi\u1ec5n session + messages + attachments.","operationId":"deleteSession","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"success":{"example":true,"type":"boolean"}},"type":"object"}}},"description":"\u0110\u00e3 x\u00f3a"}},"summary":"X\u00f3a email hi\u1ec7n t\u1ea1i v\u00e0 to\u00e0n b\u1ed9 tin nh\u1eafn","tags":["session"]}},"/api/domains":{"get":{"description":"API \u0111\u01a1n gi\u1ea3n tr\u1ea3 v\u1ec1 domain hi\u1ec7n \u0111ang ho\u1ea1t \u0111\u1ed9ng.","operationId":"getDomains","responses":{"200":{"content":{"application/json":{"schema":{"example":["rionfashion.com"],"items":{"type":"string"},"type":"array"}}},"description":"Danh s\u00e1ch domain"}},"summary":"L\u1ea5y danh s\u00e1ch domain \u0111\u01b0\u1ee3c ph\u00e9p","tags":["public"]}},"/api/download/{att_id}/{filename}":{"get":{"operationId":"downloadAttachment","parameters":[{"in":"path","name":"att_id","required":true,"schema":{"type":"string"}},{"in":"path","name":"filename","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/octet-stream":{"schema":{"format":"binary","type":"string"}}},"description":"Binary file"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"T\u1ea3i file \u0111\u00ednh k\u00e8m","tags":["inbox"]}},"/api/generate":{"post":{"description":"\n- N\u1ebfu **username r\u1ed7ng** \u2192 t\u1ea1o email random (vd: `swiftfox73@rionfashion.com`)\n- N\u1ebfu **username \u0111\u00e3 t\u1ed3n t\u1ea1i trong DB** \u2192 RESYNC (reset password m\u1edbi, fetch l\u1ea1i inbox)\n- N\u1ebfu **username m\u1edbi** \u2192 t\u1ea1o m\u1edbi\n\nK\u1ebft qu\u1ea3 tr\u1ea3 v\u1ec1 c\u00f3 `session_id` l\u01b0u v\u00e0o cookie. D\u00f9ng cookie cho c\u00e1c API ti\u1ebfp theo.\n\n**\u26a0\ufe0f Rate limit:** 30 requests/min/IP.\n                ","operationId":"generateEmail","requestBody":{"content":{"application/json":{"examples":{"custom":{"summary":"Custom username","value":{"username":"myuser"}},"random":{"summary":"Random username","value":{}},"resync":{"summary":"Resync (username \u0111\u00e3 d\u00f9ng)","value":{"username":"myuser"}}},"schema":{"properties":{"username":{"description":"T\u00ean email custom. N\u1ebfu r\u1ed7ng s\u1ebd random. Ch\u1ec9 ch\u1ee9a ch\u1eef th\u01b0\u1eddng, s\u1ed1, d\u1ea5u ch\u1ea5m, g\u1ea1ch d\u01b0\u1edbi, g\u1ea1ch ngang (1-64 k\u00fd t\u1ef1).","example":"myuser123","pattern":"^[a-z0-9._-]{1,64}$","type":"string"}},"type":"object"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateResponse"}}},"description":"T\u1ea1o th\u00e0nh c\u00f4ng"},"400":{"$ref":"#/components/responses/BadRequest"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"T\u1ea1o email m\u1edbi ho\u1eb7c RESYNC email \u0111\u00e3 t\u1ed3n t\u1ea1i","tags":["email","session"],"x-codeSamples":[{"label":"cURL","lang":"curl","source":"curl -X POST https://tempmail.rionfashion.com/api/generate \\\n  -H \"Content-Type: application/json\" \\\n  -c cookies.txt \\\n  -d '{\"username\": \"myuser\"}'"},{"label":"Python","lang":"python","source":"import requests\nsession = requests.Session()\nr = session.post('https://tempmail.rionfashion.com/api/generate',\n    json={'username': 'myuser'})\nprint(r.json())  # {email, password, session_id, ...}"},{"label":"JavaScript (fetch)","lang":"javascript","source":"const res = await fetch('https://tempmail.rionfashion.com/api/generate', {\n  method: 'POST',\n  headers: {'Content-Type': 'application/json'},\n  credentials: 'include',\n  body: JSON.stringify({username: 'myuser'})\n});\nconst data = await res.json();\nconsole.log(data);  // {email, password, ...}"}]}},"/api/health":{"get":{"description":"Ki\u1ec3m tra service c\u00f3 ho\u1ea1t \u0111\u1ed9ng kh\u00f4ng. Kh\u00f4ng c\u1ea7n auth.","operationId":"health","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"message":{"example":"Service is running","type":"string"},"status":{"example":"ok","type":"string"}},"type":"object"}}},"description":"Service \u0111ang ch\u1ea1y"}},"summary":"Health check","tags":["public"]}},"/api/inbox":{"get":{"description":"\nL\u1ea5y t\u1ea5t c\u1ea3 email trong inbox. T\u1ef1 \u0111\u1ed9ng \u0111\u1ed3ng b\u1ed9 t\u1eeb IMAP server.\n\n**C\u1ea7n session cookie** t\u1eeb `/api/generate` ho\u1eb7c `/api/paste`.\n                ","operationId":"getInbox","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"emails":{"items":{"$ref":"#/components/schemas/EmailSummary"},"type":"array"}},"type":"object"}}},"description":"Danh s\u00e1ch email"},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"L\u1ea5y danh s\u00e1ch th\u01b0 trong h\u1ed9p th\u01b0","tags":["inbox"]}},"/api/message/{mail_id}":{"get":{"description":"\nL\u1ea5y n\u1ed9i dung \u0111\u1ea7y \u0111\u1ee7 c\u1ee7a 1 email (subject, body HTML/text \u0111\u00e3 sanitize, attachments).\n\n**mail_id** l\u1ea5y t\u1eeb field `id` trong response c\u1ee7a `/api/inbox`.\n                ","operationId":"getMessage","parameters":[{"description":"ID c\u1ee7a email (l\u1ea5y t\u1eeb inbox)","in":"path","name":"mail_id","required":true,"schema":{"example":"<abc123@byteplus.com>","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDetail"}}},"description":"Chi ti\u1ebft email"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"\u0110\u1ecdc chi ti\u1ebft 1 email","tags":["inbox"]}},"/api/paste":{"post":{"description":"\nD\u00e0nh cho user mu\u1ed1n truy c\u1eadp l\u1ea1i email \u0111\u00e3 t\u1ea1o tr\u01b0\u1edbc \u0111\u00f3 (k\u1ec3 c\u1ea3 khi session h\u1ebft h\u1ea1n).\n\nC\u1ea7n password \u0111\u1ec3 IMAP login v\u00e0o mail server l\u1ea5y inbox.\n                ","operationId":"pasteEmail","requestBody":{"content":{"application/json":{"schema":{"properties":{"email":{"description":"Email \u0111\u1ea7y \u0111\u1ee7 bao g\u1ed3m domain","example":"myuser@rionfashion.com","type":"string"},"password":{"description":"Password c\u1ee7a email (b\u1eaft bu\u1ed9c n\u1ebfu mu\u1ed1n fetch inbox)","example":"abc123def456","type":"string"},"provider":{"default":"custom","description":"Provider - lu\u00f4n l\u00e0 'custom'","type":"string"}},"required":["email"],"type":"object"}}},"required":true},"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/BadRequest"}},"summary":"Paste l\u1ea1i email \u0111\u00e3 c\u00f3 (c\u1ea7n password)","tags":["email","session"]}},"/api/session-info":{"get":{"description":"D\u00f9ng \u0111\u1ec3 check session c\u00f2n h\u1ea1n kh\u00f4ng. Tr\u1ea3 v\u1ec1 email + expires_in.","operationId":"getSessionInfo","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionInfo"}}},"description":"Th\u00f4ng tin phi\u00ean"}},"summary":"L\u1ea5y th\u00f4ng tin phi\u00ean hi\u1ec7n t\u1ea1i","tags":["session"]}}},"servers":[{"description":"Production","url":"https://tempmail.rionfashion.com"},{"description":"Local development","url":"http://localhost:5000"}],"tags":[{"description":"API c\u00f4ng khai - kh\u00f4ng c\u1ea7n auth","name":"public"},{"description":"Qu\u1ea3n l\u00fd phi\u00ean email","name":"session"},{"description":"T\u1ea1o v\u00e0 qu\u1ea3n l\u00fd email","name":"email"},{"description":"\u0110\u1ecdc th\u01b0 trong h\u1ed9p th\u01b0","name":"inbox"},{"description":"API qu\u1ea3n tr\u1ecb (c\u1ea7n auth admin)","name":"admin"}]}
