Files
phython-mimic-smtp-clientse…/Server/RawMail.py
2025-07-05 14:24:22 +01:00

136 lines
5.8 KiB
Python

import User
from DBConn import DBConn, get_unix_timestamp
class RawMail:
"""Class for holding the raw mail variables whilst they are being added by a client"""
def __init__(self):
self.__raw_id = None
self.from_id = None
self.__raw_mail = None
self.__raw_date_sent = None
# Temp fields for holding the actual mail content, these can be parsed back from the raw_mail variable
self.from_address = None
self.to_address_list = []
self.subject = None
self.text_body = None
self.__from_user = None
self.__is_valid = False
def get_raw_id(self):
"""Method to return the raw id"""
return self.__raw_id
def get_raw_mail_content(self):
"""Method to get the raw mail body contents"""
return self.__raw_mail
def load_raw_mail(self, raw_id: int):
"""Method for loading a raw mail from its id"""
self.__raw_id = raw_id
self.__load_raw_mail()
def __load_raw_mail(self) -> None:
"""Private method to load the raw mail from the database"""
db_connection = DBConn()
raw_mail_details = db_connection.do_select("raw_mail", "row", "*", "raw_id = :raw_id",
[
{
"field": "raw_id",
"value": self.__raw_id
}
])
if raw_mail_details is not None and len(raw_mail_details) > 0:
self.__raw_id = raw_mail_details['raw_id']
self.from_id = raw_mail_details['from_id']
self.__raw_mail = raw_mail_details['raw_mail']
self.__raw_date_sent = raw_mail_details['raw_date_sent']
self.__is_valid = True
def raw_mail_is_valid(self):
"""Method to check if a valid raw mail has been loaded from the database"""
return self.__is_valid
def get_from_user(self) -> User.User or None:
"""Method to fill the from user variable with a user object"""
if self.from_id:
# Preload the user into the object if not loaded beforehand
if not self.__from_user:
self.__from_user = User.User(self.from_id)
return self.__from_user
else:
return None
def strip_headers_from_body(self) -> str:
"""Method for stripping the header lines from the mail body for storing in the database mail_store"""
body_lines = self.text_body.split("\n")
body_text = ""
# There should be 4 "header" lines, but we dont just want to accept all lines that start with a header as
# the user could have entered one into the body of the email. Its not ideal but text parsers rarely are...
header_count = 0
for line in body_lines:
if (line.startswith("From: ") or line.startswith("Date: ") or line.startswith("To: ")) and header_count < 4:
header_count += 1
elif line.startswith("Subject: ") and header_count < 4:
header_count += 1
# Set the subject since that is only set in the data state with the body
if not self.subject:
self.subject = line.replace("Subject: ", "", 1)
else:
# Anything else should be the actual email content
body_text += line + "\n"
return body_text
def parse_raw_mail(self):
"""Method for parsing a raw mail header lines to extract the from, to, date and subject values"""
email_lines = self.__raw_mail.split("\n")
self.text_body = ""
# There should be 4 "header" lines, but we dont just want to accept all lines that start with a header as
# the user could have entered one into the body of the email. Its not ideal but text parsers rarely are...
header_count = 0
for line in email_lines:
if line.startswith("From: ") and header_count < 4:
# From user id is already stored in the actual raw email record
header_count += 1
pass
elif line.startswith("Date: ") and header_count < 4:
# The date is stored in the actual table so no need to text parse it
header_count += 1
pass
elif line.startswith("To: ") and header_count < 4:
header_count += 1
if len(self.to_address_list) == 0:
addresses_only = line.replace("To: ", "", 1)
self.to_address_list = addresses_only.split(",")
elif line.startswith("Subject: ") and header_count < 4:
header_count += 1
if not self.subject:
self.subject = line.replace("Subject: ", "", 1)
else:
self.text_body += line + "\n"
def create_raw_mail(self, from_id: int, raw: str) -> bool:
"""Method for saving the raw mail into the database"""
result = False
if not self.__is_valid:
if from_id and len(raw) > 0:
db_connection = DBConn()
self.__raw_id = db_connection.do_insert("raw_mail",
[{"field": "from_id", "value": from_id},
{"field": "raw_mail", "value": raw},
{"field": "raw_date_sent", "value": get_unix_timestamp()}],
True)
if self.__raw_id:
self.__load_raw_mail()
result = True
return result