diff --git a/Examples/Example-SendEmail-01-Text.ps1 b/Examples/Example-SendEmail-01-Text.ps1 new file mode 100644 index 0000000..8a44067 --- /dev/null +++ b/Examples/Example-SendEmail-01-Text.ps1 @@ -0,0 +1,10 @@ +Import-Module $PSScriptRoot\..\Mailozaurr.psd1 -Force + +if (-not $MailCredentials) { + $MailCredentials = Get-Credential +} + +$Text = Get-Content -Path "$PSScriptRoot\Input\Test.txt" -Raw + +# this is simple replacement (drag & drop to Send-MailMessage) +Send-EmailMessage -To 'przemyslaw.klys@test.pl' -Subject 'Test' -Text $Text -SmtpServer 'smtp.office365.com' -From 'przemyslaw.klys@test.pl' -Priority High -Credential $MailCredentials -UseSsl -Port 587 -Verbose \ No newline at end of file diff --git a/Examples/Input/Test.txt b/Examples/Input/Test.txt new file mode 100644 index 0000000..0bc250b --- /dev/null +++ b/Examples/Input/Test.txt @@ -0,0 +1,3 @@ +Hello +My Friend +What's up \ No newline at end of file diff --git a/Lib/Core/BouncyCastle.Crypto.dll b/Lib/Core/BouncyCastle.Crypto.dll index b5e6908..b811138 100644 Binary files a/Lib/Core/BouncyCastle.Crypto.dll and b/Lib/Core/BouncyCastle.Crypto.dll differ diff --git a/Lib/Core/MailKit.dll b/Lib/Core/MailKit.dll index 5f57fb5..3ab6f8a 100644 Binary files a/Lib/Core/MailKit.dll and b/Lib/Core/MailKit.dll differ diff --git a/Lib/Core/MimeKit.dll b/Lib/Core/MimeKit.dll index 44c9d5c..c7dda6b 100644 Binary files a/Lib/Core/MimeKit.dll and b/Lib/Core/MimeKit.dll differ diff --git a/Lib/Default/BouncyCastle.Crypto.dll b/Lib/Default/BouncyCastle.Crypto.dll index f2ba673..5ef4591 100644 Binary files a/Lib/Default/BouncyCastle.Crypto.dll and b/Lib/Default/BouncyCastle.Crypto.dll differ diff --git a/Lib/Default/MailKit.dll b/Lib/Default/MailKit.dll index 6611eed..07cac57 100644 Binary files a/Lib/Default/MailKit.dll and b/Lib/Default/MailKit.dll differ diff --git a/Lib/Default/MimeKit.dll b/Lib/Default/MimeKit.dll index f81252c..299ff1d 100644 Binary files a/Lib/Default/MimeKit.dll and b/Lib/Default/MimeKit.dll differ diff --git a/Mailozaurr.psd1 b/Mailozaurr.psd1 index 27bd14e..752f4d5 100644 --- a/Mailozaurr.psd1 +++ b/Mailozaurr.psd1 @@ -8,7 +8,7 @@ Description = 'Mailozaurr is a PowerShell module that aims to provide SMTP, POP3, IMAP and few other ways to interact with Email. Underneath it uses MimeKit and MailKit and EmailValidation libraries written by Jeffrey Stedfast. ' FunctionsToExport = @('Connect-IMAP', 'Connect-oAuthGoogle', 'Connect-oAuthO365', 'Connect-POP', 'ConvertTo-GraphCredential', 'ConvertTo-OAuth2Credential', 'ConvertTo-SendGridCredential', 'Disconnect-IMAP', 'Disconnect-POP', 'Find-DKIMRecord', 'Find-DMARCRecord', 'Find-DNSBL', 'Find-MxRecord', 'Find-SPFRecord', 'Get-IMAPFolder', 'Get-IMAPMessage', 'Get-MailFolder', 'Get-MailMessage', 'Get-POPMessage', 'Resolve-DnsQuery', 'Resolve-DnsQueryRest', 'Save-MailMessage', 'Save-POPMessage', 'Send-EmailMessage', 'Test-EmailAddress') GUID = '2b0ea9f1-3ff1-4300-b939-106d5da608fa' - ModuleVersion = '0.0.21' + ModuleVersion = '0.0.22' PowerShellVersion = '5.1' PrivateData = @{ PSData = @{ diff --git a/Private/ConvertTo-MailboxAddress.ps1 b/Private/ConvertTo-MailboxAddress.ps1 index cb1b076..cf80884 100644 --- a/Private/ConvertTo-MailboxAddress.ps1 +++ b/Private/ConvertTo-MailboxAddress.ps1 @@ -3,17 +3,9 @@ param( [Array] $MailboxAddress ) - <# - MimeKit.MailboxAddress new(System.Text.Encoding encoding, string name, System.Collections.Generic.IEnumerable[string] route, string address) - MimeKit.MailboxAddress new(string name, System.Collections.Generic.IEnumerable[string] route, string address) - MimeKit.MailboxAddress new(System.Collections.Generic.IEnumerable[string] route, string address) - MimeKit.MailboxAddress new(System.Text.Encoding encoding, string name, string address) - MimeKit.MailboxAddress new(string name, string address) - MimeKit.MailboxAddress new(string address) - #> foreach ($_ in $MailboxAddress) { if ($_ -is [string]) { - $SmtpTo = [MimeKit.MailboxAddress]::new("$_") + $SmtpTo = [MimeKit.MailboxAddress]::new("$_", "$_") } elseif ($_ -is [System.Collections.IDictionary]) { $SmtpTo = [MimeKit.MailboxAddress]::new($_.Name, $_.Email) } elseif ($_ -is [MimeKit.MailboxAddress]) { @@ -22,7 +14,7 @@ if ($_.Name -and $_.Email) { $SmtpTo = [MimeKit.MailboxAddress]::new($_.Name, $_.Email) } elseif ($_.Email) { - $SmtpTo = [MimeKit.MailboxAddress]::new($_.Email) + $SmtpTo = [MimeKit.MailboxAddress]::new($_.Email, $_.Email) } } $SmtpTo diff --git a/Private/Send-GraphMailMessage.ps1 b/Private/Send-GraphMailMessage.ps1 index 8d5283f..d696529 100644 --- a/Private/Send-GraphMailMessage.ps1 +++ b/Private/Send-GraphMailMessage.ps1 @@ -12,7 +12,8 @@ function Send-GraphMailMessage { [alias('Attachments')][string[]] $Attachment, [PSCredential] $Credential, [alias('Importance')][ValidateSet('Low', 'Normal', 'High')][string] $Priority, - [switch] $DoNotSaveToSentItems + [switch] $DoNotSaveToSentItems, + [System.Diagnostics.Stopwatch] $StopWatch ) if ($Credential) { $AuthorizationData = ConvertFrom-GraphCredential -Credential $Credential @@ -87,18 +88,23 @@ function Send-GraphMailMessage { $null = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/users/$FromField/sendMail" -Headers $Authorization -Method POST -Body $Body -ContentType 'application/json; charset=UTF-8' -ErrorAction Stop if (-not $Suppress) { [PSCustomObject] @{ - Status = $True - Error = '' - SentTo = $MailSentTo - SentFrom = $FromField + Status = $True + Error = '' + SentTo = $MailSentTo + SentFrom = $FromField + Message = '' + TimeToExecute = $StopWatch.Elapsed } } } else { if (-not $Suppress) { [PSCustomObject] @{ - Status = $false - Error = 'Email not sent (WhatIf)' - SentTo = $MailSentTo + Status = $false + Error = 'Email not sent (WhatIf)' + SentTo = $MailSentTo + SentFrom = $FromField + Message = '' + TimeToExecute = $StopWatch.Elapsed } } } @@ -127,10 +133,12 @@ function Send-GraphMailMessage { } if (-not $Suppress) { [PSCustomObject] @{ - Status = $False - Error = if ($RestError) { "$($RestMessage) $($ErrorText)" } else { $RestMessage } - SentTo = $MailSentTo - SentFrom = $FromField + Status = $False + Error = if ($RestError) { "$($RestMessage) $($ErrorText)" } else { $RestMessage } + SentTo = $MailSentTo + SentFrom = $FromField + Message = '' + TimeToExecute = $StopWatch.Elapsed } } } diff --git a/Private/Send-SendGridMailMessage.ps1 b/Private/Send-SendGridMailMessage.ps1 index 9177ee6..b19f7e3 100644 --- a/Private/Send-SendGridMailMessage.ps1 +++ b/Private/Send-SendGridMailMessage.ps1 @@ -12,7 +12,8 @@ [alias('Attachments')][string[]] $Attachment, [PSCredential] $Credential, [alias('Importance')][ValidateSet('Low', 'Normal', 'High')][string] $Priority, - [switch] $SeparateTo + [switch] $SeparateTo, + [System.Diagnostics.Stopwatch] $StopWatch ) # https://sendgrid.api-docs.io/v3.0/mail-send/v3-mail-send if ($Credential) { @@ -104,10 +105,12 @@ $null = Invoke-RestMethod @InvokeRestMethodParams if (-not $Suppress) { [PSCustomObject] @{ - Status = $True - Error = '' - SentTo = $MailSentList - SentFrom = $SendGridMessage.From.Email + Status = $True + Error = '' + SentTo = $MailSentList + SentFrom = $SendGridMessage.From.Email + Message = '' + TimeToExecute = $StopWatch.Elapsed } } } @@ -126,10 +129,12 @@ } if (-not $Suppress) { [PSCustomObject] @{ - Status = $False - Error = -join ( $($_.Exception.Message), $ErrorDetails) - SentTo = $MailSentTo - SentFrom = $SendGridMessage.From.Email + Status = $False + Error = -join ( $($_.Exception.Message), $ErrorDetails) + SentTo = $MailSentTo + SentFrom = $SendGridMessage.From.Email + Message = '' + TimeToExecute = $StopWatch.Elapsed } } } diff --git a/Public/Resolve-DnsRequestRest.ps1 b/Public/Resolve-DnsRequestRest.ps1 index 0338ba5..db006da 100644 --- a/Public/Resolve-DnsRequestRest.ps1 +++ b/Public/Resolve-DnsRequestRest.ps1 @@ -35,7 +35,7 @@ $Name = $Name -replace '^(\d+)\.(\d+)\.(\d+)\.(\d+)$', '$4.$3.$2.$1.in-addr.arpa' } if ($DNSProvider -eq 'Cloudflare') { - $Q = Invoke-RestMethod -Uri "https://cloudflare-dns.com/dns-query?ct=application/dns-json&name=$Name&type=$Type" + $Q = Invoke-RestMethod -Uri "https://cloudflare-dns.com/dns-query?name=$Name&type=$Type" -Headers @{ accept = 'application/dns-json' } } else { $Q = Invoke-RestMethod -Uri "https://dns.google.com/resolve?name=$Name&type=$Type" } diff --git a/Public/Send-EmailMessage.ps1 b/Public/Send-EmailMessage.ps1 index 82699c1..4c42804 100644 --- a/Public/Send-EmailMessage.ps1 +++ b/Public/Send-EmailMessage.ps1 @@ -96,6 +96,9 @@ .PARAMETER Graph Send email via Office 365 Graph API + .PARAMETER AsSecureString + Informs command that password provided is secure string, rather than clear text + .PARAMETER SendGrid Send email via SendGrid API @@ -111,8 +114,26 @@ .PARAMETER Suppress Do not display summary in [PSCustomObject] - .PARAMETER AsSecureString - Informs command that password provided is secure string, rather than clear text + .PARAMETER LogPath + When defined save the communication with server to file + + .PARAMETER LogTimestamps + Configures whether log should use timestamps + + .PARAMETER LogTimeStampsFormat + Configures the format of the timestamps in the log file. + + .PARAMETER LogSecrets + Configures whether log should include secrets + + .PARAMETER LogClientPrefix + Sets log prefix for client to specific value. + + .PARAMETER LogServerPrefix + Sets log prefix for server to specific value. + + .PARAMETER MimeMessagePath + Adds ability to save email message to file for troubleshooting purposes .EXAMPLE if (-not $MailCredentials) { @@ -388,8 +409,14 @@ [Parameter(ParameterSetName = 'SecureString')] [Parameter(ParameterSetName = 'oAuth')] [Parameter(ParameterSetName = 'Compatibility')] - [string] $LogServerPrefix + [string] $LogServerPrefix, + + [Parameter(ParameterSetName = 'SecureString')] + [Parameter(ParameterSetName = 'oAuth')] + [Parameter(ParameterSetName = 'Compatibility')] + [string] $MimeMessagePath ) + $StopWatch = [system.diagnostics.stopwatch]::StartNew() if ($Email) { # Following code makes sure both formats are accepted. if ($Email.EmailTo) { @@ -470,6 +497,7 @@ Priority = $Priority ReplyTo = $ReplyTo DoNotSaveToSentItems = $DoNotSaveToSentItems.IsPresent + StopWatch = $StopWatch } Remove-EmptyValue -Hashtable $sendGraphMailMessageSplat return Send-GraphMailMessage @sendGraphMailMessageSplat @@ -488,6 +516,7 @@ Priority = $Priority ReplyTo = $ReplyTo SeparateTo = $SeparateTo.IsPresent + StopWatch = $StopWatch } Remove-EmptyValue -Hashtable $sendGraphMailMessageSplat return Send-SendGridMailMessage @sendGraphMailMessageSplat @@ -507,8 +536,6 @@ #void Authenticate(string userName, string password, System.Threading.CancellationToken cancellationToken) } - - $Message = [MimeKit.MimeMessage]::new() # Doing translation for compatibility with Send-MailMessage @@ -562,7 +589,7 @@ ### SMTP Part Below - if ($LogPath){ + if ($LogPath) { $ProtocolLogger = [MailKit.ProtocolLogger]::new($LogPath) $ProtocolLogger.LogTimestamps = $LogTimestamps.IsPresent $ProtocolLogger.RedactSecrets = -not $LogSecrets.IsPresent @@ -615,9 +642,14 @@ Write-Warning "Send-EmailMessage - Possible issue: Port? ($Port was used), Using SSL? ($SecureSocketOptions was used). You can also try SkipCertificateValidation or SkipCertificateRevocation. " if (-not $Suppress) { return [PSCustomObject] @{ - Status = $False - Error = $($_.Exception.Message) - SentTo = $MailSentTo + Status = $False + Error = $($_.Exception.Message) + SentTo = $MailSentTo + SentFrom = $From + Message = '' + TimeToExecute = $StopWatch.Elapsed + Server = $Server + Port = $Port } } } @@ -634,9 +666,14 @@ Write-Warning "Send-EmailMessage - Error: $($_.Exception.Message)" if (-not $Suppress) { return [PSCustomObject] @{ - Status = $False - Error = $($_.Exception.Message) - SentTo = $MailSentTo + Status = $False + Error = $($_.Exception.Message) + SentTo = $MailSentTo + SentFrom = $From + Message = '' + TimeToExecute = $StopWatch.Elapsed + Server = $Server + Port = $Port } } } @@ -654,9 +691,14 @@ Write-Warning "Send-EmailMessage - Error: $($_.Exception.Message)" if (-not $Suppress) { return [PSCustomObject] @{ - Status = $False - Error = $($_.Exception.Message) - SentTo = $MailSentTo + Status = $False + Error = $($_.Exception.Message) + SentTo = $MailSentTo + SentFrom = $From + Message = '' + TimeToExecute = $StopWatch.Elapsed + Server = $Server + Port = $Port } } } @@ -673,9 +715,14 @@ Write-Warning "Send-EmailMessage - Error: $($_.Exception.Message)" if (-not $Suppress) { return [PSCustomObject] @{ - Status = $False - Error = $($_.Exception.Message) - SentTo = $MailSentTo + Status = $False + Error = $($_.Exception.Message) + SentTo = $MailSentTo + SentFrom = $From + Message = '' + TimeToExecute = $StopWatch.Elapsed + Server = $Server + Port = $Port } } } @@ -684,20 +731,30 @@ $SmtpClient.Timeout = $Timeout try { if ($PSCmdlet.ShouldProcess("$MailSentTo", 'Send-EmailMessage')) { - $SmtpClient.Send($Message) + $OutputMessage = $SmtpClient.Send($Message) if (-not $Suppress) { [PSCustomObject] @{ - Status = $True - Error = '' - SentTo = $MailSentTo + Status = $True + Error = '' + SentTo = $MailSentTo + SentFrom = $From + Message = $OutputMessage + TimeToExecute = $StopWatch.Elapsed + Server = $Server + Port = $Port } } } else { if (-not $Suppress) { [PSCustomObject] @{ - Status = $false - Error = 'Email not sent (WhatIf)' - SentTo = $MailSentTo + Status = $false + Error = 'Email not sent (WhatIf)' + SentTo = $MailSentTo + SentFrom = $From + Message = '' + TimeToExecute = $StopWatch.Elapsed + Server = $Server + Port = $Port } } } @@ -710,11 +767,20 @@ } if (-not $Suppress) { [PSCustomObject] @{ - Status = $False - Error = $($_.Exception.Message) - SentTo = $MailSentTo + Status = $False + Error = $($_.Exception.Message) + SentTo = $MailSentTo + SentFrom = $From + Message = '' + TimeToExecute = $StopWatch.Elapsed + Server = $Server + Port = $Port } } } $SmtpClient.Disconnect($true) + if ($MimeMessagePath) { + $Message.WriteTo($MimeMessagePath) + } + $StopWatch.Stop() } \ No newline at end of file