Adding methods for authentication via Gmail and update manifest.json
This commit is contained in:
parent
490687a609
commit
7d649bdcfd
@ -1,95 +0,0 @@
|
|||||||
from flask import Flask, request, jsonify
|
|
||||||
from flask_cors import CORS
|
|
||||||
import imaplib
|
|
||||||
import email
|
|
||||||
from email.header import decode_header
|
|
||||||
import joblib
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
CORS(app)
|
|
||||||
|
|
||||||
model = joblib.load('spam_classifier_model.pkl')
|
|
||||||
vectorizer = joblib.load('vectorizer.pkl')
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/fetch-emails', methods=['POST'])
|
|
||||||
def fetch_emails():
|
|
||||||
data = request.json
|
|
||||||
username = data['username']
|
|
||||||
password = data['password']
|
|
||||||
|
|
||||||
try:
|
|
||||||
mail = imaplib.IMAP4_SSL("outlook.office365.com")
|
|
||||||
mail.login(username, password)
|
|
||||||
mail.select("inbox")
|
|
||||||
except imaplib.IMAP4.error:
|
|
||||||
return jsonify({"error": "Login failed. Check your email and password."}), 401
|
|
||||||
|
|
||||||
status, messages = mail.search(None, "ALL")
|
|
||||||
email_ids = messages[0].split()
|
|
||||||
|
|
||||||
emails = []
|
|
||||||
|
|
||||||
for email_id in email_ids:
|
|
||||||
res, msg = mail.fetch(email_id, "(RFC822)")
|
|
||||||
for response_part in msg:
|
|
||||||
if isinstance(response_part, tuple):
|
|
||||||
msg = email.message_from_bytes(response_part[1])
|
|
||||||
subject, encoding = decode_header(msg["Subject"])[0]
|
|
||||||
if isinstance(subject, bytes):
|
|
||||||
subject = subject.decode(encoding if encoding else "utf-8")
|
|
||||||
from_ = msg.get("From")
|
|
||||||
name, email_address = email.utils.parseaddr(from_)
|
|
||||||
body = ""
|
|
||||||
if msg.is_multipart():
|
|
||||||
for part in msg.walk():
|
|
||||||
if part.get_content_type() == "text/plain" and part.get("Content-Disposition") is None:
|
|
||||||
body += part.get_payload(decode=True).decode(part.get_content_charset() or "utf-8")
|
|
||||||
else:
|
|
||||||
body = msg.get_payload(decode=True).decode(msg.get_content_charset() or "utf-8")
|
|
||||||
|
|
||||||
emails.append({"id": email_id.decode(), "from": from_, "name": name, "email_address": email_address,
|
|
||||||
"subject": subject, "body": body})
|
|
||||||
|
|
||||||
return jsonify(emails)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/classify-email', methods=['POST'])
|
|
||||||
def classify_email():
|
|
||||||
data = request.json
|
|
||||||
email_body = data['body']
|
|
||||||
email_vectorized = vectorizer.transform([email_body])
|
|
||||||
prediction = model.predict(email_vectorized)
|
|
||||||
result = "Suspicious" if prediction == 1 else "Not suspicious"
|
|
||||||
return jsonify({"result": result})
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/mark-safe', methods=['POST'])
|
|
||||||
def mark_safe():
|
|
||||||
data = request.json
|
|
||||||
email_id = data['email_id']
|
|
||||||
# Logic to mark email as safe
|
|
||||||
return jsonify({"message": f"Email {email_id} marked as safe"})
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/delete-email', methods=['POST'])
|
|
||||||
def delete_email():
|
|
||||||
data = request.json
|
|
||||||
email_id = data['email_id']
|
|
||||||
|
|
||||||
# Connect to the mail server and delete the email
|
|
||||||
username = data['username']
|
|
||||||
password = data['password']
|
|
||||||
try:
|
|
||||||
mail = imaplib.IMAP4_SSL("outlook.office365.com")
|
|
||||||
mail.login(username, password)
|
|
||||||
mail.select("inbox")
|
|
||||||
mail.store(email_id, '+FLAGS', '\\Deleted')
|
|
||||||
mail.expunge()
|
|
||||||
return jsonify({"message": f"Email {email_id} deleted"})
|
|
||||||
except imaplib.IMAP4.error:
|
|
||||||
return jsonify({"error": "Failed to delete email"}), 500
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
app.run(debug=True)
|
|
184
backend/backend.py
Normal file
184
backend/backend.py
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
from flask import Flask, request, jsonify, session, redirect, url_for
|
||||||
|
from flask_cors import CORS
|
||||||
|
import google.oauth2.credentials
|
||||||
|
import google_auth_oauthlib.flow
|
||||||
|
import googleapiclient.discovery
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import traceback
|
||||||
|
from sklearn.feature_extraction.text import TfidfVectorizer
|
||||||
|
from sklearn.naive_bayes import MultinomialNB
|
||||||
|
import pandas as pd
|
||||||
|
import re
|
||||||
|
import joblib
|
||||||
|
import imaplib
|
||||||
|
import email
|
||||||
|
from email.header import decode_header
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
CORS(app)
|
||||||
|
app.secret_key = 'your_secret_key'
|
||||||
|
|
||||||
|
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
|
||||||
|
|
||||||
|
CLIENT_SECRETS_FILE = "client_secret.json"
|
||||||
|
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly','https://www.googleapis.com/auth/gmail.modify']
|
||||||
|
API_SERVICE_NAME = 'gmail'
|
||||||
|
API_VERSION = 'v1'
|
||||||
|
|
||||||
|
model = joblib.load('spam_classifier_model.pkl')
|
||||||
|
vectorizer = joblib.load('vectorizer.pkl')
|
||||||
|
def load_client_secrets():
|
||||||
|
with open(CLIENT_SECRETS_FILE) as f:
|
||||||
|
return json.load(f)
|
||||||
|
|
||||||
|
def save_credentials(credentials):
|
||||||
|
session['credentials'] = credentials_to_dict(credentials)
|
||||||
|
app.logger.info("Credentials saved in session.")
|
||||||
|
|
||||||
|
def load_credentials():
|
||||||
|
if 'credentials' in session:
|
||||||
|
return google.oauth2.credentials.Credentials(
|
||||||
|
**session['credentials'])
|
||||||
|
return None
|
||||||
|
|
||||||
|
@app.route('/authorize')
|
||||||
|
def authorize():
|
||||||
|
client_secrets = load_client_secrets()
|
||||||
|
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
|
||||||
|
CLIENT_SECRETS_FILE, scopes=SCOPES)
|
||||||
|
flow.redirect_uri = url_for('oauth2callback', _external=True)
|
||||||
|
authorization_url, state = flow.authorization_url(
|
||||||
|
access_type='offline',
|
||||||
|
include_granted_scopes='true')
|
||||||
|
session['state'] = state
|
||||||
|
app.logger.info(f"Authorization URL: {authorization_url}, State: {state}")
|
||||||
|
return jsonify({'url': authorization_url, 'state': state})
|
||||||
|
|
||||||
|
@app.route('/oauth2callback')
|
||||||
|
def oauth2callback():
|
||||||
|
state = session.pop('state', None)
|
||||||
|
if not state:
|
||||||
|
app.logger.error('CSRF Warning: State mismatch')
|
||||||
|
return jsonify({'error': 'CSRF Warning: State mismatch'}), 400
|
||||||
|
|
||||||
|
client_secrets = load_client_secrets()
|
||||||
|
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
|
||||||
|
CLIENT_SECRETS_FILE, scopes=SCOPES, state=state)
|
||||||
|
flow.redirect_uri = url_for('oauth2callback', _external=True)
|
||||||
|
|
||||||
|
authorization_response = request.url
|
||||||
|
app.logger.info(f"Authorization response: {authorization_response}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
flow.fetch_token(authorization_response=authorization_response)
|
||||||
|
credentials = flow.credentials
|
||||||
|
save_credentials(credentials)
|
||||||
|
app.logger.info(f"Token received and saved: {credentials.token}")
|
||||||
|
return """
|
||||||
|
<script>
|
||||||
|
window.opener.postMessage('auth_complete', 'http://localhost:5000');
|
||||||
|
window.close();
|
||||||
|
</script>
|
||||||
|
"""
|
||||||
|
except KeyError as e:
|
||||||
|
app.logger.error(f"KeyError: {str(e)}")
|
||||||
|
app.logger.error("Client secrets: " + json.dumps(client_secrets, indent=2))
|
||||||
|
app.logger.error("Authorization response: " + authorization_response)
|
||||||
|
return jsonify({'error': 'KeyError', 'message': str(e)}), 500
|
||||||
|
except Exception as e:
|
||||||
|
app.logger.error(f"Exception: {str(e)}")
|
||||||
|
app.logger.error("Traceback: " + traceback.format_exc())
|
||||||
|
return jsonify({'error': 'Exception', 'message': str(e)}), 500
|
||||||
|
|
||||||
|
@app.route('/fetch-emails', methods=['POST'])
|
||||||
|
def fetch_emails():
|
||||||
|
data = request.json
|
||||||
|
username = data['username']
|
||||||
|
password = data['password']
|
||||||
|
|
||||||
|
try:
|
||||||
|
mail = imaplib.IMAP4_SSL("outlook.office365.com")
|
||||||
|
mail.login(username, password)
|
||||||
|
mail.select("inbox")
|
||||||
|
except imaplib.IMAP4.error:
|
||||||
|
return jsonify({"error": "Login failed. Check your email and password."}), 401
|
||||||
|
|
||||||
|
status, messages = mail.search(None, "ALL")
|
||||||
|
email_ids = messages[0].split()
|
||||||
|
|
||||||
|
emails = []
|
||||||
|
|
||||||
|
for email_id in email_ids:
|
||||||
|
res, msg = mail.fetch(email_id, "(RFC822)")
|
||||||
|
for response_part in msg:
|
||||||
|
if isinstance(response_part, tuple):
|
||||||
|
msg = email.message_from_bytes(response_part[1])
|
||||||
|
subject, encoding = decode_header(msg["Subject"])[0]
|
||||||
|
if isinstance(subject, bytes):
|
||||||
|
subject = subject.decode(encoding if encoding else "utf-8")
|
||||||
|
from_ = msg.get("From")
|
||||||
|
name, email_address = email.utils.parseaddr(from_)
|
||||||
|
body = ""
|
||||||
|
if msg.is_multipart():
|
||||||
|
for part in msg.walk():
|
||||||
|
if part.get_content_type() == "text/plain" and part.get("Content-Disposition") is None:
|
||||||
|
body += part.get_payload(decode=True).decode(part.get_content_charset() or "utf-8")
|
||||||
|
else:
|
||||||
|
body = msg.get_payload(decode=True).decode(msg.get_content_charset() or "utf-8")
|
||||||
|
|
||||||
|
emails.append({"id": email_id.decode(), "from": from_, "name": name, "email_address": email_address,
|
||||||
|
"subject": subject, "body": body})
|
||||||
|
|
||||||
|
return jsonify(emails)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/classify-email', methods=['POST'])
|
||||||
|
def classify_email():
|
||||||
|
data = request.json
|
||||||
|
email_body = data['body']
|
||||||
|
email_vectorized = vectorizer.transform([email_body])
|
||||||
|
prediction = model.predict(email_vectorized)
|
||||||
|
result = "Suspicious" if prediction == 1 else "Not suspicious"
|
||||||
|
return jsonify({"result": result})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/mark-safe', methods=['POST'])
|
||||||
|
def mark_safe():
|
||||||
|
data = request.json
|
||||||
|
email_id = data['email_id']
|
||||||
|
# Logic to mark email as safe
|
||||||
|
return jsonify({"message": f"Email {email_id} marked as safe"})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/delete-email', methods=['POST'])
|
||||||
|
def delete_email():
|
||||||
|
data = request.json
|
||||||
|
email_id = data['email_id']
|
||||||
|
|
||||||
|
# Connect to the mail server and delete the email
|
||||||
|
username = data['username']
|
||||||
|
password = data['password']
|
||||||
|
try:
|
||||||
|
mail = imaplib.IMAP4_SSL("outlook.office365.com")
|
||||||
|
mail.login(username, password)
|
||||||
|
mail.select("inbox")
|
||||||
|
mail.store(email_id, '+FLAGS', '\\Deleted')
|
||||||
|
mail.expunge()
|
||||||
|
return jsonify({"message": f"Email {email_id} deleted"})
|
||||||
|
except imaplib.IMAP4.error:
|
||||||
|
return jsonify({"error": "Failed to delete email"}), 500
|
||||||
|
|
||||||
|
def credentials_to_dict(credentials):
|
||||||
|
return {
|
||||||
|
'token': credentials.token,
|
||||||
|
'refresh_token': credentials.refresh_token,
|
||||||
|
'token_uri': credentials.token_uri,
|
||||||
|
'client_id': credentials.client_id,
|
||||||
|
'client_secret': credentials.client_secret,
|
||||||
|
'scopes': credentials.scopes
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(debug=True)
|
@ -2,16 +2,38 @@
|
|||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "PhishGuardian",
|
"name": "PhishGuardian",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"description": "Classify emails as spam or not spam.",
|
"permissions": [
|
||||||
"permissions": ["storage", "activeTab", "scripting", "windows"],
|
"storage",
|
||||||
|
"activeTab",
|
||||||
|
"scripting",
|
||||||
|
"notifications",
|
||||||
|
"identity"
|
||||||
|
],
|
||||||
|
"host_permissions": [
|
||||||
|
"http://localhost:5000/*",
|
||||||
|
"https://www.googleapis.com/"
|
||||||
|
],
|
||||||
"background": {
|
"background": {
|
||||||
"service_worker": "background.js"
|
"service_worker": "background.js"
|
||||||
},
|
},
|
||||||
"action": {
|
"action": {
|
||||||
|
"default_popup": "popup.html",
|
||||||
"default_icon": {
|
"default_icon": {
|
||||||
"16": "images/icon16.png",
|
"16": "icon16.png",
|
||||||
"48": "images/icon48.png",
|
"48": "icon48.png",
|
||||||
"128": "images/icon128.png"
|
"128": "icon128.png"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"icons": {
|
||||||
|
"16": "icon16.png",
|
||||||
|
"48": "icon48.png",
|
||||||
|
"128": "icon128.png"
|
||||||
|
},
|
||||||
|
"oauth2": {
|
||||||
|
"client_id": "",
|
||||||
|
"scopes": ["https://www.googleapis.com/auth/gmail.readonly"]
|
||||||
|
},
|
||||||
|
"content_security_policy": {
|
||||||
|
"extension_pages": "script-src 'self'; object-src 'self'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user