From 0735c95c3f2f48308cdbbcfc42ddcfc5823cc1dd Mon Sep 17 00:00:00 2001 From: ThreeFive-O Date: Thu, 2 May 2019 19:37:50 +0200 Subject: [PATCH] Add unit and feature tests for Send-MailMessage (#9213) --- .../Send-MailMessage.Tests.ps1 | 267 +++++++++++++++--- 1 file changed, 234 insertions(+), 33 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Send-MailMessage.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Send-MailMessage.Tests.ps1 index 9b003a208..723e2dc05 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Send-MailMessage.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Send-MailMessage.Tests.ps1 @@ -1,16 +1,27 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -Describe "Send-MailMessage" -Tags CI, RequireSudoOnUnix { +if(-not ("netDumbster.smtp.SimpleSmtpServer" -as [type])) +{ + Register-PackageSource -Name nuget.org -Location https://api.nuget.org/v3/index.json -ProviderName NuGet -ErrorAction SilentlyContinue + + $nugetPackage = "netDumbster" + Install-Package -Name $nugetPackage -ProviderName NuGet -Scope CurrentUser -Force -Source 'nuget.org' + + $dll = "$(Split-Path (Get-Package $nugetPackage).Source)\lib\netstandard2.0\netDumbster.dll" + Add-Type -Path $dll +} + +$DefaultInputObject = @{ + From = "user01@example.com" + To = "user02@example.com" + Subject = "Subject $(Get-Date)" + Body = "Body $(Get-Date)" + SmtpServer = "127.0.0.1" +} + +Describe "Send-MailMessage DRT Unit Tests" -Tags CI, RequireSudoOnUnix { BeforeAll { - Register-PackageSource -Name nuget.org -Location https://api.nuget.org/v3/index.json -ProviderName NuGet -ErrorAction SilentlyContinue - - $nugetPackage = "netDumbster" - Install-Package -Name $nugetPackage -ProviderName NuGet -Scope CurrentUser -Force -Source 'nuget.org' - - $dll = "$(Split-Path (Get-Package $nugetPackage).Source)\lib\netstandard2.0\netDumbster.dll" - Add-Type -Path $dll - $server = [netDumbster.smtp.SimpleSmtpServer]::Start(25) function Read-Mail @@ -25,7 +36,7 @@ Describe "Send-MailMessage" -Tags CI, RequireSudoOnUnix { } } - AfterEach { + BeforeEach { if($server) { $server.ClearReceivedEmail() @@ -42,13 +53,7 @@ Describe "Send-MailMessage" -Tags CI, RequireSudoOnUnix { $testCases = @( @{ Name = "with mandatory parameters" - InputObject = @{ - From = "user01@example.com" - To = "user02@example.com" - Subject = "Subject $(Get-Date)" - Body = "Body $(Get-Date)" - SmtpServer = "127.0.0.1" - } + InputObject = $DefaultInputObject } @{ Name = "with ReplyTo" @@ -61,45 +66,91 @@ Describe "Send-MailMessage" -Tags CI, RequireSudoOnUnix { SmtpServer = "127.0.0.1" } } + @{ + Name = "with multiple To" + InputObject = @{ + From = "user01@example.com" + To = "user02@example.com","user03@example.com","user04@example.com" + Subject = "Subject $(Get-Date)" + Body = "Body $(Get-Date)" + SmtpServer = "127.0.0.1" + } + } + @{ + Name = "with multiple Cc" + InputObject = @{ + From = "user01@example.com" + To = "user02@example.com" + Cc = "user03@example.com","user04@example.com" + Subject = "Subject $(Get-Date)" + Body = "Body $(Get-Date)" + SmtpServer = "127.0.0.1" + } + } + @{ + Name = "with multiple Bcc" + InputObject = @{ + From = "user01@example.com" + To = "user02@example.com" + Bcc = "user03@example.com","user04@example.com" + Subject = "Subject $(Get-Date)" + Body = "Body $(Get-Date)" + SmtpServer = "127.0.0.1" + } + } @{ Name = "with No Subject" InputObject = @{ From = "user01@example.com" To = "user02@example.com" - ReplyTo = "noreply@example.com" Body = "Body $(Get-Date)" SmtpServer = "127.0.0.1" } } ) - It "Can send mail message using named parameters " -TestCases $testCases { - param($InputObject) - + It "Shows obsolete message for cmdlet" { $server | Should -Not -Be $null $powershell = [PowerShell]::Create() - $null = $powershell.AddCommand("Send-MailMessage").AddParameters($InputObject).AddParameter("ErrorAction","SilentlyContinue") + $null = $powershell.AddCommand("Send-MailMessage").AddParameters($testCases[0].InputObject).AddParameter("ErrorAction","SilentlyContinue") $powershell.Invoke() $warnings = $powershell.Streams.Warning $warnings.count | Should -BeGreaterThan 0 - $warnings[0].ToString() | Should -BeLike "The command 'Send-MailMessage' is obsolete. *" + $warnings[0].ToString() | Should -BeLike "The command 'Send-MailMessage' is obsolete. *" + } + + It "Can send mail message using named parameters " -TestCases $testCases { + param($InputObject) + + $server | Should -Not -Be $null + + Send-MailMessage @InputObject -ErrorAction SilentlyContinue $mail = Read-Mail $mail.FromAddress | Should -BeExactly $InputObject.From - $mail.ToAddresses | Should -BeExactly $InputObject.To + $mail.ToAddresses.Count | Should -BeExactly ($InputObject.To.Count + $InputObject.Cc.Count + $InputObject.Bcc.Count) + $mail.ToAddresses | Should -BeIn ([array]$InputObject.To + $InputObject.Cc + $InputObject.Bcc) $mail.Headers["From"] | Should -BeExactly $InputObject.From - $mail.Headers["To"] | Should -BeExactly $InputObject.To - $mail.Headers["Reply-To"] | Should -BeExactly $InputObject.ReplyTo - If ($InputObject.Subject -ne $null) { - $mail.Headers["Subject"] | Should -BeExactly $InputObject.Subject + $mail.Headers["To"] | Should -Not -BeNullOrEmpty + $mail.Headers["To"].Split(", ") | Should -BeExactly $InputObject.To + If($InputObject.Cc) + { + $mail.Headers["Cc"] | Should -Not -BeNullOrEmpty + $mail.Headers["Cc"].Split(", ") | Should -BeExactly $InputObject.Cc } + # BCC addresses can't be tested against mail message header, as this information is by design never included in the mail message itself. + If($InputObject.ReplyTo) + { + $mail.Headers["Reply-To"] | Should -BeExactly $InputObject.ReplyTo + } + $mail.Headers["Subject"] | Should -BeExactly $InputObject.Subject $mail.MessageParts.Count | Should -BeExactly 1 $mail.MessageParts[0].BodyData | Should -BeExactly $InputObject.Body @@ -117,16 +168,166 @@ Describe "Send-MailMessage" -Tags CI, RequireSudoOnUnix { $mail = Read-Mail $mail.FromAddress | Should -BeExactly $InputObject.From - $mail.ToAddresses | Should -BeExactly $InputObject.To + $mail.ToAddresses.Count | Should -BeExactly ($InputObject.To.Count + $InputObject.Cc.Count + $InputObject.Bcc.Count) + $mail.ToAddresses | Should -BeIn ([array]$InputObject.To + $InputObject.Cc + $InputObject.Bcc) $mail.Headers["From"] | Should -BeExactly $InputObject.From - $mail.Headers["To"] | Should -BeExactly $InputObject.To - $mail.Headers["Reply-To"] | Should -BeExactly $InputObject.ReplyTo - If ($InputObject.Subject -ne $null) { - $mail.Headers["Subject"] | Should -BeExactly $InputObject.Subject + $mail.Headers["To"] | Should -Not -BeNullOrEmpty + $mail.Headers["To"].Split(", ") | Should -BeExactly $InputObject.To + If($InputObject.Cc) + { + $mail.Headers["Cc"] | Should -Not -BeNullOrEmpty + $mail.Headers["Cc"].Split(", ") | Should -BeExactly $InputObject.Cc } + # BCC addresses can't be tested against mail message header, as this information is by design never included in the mail message itself. + If($InputObject.ReplyTo) + { + $mail.Headers["Reply-To"] | Should -BeExactly $InputObject.ReplyTo + } + $mail.Headers["Subject"] | Should -BeExactly $InputObject.Subject $mail.MessageParts.Count | Should -BeExactly 1 $mail.MessageParts[0].BodyData | Should -BeExactly $InputObject.Body } } + +Describe "Send-MailMessage Feature Tests" -Tags Feature, RequireSudoOnUnix { + BeforeAll { + function Read-Mail + { + param() + + if($server) + { + return $server.ReceivedEmail[0] + } + return $null + } + } + + BeforeEach { + if($server) + { + $server.ClearReceivedEmail() + } + } + + Context "Default Port 25" { + BeforeAll { + $server = [netDumbster.smtp.SimpleSmtpServer]::Start(25) + } + + AfterAll { + if($server) + { + $server.Stop() + } + } + + It "Can throw on wrong mail addresses" { + $server | Should -Not -Be $null + + $obj = $DefaultInputObject.Clone() + $obj.To = "not_a_valid_mail.address" + + { Send-MailMessage @obj -ErrorAction Stop } | Should -Throw -ErrorId "FormatException,Microsoft.PowerShell.Commands.SendMailMessage" + } + + It "Can send mail with free-form email address" { + $server | Should -Not -Be $null + + $obj = $DefaultInputObject.Clone() + $obj.From = "User01 " + $obj.To = "User02 " + + Send-MailMessage @obj -ErrorAction SilentlyContinue + + $mail = Read-Mail + + $mail.FromAddress | Should -BeExactly "user01@example.com" + $mail.ToAddresses | Should -BeExactly "user02@example.com" + } + + It "Can send mail with high priority" { + $server | Should -Not -Be $null + + Send-MailMessage @DefaultInputObject -Priority High -ErrorAction SilentlyContinue + + $mail = Read-Mail + $mail.Priority | Should -BeExactly "urgent" + } + + It "Can send mail with HTML content as body" { + $server | Should -Not -Be $null + + $obj = $DefaultInputObject.Clone() + $obj.Body = "

PowerShell

" + + Send-MailMessage @obj -BodyAsHtml -Encoding utf8 -ErrorAction SilentlyContinue + + $mail = Read-Mail + $mail.Headers["content-type"] | Should -BeLike "text/html*" + $mail.MessageParts.Count | Should -BeExactly 1 + $mail.MessageParts[0].BodyData | Should -Be $obj.Body + } + + It "Can send mail with UTF8 encoding" { + $server | Should -Not -Be $null + + $obj = $DefaultInputObject.Clone() + $obj.Body = "We ❤ PowerShell" + + Send-MailMessage @obj -Encoding utf8Bom -ErrorAction SilentlyContinue + + $mail = Read-Mail + $mail.MessageParts.Count | Should -BeExactly 1 + $mail.Headers["content-transfer-encoding"] | Should -BeExactly "base64" + $utf8Text = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($mail.MessageParts[0].BodyData)) + $utf8Text | Should -Be $obj.Body + } + + It "Can send mail with attachments" { + $attachment1 = "TestDrive:\attachment1.txt" + $attachment2 = "TestDrive:\attachment2.txt" + + $pngBase64 = "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAnElEQVR42u3RAQ0AAAgDoL9/aK3hHFSgyUw4o0KEIEQIQoQgRAhChAgRghAhCBGCECEIEYIQhAhBiBCECEGIEIQgRAhChCBECEKEIAQhQhAiBCFCECIEIQgRghAhCBGCECEIQYgQhAhBiBCECEEIQoQgRAhChCBECEIQIgQhQhAiBCFCEIIQIQgRghAhCBGCECFChCBECEKEIOS7BU5Hx50BmcQaAAAAAElFTkSuQmCC" + + Set-Content $attachment1 -Value "First attachment" + Set-Content $attachment2 -AsByteStream -Value ([Convert]::FromBase64String($pngBase64)) + + $server | Should -Not -Be $null + + Send-MailMessage @DefaultInputObject -Attachments $attachment1,$attachment2 -ErrorAction SilentlyContinue + + $mail = Read-Mail + $mail.MessageParts.Count | Should -BeExactly 3 + + $txt = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($mail.MessageParts[1].BodyData)) -replace "`n|`r" + $txt | Should -BeExactly "First attachment" + + ($mail.MessageParts[2].BodyData -replace "`n|`r") | Should -BeExactly $pngBase64 + } + } + + Context "Custom Port 2525" { + BeforeAll { + $server = [netDumbster.smtp.SimpleSmtpServer]::Start(2525) + } + + AfterAll { + if($server) + { + $server.Stop() + } + } + + It "Can send mail message using custom port 2525" { + $server | Should -Not -Be $null + $server.ReceivedEmailCount | Should -BeExactly 0 + + Send-MailMessage @DefaultInputObject -Port 2525 -ErrorAction SilentlyContinue + + $server.ReceivedEmailCount | Should -BeExactly 1 + } + } +}