From 9d639ab7ca070ec89df156067e65f264f342c29e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Mon, 29 Sep 2025 12:05:46 +0200 Subject: [PATCH] debugging log monitoring 8 --- .github/workflows/butler-sos-log-monitor.yaml | 58 ++++++- docs/scripts/insiders-build-monitor/README.md | 63 +++++++- .../Send-Email-Modern.ps1 | 20 +++ .../Send-Email-PS51.ps1 | 18 +++ .../Send-ErrorAlert.ps1 | 28 +++- .../insiders-build-monitor/Test-Email.ps1 | 143 ++++++++++++++++++ ...butler-sos-email-template-error-alert.html | 8 +- .../test-encoding-template.html | 59 ++++++++ 8 files changed, 378 insertions(+), 19 deletions(-) create mode 100644 docs/scripts/insiders-build-monitor/Test-Email.ps1 create mode 100644 docs/scripts/insiders-build-monitor/test-encoding-template.html diff --git a/.github/workflows/butler-sos-log-monitor.yaml b/.github/workflows/butler-sos-log-monitor.yaml index 94897b7..244f90d 100644 --- a/.github/workflows/butler-sos-log-monitor.yaml +++ b/.github/workflows/butler-sos-log-monitor.yaml @@ -281,20 +281,64 @@ jobs: # Add credentials if available (PowerShell 5.1 compatible) if ($env:SMTP_USERNAME) { $emailParams.Username = $env:SMTP_USERNAME + Write-Host "SMTP Username configured: $($env:SMTP_USERNAME)" if ($env:SMTP_PASSWORD) { # Use plain text password for PS 5.1 compatibility $emailParams.Password = $env:SMTP_PASSWORD + Write-Host "SMTP Password configured: [HIDDEN]" + } else { + Write-Host "⚠️ SMTP_PASSWORD not set" } + } else { + Write-Host "⚠️ SMTP_USERNAME not set" } - Write-Host "Calling Send-ErrorAlert.ps1..." - $result = & $emailScript @emailParams + # Debug email parameters + Write-Host "Email Parameters:" + Write-Host " SMTP Server: $($emailParams.SmtpServer)" + Write-Host " SMTP Port: $($emailParams.SmtpPort)" + Write-Host " From: $($emailParams.From)" + Write-Host " To: $($emailParams.To)" + Write-Host " Server Name: $($emailParams.ServerName)" + Write-Host " Service Name: $($emailParams.ServiceName)" + Write-Host " Use SSL: $($emailParams.UseSSL)" + Write-Host " Error Entries Count: $($emailParams.ErrorEntries.Count)" - if ($result) { - Write-Host "✅ Error alert email sent successfully!" - } else { - Write-Host "❌ Failed to send error alert email" - Write-Host "::warning::Email sending failed" + Write-Host "Calling Send-ErrorAlert.ps1..." + Write-Host "Email script path: $emailScript" + Write-Host "Template path: $($emailParams.TemplatePath)" + + # Create log files for debugging + $logDir = "D:\tools\scripts\insiders-build-monitor\logs" + if (-not (Test-Path $logDir)) { + New-Item -Path $logDir -ItemType Directory -Force | Out-Null + } + $outputLogPath = Join-Path $logDir "email-output.log" + $errorLogPath = Join-Path $logDir "email-error.log" + + # Execute script and capture all output + Write-Host "Executing email script with output capture..." + try { + $output = & $emailScript @emailParams 2>&1 + $output | Out-File -FilePath $outputLogPath -Encoding UTF8 + + Write-Host "Email script completed. Output captured to: $outputLogPath" + Write-Host "--- Script Output ---" + Write-Host $output + Write-Host "--- End Script Output ---" + + if ($LASTEXITCODE -eq 0) { + Write-Host "✅ Error alert email sent successfully!" + "email_sent=true" | Out-File -FilePath $env:GITHUB_OUTPUT -Append + } else { + Write-Host "❌ Email script returned exit code: $LASTEXITCODE" + "email_sent=false" | Out-File -FilePath $env:GITHUB_OUTPUT -Append + } + } catch { + $_.Exception.Message | Out-File -FilePath $errorLogPath -Encoding UTF8 + Write-Host "❌ Exception while running email script: $($_.Exception.Message)" + Write-Host "Error details saved to: $errorLogPath" + "email_sent=error" | Out-File -FilePath $env:GITHUB_OUTPUT -Append } # Clean up diff --git a/docs/scripts/insiders-build-monitor/README.md b/docs/scripts/insiders-build-monitor/README.md index e2680e7..a875ee9 100644 --- a/docs/scripts/insiders-build-monitor/README.md +++ b/docs/scripts/insiders-build-monitor/README.md @@ -57,6 +57,20 @@ Generic script for sending service error alerts using customizable HTML template - `TemplatePath` (required): Full path to the HTML email template file - Various log statistics parameters for the email template +#### `Test-Email.ps1` + +Convenient test script for quickly testing the email functionality. Automatically detects PowerShell version and uses the appropriate email script. + +**Parameters:** + +- `From` (required): Sender email address +- `To` (required): Recipient email address +- `Username` (required): SMTP authentication username +- `Password` (required): SMTP authentication password +- `SmtpServer` (optional): SMTP server (default: smtp.gmail.com) +- `SmtpPort` (optional): SMTP port (default: 587) +- `TestHtml` (optional): Send HTML formatted test email instead of plain text + ### Email Template #### Template Structure @@ -198,16 +212,30 @@ Run the workflow manually using GitHub Actions: Test the PowerShell scripts locally: ```powershell -# Test email sending (PowerShell 5.1) -.\Send-Email-PS51.ps1 -SmtpServer "smtp.example.com" -SmtpPort 587 -From "test@example.com" -To "admin@example.com" -Subject "Test" -Body "Test message" -UseSSL +# Quick test using the Test-Email.ps1 script (Plain Text) +.\Test-Email.ps1 -From "your-email@gmail.com" -To "recipient@example.com" -Username "your-email@gmail.com" -Password "your-app-password" + +# Quick test using the Test-Email.ps1 script (HTML) +.\Test-Email.ps1 -From "your-email@gmail.com" -To "recipient@example.com" -Username "your-email@gmail.com" -Password "your-app-password" -TestHtml + +# Test basic email sending (PowerShell 5.1) +.\Send-Email-PS51.ps1 -SmtpServer "smtp.gmail.com" -SmtpPort 587 -From "your-email@gmail.com" -To "recipient@example.com" -Subject "Test Email" -Body "This is a test message" -Username "your-email@gmail.com" -Password "your-app-password" -UseSSL + +# Test HTML email sending (PowerShell 5.1) +.\Send-Email-PS51.ps1 -SmtpServer "smtp.gmail.com" -SmtpPort 587 -From "your-email@gmail.com" -To "recipient@example.com" -Subject "HTML Test Email" -Body "

