βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β M365 Digest Email System β
β β
β Professional HTML email sending with inline images & OAuth2 β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββ ββββββββββββββββββββββββ ββββββββββββββββββββ
β β β β β β
β CSV Data File βββββββΆβ PowerShell βββββββΆβ Microsoft 365 β
β (Recipients) β β Control Script β β Exchange Online β
β β β β β β
βββββββββββββββββββββ ββββββββββββββββββββββββ ββββββββββββββββββββ
β
β Uses
βΌ
ββββββββββββββββββββββββ
β β
β M365DigestEmail β
β PowerShell Module β
β β
ββββββββββββββββββββββββ
β
βββββββββββββββββββΌββββββββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββ
β Authentication β β Template β β SMTP Sending β
β Module β β Processor β β with Batching β
βββββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββ
β β β
ββββββββββββ΄βββββββββ β ββββββββββ΄βββββββββββ
β β β β β
βΌ βΌ βΌ βΌ βΌ
ββββββββββ ββββββββββ ββββββββ ββββββββββ ββββββββββββ
β Basic β β OAuth2 β β HTML β β Inline β βCheckpointβ
β Auth β β (AAD) β β Body β β Images β β File β
ββββββββββ ββββββββββ ββββββββ ββββββββββ ββββββββββββ
START
β
βΌ
βββββββββββββββββββββββββββββββββββ
β Load Configuration β
β - CSV path β
β - HTML template β
β - Inline images β
β - SMTP settings β
β - Auth method β
βββββββββββββββββββ¬ββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββ
β Validate Configuration β
β - Check files exist β
β - Verify image CIDs β
β - Test authentication β
βββββββββββββββββββ¬ββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββ
β Load Checkpoint File β
β (Resume from previous run) β
βββββββββββββββββββ¬ββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββ
β Import & Parse CSV β
β - Filter already-sent emails β
β - Build recipient objects β
βββββββββββββββββββ¬ββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββ
β For Each Batch (20 emails): β
β β
β βββββββββββββββββββββββββββ β
β β For Each Recipient: β β
β β β β
β β 1. Process HTML β β
β β template β β
β β 2. Replace placeholders β β
β β 3. Create AlternateView β β
β β 4. Embed inline images β β
β β 5. Add attachments β β
β β 6. Send via SMTP β β
β β 7. Retry if failed (3x) β β
β β 8. Write to checkpoint β β
β β β β
β βββββββββββββββββββββββββββ β
β β
β Wait for batch window (3 min) β
βββββββββββββββββββ¬ββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββ
β Campaign Complete β
β - Display statistics β
β - Close connections β
βββββββββββββββββββββββββββββββββββ
β
βΌ
END
M365DigestEmailModule.psm1
β
βββ Get-EmailAuthenticationCredential
β β
β βββ Basic Authentication
β β βββ PSCredential (username/password)
β β
β βββ OAuth2 Authentication
β βββ Token Endpoint Request
β βββ Client Credentials Flow
β βββ PSCredential (username/token)
β
βββ Get-ProcessedHtmlTemplate
β β
β βββ Load HTML file
β βββ HTML-encode values (XSS protection)
β βββ Replace placeholders
β
βββ New-EmailAlternateViewWithImages
β β
β βββ Create AlternateView object
β βββ For each inline image:
β β βββ Create LinkedResource
β β βββ Set ContentType (image/png, image/jpeg)
β β βββ Set ContentId (CID reference)
β β βββ Add to AlternateView
β βββ Return AlternateView
β
βββ Send-HtmlEmail
β β
β βββ Create MailMessage object
β βββ Set To, From, Subject, BCC
β βββ Create AlternateView with images
β βββ Add attachments
β βββ Create SmtpClient
β βββ Set credentials & SSL
β βββ Send email
β βββ Dispose objects (cleanup)
β
βββ Send-BulkHtmlEmail
β
βββ Load checkpoint file
βββ Filter pending recipients
βββ For each batch:
β βββ Process template per recipient
β βββ Call Send-HtmlEmail
β βββ Retry logic (exponential backoff)
β βββ Update checkpoint file
β βββ Wait for window interval
βββ Return statistics
User Script
β
βΌ
Get-EmailAuthenticationCredential
β
βββ Convert password to SecureString
β
βββ Create PSCredential object
β (username + secure password)
β
βββ Return credential
β
βΌ
SmtpClient.Credentials = PSCredential
β
βΌ
SMTP AUTH LOGIN
(Base64 encoded credentials)
β
βΌ
Office 365 validates
β
βΌ
Authentication SUCCESS/FAIL
User Script
β
βΌ
Get-EmailAuthenticationCredential
β
βββ Build token request
β - TenantId
β - ClientId
β - ClientSecret
β - Scope: outlook.office365.com/.default
β
βββ POST to token endpoint
β https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
β
βββ Receive access token
β
βββ Create PSCredential
β (username + token as password)
β
βββ Return credential
β
βΌ
SmtpClient.Credentials = PSCredential
β
βΌ
SMTP AUTH XOAUTH2
(OAuth bearer token)
β
βΌ
Azure AD validates token
β
βΌ
Authentication SUCCESS/FAIL
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MailMessage β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Headers: β
β From: sender@example.com β
β To: recipient@example.com β
β Subject: Microsoft 365 Monthly Digest β
β BCC: admin@example.com β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β
β β AlternateView (text/html) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ€ β
β β β β
β β <html> β β
β β <body> β β
β β ...HTML content... β β
β β <img src="cid:logo1"> β β
β β <img src="cid:icon1"> β β
β β </body> β β
β β </html> β β
β β β β
β β ββββββββββββββββββββββββββββββββββββββββββ β β
β β β LinkedResource (logo1) β β β
β β β - ContentId: logo1 β β β
β β β - ContentType: image/png β β β
β β β - TransferEncoding: Base64 β β β
β β β - Data: [PNG bytes] β β β
β β ββββββββββββββββββββββββββββββββββββββββββ β β
β β β β
β β ββββββββββββββββββββββββββββββββββββββββββ β β
β β β LinkedResource (icon1) β β β
β β β - ContentId: icon1 β β β
β β β - ContentType: image/png β β β
β β β - TransferEncoding: Base64 β β β
β β β - Data: [PNG bytes] β β β
β β ββββββββββββββββββββββββββββββββββββββββββ β β
β β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Attachments: β
β βββ Manual.pdf (application/pdf) β
β βββ Guide.pdf (application/pdf) β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Batch 1 (emails 1-20)
βββ Email 1 βββββββββ
βββ Email 2 β
βββ Email 3 β
βββ ... β Sending Phase
βββ Email 19 β (~30-60 seconds)
βββ Email 20 ββββββββ
βββ WAIT 3 minutes ββββ Rate Limiting Window
Batch 2 (emails 21-40)
βββ Email 21 βββββββββ
βββ Email 22 β
βββ ... β Sending Phase
βββ Email 39 β
βββ Email 40 ββββββββ
βββ WAIT 3 minutes
... Continue for all batches
Send Email
β
βΌ
βββββββββββββββββββββββ
β Attempt 1 β
β (immediate) β
ββββββββ¬βββββββββββββββ
β
βββββ΄ββββ
β OK? β
βββββ¬ββββ
β
βββββ΄ββββββββββββββββββββββββ
β Success β Write checkpointβ
β Fail β Wait 2s β
βββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β Attempt 2 β
β (after 2s) β
ββββββββ¬βββββββββββββββ
β
βββββ΄ββββ
β OK? β
βββββ¬ββββ
β
βββββ΄ββββββββββββββββββββββββ
β Success β Write checkpointβ
β Fail β Wait 4s β
βββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β Attempt 3 β
β (after 4s) β
ββββββββ¬βββββββββββββββ
β
βββββ΄ββββ
β OK? β
βββββ¬ββββ
β
βββββ΄ββββββββββββββββββββββββ
β Success β Write checkpointβ
β Fail β Log permanent error β
βββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Email Campaign Execution β
βββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Email 1 β Success βββ¬ββ checkpoint.txt β
β Email 2 β Success βββ€ user1@example.com β
β Email 3 β Success βββ€ user2@example.com β
β Email 4 β FAIL β user3@example.com β
β Email 5 β Success βββ€ user5@example.com β
β Email 6 β Success βββ β
β β
β ββββββββββββββββββββββββββββββββββββββ β
β β SCRIPT INTERRUPTED (Ctrl+C) β β
β ββββββββββββββββββββββββββββββββββββββ β
β β
β βββββββββββββββββββββββββββββββββββ β
β β Restart script β β
β β β β β
β β Load checkpoint.txt β β
β β β β β
β β Skip: user1, user2, user3, user5β β
β β β β β
β β Resume: Email 4, 7, 8, 9... β β
β βββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
Project Root
β
βββ M365DigestEmailModule.psm1 ββββ Core module (REQUIRED)
β
βββ M365_Digest_Template.htm ββββ HTML template (REQUIRED)
β
βββ Send-M365Digest-BasicAuth.ps1 ββββ Example script (Basic)
βββ Send-M365Digest-OAuth.ps1 ββββ Example script (OAuth)
βββ Test-M365DigestConfig.ps1 ββββ Configuration validator
β
βββ recipients.csv ββββ Recipient data (USER PROVIDED)
β
βββ Images/ ββββ Inline images (USER PROVIDED)
β βββ datagroup_logo.png
β βββ m365_icon.png
β βββ exchange_icon.png
β βββ sharepoint_icon.png
β
βββ Attachments/ ββββ PDF files (USER PROVIDED)
β βββ Manual1.pdf
β βββ Manual2.pdf
β βββ Manual3.pdf
β
βββ Logs/ ββββ Runtime files (AUTO GENERATED)
βββ smtp_send_checkpoint.txt
βββ campaign_YYYYMMDD_HHmmss.log
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Campaign Size: 1000 recipients β
β Batch Size: 20 emails β
β Window Interval: 3 minutes β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Total Batches: 50 β
β Total Time: ~150 minutes (2.5 hours) β
β β
β Time Breakdown: β
β - Sending: ~50 minutes (1 min/batch) β
β - Waiting: ~147 minutes (3 min Γ 49 intervals) β
β - Retries: ~3 minutes (if 1% failure rate) β
β β
β Throughput: ~6.7 emails/minute (sustainable) β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Security Measures β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β 1. HTML Encoding β
β βββ Prevents XSS injection attacks β
β β
β 2. Secure Credentials β
β βββ PSCredential with SecureString β
β βββ OAuth tokens (short-lived) β
β β
β 3. TLS/SSL Encryption β
β βββ SMTP over TLS (port 587) β
β β
β 4. Application Permissions β
β βββ OAuth: Mail.Send only (least privilege) β
β β
β 5. Input Validation β
β βββ File path validation β
β βββ Email address format check β
β βββ Content size limits β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Architecture Documentation v1.0.0 | Built for Microsoft 365 Enterprise Email Campaigns