diff --git a/.gitignore b/.gitignore
index 6bb9750..e282a03 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,7 @@ current1
current2
*.html
*.txt
+accounts
+configuration
+domains
+hosts
diff --git a/root/opt/mailstats/templates/mailstats-sub-table.html.pt b/root/opt/mailstats/templates/mailstats-sub-table.html.pt
index 2398be6..98b93ca 100644
--- a/root/opt/mailstats/templates/mailstats-sub-table.html.pt
+++ b/root/opt/mailstats/templates/mailstats-sub-table.html.pt
@@ -6,9 +6,10 @@
-
+
${item[0]} |
${item[1]} |
+ ${item[2]} |
diff --git a/root/usr/bin/mailstats.py b/root/usr/bin/mailstats.py
index 7576ac7..78e6040 100644
--- a/root/usr/bin/mailstats.py
+++ b/root/usr/bin/mailstats.py
@@ -23,7 +23,9 @@ import ipaddress
import subprocess
import os
from collections import defaultdict
-
+import smtplib
+from email.mime.multipart import MIMEMultipart
+from email.mime.text import MIMEText
Mailstats_version = '1.2'
@@ -59,6 +61,7 @@ Ham = 14
TOTALS = 15
PERCENT = 16
ColTotals = 24
+ColPercent = 25
@@ -433,24 +436,130 @@ def split_timestamp_and_data(log_entry: str) -> list:
def render_sub_table(table_title,table_headers,found_values):
# NeedNOTE: also need to compute the percentages here.
- template_path = template_dir+'mailstats-sub-table.html.pt'
+ # and sort it.
+ # Get the total
+ total_sum = sum(found_values.values())
+ # and add in list with second element the percentage
+ # Create a list of tuples with each tuple containing (key, value, percentage)
+ sub_result = [(key, value, (round(round(value / total_sum,4) * 100,2))) for key, value in found_values.items()]
+ sub_result.sort(key=lambda x: x[2], reverse=True) # Sort by percentage in descending order
+
+
+ sub_template_path = template_dir+'mailstats-sub-table.html.pt'
# Load the template
- with open(template_path, 'r') as template_file:
+ with open(sub_template_path, 'r') as template_file:
template_content = template_file.read()
# Create a Chameleon template instance
try:
template = PageTemplate(template_content)
# Render the template with the 2D array data and column headers
try:
- rendered_html = template(array_2d=found_values, column_headers=table_headers, title=table_title)
+ rendered_html = template(array_2d=sub_result, column_headers=table_headers, title=table_title)
except Exception as e:
- print(f"{table_title}: A chameleon controller render error occurred: {e}")
- raise ValueError
+ raise ValueError(f"{table_title}: A chameleon controller render error occurred: {e}")
except Exception as e:
- print(f"{table_title}: A chameleon controller template error occurred: {e}")
- raise ValueError
+ raise ValueError(f"{table_title}: A chameleon controller template error occurred: {e}")
return rendered_html
-
+
+
+def get_spamassassin_version():
+ """
+ Get the installed SpamAssassin version.
+
+ Returns:
+ str: Version number of SpamAssassin if installed, otherwise an error message.
+ """
+ try:
+ result = subprocess.run(['spamassassin', '--version'], capture_output=True, text=True)
+ if result.returncode == 0:
+ version_line = result.stdout.split('\n')[0]
+ version = version_line.split()[1]
+ return version
+ else:
+ return "SpamAssassin is not installed or an error occurred."
+ except Exception as e:
+ return f"Error: {e}"
+
+def get_clamav_version():
+ """
+ Get the installed ClamAV version.
+
+ Returns:
+ str: Version number of ClamAV if installed, otherwise an error message.
+ """
+ try:
+ result = subprocess.run(['clamscan', '--version'], capture_output=True, text=True)
+ if result.returncode == 0:
+ version_line = result.stdout.split('\n')[0]
+ version = version_line.split()[1]
+ return version
+ else:
+ return "ClamAV is not installed or an error occurred."
+ except Exception as e:
+ return f"Error: {e}"
+
+def read_html_from_file(filepath):
+ """
+ Reads HTML content from a given file.
+
+ Args:
+ filepath (str): Path to the HTML file.
+
+ Returns:
+ str: HTML content of the file.
+ """
+ # Need to add in here the contents of the css file at the end of the head section.
+ with open(filepath, 'r', encoding='utf-8') as file:
+ html_contents = file.read()
+ # Get Filepath
+ css_path = os.path.dirname(filepath)+"mailstats.css"
+ # Read in CSS
+ with open(css_path, 'r', encoding='utf-8') as file:
+ css_contents = file.read()
+ html_contents = insert_string_after(html_contents,css_contents+"","")
+ return html_contents
+
+def send_email(html_content, subject, from_email, to_email, smtp_server, smtp_port, smtp_user=None, smtp_password=None):
+ """
+ Sends an HTML email.
+
+ Args:
+ html_content (str): The HTML content to send in the email.
+ subject (str): The subject of the email.
+ from_email (str): The sender's email address.
+ to_email (str): The recipient's email address.
+ smtp_server (str): SMTP server address.
+ smtp_port (int): SMTP server port.
+ smtp_user (str, optional): SMTP server username. Default is None.
+ smtp_password (str, optional): SMTP server password. Default is None.
+ """
+ #Example (which works!)
+ # send_email(
+ # html_content=html_content,
+ # subject="Your subject",
+ # from_email="mailstats@bjsystems.co.uk",
+ # to_email="brianr@bjsystems.co.uk",
+ # smtp_server="mail.bjsystems.co.uk",
+ # smtp_port=25
+ # )
+
+ # Set up the email
+ msg = MIMEMultipart('alternative')
+ msg['Subject'] = subject
+ msg['From'] = from_email
+ msg['To'] = to_email
+
+ # Attach the HTML content
+ part = MIMEText(html_content, 'html')
+ msg.attach(part)
+
+ # Sending the email
+ with smtplib.SMTP(smtp_server, smtp_port) as server:
+ server.starttls() # Upgrade the connection to secure
+ if smtp_user and smtp_password:
+ server.login(smtp_user, smtp_password) # Authenticate only if credentials are provided
+ server.sendmail(from_email, to_email, msg.as_string())
+
if __name__ == "__main__":
try:
chameleon_version = pkg_resources.get_distribution("Chameleon").version
@@ -469,6 +578,9 @@ if __name__ == "__main__":
SARejectLevel = int(get_value(ConfigDB, "spamassassin", "RejectLevel")) #12 #$cdb->get('spamassassin')->prop('RejectLevel');
SATagLevel = int(get_value(ConfigDB, "spamassassin", "TagLevel")) #4 #$cdb->get('spamassassin')->prop('TagLevel');
+ spamassassin_version = get_spamassassin_version()
+ clamav_version = get_clamav_version()
+
FetchmailIP = '127.0.0.200'; #Apparent Ip address of fetchmail deliveries
WebmailIP = '127.0.0.1'; #Apparent Ip of Webmail sender
localhost = 'localhost'; #Apparent sender for webmail
@@ -650,8 +762,27 @@ if __name__ == "__main__":
found_qpcodes['Unknown'] += 1
else:
found_qpcodes[parsed_data['action1']] += 1
-
- print()
+ print() #seperate the [progress bar]
+ # Compute percentages
+ total_Count = columnCounts_2d[ColTotals][TOTALS]
+ #Column of percentages
+ for row in range(24):
+ if total_Count == 0:
+ percentage_of_total = 0
+ else:
+ percentage_of_total = round(round(columnCounts_2d[row][TOTALS] / total_Count,4) * 100,2)
+ columnCounts_2d[row][PERCENT] = percentage_of_total
+ #Row of percentages
+ for col in range(TOTALS):
+ if total_Count == 0:
+ percentage_of_total = 0
+ else:
+ percentage_of_total = round(round(columnCounts_2d[ColTotals][col] / total_Count,4) * 100,2)
+ columnCounts_2d[ColPercent][col] = percentage_of_total
+ # and drop in the 100% to make it look correct!
+ columnCounts_2d[ColPercent][PERCENT] = 100
+ columnCounts_2d[ColTotals][PERCENT] = 100
+ columnCounts_2d[ColPercent][TOTALS] = 100
# Now scan for the other lines in the log of interest
found_countries = defaultdict(int)