Moving the project to the final repository
This commit is contained in:
commit
2dcd2a1b94
3
backend/.idea/.gitignore
vendored
Normal file
3
backend/.idea/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
1
backend/.idea/.name
Normal file
1
backend/.idea/.name
Normal file
@ -0,0 +1 @@
|
||||
backend.py
|
8
backend/.idea/backend.iml
Normal file
8
backend/.idea/backend.iml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
6
backend/.idea/inspectionProfiles/profiles_settings.xml
Normal file
6
backend/.idea/inspectionProfiles/profiles_settings.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
7
backend/.idea/misc.xml
Normal file
7
backend/.idea/misc.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
|
||||
<component name="PyCharmProfessionalAdvertiser">
|
||||
<option name="shown" value="true" />
|
||||
</component>
|
||||
</project>
|
8
backend/.idea/modules.xml
Normal file
8
backend/.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/backend.iml" filepath="$PROJECT_DIR$/.idea/backend.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
202
backend/backend.py
Normal file
202
backend/backend.py
Normal file
@ -0,0 +1,202 @@
|
||||
from flask import Flask, request, jsonify, session
|
||||
from flask_cors import CORS
|
||||
import imaplib
|
||||
import email
|
||||
from email.header import decode_header
|
||||
from sklearn.feature_extraction.text import TfidfVectorizer
|
||||
from sklearn.naive_bayes import MultinomialNB
|
||||
import traceback
|
||||
import json
|
||||
import os
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(app)
|
||||
app.secret_key = 'your_secret_key'
|
||||
|
||||
SAFE_EMAILS_FILE = 'safe_emails.json'
|
||||
|
||||
# Load safe emails from file
|
||||
def load_safe_emails():
|
||||
if os.path.exists(SAFE_EMAILS_FILE):
|
||||
with open(SAFE_EMAILS_FILE, 'r') as file:
|
||||
return json.load(file)
|
||||
return []
|
||||
|
||||
# Save safe emails to file
|
||||
def save_safe_emails(safe_emails):
|
||||
with open(SAFE_EMAILS_FILE, 'w') as file:
|
||||
json.dump(safe_emails, file)
|
||||
|
||||
safe_emails = load_safe_emails()
|
||||
|
||||
# Dane treningowe
|
||||
training_data = [
|
||||
("Urgent account verification", "support@example.com", 1),
|
||||
("Meeting agenda", "boss@example.com", 0),
|
||||
("Password reset request", "no-reply@example.com", 1),
|
||||
("Team lunch schedule", "hr@example.com", 0),
|
||||
("Suspicious login attempt", "security@example.com", 1),
|
||||
("Project update", "colleague@example.com", 0),
|
||||
("Verify your email address", "verification@example.com", 1),
|
||||
("Weekly report", "manager@example.com", 0),
|
||||
("Your account has been suspended", "no-reply@example.com", 1),
|
||||
("Company policy update", "admin@example.com", 0),
|
||||
("Immediate action required", "alert@example.com", 1),
|
||||
("Holiday party invitation", "events@example.com", 0),
|
||||
("Important security update", "security@example.com", 1),
|
||||
("Monthly performance review", "boss@example.com", 0),
|
||||
("Claim your prize now", "lottery@example.com", 1),
|
||||
("Training session details", "training@example.com", 0),
|
||||
("Unauthorized access detected", "alert@example.com", 1),
|
||||
("Office relocation notice", "admin@example.com", 0),
|
||||
("Confirm your subscription", "newsletter@example.com", 1),
|
||||
("Sales team meeting", "sales@example.com", 0),
|
||||
("Your payment is overdue", "billing@example.com", 1),
|
||||
("Client feedback", "client@example.com", 0),
|
||||
("Update your account details", "update@example.com", 1),
|
||||
("Social event invitation", "social@example.com", 0),
|
||||
("Action required: Update password", "security@example.com", 1),
|
||||
("New project assignment", "manager@example.com", 0),
|
||||
("Notice of data breach", "security@example.com", 1),
|
||||
("Weekly newsletter", "newsletter@example.com", 0),
|
||||
("Re: Your recent purchase", "support@example.com", 1),
|
||||
("Performance appraisal meeting", "hr@example.com", 0),
|
||||
("Important account notice", "no-reply@example.com", 1),
|
||||
("Quarterly earnings report", "finance@example.com", 0),
|
||||
("Urgent: Verify your identity", "security@example.com", 1),
|
||||
("Birthday celebration", "events@example.com", 0),
|
||||
]
|
||||
|
||||
subjects = [x[0] for x in training_data]
|
||||
senders = [x[1] for x in training_data]
|
||||
labels = [x[2] for x in training_data]
|
||||
|
||||
# Połączenie tytułów i nadawców
|
||||
combined_features = [s + ' ' + senders[i] for i, s in enumerate(subjects)]
|
||||
vectorizer = TfidfVectorizer()
|
||||
X = vectorizer.fit_transform(combined_features)
|
||||
y = labels
|
||||
|
||||
model = MultinomialNB()
|
||||
model.fit(X, y)
|
||||
|
||||
@app.route('/login', methods=['POST'])
|
||||
def login():
|
||||
data = request.get_json()
|
||||
username = data.get('username')
|
||||
password = data.get('password')
|
||||
|
||||
try:
|
||||
mail = imaplib.IMAP4_SSL('imap.wp.pl')
|
||||
mail.login(username, password)
|
||||
session['username'] = username
|
||||
session['password'] = password
|
||||
return jsonify({'message': 'Login successful'}), 200
|
||||
except imaplib.IMAP4.error as e:
|
||||
print(f'Login failed: {e}')
|
||||
return jsonify({'message': 'Login failed'}), 401
|
||||
except Exception as e:
|
||||
print('Error during login:', e)
|
||||
traceback.print_exc()
|
||||
return jsonify({'message': 'Internal server error'}), 500
|
||||
|
||||
@app.route('/check_mail', methods=['GET'])
|
||||
def check_mail():
|
||||
if 'username' not in session or 'password' not in session:
|
||||
return jsonify({'message': 'Not logged in'}), 401
|
||||
|
||||
username = session['username']
|
||||
password = session['password']
|
||||
|
||||
try:
|
||||
mail = imaplib.IMAP4_SSL('imap.wp.pl')
|
||||
mail.login(username, password)
|
||||
mail.select('INBOX')
|
||||
result, data = mail.search(None, 'ALL')
|
||||
email_ids = data[0].split()[-10:] # Pobierz ostatnie 10 e-maili
|
||||
emails = []
|
||||
|
||||
for e_id in email_ids:
|
||||
result, email_data = mail.fetch(e_id, '(RFC822)')
|
||||
raw_email = email_data[0][1]
|
||||
msg = email.message_from_bytes(raw_email)
|
||||
subject = decode_header_value(msg['subject'])
|
||||
sender = decode_header_value(msg['from'])
|
||||
is_phishing = detect_phishing(subject, sender, e_id.decode())
|
||||
emails.append({'subject': subject, 'from': sender, 'is_phishing': is_phishing, 'id': e_id.decode()})
|
||||
|
||||
return jsonify(emails), 200
|
||||
except Exception as e:
|
||||
print('Error during email check:', e)
|
||||
traceback.print_exc()
|
||||
return jsonify({'message': 'Internal server error'}), 500
|
||||
|
||||
@app.route('/logout', methods=['POST'])
|
||||
def logout():
|
||||
try:
|
||||
session.pop('username', None)
|
||||
session.pop('password', None)
|
||||
return jsonify({'message': 'Logged out'}), 200
|
||||
except Exception as e:
|
||||
print('Error during logout:', e)
|
||||
traceback.print_exc()
|
||||
return jsonify({'message': 'Internal server error'}), 500
|
||||
|
||||
@app.route('/mark_safe/<email_id>', methods=['POST'])
|
||||
def mark_safe(email_id):
|
||||
global safe_emails
|
||||
safe_emails.append(email_id)
|
||||
save_safe_emails(safe_emails)
|
||||
print(f'Email {email_id} marked as safe')
|
||||
return jsonify({"message": f"Email {email_id} marked as safe"}), 200
|
||||
|
||||
@app.route('/move_trash/<email_id>', methods=['POST'])
|
||||
def move_trash(email_id):
|
||||
if 'username' not in session or 'password' not in session:
|
||||
return jsonify({'message': 'Not logged in'}), 401
|
||||
|
||||
username = session['username']
|
||||
password = session['password']
|
||||
|
||||
try:
|
||||
mail = imaplib.IMAP4_SSL('imap.wp.pl')
|
||||
mail.login(username, password)
|
||||
mail.select('INBOX')
|
||||
print(f'Trying to move email ID {email_id} to Trash') # Logging email ID
|
||||
mail.store(email_id, '+FLAGS', '\\Deleted')
|
||||
mail.expunge()
|
||||
print(f'Email {email_id} deleted') # Logging deletion
|
||||
return jsonify({"message": f"Email {email_id} deleted"}), 200
|
||||
except Exception as e:
|
||||
print(f'Error during moving email to trash: {e}')
|
||||
traceback.print_exc()
|
||||
return jsonify({'message': 'Internal server error'}), 500
|
||||
|
||||
def decode_header_value(value):
|
||||
parts = decode_header(value)
|
||||
header_parts = []
|
||||
for part, encoding in parts:
|
||||
if isinstance(part, bytes):
|
||||
try:
|
||||
if encoding:
|
||||
header_parts.append(part.decode(encoding))
|
||||
else:
|
||||
header_parts.append(part.decode('utf-8'))
|
||||
except (LookupError, UnicodeDecodeError):
|
||||
header_parts.append(part.decode('utf-8', errors='ignore'))
|
||||
else:
|
||||
header_parts.append(part)
|
||||
return ''.join(header_parts)
|
||||
|
||||
def detect_phishing(subject, sender, email_id):
|
||||
if email_id in safe_emails:
|
||||
return False # If email is marked as safe, it's not phishing
|
||||
|
||||
phishing_keywords = ['urgent', 'verify', 'account', 'suspend', 'login']
|
||||
phishing_senders = ['support@example.com', 'no-reply@example.com']
|
||||
if any(keyword in subject.lower() for keyword in phishing_keywords) or sender.lower() in phishing_senders:
|
||||
return True
|
||||
return False
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(port=5000)
|
1
backend/safe_emails.json
Normal file
1
backend/safe_emails.json
Normal file
@ -0,0 +1 @@
|
||||
["3", "13", "14", "15"]
|
51
extension/background.js
Normal file
51
extension/background.js
Normal file
@ -0,0 +1,51 @@
|
||||
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
if (message.type === 'phishing-detected') {
|
||||
const emails = message.emails;
|
||||
let notificationTitle = 'You are safe!';
|
||||
let notificationMessage = 'No phishing emails detected.';
|
||||
|
||||
const phishingEmails = emails.filter(email => email.is_phishing);
|
||||
if (phishingEmails.length > 0) {
|
||||
notificationTitle = 'You are in danger!';
|
||||
notificationMessage = `Email from ${phishingEmails[0].from} titled "${phishingEmails[0].subject}" has been identified as phishing.`;
|
||||
|
||||
chrome.windows.create({
|
||||
url: 'notification.html',
|
||||
type: 'popup',
|
||||
width: 300,
|
||||
height: 200
|
||||
}, function(window) {
|
||||
chrome.storage.local.set({
|
||||
notificationTitle: notificationTitle,
|
||||
notificationMessage: notificationMessage,
|
||||
emailId: phishingEmails[0].id
|
||||
});
|
||||
});
|
||||
} else {
|
||||
chrome.windows.create({
|
||||
url: 'notification.html',
|
||||
type: 'popup',
|
||||
width: 300,
|
||||
height: 200
|
||||
}, function(window) {
|
||||
chrome.storage.local.set({
|
||||
notificationTitle: notificationTitle,
|
||||
notificationMessage: notificationMessage,
|
||||
emailId: null
|
||||
});
|
||||
});
|
||||
}
|
||||
} else if (message.type === 'mark-safe') {
|
||||
fetch(`http://localhost:5000/mark_safe/${message.emailId}`, {
|
||||
method: 'POST'
|
||||
}).then(response => response.json())
|
||||
.then(data => console.log(data))
|
||||
.catch(error => console.error('Error:', error));
|
||||
} else if (message.type === 'move-trash') {
|
||||
fetch(`http://localhost:5000/move_trash/${message.emailId}`, {
|
||||
method: 'POST'
|
||||
}).then(response => response.json())
|
||||
.then(data => console.log(data))
|
||||
.catch(error => console.error('Error:', error));
|
||||
}
|
||||
});
|
BIN
extension/icon128.png
Normal file
BIN
extension/icon128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
extension/icon16.png
Normal file
BIN
extension/icon16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 537 B |
BIN
extension/icon48.png
Normal file
BIN
extension/icon48.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
28
extension/manifest.json
Normal file
28
extension/manifest.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "PhishGuardian",
|
||||
"version": "1.0",
|
||||
"permissions": ["storage", "activeTab", "scripting", "notifications"],
|
||||
"host_permissions": [
|
||||
"http://localhost:5000/*"
|
||||
],
|
||||
"background": {
|
||||
"service_worker": "background.js"
|
||||
},
|
||||
"action": {
|
||||
"default_popup": "popup.html",
|
||||
"default_icon": {
|
||||
"16": "icon16.png",
|
||||
"48": "icon48.png",
|
||||
"128": "icon128.png"
|
||||
}
|
||||
},
|
||||
"icons": {
|
||||
"16": "icon16.png",
|
||||
"48": "icon48.png",
|
||||
"128": "icon128.png"
|
||||
},
|
||||
"content_security_policy": {
|
||||
"extension_pages": "script-src 'self'; object-src 'self'"
|
||||
}
|
||||
}
|
17
extension/notification.html
Normal file
17
extension/notification.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Notification</title>
|
||||
<script src="notification.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="notification-content">
|
||||
<p id="notification-message"></p>
|
||||
<button id="mark-safe">Mark as Safe</button>
|
||||
<button id="move-trash">Move to Trash</button>
|
||||
<button id="close">Close</button>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
47
extension/notification.js
Normal file
47
extension/notification.js
Normal file
@ -0,0 +1,47 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const markSafeButton = document.getElementById('mark-safe');
|
||||
const moveTrashButton = document.getElementById('move-trash');
|
||||
const closeButton = document.getElementById('close');
|
||||
const notificationMessage = document.getElementById('notification-message');
|
||||
|
||||
chrome.storage.local.get(['notificationTitle', 'notificationMessage', 'emailId'], function(items) {
|
||||
notificationMessage.textContent = items.notificationMessage;
|
||||
|
||||
if (items.emailId) {
|
||||
// Show action buttons if there's a phishing email
|
||||
markSafeButton.style.display = 'inline-block';
|
||||
moveTrashButton.style.display = 'inline-block';
|
||||
} else {
|
||||
// Hide action buttons if no phishing emails
|
||||
markSafeButton.style.display = 'none';
|
||||
moveTrashButton.style.display = 'none';
|
||||
}
|
||||
|
||||
markSafeButton.addEventListener('click', function() {
|
||||
console.log('Mark Safe button clicked for emailId:', items.emailId);
|
||||
chrome.runtime.sendMessage({
|
||||
type: 'mark-safe',
|
||||
emailId: items.emailId
|
||||
}, function(response) {
|
||||
console.log('Mark safe response:', response);
|
||||
});
|
||||
setTimeout(() => window.close(), 50); // Wait for 50ms before closing the window
|
||||
});
|
||||
|
||||
moveTrashButton.addEventListener('click', function() {
|
||||
console.log('Move to Trash button clicked for emailId:', items.emailId);
|
||||
chrome.runtime.sendMessage({
|
||||
type: 'move-trash',
|
||||
emailId: items.emailId
|
||||
}, function(response) {
|
||||
console.log('Move to trash response:', response);
|
||||
});
|
||||
setTimeout(() => window.close(), 50); // Wait for 50ms before closing the window
|
||||
});
|
||||
|
||||
closeButton.addEventListener('click', function() {
|
||||
console.log('Close button clicked');
|
||||
window.close();
|
||||
});
|
||||
});
|
||||
});
|
21
extension/popup.html
Normal file
21
extension/popup.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Phishing Email Detector</title>
|
||||
<script src="popup.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="login-section">
|
||||
<h2>Login</h2>
|
||||
<input type="text" id="username" placeholder="Username">
|
||||
<input type="password" id="password" placeholder="Password">
|
||||
<button id="login">Login</button>
|
||||
</div>
|
||||
<div id="control-section" style="display: none;">
|
||||
<button id="check-mail">Check Mail</button>
|
||||
<button id="logout">Logout</button>
|
||||
</div>
|
||||
<div id="results"></div>
|
||||
</body>
|
||||
</html>
|
92
extension/popup.js
Normal file
92
extension/popup.js
Normal file
@ -0,0 +1,92 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const loginButton = document.getElementById('login');
|
||||
const checkMailButton = document.getElementById('check-mail');
|
||||
const logoutButton = document.getElementById('logout');
|
||||
const loginSection = document.getElementById('login-section');
|
||||
const controlSection = document.getElementById('control-section');
|
||||
|
||||
// Check if already logged in
|
||||
chrome.storage.local.get(['username', 'password'], function(items) {
|
||||
if (items.username && items.password) {
|
||||
loginSection.style.display = 'none';
|
||||
controlSection.style.display = 'block';
|
||||
} else {
|
||||
loginSection.style.display = 'block';
|
||||
controlSection.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
loginButton.addEventListener('click', function() {
|
||||
const username = document.getElementById('username').value;
|
||||
const password = document.getElementById('password').value;
|
||||
|
||||
fetch('http://localhost:5000/login', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ username, password }),
|
||||
credentials: 'include'
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
alert(data.message);
|
||||
if (data.message === 'Login successful') {
|
||||
chrome.storage.local.set({ 'username': username, 'password': password }, function() {
|
||||
loginSection.style.display = 'none';
|
||||
controlSection.style.display = 'block';
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during login request:', error);
|
||||
alert('An error occurred while logging in');
|
||||
});
|
||||
});
|
||||
|
||||
checkMailButton.addEventListener('click', function() {
|
||||
fetch('http://localhost:5000/check_mail', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'include'
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log('Check mail response:', data);
|
||||
chrome.runtime.sendMessage({
|
||||
type: 'phishing-detected',
|
||||
emails: data
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during check mail request:', error);
|
||||
alert('An error occurred while checking mail');
|
||||
});
|
||||
});
|
||||
|
||||
logoutButton.addEventListener('click', function() {
|
||||
fetch('http://localhost:5000/logout', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'include'
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
alert(data.message);
|
||||
if (data.message === 'Logged out') {
|
||||
chrome.storage.local.remove(['username', 'password'], function() {
|
||||
loginSection.style.display = 'block';
|
||||
controlSection.style.display = 'none';
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during logout request:', error);
|
||||
alert('An error occurred while logging out');
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user