Add in two tables on header, sort out permission and ownership of params file
This commit is contained in:
@@ -305,3 +305,43 @@ p.cssvalid,p.htmlvalid {float:left;margin-right:20px}
|
|||||||
.mailstats-detail a:hover {
|
.mailstats-detail a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==============================================
|
||||||
|
Status header at top of table (scoped under emailstatus)
|
||||||
|
============================================== */
|
||||||
|
.emailstatus-wrapper {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.emailstatus-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.emailstatus-tablecontainer {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.emailstatus-table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
min-width: 300px;
|
||||||
|
flex: 1 1 45%;
|
||||||
|
}
|
||||||
|
.emailstatus-table th {
|
||||||
|
background-color: #a9a9a9;
|
||||||
|
color: black;
|
||||||
|
text-align: left;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
.emailstatus-table td {
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
.emailstatus-table tr:nth-child(even) {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.emailstatus-tablecontainer {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
@@ -16,9 +16,30 @@
|
|||||||
<br />
|
<br />
|
||||||
<h2>${structure:title}</h2>
|
<h2>${structure:title}</h2>
|
||||||
<br />
|
<br />
|
||||||
<div class="headerpanel">
|
<div class="emailstatus-wrapper">
|
||||||
<div class = "innerheaderpanel">
|
<h2 class="emailstatus-header">Email System Status</h2>
|
||||||
<!---Add in header information here -->
|
<div class="emailstatus-tablecontainer">
|
||||||
|
<!-- Table 1 -->
|
||||||
|
<table class="emailstatus-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="2">Security & Filtering</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<!---Add in table1 information here -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table class="emailstatus-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="2">Mail Traffic Statistics</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<!---Add in table2 information here -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
|
@@ -1020,6 +1020,9 @@ def replace_between(text, start, end, replacement):
|
|||||||
replaced_text = re.sub(pattern, replacement, text, flags=re.DOTALL)
|
replaced_text = re.sub(pattern, replacement, text, flags=re.DOTALL)
|
||||||
return replaced_text
|
return replaced_text
|
||||||
|
|
||||||
|
def assemble_heading_row(label,value):
|
||||||
|
return f"<tr><td>{label}</td><td>{value}</td><tr>"
|
||||||
|
|
||||||
def get_heading():
|
def get_heading():
|
||||||
#
|
#
|
||||||
# Needs from anaytsis
|
# Needs from anaytsis
|
||||||
@@ -1037,44 +1040,50 @@ def get_heading():
|
|||||||
|
|
||||||
# Clam Version/DB Count/Last DB update
|
# Clam Version/DB Count/Last DB update
|
||||||
clam_output = subprocess.getoutput("freshclam -V")
|
clam_output = subprocess.getoutput("freshclam -V")
|
||||||
clam_info = f"Clam Version/DB Count/Last DB update: {clam_output}"
|
clam_info = assemble_heading_row("Clam Version/DB Count/Last DB update:", clam_output)
|
||||||
|
|
||||||
# SpamAssassin Version
|
# SpamAssassin Version
|
||||||
sa_output = subprocess.getoutput("spamassassin -V")
|
sa_output = subprocess.getoutput("spamassassin -V")
|
||||||
sa_info = f"SpamAssassin Version: {sa_output}"
|
sa_info = assemble_heading_row("SpamAssassin Version: ",sa_output)
|
||||||
|
|
||||||
# Tag level and Reject level
|
# Tag level and Reject level
|
||||||
tag_reject_info = f"Tag level: {SATagLevel}; Reject level: {SARejectLevel} {warnnoreject}"
|
tag_reject_info = assemble_heading_row("Tag level:",SATagLevel)
|
||||||
|
tag_reject_info += assemble_heading_row("Reject level: ",f"{SARejectLevel} {warnnoreject}")
|
||||||
|
|
||||||
# SMTP connection stats
|
# SMTP connection stats
|
||||||
smtp_stats = f"External SMTP connections accepted: {totalexternalsmtpsessions}\n"\
|
smtp_stats = assemble_heading_row("External SMTP connections accepted:",totalexternalsmtpsessions)
|
||||||
f"Internal SMTP connections accepted: {totalinternalsmtpsessions}"
|
smtp_stats += assemble_heading_row("Internal SMTP connections accepted:",totalinternalsmtpsessions)
|
||||||
|
|
||||||
if len(connection_type_counts)>0:
|
if len(connection_type_counts)>0:
|
||||||
for connection_type in connection_type_counts.keys():
|
for connection_type in connection_type_counts.keys():
|
||||||
smtp_stats += f"\nCount of {connection_type} connections: {connection_type_counts[connection_type]}"
|
smtp_stats += assemble_heading_row(f"\nCount of {connection_type} connections:",connection_type_counts[connection_type])
|
||||||
|
|
||||||
if len(total_ports)>0:
|
if len(total_ports)>0:
|
||||||
for port_number in total_ports.keys():
|
for port_number in total_ports.keys():
|
||||||
smtp_stats += f"\nCount of port {port_number} connections: {total_ports[port_number]}"
|
smtp_stats += assemble_heading_row(f"\nCount of port {port_number} connections: ",total_ports[port_number])
|
||||||
|
|
||||||
smtp_stats = smtp_stats + f"\nEmails per hour: {emailperhour:.1f}/hr\n"\
|
rows = [
|
||||||
f"Average spam score (accepted): {spamavg or 0:.2f}\n"\
|
assemble_heading_row("Emails per hour:", f"{(emailperhour if emailperhour is not None else 0):.1f}/hr"),
|
||||||
f"Average spam score (rejected): {rejectspamavg or 0:.2f}\n"\
|
assemble_heading_row("Average spam score (accepted):", f"{(spamavg if spamavg is not None else 0):.2f}"),
|
||||||
f"Average ham score: {hamavg or 0:.2f}\n"\
|
assemble_heading_row("Average spam score (rejected):", f"{(rejectspamavg if rejectspamavg is not None else 0):.2f}"),
|
||||||
f"Number of DMARC reporting emails sent: {DMARCSendCount or 0} (not shown on table)"
|
assemble_heading_row("Average ham score:", f"{(hamavg if hamavg is not None else 0):.2f}"),
|
||||||
|
assemble_heading_row("Number of DMARC reporting emails sent:", f"{DMARCSendCount if DMARCSendCount is not None else 0} (not shown on table)"),
|
||||||
|
]
|
||||||
|
smtp_stats += " ".join(rows) # or "\n".join(rows) if assemble_heading_row doesn’t add its own newline
|
||||||
|
|
||||||
# DMARC approved emails
|
# DMARC approved emails
|
||||||
dmarc_info = ""
|
dmarc_info = ""
|
||||||
if hamcount != 0:
|
if hamcount != 0:
|
||||||
dmarc_ok_percentage = DMARCOkCount * 100 / hamcount
|
dmarc_ok_percentage = DMARCOkCount * 100 / hamcount
|
||||||
dmarc_info = f"Number of emails approved through DMARC: {DMARCOkCount or 0} ({dmarc_ok_percentage:.2f}% of Ham count)"
|
dmarc_info = assemble_heading_row("Number of emails approved through DMARC:",f"{DMARCOkCount or 0} ({dmarc_ok_percentage:.2f}% of Ham count)")
|
||||||
|
|
||||||
# Accumulate all strings
|
# Accumulate all strings
|
||||||
header_str = "\n".join([clam_info, sa_info, tag_reject_info, smtp_stats, dmarc_info])
|
#header_str = "<br />".join([clam_info, sa_info, tag_reject_info, smtp_stats, dmarc_info])
|
||||||
# switch newlines to <br />
|
# switch newlines to <br />
|
||||||
header_str = header_str.replace("\n","<br />")
|
#header_str = header_str.replace("\n","<br />")
|
||||||
return header_str
|
header_str1 = clam_info + sa_info + tag_reject_info
|
||||||
|
header_str2 = smtp_stats + dmarc_info
|
||||||
|
return header_str1,header_str2
|
||||||
|
|
||||||
def scan_mail_users():
|
def scan_mail_users():
|
||||||
#
|
#
|
||||||
@@ -1181,7 +1190,7 @@ def extract_blacklist_domain(text):
|
|||||||
"""
|
"""
|
||||||
s = text if isinstance(text, str) else str(text or "")
|
s = text if isinstance(text, str) else str(text or "")
|
||||||
s_lower = s.lower()
|
s_lower = s.lower()
|
||||||
logging.info(f"extract blacklist called:{text}")
|
logging.debug(f"extract blacklist called:{text}")
|
||||||
|
|
||||||
combined = ",".join([RBLList, SBLList, UBLList])
|
combined = ",".join([RBLList, SBLList, UBLList])
|
||||||
|
|
||||||
@@ -1213,7 +1222,7 @@ def extract_blacklist_domain(text):
|
|||||||
|
|
||||||
for part in combined.split(","):
|
for part in combined.split(","):
|
||||||
entry = part.strip()
|
entry = part.strip()
|
||||||
logging.info(f"Comparing: {entry}")
|
logging.debug(f"Comparing: {entry}")
|
||||||
if not entry:
|
if not entry:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -1868,8 +1877,10 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
total_html = rendered_html
|
total_html = rendered_html
|
||||||
# Add in the header information
|
# Add in the header information
|
||||||
header_rendered_html = get_heading()
|
header_rendered_html1,header_rendered_html2 = get_heading()
|
||||||
total_html = insert_string_after(total_html,header_rendered_html, "<!---Add in header information here -->")
|
total_html = insert_string_after(total_html,header_rendered_html1, "<!---Add in table1 information here -->")
|
||||||
|
total_html = insert_string_after(total_html,header_rendered_html2, "<!---Add in table2 information here -->")
|
||||||
|
header_rendered_html = header_rendered_html1 + header_rendered_html2
|
||||||
|
|
||||||
#add in the subservient tables..(remeber they appear in the reverse order of below!)
|
#add in the subservient tables..(remeber they appear in the reverse order of below!)
|
||||||
|
|
||||||
|
@@ -28,6 +28,7 @@ Requires: python3-chameleon
|
|||||||
Requires: python3-mysql
|
Requires: python3-mysql
|
||||||
Requires: python3-matplotlib
|
Requires: python3-matplotlib
|
||||||
Requires: python3-pip
|
Requires: python3-pip
|
||||||
|
Requires: systemd-libs
|
||||||
AutoReqProv: no
|
AutoReqProv: no
|
||||||
|
|
||||||
%description
|
%description
|
||||||
@@ -42,8 +43,8 @@ See https://wiki.koozali.org/mailstats
|
|||||||
- Fix up CSS for Summary Page [SME: 13121]
|
- Fix up CSS for Summary Page [SME: 13121]
|
||||||
- Get Detail logs page working and prettyfy [SME: 13121]
|
- Get Detail logs page working and prettyfy [SME: 13121]
|
||||||
- Add in C wrapper source code to interrogate journal [SME: 13121]
|
- Add in C wrapper source code to interrogate journal [SME: 13121]
|
||||||
|
- Get permission and ownership right for /etc/mailstats/db.php [SME: 13121]
|
||||||
|
- Refactor main table header into two tables side by side [SME: 13121]
|
||||||
|
|
||||||
* Mon Sep 01 2025 Brian Read <brianr@koozali.org> 11.1-4.sme
|
* Mon Sep 01 2025 Brian Read <brianr@koozali.org> 11.1-4.sme
|
||||||
- More fixes for Journal bytes instead of characters [SME: 13117]
|
- More fixes for Journal bytes instead of characters [SME: 13117]
|
||||||
@@ -138,8 +139,9 @@ perl createlinks
|
|||||||
/bin/rm -rf $RPM_BUILD_ROOT
|
/bin/rm -rf $RPM_BUILD_ROOT
|
||||||
(cd root ; /usr/bin/find . -depth -print | /bin/cpio -dump $RPM_BUILD_ROOT)
|
(cd root ; /usr/bin/find . -depth -print | /bin/cpio -dump $RPM_BUILD_ROOT)
|
||||||
chmod +x $RPM_BUILD_ROOT/usr/bin/runmailstats.sh
|
chmod +x $RPM_BUILD_ROOT/usr/bin/runmailstats.sh
|
||||||
chown root:root $RPM_BUILD_ROOT/etc/mailstats/dp.php
|
#chmod 0640 $RPM_BUILD_ROOT/etc/mailstats/db.php
|
||||||
chmod 0600 $RPM_BUILD_ROOT/etc/mailstats/db.php
|
#ls -l /builddir/build/BUILDROOT/smeserver-mailstats-11.1-5.el8.sme.x86_64/etc/mailstats/
|
||||||
|
#chown root:102 $RPM_BUILD_ROOT/etc/mailstats/db.php
|
||||||
# Define the placeholder and generate the current date and time
|
# Define the placeholder and generate the current date and time
|
||||||
now=$(date +"%Y-%m-%d %H:%M:%S")
|
now=$(date +"%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
@@ -159,3 +161,4 @@ sed -i "s|__BUILD_DATE_TIME__|$now|" $RPM_BUILD_ROOT/usr/bin/mailstats.py
|
|||||||
|
|
||||||
%files -f %{name}-%{version}-filelist
|
%files -f %{name}-%{version}-filelist
|
||||||
%defattr(-,root,root)
|
%defattr(-,root,root)
|
||||||
|
%attr(0640, root, apache) %config(noreplace) /etc/mailstats/db.php
|
||||||
|
Reference in New Issue
Block a user