A full-stack application that detects Spam / Smishing / Offensive content using Machine Learning. The system includes:
- π§ ML Model (Python)
- β‘ Python API (Flask / FastAPI)
- π Node.js Backend
- π» React Web App
- π± React Native Mobile App (Android & iOS)
User Input (Web / Mobile)
β
React / React Native UI
β
Node.js Backend (API Gateway)
β
Python ML API (Model Inference)
β
Prediction (Spam / Ham / Offensive)
This update addresses critical runtime issues that prevented the system from executing in the local development environment:
- Security Policy Compliance: Migrated the project to a directory with appropriate execution permissions to resolve
DLL loaderrors. - Model Loading Error: Corrected file path references to ensure the ML models are properly detected at runtime.
- API Stability: Fixed
500 Internal Server Errorby correctly serializing NumPy model outputs to JSON.
For a detailed breakdown, please refer to the recently merged Pull Request.
-
CSV format:
text/messagelabel(spam / ham / offensive)
- Logistic Regression
- Naive Bayes
- Linear SVM (Best Accuracy)
-
Accuracy: ~97β98%
-
Metrics:
- Precision
- Recall
- F1-score
- Confusion Matrix
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.svm import LinearSVC
import pickle
# Load dataset
X = df['text']
y = df['label']
# Vectorization
vectorizer = TfidfVectorizer()
X_vec = vectorizer.fit_transform(X)
# Model
model = LinearSVC()
model.fit(X_vec, y)
# Save
pickle.dump(model, open("model.pkl", "wb"))
pickle.dump(vectorizer, open("vectorizer.pkl", "wb"))pip install flask scikit-learnfrom flask import Flask, request, jsonify
import pickle
app = Flask(__name__)
model = pickle.load(open("model.pkl", "rb"))
vectorizer = pickle.load(open("vectorizer.pkl", "rb"))
@app.route('/predict', methods=['POST'])
def predict():
data = request.json['text']
vec = vectorizer.transform([data])
prediction = model.predict(vec)[0]
return jsonify({"result": prediction})
if __name__ == "__main__":
app.run(port=5000)npm install express axios corsconst express = require("express");
const axios = require("axios");
const cors = require("cors");
const app = express();
app.use(cors());
app.use(express.json());
app.post("/predict", async (req, res) => {
try {
const response = await axios.post("http://localhost:5000/predict", {
text: req.body.text,
});
res.json(response.data);
} catch (err) {
res.status(500).send("Error");
}
});
app.listen(3000, () => console.log("Node server running"));npm create vite@latest
npm install axiosimport { useState } from "react";
import axios from "axios";
function App() {
const [text, setText] = useState("");
const [result, setResult] = useState("");
const handlePredict = async () => {
const res = await axios.post("http://localhost:3000/predict", { text });
setResult(res.data.result);
};
return (
<div>
<h1>Spam Detection</h1>
<input onChange={(e) => setText(e.target.value)} />
<button onClick={handlePredict}>Check</button>
<p>{result}</p>
</div>
);
}
export default App;npx create-expo-app
npm install axiosimport { useState } from "react";
import { View, Text, TextInput, Button } from "react-native";
import axios from "axios";
export default function App() {
const [text, setText] = useState("");
const [result, setResult] = useState("");
const predict = async () => {
const res = await axios.post("http://YOUR_IP:3000/predict", { text });
setResult(res.data.result);
};
return (
<View>
<Text>Spam Detection</Text>
<TextInput onChangeText={setText} />
<Button title="Check" onPress={predict} />
<Text>{result}</Text>
</View>
);
}A MySQL-based system to store and manage classified email records.
mysql -u root -p < backend/schema.sql| Method | Endpoint | Description |
|---|---|---|
| POST | /api/emails/ |
Insert new email record |
| PATCH | /api/emails/{id}/mark |
Mark as spam or legitimate |
| GET | /api/emails/spam |
Retrieve all spam emails |
| GET | /api/emails/legitimate |
Retrieve all legitimate emails |
| GET | /api/emails/count/spam |
Count total spam emails |
| GET | /api/emails/count/legitimate |
Count total legitimate emails |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/emails/export?format=csv |
Download all emails as CSV |
| GET | /api/emails/export?format=pdf |
Download all emails as PDF report |
email_id, subject, sender, is_spam, timestamp 1, Win a FREE iPhone!!!, promo@spam.com, Spam, 2024-01-01 10:00:00 2, Team standup at 10am, manager@company.com, Legitimate, 2024-01-01 11:00:00
- Summary: total emails, spam count, legitimate count
- Full table with all email records
email_idβ Auto-generated unique IDsubjectβ Email subjectsenderβ Sender email addressis_spamβ Boolean spam statustimestampβ Record creation time
After every prediction, the web app asks "Was this prediction correct?":
- β Yes β records the prediction as confirmed correct
- β No β shows a dropdown to pick the correct label (
ham,spam,smishing), then submits the correction
React Widget β POST /feedback (Node backend) β POST /feedback (Flask ML API) β feedback_store.csv
Available on both the Node backend (/feedback, requires authentication) and the Flask ML API (/feedback).
Request body:
{
"text": "Congratulations! You won a free prize, click here",
"predicted_label": "ham",
"correct_label": "spam"
}Responses:
201β{"message": "Feedback recorded. Thank you!"}400β{"error": "Invalid feedback data"}iftextis empty orcorrect_labelis not one ofham,spam,smishing
Feedback is appended to backend/feedback_store.csv (gitignored) with columns:
| Column | Description |
|---|---|
text |
The original input text |
predicted_label |
What the model predicted |
correct_label |
What the user said it should be |
submitted_at |
UTC timestamp |
Once enough feedback has accumulated, run:
cd backend
python retrain.pyThis merges feedback_store.csv with the original training dataset (DATASET_PATH, default dataset.csv), retrains the TF-IDF vectorizer, LinearSVC model and label encoder, and overwrites linear_svm_model.pkl, tfidf_vectorizer.pkl and label_encoder.pkl.
- β Spam / Smishing Detection
- β Offensive Content Classification
- β Real-time Prediction API
- β Cross-platform (Web + Mobile)
- β Scalable Architecture
- Python (ML + API)
- Scikit-learn
- Flask
- Node.js
- Express
- React
- React Native
- Axios
- Use Deep Learning (LSTM / BERT / CLIP)
- Multilingual Support
- More accuracy and advanced model
- Include Email predicton perfectly and add mobile numbers also to track
- Include Url prediction perfectly to check url is safe or not
- Docker installed
- Docker Compose installed
Pre-built images are available β no build step required:
| Service | Docker Hub |
|---|---|
| Flask ML API | rudra2006/spam-ml-api |
| Node.js Backend | rudra2006/spam-node-backend |
| React Frontend | rudra2006/spam-frontend |
Images are pre-built on Docker Hub. Just download the compose file and run:
curl -O https://raw.githubusercontent.com/Userunknown84/Spam-Detection-System/main/docker-compose.yml
docker-compose upDocker will automatically pull all 3 images. No build step, no clone required.
git clone https://github.com/Userunknown84/Spam-Detection-System.git
cd Spam-Detection-System
docker-compose up --build| Service | URL |
|---|---|
| React Frontend | http://localhost |
| Node.js Backend | http://localhost:3000 |
| Flask ML API | http://localhost:5000 |
docker-compose downBrowser β nginx (port 80) β node-backend (port 3000) β ml-api (port 5000)
- ml-api: Python Flask service that loads the SVM model and serves
/predict - node-backend: Node.js API gateway forwarding requests to ml-api
- frontend: React app built with Vite, served via nginx; nginx proxies
/predictto node-backend
Aditya Sharma
Feel free to fork, improve and contribute to this project!
This project is open-source and available under the MIT License.
You are free to use, modify, and distribute this project for personal or commercial use, provided that proper credit is given.
For more details, see the LICENSE file.