How to Build a Spam Email Classifier
One of the most annoying things for people is waiting for an important email or message only to get something completely irrelevant to your…
How to Build a Spam Email Classifier

One of the most annoying things for people is waiting for an important email or message only to get something completely irrelevant to your expectations leaving you with an inbox cluttered with promises of fortune, urgent warnings about accounts you never opened, or strange messages from people you’ve never met. The worst part is how they arrive with a kind of confidence, assuming they belong. But they don’t.
To most of us, spam emails are just a nuisance, a few extra clicks to delete and forget about. But to many others, those caught off guard or simply curious, they can become something far more malicious. Some carry invisible keys, unlocking doors you didn’t even know existed while others may pretend to be your trusted friends, maybe even companies you’ve dealt with, or services you use. And in a world where everything is connected, trust can be a dangerous thing.
Spam emails are like stories sent into the world without consent. They work because they speak the language of emotion. fear, urgency, greed, loneliness. They say, “Click here,” and hope you do so before you ask why.
A single spam email campaign can reach millions. And it only takes one person, just one, to fall for the trick. That’s the math that makes spam so stubbornly effective.
And they are getting smarter. You used to be able to spot them easily with their misspelled words, strange fonts and broken grammar. But like recently, spam has learned to adapt. It now dresses itself in the tone and texture of legitimacy. It can look like your bank, your delivery service, even your mother.
So what can we do? We must listen more closely, look more carefully. We need to teach our machines to read between the lines, to spot the fraud behind the flourish. That is what we’re about to look into: an example on how to build something that can look at an email and know, this one is safe, that one is not.
In this walkthrough, you can use any environment of your choice be it Google collab or Jupyter or even VS Code and you can get a dataset online, Kaggle.com is a good place to start.
Gathering the Evidence
Imagine you’re trying to train your dog to sniff out suspicious packages. You’re going to need examples first of both good and bad. In our case, the Enron email dataset is the training ground. It gives us real emails, some harmless (“ham”) and some…let’s say spammy.
We load these emails into Python, clean up the unreadable ones, and tag them properly.
import os
import pandas as pd
def read_category(category, directory):
emails = []
for filename in os.listdir(directory):
if not filename.endswith(".txt"):
continue
with open(os.path.join(directory, filename), 'r') as fp:
try:
content = fp.read()
emails.append({'name': filename, 'content': content, 'category': category})
except:
print(f'skipped {filename}')
return emails
ham = read_category('ham', './enron1/ham')
spam = read_category('spam', './enron1/spam')
df = pd.concat([pd.DataFrame(ham), pd.DataFrame(spam)], ignore_index=True)
Cleaning Up the Mess
Emails are usually messy, with different formats, random characters, upper and lowercase chaos. We need to simplify things by removing the junk and making everything lowercase.
import re
def preprocessor(text):
return re.sub(r'\W', ' ', text).lower()
df['content'] = df['content'].apply(preprocessor)
Teaching the Computer to Read
Now of course we can’t just give text to a machine and expect it to understand. We have to turn it into numbers first.
We’ll use a simple technique called Bag-of-Words. It counts how often each word appears. so in the case where there are more spammy words, there’s a higher chance it’s spam.
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer(preprocessor=preprocessor)
We need to split the data into training and test sets so we can evaluate performance
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(df['content'], df['category'], test_size=0.2, random_state=42)
X_train = vectorizer.fit_transform(X_train)
X_test = vectorizer.transform(X_test)
Training the Classifier
Next we get to the fun part. We will be training a Logistic Regression model since It’s fast, easy to use, and surprisingly effective.
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X_train, y_train)
predictions = model.predict(X_test)
Measuring Success
Now all we need to do is measure how well our model was able to learn from the data set
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
print(accuracy_score(y_test, predictions))
print(confusion_matrix(y_test, predictions))
print(classification_report(y_test, predictions))
We can look at the terminal for the results and we would get something like this :
Accuracy: 0.97
Confusion Matrix:
[[317 11]
[ 7 205]]
This is pretty good for any model: A 97% chance of predicting correctly between spam and harmless emails
What Triggers the Spam Alarm?
Now let’s take a look at the code and try to see what words make the model raise a red flag.
features = vectorizer.get_feature_names_out()
importance = model.coef_[0]
indices = importance.argsort()
print('Top 10 positive features:', [features[i] for i in indices[-10:]])
print('Top 10 negative features:', [features[i] for i in indices[:10]])
The Output of this will give :
Top 10 spam indicators: ['more', 'want', 'money', '2004', 'best', 'prices', 'link', 'only', 'no', 'http']
Top 10 ham indicators: ['attached', 'daren', 'doc', 'thanks', 'enron', 'neon', 'deal', 'meter', '2001', 'hpl']
Why Does This Actually Work?
At the heart of it, this approach works because:
- Logistic Regression is built for yes/no classification problems like this , spam or not.
- Bag-of-Words turns messy human language into structured data we can analyze. it simply counts how often each word shows up.
- Preprocessing acts like a good spellcheck and janitor rolled into one. It tidies up the data so the model isn’t distracted by clutter.
But it’s not flawless. This method doesn’t really understand meaning, context, or clever tricks like sarcasm. Someone who knows what they’re doing with spam can still find ways to get through with enough effort.
Once you’ve got this basic version working, you can explore:
- TF-IDF (Term Frequency–Inverse Document Frequency): A smarter way to weigh words that appear often in spam but rarely in ham.
- Swap out the model — try Naive Bayes, which often shines in spam detection tasks, or experiment with Neural Networks if you’re feeling bold.
- Don’t stop at email bodies. Include subject lines, sender addresses, or even timestamps to enrich your data.
- Try ensemble methods (mixing multiple models together) to boost accuracy.
Final Thoughts: Building a Real-World Spam Filter, One Step at a Time
At the end of all this, you didn’t just learn to copy and paste code, you understood what’s happening behind the scenes. You saw how raw text becomes data, how models make decisions, and how those decisions power something as everyday (and essential) as a spam filter.
And this is just the beginning.
Now you’re in a position to take it further. You could wrap your model in a simple web interface so others can try it out. Or turn it into a backend API and plug it into real apps. You could even improve your model to catch trickier, more disguised spam. the kind that slips past basic filters.
메타데이터
- post_id
- 045b94ece4ed
- slug
- how-to-build-a-spam-email-classifier-045b94ece4ed
- url
- https://medium.com/@adedaniel502/how-to-build-a-spam-email-classifier-045b94ece4ed
- canonical_url
- https://medium.com/@adedaniel502/how-to-build-a-spam-email-classifier-045b94ece4ed
- author_url
- https://medium.com/@adedaniel502
- status
- ok
- fetched_at
- 2026-06-28 14:26:31