Update test email generator with fixed sets and separate buttons

Changed from configurable count input to three separate buttons for
success, warning, and error test emails. Each button generates exactly
3 emails with consistent data for reproducible testing.

Changes:
- Updated routes_settings.py to use fixed email sets instead of random data
- Changed route from /settings/test-emails/generate to /settings/test-emails/generate/<status_type>
- Created three predefined email sets (success, warning, error) with fixed content
- Updated settings.html UI to show three separate buttons instead of count input
- Each set contains 3 emails simulating Veeam, Synology, and NAKIVO backups
- Updated changelog with detailed description

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Ivo Oskamp 2026-02-09 14:44:19 +01:00
parent e187bc3fa5
commit 19ef9dc32a
3 changed files with 153 additions and 125 deletions

View File

@ -298,136 +298,162 @@ def settings_jobs_delete_orphaned():
return redirect(url_for("main.settings", section="maintenance")) return redirect(url_for("main.settings", section="maintenance"))
@main_bp.route("/settings/test-emails/generate", methods=["POST"]) @main_bp.route("/settings/test-emails/generate/<status_type>", methods=["POST"])
@login_required @login_required
@roles_required("admin") @roles_required("admin")
def settings_generate_test_emails(): def settings_generate_test_emails(status_type):
"""Generate test emails in inbox for testing parsers and orphaned jobs cleanup.""" """Generate test emails in inbox for testing parsers and orphaned jobs cleanup.
Fixed sets for consistent testing and reproducibility.
"""
try: try:
count_str = request.form.get("count", "5")
try:
count = int(count_str)
count = max(1, min(count, 50)) # Limit between 1 and 50
except Exception:
count = 5
from datetime import datetime, timedelta from datetime import datetime, timedelta
import random
# Template configurations for different backup software # Fixed test email sets per status type
templates = [ email_sets = {
{ "success": [
"software": "Veeam", {
"sender": "veeam@test.local", "from_address": "veeam@test.local",
"subject_template": "Backup job '{job}' completed {status}", "subject": "Backup job 'Daily VM Backup' completed successfully",
"body_template": """Job name: {job} "body": """Job name: Daily VM Backup
Status: {status} Status: Success
Start time: {start_time} Start time: 2026-02-09 01:00:00
End time: {end_time} End time: 2026-02-09 02:15:00
Total size: {size} GB Total size: 150 GB
Objects processed: {objects} Objects processed: 25
{message} All backup operations completed without issues.""",
""", },
"statuses": ["successfully", "with warnings", "failed"], {
}, "from_address": "synology@test.local",
{ "subject": "[Synology] Backup Task SQL Database Backup completed successfully",
"software": "Synology", "body": """Dear Administrator,
"sender": "synology@test.local",
"subject_template": "[Synology] Backup Task {job} {status}",
"body_template": """Dear Administrator,
Backup task '{job}' has {status}. Backup task 'SQL Database Backup' has completed successfully.
Task: {job} Task: SQL Database Backup
Status: {status} Status: Success
Start: {start_time} Start: 2026-02-09 02:00:00
Finish: {end_time} Finish: 2026-02-09 02:45:00
Data transferred: {size} GB Data transferred: 75 GB
{message} All backup operations completed without issues.""",
""", },
"statuses": ["completed successfully", "completed with warnings", "failed"], {
}, "from_address": "nakivo@test.local",
{ "subject": "Job 'Exchange Mailbox' finished successfully",
"software": "NAKIVO", "body": """NAKIVO Backup & Replication
"sender": "nakivo@test.local",
"subject_template": "Job '{job}' finished {status}",
"body_template": """NAKIVO Backup & Replication
Job: {job} Job: Exchange Mailbox
Status: {status} Status: Success
Started: {start_time} Started: 2026-02-09 03:00:00
Completed: {end_time} Completed: 2026-02-09 03:30:00
Size: {size} GB Size: 50 GB
{message} All backup operations completed without issues.""",
""", },
"statuses": ["successfully", "with warnings", "with errors"], ],
}, "warning": [
] {
"from_address": "veeam@test.local",
"subject": "Backup job 'Weekly File Server' completed with warnings",
"body": """Job name: Weekly File Server
Status: Warning
Start time: 2026-02-09 01:00:00
End time: 2026-02-09 02:30:00
Total size: 200 GB
Objects processed: 35
job_names = [ Backup completed but some files were skipped.""",
"Daily VM Backup", },
"Weekly File Server", {
"SQL Database Backup", "from_address": "synology@test.local",
"Exchange Mailbox", "subject": "[Synology] Backup Task Critical Servers completed with warnings",
"Critical Servers", "body": """Dear Administrator,
"Development Environment",
"Production Backup",
"Archive Job",
]
messages = { Backup task 'Critical Servers' has completed with warnings.
"successfully": "All backup operations completed without issues.",
"with warnings": "Backup completed but some files were skipped.", Task: Critical Servers
"failed": "Backup failed. Please check the logs for details.", Status: Warning
"with errors": "Some backup objects failed to process.", Start: 2026-02-09 02:00:00
Finish: 2026-02-09 03:00:00
Data transferred: 300 GB
Backup completed but some files were skipped.""",
},
{
"from_address": "nakivo@test.local",
"subject": "Job 'Production Backup' finished with warnings",
"body": """NAKIVO Backup & Replication
Job: Production Backup
Status: Warning
Started: 2026-02-09 03:00:00
Completed: 2026-02-09 04:00:00
Size: 250 GB
Some backup objects were skipped.""",
},
],
"error": [
{
"from_address": "veeam@test.local",
"subject": "Backup job 'Development Environment' failed",
"body": """Job name: Development Environment
Status: Failed
Start time: 2026-02-09 01:00:00
End time: 2026-02-09 01:15:00
Total size: 0 GB
Objects processed: 0
Backup failed. Please check the logs for details.""",
},
{
"from_address": "synology@test.local",
"subject": "[Synology] Backup Task Archive Job failed",
"body": """Dear Administrator,
Backup task 'Archive Job' has failed.
Task: Archive Job
Status: Failed
Start: 2026-02-09 02:00:00
Finish: 2026-02-09 02:05:00
Data transferred: 0 GB
Backup failed. Please check the logs for details.""",
},
{
"from_address": "nakivo@test.local",
"subject": "Job 'Critical Servers' finished with errors",
"body": """NAKIVO Backup & Replication
Job: Critical Servers
Status: Failed
Started: 2026-02-09 03:00:00
Completed: 2026-02-09 03:10:00
Size: 0 GB
Some backup objects failed to process.""",
},
],
} }
if status_type not in email_sets:
flash("Invalid status type.", "danger")
return redirect(url_for("main.settings", section="maintenance"))
emails = email_sets[status_type]
created_count = 0 created_count = 0
now = datetime.utcnow() now = datetime.utcnow()
for i in range(count): for email_data in emails:
template = random.choice(templates)
job_name = random.choice(job_names)
status = random.choice(template["statuses"])
start_time = now - timedelta(hours=random.randint(1, 24), minutes=random.randint(0, 59))
end_time = start_time + timedelta(minutes=random.randint(5, 120))
size = random.randint(10, 500)
objects_count = random.randint(5, 50)
# Find message for status
message = messages.get(status, messages.get("successfully"))
for key in messages:
if key in status:
message = messages[key]
break
subject = template["subject_template"].format(
job=job_name,
status=status,
)
body = template["body_template"].format(
job=job_name,
status=status,
start_time=start_time.strftime("%Y-%m-%d %H:%M:%S"),
end_time=end_time.strftime("%Y-%m-%d %H:%M:%S"),
size=size,
objects=objects_count,
message=message,
)
# Create mail message in inbox
mail = MailMessage( mail = MailMessage(
sender=template["sender"], from_address=email_data["from_address"],
subject=subject, subject=email_data["subject"],
body=body, text_body=email_data["body"],
text_body=body, html_body=f"<pre>{email_data['body']}</pre>",
html_body=f"<pre>{body}</pre>", received_at=now - timedelta(hours=created_count),
received_at=start_time,
location="inbox", location="inbox",
job_id=None, job_id=None,
) )
@ -436,12 +462,12 @@ Size: {size} GB
db.session.commit() db.session.commit()
flash(f"Generated {created_count} test email(s) in inbox.", "success") flash(f"Generated {created_count} {status_type} test email(s) in inbox.", "success")
_log_admin_event( _log_admin_event(
event_type="maintenance_generate_test_emails", event_type="maintenance_generate_test_emails",
message=f"Generated {created_count} test emails", message=f"Generated {created_count} {status_type} test emails",
details=json.dumps({"count": created_count}), details=json.dumps({"status_type": status_type, "count": created_count}),
) )
except Exception as exc: except Exception as exc:

