# Email Spam Filtering Dashboard

FastAPI web dashboard for reviewing IMAP-fetched emails and classifying them as spam, ham, or undecided using a user-uploaded training dataset.

## What This Project Does

- Displays emails fetched from IMAP and saved in PostgreSQL.
- Lets users upload a labeled CSV dataset to train a spam filtering model.
- Uses the uploaded dataset to classify the existing IMAP emails.
- Shows total emails, spam count, ham count, undecided count, and model accuracy.
- Lets users review undecided emails, submit feedback, and update the model from that feedback.
- Allows users to clear analysis results without deleting emails.

## Project Structure

```text
.
├── main.py                         # FastAPI app, routes, database model
├── spam_training.py                # CSV training, prediction, feedback learning
├── templates/
│   ├── spam_dashboard.html         # Main dashboard
│   ├── email_details.html          # Email review and feedback page
│   └── spam_add.html               # Add-email form page
├── uploads/                        # Uploaded CSV files, created at runtime
├── models/                         # Saved model/vectorizer files, created at runtime
└── requirements.txt
```

## Requirements

- Python 3.10+
- PostgreSQL database
- IMAP email source already writing emails to the `email_filter` table

Install Python dependencies:

```bash
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```

## Run Locally

```bash
python3 main.py
```

Open:

```text
http://localhost:6202/
```

Use **Sign in** on the landing page to reach the administrator login, then the dashboard after authentication.

Default credentials (override with environment variables):

- `ADMIN_USERNAME` (default: `admin123@gmail.com`)
- `ADMIN_PASSWORD` (default: `admin123`)
- `SESSION_SECRET` (change in production)

If you previously used the short username `admin`, set `ADMIN_USERNAME=admin` in your environment until you change the password from the dashboard.

After login, use **Change password** in the dashboard footer to set a new password (saved in `data/admin_credentials.json` on the server). Environment variables are used only until a password is changed in the UI.

New passwords must meet standard strength rules: 8–128 characters, upper and lower case, a number, a special character, no spaces, not a common password, and confirmation must match. The change-password page shows a live checklist as you type.

## CSV Dataset Format

The uploaded CSV must contain:

- A label column: `label`, `category`, `class`, `target`, or `v1`
- A text column: `text`, `message`, `body`, `email`, `content`, `mail`, or `v2`

Example:

```csv
label,text
spam,Win a free prize now
ham,Can we meet tomorrow
```

Supported labels include:

- `spam`
- `ham`
- `1` for spam
- `0` for ham

## Current Workflow

1. IMAP emails are stored in PostgreSQL.
2. Dashboard always displays those IMAP emails.
3. User uploads a labeled CSV dataset.
4. The model trains on that dataset.
5. Existing IMAP emails are classified using the trained model.
6. If an email is undecided, the user can submit feedback.
7. Feedback updates the model and reclassifies emails.
8. Clear Analysis resets predictions and accuracy, but keeps all emails.

## Database Notes

The app expects an `email_filter` table with fields used by `main.py`, including:

- `id`
- `sender_email`
- `subject`
- `body`
- `spam_probability`
- `predicted_label`
- `feedback_label`
- `feedback`
- `is_reviewed`
- `received_at`
- `email_summary`
- `model_accuracy`
- `imap_uid`

## Production Notes

Before making this public:

- Move database credentials out of `main.py` into environment variables.
- Do not commit Gmail app passwords or database passwords.
- Set strong `ADMIN_PASSWORD` and `SESSION_SECRET` in production.
- Use HTTPS.
- Run with Gunicorn/Uvicorn behind Nginx.

Example production command:

```bash
gunicorn main:app -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:6202
```
