* Mon Sep 01 2025 Brian Read <brianr@koozali.org> 11.1-3.sme

- Sort out ASCII escape codes in return from journalctl API  [SME: 13117]
- Add in Status enabled t default for mailstats DB [SME: 13118]
This commit is contained in:
2025-09-01 10:37:44 +01:00
parent 1858edc41c
commit 76ca0f528c
6 changed files with 55 additions and 33 deletions

7
.gitignore vendored
View File

@@ -2,14 +2,7 @@
*.log
*spec-20*
*.tgz
current.*
*.xz
current1
current2
*.html
*.txt
accounts
configuration
domains
hosts
*el8*

View File

@@ -0,0 +1 @@
enabled

View File

@@ -0,0 +1 @@
report

View File

@@ -1,6 +1,6 @@
{
# mailstats
my $status = $mailstats{'Status'} || 'disabled';
my $status = $mailstats{'status'} || 'disabled';
if ($status eq 'enabled')
{

View File

@@ -85,8 +85,8 @@ import argparse
import tempfile
#import mysql.connector
import numpy as np
import plotly.graph_objects as go
import plotly.express as px
#import plotly.graph_objects as go
#import plotly.express as px
import colorsys
import pymysql
import json
@@ -98,7 +98,7 @@ log_dir_path = "/var/log/mailstats"
# Check if the directory exists, and create it if it doesn't
if not os.path.exists(log_dir_path):
os.makedirs(log_dir_path)
logging.basicConfig(level=logging.INFO, # Default level of messages to log
logging.basicConfig(level=logging.DEBUG, # Default level of messages to log
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(), # Log to console
@@ -108,7 +108,7 @@ enable_graphs = True; #This could be a DB entry if required.
try:
import matplotlib.pyplot as plt
except ImportError:
logging.debug("Matplotlib is not installed - no graphs")
logging.warning("Matplotlib is not installed - no graphs")
enable_graphs = False;
Mailstats_version = '1.2'
@@ -150,6 +150,10 @@ PERCENT = TOTALS + 1
ColTotals = 24
ColPercent = 25
def strip_ansi_codes(text):
ansi_escape = re.compile(r'\x1b\[[0-9;]*m')
return ansi_escape.sub('', text)
def replace_bracket_content(input_filename, output_filename):
import re
@@ -242,6 +246,8 @@ def get_logs_from_Journalctl(date='yesterday'):
entry_timestamp = entry.get('__REALTIME_TIMESTAMP', None)
entry_microseconds = int(entry_timestamp.timestamp() * 1_000_000)
if entry_timestamp and since_microseconds <= entry_microseconds <= until_microseconds:
# takeout ASCII Escape sequences from the message
entry['MESSAGE'] = strip_ansi_codes(entry['MESSAGE'])
logs.append(entry)
# Sort logs by __REALTIME_TIMESTAMP in ascending order
@@ -588,32 +594,49 @@ def parse_data(data):
# and mapping:
try:
return_dict = {
'sme': fields[0].strip() if len(fields) > 0 else None,
'qpsmtpd': fields[1].strip() if len(fields) > 1 else None,
'id': fields[2].strip() if len(fields) > 2 else None,
'action': fields[3].strip() if len(fields) > 3 else None, #5
'logterse': fields[4].strip() if len(fields) > 4 else None,
'ip': fields[5].strip() if len(fields) > 5 else None,
'sendurl': fields[6].strip() if len(fields) > 6 else None, #1
'sendurl1': fields[7].strip() if len(fields) > 7 else None, #2
'from-email': fields[8].strip() if len(fields) > 8 else None, #3
'error-reason': fields[8].strip() if len(fields) > 9 else None, #3
'to-email': fields[9].strip() if len(fields) > 9 else None, #4
'error-plugin': fields[10].strip() if len(fields) > 10 else None, #5
'action1': fields[10].strip() if len(fields) > 10 else None, #5
'error-number' : fields[11].strip() if len(fields) > 11 else None, #6
'sender': fields[12].strip() if len(fields) > 12 else None, #7
'virus': fields[12].strip() if len(fields) > 12 else None, #7
'error-msg' :fields[13].strip() if len(fields) > 13 else None, #7
'spam-status': fields[13].strip() if len(fields) > 13 else None, #8
'error-result': fields[14].strip() if len(fields) > 14 else None,#8
'sme': fields[0].strip() if len(fields) > 0 else "",
'qpsmtpd': fields[1].strip() if len(fields) > 1 else "",
'id': fields[2].strip() if len(fields) > 2 else "",
'action': fields[3].strip() if len(fields) > 3 else "", #5
'logterse': fields[4].strip() if len(fields) > 4 else "",
'ip': fields[5].strip() if len(fields) > 5 else "",
'sendurl': fields[6].strip() if len(fields) > 6 else "", #1
'sendurl1': fields[7].strip() if len(fields) > 7 else "", #2
'from-email': fields[8].strip() if len(fields) > 8 else "", #3
'error-reason': fields[8].strip() if len(fields) > 9 else "", #3
'to-email': fields[9].strip() if len(fields) > 9 else "", #4
'error-plugin': fields[10].strip() if len(fields) > 10 else "", #5
'action1': fields[10].strip() if len(fields) > 10 else "", #5
'error-number' : fields[11].strip() if len(fields) > 11 else "", #6
'sender': fields[12].strip() if len(fields) > 12 else "", #7
'virus': fields[12].strip() if len(fields) > 12 else "", #7
'error-msg' :fields[13].strip() if len(fields) > 13 else "", #7
'spam-status': fields[13].strip() if len(fields) > 13 else "", #8
'error-result': fields[14].strip() if len(fields) > 14 else "",#8
# Add more fields as necessary
}
except:
logging.error(f"error:len:{len(fields)}")
return_dict = {}
return_dict = create_empty_return()
return return_dict
def safe_strip(lst, index):
if 0 <= index < len(lst):
value = lst[index]
if value is not None:
return value.strip()
return ""
def create_empty_return():
# Return dictionary with all keys, values None
keys = [
'sme', 'qpsmtpd', 'id', 'action', 'logterse', 'ip', 'sendurl', 'sendurl1',
'from-email', 'error-reason', 'to-email', 'error-plugin', 'action1', 'error-number',
'sender', 'virus', 'error-msg', 'spam-status', 'error-result'
]
return {key: "" for key in keys}
# def count_entries_by_hour(log_entries):
# hourly_counts = defaultdict(int)
# for entry in log_entries:

View File

@@ -6,7 +6,7 @@ Summary: Daily mail statistics for SME Server
%define name smeserver-mailstats
Name: %{name}
%define version 11.1
%define release 2
%define release 3
Version: %{version}
Release: %{release}%{?dist}
License: GPL
@@ -35,6 +35,10 @@ A script that via cron.d e-mails mail statistics to admin on a daily basis.
See http://www.contribs.org/bugzilla/show_bug.cgi?id=819
%changelog
* Mon Sep 01 2025 Brian Read <brianr@koozali.org> 11.1-3.sme
- Sort out ASCII escape codes in return from journalctl API [SME: 13117]
- Add in Status enabled t default for mailstats DB [SME: 13118]
* Sun Apr 06 2025 Brian Read <brianr@koozali.org> 11.1-2.sme
- First build on Koji - and Add in SM2 panel [SME: 13116]