View File

@ -563,16 +563,18 @@
<div class="card h-100 border-info"> <div class="card h-100 border-info">
<div class="card-header bg-info text-white">Generate test emails</div> <div class="card-header bg-info text-white">Generate test emails</div>
<div class="card-body"> <div class="card-body">
<p class="mb-3">Generate test emails in the inbox for testing parsers and maintenance operations. Emails simulate Veeam, Synology, and NAKIVO backups.</p> <p class="mb-3">Generate fixed test email sets in the inbox for testing parsers and maintenance operations. Each set contains 3 emails simulating Veeam, Synology, and NAKIVO backups.</p>
<form method="post" action="{{ url_for('main.settings_generate_test_emails') }}" class="row g-2 align-items-end"> <div class="d-flex flex-column gap-2">
<div class="col-md-6"> <form method="post" action="{{ url_for('main.settings_generate_test_emails', status_type='success') }}">
<label for="test_email_count" class="form-label">Number of emails</label> <button type="submit" class="btn btn-success w-100">Generate success emails (3)</button>
<input type="number" class="form-control" id="test_email_count" name="count" value="5" min="1" max="50" /> </form>
</div> <form method="post" action="{{ url_for('main.settings_generate_test_emails', status_type='warning') }}">
<div class="col-md-6"> <button type="submit" class="btn btn-warning w-100">Generate warning emails (3)</button>
<button type="submit" class="btn btn-info text-white w-100">Generate test emails</button> </form>
</div> <form method="post" action="{{ url_for('main.settings_generate_test_emails', status_type='error') }}">
</form> <button type="submit" class="btn btn-danger w-100">Generate error emails (3)</button>
</form>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -7,7 +7,7 @@ This file documents all changes made to this project via Claude Code.
### Added ### Added
- Added "Cleanup orphaned jobs" maintenance option in Settings → Maintenance to delete jobs without valid customer links and their associated emails/runs permanently from database (useful when customers are removed) - Added "Cleanup orphaned jobs" maintenance option in Settings → Maintenance to delete jobs without valid customer links and their associated emails/runs permanently from database (useful when customers are removed)
- Added "Preview orphaned jobs" button to show detailed list of jobs to be deleted with run/email counts before confirming deletion (verification step for safety) - Added "Preview orphaned jobs" button to show detailed list of jobs to be deleted with run/email counts before confirming deletion (verification step for safety)
- Added "Generate test emails" feature in Settings → Maintenance to create test emails in inbox that simulate Veeam, Synology, and NAKIVO backup notifications (useful for testing parsers, orphaned jobs cleanup, and other maintenance operations) - Added "Generate test emails" feature in Settings → Maintenance with three separate buttons to create fixed test email sets (success/warning/error) in inbox for testing parsers and maintenance operations (each set contains exactly 3 emails simulating Veeam, Synology, and NAKIVO backup notifications with consistent data for reproducible testing)
### Changed ### Changed
- Removed customer name from Autotask ticket title to keep titles concise (format changed from "[Backupchecks] Customer - Job Name - Status" to "[Backupchecks] Job Name - Status") - Removed customer name from Autotask ticket title to keep titles concise (format changed from "[Backupchecks] Customer - Job Name - Status" to "[Backupchecks] Job Name - Status")