Test HTML Email

This is a test HTML message with formatting.

" -Username "your-email@gmail.com" -Password "your-app-password" -UseSSL -IsBodyHtml # Test email sending (PowerShell 7+) -.\Send-Email-Modern.ps1 -SmtpServer "smtp.example.com" -SmtpPort 587 -From "test@example.com" -To "admin@example.com" -Subject "Test" -Body "Test message" -UseSSL +.\Send-Email-Modern.ps1 -SmtpServer "smtp.gmail.com" -SmtpPort 587 -From "your-email@gmail.com" -To "recipient@example.com" -Subject "Test Email" -Body "This is a test message" -Username "your-email@gmail.com" -Password (ConvertTo-SecureString "your-app-password" -AsPlainText -Force) -UseSSL -# Test error alert (requires error data and template path) -.\Send-ErrorAlert.ps1 -SmtpServer "smtp.example.com" -SmtpPort 587 -From "test@example.com" -To "admin@example.com" -ServerName "Test Server" -ServiceName "Test Service" -ErrorEntries @("Test error 1", "Test error 2") -TemplatePath ".\butler-sos-email-template-error-alert.html" -UseSSL +# Test complete error alert system (requires error data and template path) +.\Send-ErrorAlert.ps1 -SmtpServer "smtp.gmail.com" -SmtpPort 587 -From "your-email@gmail.com" -To "recipient@example.com" -ServerName "Test Server" -ServiceName "Test Service" -ErrorEntries @("Test error 1", "Test error 2") -TemplatePath ".\butler-sos-email-template-error-alert.html" -Username "your-email@gmail.com" -Password "your-app-password" -UseSSL + +# Test encoding fix with special template +.\Send-ErrorAlert.ps1 -SmtpServer "smtp.gmail.com" -SmtpPort 587 -From "your-email@gmail.com" -To "recipient@example.com" -ServerName "Test Server" -ServiceName "Test Service" -ErrorEntries @("ERROR: Connection failed", "ERROR: Invalid configuration") -TemplatePath ".\test-encoding-template.html" -Username "your-email@gmail.com" -Password "your-app-password" -UseSSL ``` +**Note**: Replace `your-email@gmail.com` with your actual Gmail address and `your-app-password` with your Gmail App Password. For Gmail, always use an App Password, not your regular Gmail password. + ## Troubleshooting ### Common Issues @@ -216,6 +244,7 @@ Test the PowerShell scripts locally: 2. **SMTP authentication fails**: Check SMTP credentials in GitHub secrets 3. **Service stop fails**: Verify service name in repository variables 4. **Log files not found**: Check deployment path and log directory structure +5. **Mangled characters in emails**: HTML template encoding issues - see Email Encoding section below ### Workflow Logs @@ -226,9 +255,33 @@ All actions are logged in GitHub Actions workflow logs with detailed output incl - Service stop attempts - Email sending results +**Email Script Debugging Logs**: When email sending fails, detailed logs are saved to `D:\tools\scripts\insiders-build-monitor\logs\`: + +- `email-output.log` - Complete script output and parameters +- `email-error.log` - Exception details and stack traces + +These log files are overwritten on each run to help with debugging email delivery issues. + ### Email Delivery Issues - Check SMTP server settings and credentials - Verify firewall allows outbound SMTP connections - Check email server logs for delivery status - Test SMTP settings with a simple email first + +### Email Encoding Issues + +If emails display garbled characters or corrupted emojis (like "âš¡" instead of "⚡"): + +1. **Use HTML entities instead of Unicode emojis** in templates: + - Instead of `⚡` use `⚡` + - Instead of `🚨` use `🚨` + - Instead of `⚠️` use `⚠️` + +2. **Test with the encoding test template**: + + ```powershell + .\Send-ErrorAlert.ps1 -SmtpServer "smtp.gmail.com" -SmtpPort 587 -From "your@gmail.com" -To "recipient@example.com" -ServerName "Test" -ServiceName "Test" -ErrorEntries @("Test error") -TemplatePath ".\test-encoding-template.html" -Username "your@gmail.com" -Password "app-password" -UseSSL + ``` + +3. **Ensure UTF-8 encoding**: The scripts now include explicit UTF-8 encoding for both templates and email content diff --git a/docs/scripts/insiders-build-monitor/Send-Email-Modern.ps1 b/docs/scripts/insiders-build-monitor/Send-Email-Modern.ps1 index 504001a..607f22b 100644 --- a/docs/scripts/insiders-build-monitor/Send-Email-Modern.ps1 +++ b/docs/scripts/insiders-build-monitor/Send-Email-Modern.ps1 @@ -47,6 +47,22 @@ param( [int]$TimeoutSeconds = 30 ) +Write-Host "=== Send-Email-Modern.ps1 Starting ===" +Write-Host "PowerShell Version: $($PSVersionTable.PSVersion)" +Write-Host "SMTP Server: $SmtpServer" +Write-Host "SMTP Port: $SmtpPort" +Write-Host "From: $From" +Write-Host "To: $To" +Write-Host "Subject: $Subject" +Write-Host "Body Length: $($Body.Length)" +Write-Host "Has Username: $([bool]$Username)" +Write-Host "Has Password: $([bool]$Password)" +Write-Host "Has Credential: $([bool]$Credential)" +Write-Host "Use SSL: $UseSSL" +Write-Host "Is Body HTML: $IsBodyHtml" +Write-Host "Priority: $Priority" +Write-Host "Timeout: $TimeoutSeconds seconds" + # Modern PowerShell function using Send-MailMessage with enhanced error handling function Send-EmailModern { param( @@ -165,6 +181,10 @@ try { $mailMessage.Body = $Body $mailMessage.IsBodyHtml = $IsBodyHtml.IsPresent + # Set UTF-8 encoding for proper character support + $mailMessage.BodyEncoding = [System.Text.Encoding]::UTF8 + $mailMessage.SubjectEncoding = [System.Text.Encoding]::UTF8 + # Set priority $mailMessage.Priority = switch ($Priority.ToLower()) { "high" { [System.Net.Mail.MailPriority]::High } diff --git a/docs/scripts/insiders-build-monitor/Send-Email-PS51.ps1 b/docs/scripts/insiders-build-monitor/Send-Email-PS51.ps1 index fa74a5b..1e08aab 100644 --- a/docs/scripts/insiders-build-monitor/Send-Email-PS51.ps1 +++ b/docs/scripts/insiders-build-monitor/Send-Email-PS51.ps1 @@ -38,6 +38,20 @@ param( [string]$Priority = "Normal" ) +Write-Host "=== Send-Email-PS51.ps1 Starting ===" +Write-Host "PowerShell Version: $($PSVersionTable.PSVersion)" +Write-Host "SMTP Server: $SmtpServer" +Write-Host "SMTP Port: $SmtpPort" +Write-Host "From: $From" +Write-Host "To: $To" +Write-Host "Subject: $Subject" +Write-Host "Body Length: $($Body.Length)" +Write-Host "Has Username: $([bool]$Username)" +Write-Host "Has Password: $([bool]$Password)" +Write-Host "Use SSL: $UseSSL" +Write-Host "Is Body HTML: $IsBodyHtml" +Write-Host "Priority: $Priority" + # PowerShell 5.1 compatible function to convert plain text password to SecureString function ConvertTo-SecureStringPS51 { param([string]$PlainTextPassword) @@ -83,6 +97,10 @@ try { $mailMessage.Body = $Body $mailMessage.IsBodyHtml = $IsBodyHtml.IsPresent + # Set UTF-8 encoding for proper character support + $mailMessage.BodyEncoding = [System.Text.Encoding]::UTF8 + $mailMessage.SubjectEncoding = [System.Text.Encoding]::UTF8 + # Set priority switch ($Priority.ToLower()) { "high" { $mailMessage.Priority = [System.Net.Mail.MailPriority]::High } diff --git a/docs/scripts/insiders-build-monitor/Send-ErrorAlert.ps1 b/docs/scripts/insiders-build-monitor/Send-ErrorAlert.ps1 index fc75619..9264727 100644 --- a/docs/scripts/insiders-build-monitor/Send-ErrorAlert.ps1 +++ b/docs/scripts/insiders-build-monitor/Send-ErrorAlert.ps1 @@ -77,6 +77,15 @@ param( ) try { + Write-Host "=== Send-ErrorAlert.ps1 Starting ===" + Write-Host "PowerShell Version: $($PSVersionTable.PSVersion)" + Write-Host "SMTP Server: $SmtpServer" + Write-Host "SMTP Port: $SmtpPort" + Write-Host "From: $From" + Write-Host "To: $To" + Write-Host "Template Path: $TemplatePath" + Write-Host "Error Entries Count: $($ErrorEntries.Count)" + Write-Host "Preparing service error alert email..." # Read email template @@ -85,7 +94,7 @@ try { } Write-Host "Loading email template from: $TemplatePath" - $template = Get-Content -Path $TemplatePath -Raw + $template = Get-Content -Path $TemplatePath -Raw -Encoding UTF8 # Prepare error entries HTML $errorEntriesHtml = "" @@ -96,8 +105,11 @@ try { $errorEntriesHtml = "

