Postmark is a deep learning email spam classifier. A GRU (Gated Recurrent Unit) neural network, trained on labeled spam/ham email data, is served through a FastAPI backend and paired with a clean, interactive web frontend for pasting or uploading emails and getting instant predictions.
- GRU deep learning model for spam/ham classification, built with TensorFlow/Keras
- FastAPI backend with a simple
/predictendpoint and CORS enabled for browser access - Interactive frontend (single HTML file, no build step) with:
- Paste-to-analyze text input
- Drag-and-drop
.txt/.emlfile upload - Confidence score display
- Scan history (saved locally in your browser)
- Configurable API endpoint and settings panel
- "About Model" panel explaining the preprocessing pipeline
- Dockerized for consistent, portable deployment
.
├── app/
├── main.py # FastAPI backend — loads model + tokenizer, exposes /predict
├── templates/
├── index.html # Frontend UI (open directly in a browser)
└── models/
├── best_spam_model.keras # Trained GRU model
└── tokenizer.pickle # Fitted Keras tokenizer used at training time
├── requirements.txt # Pinned, conflict-checked Python dependencies
└── experimentss/
├── train_model.ipynb # Model training code
git clone https://github.com/FaraAbbasi/Spam-Email-Detector.git
cd Spam_Email_DetectionUsing uv (recommended — much faster than pip, especially for TensorFlow):
pip install uv
uv venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
uv pip install -r requirements.txtOr with plain pip:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtPlace your trained files here:
models/best_spam_model.keras
models/tokenizer.pickle
uvicorn app:app --reloadOpen http://127.0.0.1:8000 in your browser — app.py serves the UI
directly at the / route, so the frontend loads automatically along with the
API. There's no separate file to open.
Interactive API docs (for the /predict endpoint itself): http://127.0.0.1:8000/docs
Health check.
{ "status": "Ok", "message": "Spam/Ham classifier API is running" }Request body:
{ "text": "Subject: ...\nEmail body here..." }Response:
{
"Email": "Subject: ... (truncated preview)",
"Label": "SPAM 🚨",
"Confidence": 0.9421,
"SpamProbability": 0.9421
}Confidence— how sure the model is in the label it picked (not always the spam probability directly; if the model predicts HAM, this is1 - spam_prob)SpamProbability— the raw, unadjusted probability that the email is spam
Before being tokenized, every email is cleaned using the same steps applied during training:
- Lowercased
- URLs replaced with an
urltoken - Email addresses replaced with an
emailtoken - Numbers replaced with a
numtoken - Punctuation stripped
- Extra whitespace collapsed
Sequences are then padded/truncated to a fixed length of 150 tokens before being passed to the model.
This project is open-source and available under the MIT License.
Contributions are warmly welcomed! This project thrives on community input and collaboration. We encourage you to participate in making it better, whether through bug reports, feature suggestions, or direct code contributions.
For issues and questions:
-
Open an Issue on GitHub
-
Provide detailed information about your problem
Give a ⭐ if you find this project useful!