Spaces:
Paused
Paused
feat: CI auto-import, updated Dockerfile, docs, and env config
Browse files- GitHub Actions auto-imports registered accounts to admin panel
- Added OUTLOOK2API_URL, ADMIN_PASSWORD secrets for CI
- Updated Dockerfile.api with SQLite data directory
- Updated .env.example with DATABASE_URL and admin config
- Comprehensive README with admin API documentation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- .env.example +9 -3
- .github/workflows/register-outlook.yml +49 -20
- Dockerfile.api +4 -0
- README.md +59 -52
.env.example
CHANGED
|
@@ -2,11 +2,13 @@
|
|
| 2 |
OUTLOOK2API_JWT_SECRET=change-me-in-production
|
| 3 |
OUTLOOK2API_HOST=0.0.0.0
|
| 4 |
OUTLOOK2API_PORT=8001
|
| 5 |
-
OUTLOOK2API_ACCOUNTS_FILE=data/outlook_accounts.json
|
| 6 |
-
|
| 7 |
-
# === Admin ===
|
| 8 |
ADMIN_PASSWORD=admin
|
|
|
|
|
|
|
|
|
|
| 9 |
DATABASE_URL=sqlite+aiosqlite:///./data/outlook2api.db
|
|
|
|
|
|
|
| 10 |
|
| 11 |
# === Registration (captcha) ===
|
| 12 |
CAPTCHA_CLIENT_KEY= # YesCaptcha / CapSolver API key
|
|
@@ -15,3 +17,7 @@ FUNCAPTCHA_PUBLIC_KEY=B7D8911C-5CC8-A9A3-35B0-554ACEE604DA
|
|
| 15 |
|
| 16 |
# === Optional ===
|
| 17 |
PROXY_URL= # HTTP/SOCKS5 proxy for registration
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
OUTLOOK2API_JWT_SECRET=change-me-in-production
|
| 3 |
OUTLOOK2API_HOST=0.0.0.0
|
| 4 |
OUTLOOK2API_PORT=8001
|
|
|
|
|
|
|
|
|
|
| 5 |
ADMIN_PASSWORD=admin
|
| 6 |
+
|
| 7 |
+
# === Database ===
|
| 8 |
+
# SQLite (default, no setup needed):
|
| 9 |
DATABASE_URL=sqlite+aiosqlite:///./data/outlook2api.db
|
| 10 |
+
# PostgreSQL (production):
|
| 11 |
+
# DATABASE_URL=postgresql://user:pass@host:5432/outlook2api
|
| 12 |
|
| 13 |
# === Registration (captcha) ===
|
| 14 |
CAPTCHA_CLIENT_KEY= # YesCaptcha / CapSolver API key
|
|
|
|
| 17 |
|
| 18 |
# === Optional ===
|
| 19 |
PROXY_URL= # HTTP/SOCKS5 proxy for registration
|
| 20 |
+
|
| 21 |
+
# === CI Auto-Import ===
|
| 22 |
+
# Set OUTLOOK2API_URL in GitHub Actions to auto-import registered accounts
|
| 23 |
+
# OUTLOOK2API_URL=https://ohmyapi-outlook2api.hf.space
|
.github/workflows/register-outlook.yml
CHANGED
|
@@ -17,8 +17,6 @@ on:
|
|
| 17 |
env:
|
| 18 |
CAPTCHA_CLIENT_KEY: ${{ secrets.CAPTCHA_CLIENT_KEY }}
|
| 19 |
PROXY_URL: ${{ secrets.PROXY_URL }}
|
| 20 |
-
OUTLOOK2API_URL: ${{ secrets.OUTLOOK2API_URL }}
|
| 21 |
-
ADMIN_PASSWORD: ${{ secrets.ADMIN_PASSWORD }}
|
| 22 |
|
| 23 |
jobs:
|
| 24 |
register:
|
|
@@ -70,33 +68,64 @@ jobs:
|
|
| 70 |
|
| 71 |
- name: Auto-import to admin panel
|
| 72 |
if: success()
|
|
|
|
|
|
|
|
|
|
| 73 |
run: |
|
| 74 |
if [ -z "$OUTLOOK2API_URL" ] || [ -z "$ADMIN_PASSWORD" ]; then
|
| 75 |
-
echo "OUTLOOK2API_URL or ADMIN_PASSWORD not set
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
exit 0
|
| 77 |
fi
|
| 78 |
-
#
|
| 79 |
-
ACCOUNTS=
|
| 80 |
-
|
|
|
|
|
|
|
| 81 |
accs = []
|
| 82 |
-
for
|
| 83 |
try:
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
if ':' in line:
|
| 88 |
-
accs.append(line.strip())
|
| 89 |
except: pass
|
| 90 |
print(json.dumps(accs))
|
| 91 |
")
|
| 92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
echo "No accounts to import"
|
| 94 |
exit 0
|
| 95 |
fi
|
| 96 |
-
echo "Importing
|
| 97 |
-
curl -sf -X POST "$
|
| 98 |
-
-H "Authorization: Bearer $
|
| 99 |
-
-H
|
| 100 |
-
-d "{\"accounts\": $ACCOUNTS, \"source\": \"ci\"}"
|
| 101 |
-
|
| 102 |
-
|| echo "Import failed (non-fatal)"
|
|
|
|
| 17 |
env:
|
| 18 |
CAPTCHA_CLIENT_KEY: ${{ secrets.CAPTCHA_CLIENT_KEY }}
|
| 19 |
PROXY_URL: ${{ secrets.PROXY_URL }}
|
|
|
|
|
|
|
| 20 |
|
| 21 |
jobs:
|
| 22 |
register:
|
|
|
|
| 68 |
|
| 69 |
- name: Auto-import to admin panel
|
| 70 |
if: success()
|
| 71 |
+
env:
|
| 72 |
+
OUTLOOK2API_URL: ${{ secrets.OUTLOOK2API_URL }}
|
| 73 |
+
ADMIN_PASSWORD: ${{ secrets.ADMIN_PASSWORD }}
|
| 74 |
run: |
|
| 75 |
if [ -z "$OUTLOOK2API_URL" ] || [ -z "$ADMIN_PASSWORD" ]; then
|
| 76 |
+
echo "Skipping auto-import (OUTLOOK2API_URL or ADMIN_PASSWORD not set)"
|
| 77 |
+
exit 0
|
| 78 |
+
fi
|
| 79 |
+
# Login and get token
|
| 80 |
+
TOKEN=$(curl -sf -X POST "$OUTLOOK2API_URL/admin/api/login" \
|
| 81 |
+
-H 'Content-Type: application/json' \
|
| 82 |
+
-d "{\"password\": \"$ADMIN_PASSWORD\"}" | python3 -c "import sys,json;print(json.load(sys.stdin)['token'])" 2>/dev/null)
|
| 83 |
+
if [ -z "$TOKEN" ]; then
|
| 84 |
+
echo "Admin login failed, skipping import"
|
| 85 |
exit 0
|
| 86 |
fi
|
| 87 |
+
# Collect accounts from staging files
|
| 88 |
+
ACCOUNTS="[]"
|
| 89 |
+
if [ -d "output/.staging_outlook" ]; then
|
| 90 |
+
ACCOUNTS=$(python3 -c "
|
| 91 |
+
import os, json, glob
|
| 92 |
accs = []
|
| 93 |
+
for f in glob.glob('output/.staging_outlook/outlook_*.json'):
|
| 94 |
try:
|
| 95 |
+
d = json.load(open(f))
|
| 96 |
+
if d.get('email') and d.get('password'):
|
| 97 |
+
accs.append(d['email'] + ':' + d['password'])
|
|
|
|
|
|
|
| 98 |
except: pass
|
| 99 |
print(json.dumps(accs))
|
| 100 |
")
|
| 101 |
+
fi
|
| 102 |
+
# Also try the zip file
|
| 103 |
+
for z in output/*Outlook.zip; do
|
| 104 |
+
[ -f "$z" ] || continue
|
| 105 |
+
python3 -c "
|
| 106 |
+
import zipfile, json, sys
|
| 107 |
+
with zipfile.ZipFile('$z') as zf:
|
| 108 |
+
for name in zf.namelist():
|
| 109 |
+
if name.endswith('.txt'):
|
| 110 |
+
content = zf.read(name).decode('utf-8', errors='replace')
|
| 111 |
+
existing = json.loads(sys.argv[1]) if sys.argv[1] != '[]' else []
|
| 112 |
+
for line in content.strip().splitlines():
|
| 113 |
+
line = line.strip()
|
| 114 |
+
if ':' in line and line not in existing:
|
| 115 |
+
existing.append(line)
|
| 116 |
+
print(json.dumps(existing))
|
| 117 |
+
sys.exit(0)
|
| 118 |
+
print(sys.argv[1])
|
| 119 |
+
" "$ACCOUNTS" > /tmp/accs.json && ACCOUNTS=$(cat /tmp/accs.json)
|
| 120 |
+
done
|
| 121 |
+
COUNT=$(echo "$ACCOUNTS" | python3 -c "import sys,json;print(len(json.load(sys.stdin)))")
|
| 122 |
+
if [ "$COUNT" = "0" ]; then
|
| 123 |
echo "No accounts to import"
|
| 124 |
exit 0
|
| 125 |
fi
|
| 126 |
+
echo "Importing $COUNT accounts..."
|
| 127 |
+
RESULT=$(curl -sf -X POST "$OUTLOOK2API_URL/admin/api/accounts/bulk" \
|
| 128 |
+
-H "Authorization: Bearer $TOKEN" \
|
| 129 |
+
-H 'Content-Type: application/json' \
|
| 130 |
+
-d "{\"accounts\": $ACCOUNTS, \"source\": \"ci\"}")
|
| 131 |
+
echo "Import result: $RESULT"
|
|
|
Dockerfile.api
CHANGED
|
@@ -8,4 +8,8 @@ RUN pip install --no-cache-dir -r requirements-api.txt
|
|
| 8 |
COPY outlook2api/ outlook2api/
|
| 9 |
COPY pyproject.toml .
|
| 10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
CMD ["uvicorn", "outlook2api.app:app", "--host", "0.0.0.0", "--port", "8001"]
|
|
|
|
| 8 |
COPY outlook2api/ outlook2api/
|
| 9 |
COPY pyproject.toml .
|
| 10 |
|
| 11 |
+
RUN mkdir -p /tmp/data
|
| 12 |
+
|
| 13 |
+
ENV DATABASE_URL=sqlite+aiosqlite:////tmp/data/outlook2api.db
|
| 14 |
+
|
| 15 |
CMD ["uvicorn", "outlook2api.app:app", "--host", "0.0.0.0", "--port", "8001"]
|
README.md
CHANGED
|
@@ -1,45 +1,47 @@
|
|
| 1 |
# Outlook2API
|
| 2 |
|
| 3 |
-
Mail.tm-compatible REST API for Outlook/Hotmail/Live accounts with admin panel
|
| 4 |
|
| 5 |
## Features
|
| 6 |
|
| 7 |
-
- Mail.tm-compatible Hydra API (
|
| 8 |
-
- Admin
|
| 9 |
-
- Batch account
|
| 10 |
-
- CI
|
| 11 |
-
-
|
| 12 |
-
- HuggingFace Spaces deployment
|
| 13 |
|
| 14 |
## Quick Start
|
| 15 |
|
| 16 |
```bash
|
|
|
|
| 17 |
pip install -r requirements-api.txt
|
|
|
|
|
|
|
| 18 |
python -m outlook2api.app
|
| 19 |
-
|
| 20 |
-
#
|
|
|
|
| 21 |
```
|
| 22 |
|
| 23 |
-
##
|
| 24 |
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
- Full API documentation with curl examples
|
| 30 |
|
| 31 |
## API Endpoints
|
| 32 |
|
| 33 |
-
### Mail API (
|
| 34 |
|
| 35 |
| Method | Path | Auth | Description |
|
| 36 |
|--------|------|------|-------------|
|
| 37 |
-
| GET | `/domains` | No | List supported domains |
|
| 38 |
-
| POST | `/accounts` | No | Register account (
|
| 39 |
-
| POST | `/token` | No | Get JWT token |
|
| 40 |
| GET | `/me` | Bearer | Current user info |
|
| 41 |
-
| GET | `/messages` | Bearer | List messages |
|
| 42 |
-
| GET | `/messages/{id}` | Bearer | Get message |
|
| 43 |
| GET | `/messages/{id}/code` | Bearer | Extract verification code |
|
| 44 |
| DELETE | `/accounts/me` | Bearer | Delete account |
|
| 45 |
|
|
@@ -48,61 +50,66 @@ Access at `/admin`. Features:
|
|
| 48 |
| Method | Path | Description |
|
| 49 |
|--------|------|-------------|
|
| 50 |
| POST | `/admin/api/login` | Login (returns token) |
|
| 51 |
-
| GET | `/admin/api/stats` | Dashboard
|
| 52 |
-
| GET | `/admin/api/accounts` | List accounts (
|
| 53 |
| POST | `/admin/api/accounts` | Add single account |
|
| 54 |
-
| POST | `/admin/api/accounts/bulk` | Bulk import |
|
| 55 |
-
| POST | `/admin/api/accounts/upload` | File upload
|
| 56 |
-
| PATCH | `/admin/api/accounts/{id}` |
|
| 57 |
| DELETE | `/admin/api/accounts/{id}` | Delete account |
|
| 58 |
-
| GET | `/admin/api/
|
|
|
|
| 59 |
|
| 60 |
## CI Auto-Import
|
| 61 |
|
| 62 |
-
GitHub Actions
|
| 63 |
|
| 64 |
-
Required secrets:
|
| 65 |
-
- `CAPTCHA_CLIENT_KEY` β YesCaptcha API key
|
| 66 |
-
- `PROXY_URL` β
|
| 67 |
-
- `OUTLOOK2API_URL` β Admin panel URL (e.g. `https://ohmyapi-outlook2api.hf.space`)
|
| 68 |
-
- `ADMIN_PASSWORD` β Admin password
|
| 69 |
|
| 70 |
```bash
|
| 71 |
-
|
|
|
|
| 72 |
```
|
| 73 |
|
| 74 |
## Environment Variables
|
| 75 |
|
| 76 |
| Name | Default | Description |
|
| 77 |
|------|---------|-------------|
|
|
|
|
| 78 |
| `ADMIN_PASSWORD` | `admin` | Admin panel password |
|
| 79 |
| `DATABASE_URL` | `sqlite+aiosqlite:///./data/outlook2api.db` | Database URL |
|
| 80 |
-
| `
|
| 81 |
-
| `OUTLOOK2API_PORT` | `8001` | API port |
|
| 82 |
|
| 83 |
-
## Deployment
|
| 84 |
|
| 85 |
-
|
| 86 |
|
| 87 |
## Project Structure
|
| 88 |
|
| 89 |
```
|
| 90 |
outlook2api/
|
| 91 |
-
βββ outlook2api/
|
| 92 |
-
β βββ app.py
|
| 93 |
-
β βββ
|
| 94 |
-
β βββ admin_routes.py
|
| 95 |
-
β βββ
|
| 96 |
-
β βββ auth.py
|
| 97 |
-
β βββ config.py
|
| 98 |
-
β βββ outlook_imap.py
|
| 99 |
-
β βββ store.py
|
| 100 |
-
β βββ static/
|
| 101 |
-
βββ
|
| 102 |
-
β
|
| 103 |
-
|
|
|
|
|
|
|
| 104 |
βββ .github/workflows/
|
| 105 |
-
β βββ register-outlook.yml
|
| 106 |
βββ Dockerfile.api
|
| 107 |
βββ Dockerfile.register
|
| 108 |
βββ docker-compose.yml
|
|
|
|
| 1 |
# Outlook2API
|
| 2 |
|
| 3 |
+
Mail.tm-compatible REST API for Outlook/Hotmail/Live accounts with admin panel and batch account registration.
|
| 4 |
|
| 5 |
## Features
|
| 6 |
|
| 7 |
+
- **Mail API** β Mail.tm-compatible Hydra API endpoints (domains, accounts, token, messages)
|
| 8 |
+
- **Admin Panel** β Web UI for account management, bulk import/export, stats dashboard
|
| 9 |
+
- **Batch Registration** β Automated Outlook account creation via GitHub Actions
|
| 10 |
+
- **CI Auto-Import** β Registered accounts automatically imported to admin panel
|
| 11 |
+
- **Verification Code Extraction** β `GET /messages/{id}/code` extracts OTP from emails
|
|
|
|
| 12 |
|
| 13 |
## Quick Start
|
| 14 |
|
| 15 |
```bash
|
| 16 |
+
# Install dependencies
|
| 17 |
pip install -r requirements-api.txt
|
| 18 |
+
|
| 19 |
+
# Start the API server
|
| 20 |
python -m outlook2api.app
|
| 21 |
+
|
| 22 |
+
# Open http://localhost:8001 for homepage
|
| 23 |
+
# Open http://localhost:8001/admin for admin panel (default password: admin)
|
| 24 |
```
|
| 25 |
|
| 26 |
+
### Docker
|
| 27 |
|
| 28 |
+
```bash
|
| 29 |
+
cp .env.example .env
|
| 30 |
+
docker compose up -d outlook2api
|
| 31 |
+
```
|
|
|
|
| 32 |
|
| 33 |
## API Endpoints
|
| 34 |
|
| 35 |
+
### Mail API (Mail.tm-compatible)
|
| 36 |
|
| 37 |
| Method | Path | Auth | Description |
|
| 38 |
|--------|------|------|-------------|
|
| 39 |
+
| GET | `/domains` | No | List supported email domains |
|
| 40 |
+
| POST | `/accounts` | No | Register account (validates IMAP) |
|
| 41 |
+
| POST | `/token` | No | Get JWT bearer token |
|
| 42 |
| GET | `/me` | Bearer | Current user info |
|
| 43 |
+
| GET | `/messages` | Bearer | List inbox messages |
|
| 44 |
+
| GET | `/messages/{id}` | Bearer | Get single message |
|
| 45 |
| GET | `/messages/{id}/code` | Bearer | Extract verification code |
|
| 46 |
| DELETE | `/accounts/me` | Bearer | Delete account |
|
| 47 |
|
|
|
|
| 50 |
| Method | Path | Description |
|
| 51 |
|--------|------|-------------|
|
| 52 |
| POST | `/admin/api/login` | Login (returns token) |
|
| 53 |
+
| GET | `/admin/api/stats` | Dashboard statistics |
|
| 54 |
+
| GET | `/admin/api/accounts` | List accounts (search, filter, paginate) |
|
| 55 |
| POST | `/admin/api/accounts` | Add single account |
|
| 56 |
+
| POST | `/admin/api/accounts/bulk` | Bulk import (`["email:pass",...]`) |
|
| 57 |
+
| POST | `/admin/api/accounts/upload` | File upload (email:password per line) |
|
| 58 |
+
| PATCH | `/admin/api/accounts/{id}` | Toggle active / update notes |
|
| 59 |
| DELETE | `/admin/api/accounts/{id}` | Delete account |
|
| 60 |
+
| GET | `/admin/api/accounts/{id}/password` | Reveal password |
|
| 61 |
+
| GET | `/admin/api/export` | Export all active accounts |
|
| 62 |
|
| 63 |
## CI Auto-Import
|
| 64 |
|
| 65 |
+
GitHub Actions automatically imports registered accounts to the admin panel.
|
| 66 |
|
| 67 |
+
**Required secrets:**
|
| 68 |
+
- `CAPTCHA_CLIENT_KEY` β YesCaptcha/CapSolver API key
|
| 69 |
+
- `PROXY_URL` β HTTP/SOCKS5 proxy
|
| 70 |
+
- `OUTLOOK2API_URL` β Admin panel URL (e.g., `https://ohmyapi-outlook2api.hf.space`)
|
| 71 |
+
- `ADMIN_PASSWORD` β Admin panel password
|
| 72 |
|
| 73 |
```bash
|
| 74 |
+
# Trigger registration + auto-import
|
| 75 |
+
gh workflow run register-outlook.yml -f count=5 -f threads=1
|
| 76 |
```
|
| 77 |
|
| 78 |
## Environment Variables
|
| 79 |
|
| 80 |
| Name | Default | Description |
|
| 81 |
|------|---------|-------------|
|
| 82 |
+
| `OUTLOOK2API_JWT_SECRET` | `change-me-in-production` | JWT signing secret |
|
| 83 |
| `ADMIN_PASSWORD` | `admin` | Admin panel password |
|
| 84 |
| `DATABASE_URL` | `sqlite+aiosqlite:///./data/outlook2api.db` | Database URL |
|
| 85 |
+
| `OUTLOOK2API_HOST` | `0.0.0.0` | API bind host |
|
| 86 |
+
| `OUTLOOK2API_PORT` | `8001` | API bind port |
|
| 87 |
|
| 88 |
+
## HuggingFace Deployment
|
| 89 |
|
| 90 |
+
Deployed at: **https://ohmyapi-outlook2api.hf.space**
|
| 91 |
|
| 92 |
## Project Structure
|
| 93 |
|
| 94 |
```
|
| 95 |
outlook2api/
|
| 96 |
+
βββ outlook2api/ # FastAPI mail API + admin
|
| 97 |
+
β βββ app.py # Application entry point
|
| 98 |
+
β βββ routes.py # Mail.tm-compatible API routes
|
| 99 |
+
β βββ admin_routes.py # Admin API routes
|
| 100 |
+
β βββ database.py # SQLAlchemy models (Account)
|
| 101 |
+
β βββ auth.py # JWT auth helpers
|
| 102 |
+
β βββ config.py # Environment config
|
| 103 |
+
β βββ outlook_imap.py # IMAP client
|
| 104 |
+
β βββ store.py # Legacy JSON file store
|
| 105 |
+
β βββ static/ # Frontend
|
| 106 |
+
β βββ index.html # Homepage
|
| 107 |
+
β βββ admin.html # Admin panel
|
| 108 |
+
βββ register/ # Batch registration
|
| 109 |
+
β βββ outlook_register.py # DrissionPage registrar
|
| 110 |
+
β βββ captcha.py # FunCaptcha cloud solver
|
| 111 |
βββ .github/workflows/
|
| 112 |
+
β βββ register-outlook.yml # CI: register + auto-import
|
| 113 |
βββ Dockerfile.api
|
| 114 |
βββ Dockerfile.register
|
| 115 |
βββ docker-compose.yml
|