Found $errorCount error(s):

`n" foreach ($entry in $ErrorEntries) { - $errorEntriesHtml += "
$([System.Web.HttpUtility]::HtmlEncode($entry))
`n" + # Simple HTML encoding without System.Web dependency + $encodedEntry = $entry -replace "&", "&" -replace "<", "<" -replace ">", ">" -replace '"', """ + $errorEntriesHtml += "
$encodedEntry
`n" } + Write-Host "Processed $errorCount error entries for email" } else { $errorEntriesHtml = "

No specific error entries to display.

" @@ -129,7 +141,7 @@ try { $emailBody = $emailBody -replace "{{GENERATION_TIME}}", $generationTime # Create subject - $subject = "🚨 Service Error Alert - $errorCount error(s) detected on $ServerName" + $subject = "ALERT: Service Error Alert - $errorCount error(s) detected on $ServerName" # Call the appropriate Send-Email script based on PowerShell version $scriptDir = Split-Path $TemplatePath -Parent @@ -150,6 +162,15 @@ try { } Write-Host "Calling email script: $sendEmailScript" + Write-Host "Email parameters:" + Write-Host " Subject: $subject" + Write-Host " Body length: $($emailBody.Length) characters" + Write-Host " IsBodyHtml: True" + Write-Host " Priority: High" + if ($Username) { Write-Host " Using authentication with username: $Username" } + if ($UseSSL) { Write-Host " Using SSL" } + + Write-Host "Executing email script..." $params = @{ SmtpServer = $SmtpServer @@ -167,6 +188,7 @@ try { if ($UseSSL) { $params.UseSSL = $true } $result = & $sendEmailScript @params + Write-Host "Email script returned: $result" if ($result) { Write-Host "✅ Service error alert sent successfully!" diff --git a/docs/scripts/insiders-build-monitor/Test-Email.ps1 b/docs/scripts/insiders-build-monitor/Test-Email.ps1 new file mode 100644 index 0000000..14db4e9 --- /dev/null +++ b/docs/scripts/insiders-build-monitor/Test-Email.ps1 @@ -0,0 +1,143 @@ +# Test-Email.ps1 +# Quick test script for the email sending functionality +# Automatically detects PowerShell version and uses appropriate email script + +param( + [Parameter(Mandatory = $true)] + [string]$From, + + [Parameter(Mandatory = $true)] + [string]$To, + + [Parameter(Mandatory = $true)] + [string]$Username, + + [Parameter(Mandatory = $true)] + [string]$Password, + + [Parameter(Mandatory = $false)] + [string]$SmtpServer = "smtp.gmail.com", + + [Parameter(Mandatory = $false)] + [int]$SmtpPort = 587, + + [Parameter(Mandatory = $false)] + [switch]$TestHtml +) + +Write-Host "=== Email Test Script ===" +Write-Host "PowerShell Version: $($PSVersionTable.PSVersion)" +Write-Host "Testing email functionality..." + +$scriptDir = Split-Path $MyInvocation.MyCommand.Path -Parent + +# Determine which email script to use +$psVersion = $PSVersionTable.PSVersion.Major +if ($psVersion -ge 7) { + $emailScript = Join-Path $scriptDir "Send-Email-Modern.ps1" + Write-Host "Using modern PowerShell email script for PS $psVersion" +} +else { + $emailScript = Join-Path $scriptDir "Send-Email-PS51.ps1" + Write-Host "Using PowerShell 5.1 compatible email script for PS $psVersion" +} + +if (-not (Test-Path $emailScript)) { + Write-Host "❌ Email script not found: $emailScript" -ForegroundColor Red + exit 1 +} + +# Prepare test content +if ($TestHtml) { + $subject = "HTML Email Test from Butler SOS Monitor" + $body = @" + + + + + +

🧪 HTML Email Test

+
+

✅ Success!

+

If you're seeing this formatted HTML email, the email system is working correctly!

+
+ +

Test Details:

+ + +

This is a test email from the Butler SOS monitoring system.

+ + +"@ + $isBodyHtml = $true +} +else { + $subject = "Plain Text Email Test from Butler SOS Monitor" + $body = @" +Plain Text Email Test + +✅ Success! +If you're receiving this email, the email system is working correctly! + +Test Details: +- PowerShell Version: $($PSVersionTable.PSVersion) +- Script Used: $(Split-Path $emailScript -Leaf) +- SMTP Server: $SmtpServer +- SMTP Port: $SmtpPort +- Test Time: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss UTC') + +This is a test email from the Butler SOS monitoring system. +"@ + $isBodyHtml = $false +} + +# Prepare parameters +$params = @{ + SmtpServer = $SmtpServer + SmtpPort = $SmtpPort + From = $From + To = $To + Subject = $subject + Body = $body + Username = $Username + Password = $Password + UseSSL = $true + Priority = "High" +} + +if ($isBodyHtml) { + $params.IsBodyHtml = $true +} + +Write-Host "Sending test email..." +Write-Host " From: $From" +Write-Host " To: $To" +Write-Host " Type: $(if ($TestHtml) { 'HTML' } else { 'Plain Text' })" + +try { + $result = & $emailScript @params + + if ($result) { + Write-Host "✅ Test email sent successfully!" -ForegroundColor Green + Write-Host "Check your inbox at: $To" + } + else { + Write-Host "❌ Test email failed to send" -ForegroundColor Red + } +} +catch { + Write-Host "❌ Exception occurred: $($_.Exception.Message)" -ForegroundColor Red +} + +Write-Host "=== Test Complete ===" \ No newline at end of file diff --git a/docs/scripts/insiders-build-monitor/butler-sos-email-template-error-alert.html b/docs/scripts/insiders-build-monitor/butler-sos-email-template-error-alert.html index 409b721..b04642f 100644 --- a/docs/scripts/insiders-build-monitor/butler-sos-email-template-error-alert.html +++ b/docs/scripts/insiders-build-monitor/butler-sos-email-template-error-alert.html @@ -116,13 +116,13 @@
-
⚠️
+
⚠️

Butler SOS Error Alert

Errors detected in log files

-

🔍 Summary

+

🔍 Summary

{{ERROR_COUNT}} error(s) found in Butler SOS log files

Detection Time: {{DETECTION_TIME}}

Server: {{SERVER_NAME}}

@@ -179,12 +179,12 @@
-

🚨 Error Details

+

🚨 Error Details

{{ERROR_ENTRIES}}
-

ℹ️ Next Steps

+

ℹ️ Next Steps

  1. Review the error messages above to identify the root cause
  2. Check system connectivity (InfluxDB, network, etc.)
  3. diff --git a/docs/scripts/insiders-build-monitor/test-encoding-template.html b/docs/scripts/insiders-build-monitor/test-encoding-template.html new file mode 100644 index 0000000..839ffd8 --- /dev/null +++ b/docs/scripts/insiders-build-monitor/test-encoding-template.html @@ -0,0 +1,59 @@ + + + + + Encoding Test + + + +
    +

    ⚠️ Encoding Test

    +

    Testing HTML entity encoding

    +
    + +
    +

    🚨 Error Test

    +

    This email tests proper HTML entity encoding instead of Unicode emojis.

    + +

    HTML Entities Used:

    +
      +
    • ⚠️ Warning Sign (&#9888;&#65039;)
    • +
    • 🚨 Siren (&#128680;)
    • +
    • 🔍 Magnifying Glass (&#128269;)
    • +
    • ℹ️ Information (&#8505;&#65039;)
    • +
    + +

    Server: {{SERVER_NAME}}

    +

    Service: {{SERVICE_NAME}}

    +

    Error Count: {{ERROR_COUNT}}

    + +
    + {{ERROR_ENTRIES}} +
    +
    + +

    Generated at: {{GENERATION_TIME}}

    + + \ No newline at end of file