In the past, a simple email relay script was sufficient to spool internal messages. However, information security had been enforced with many cloud service providers whereby SSL/TLS with credentials were required for STMP connections. Hence, this little snippet helps us keep up with the times, while being backward compatible to legacy systems.
Current Version
# sendEmail.ps1
# Version 0.03
# This iteration includes the workaround for anonymous email relays
$emailFrom="[email protected]"
$emailPassword="PASSWORD"
$emailTo="[email protected]"
$subject="Test Email to Validate SMTP"
$body="This is a test email.<br><br>Please disregard"
$smtpServer='smtp.office365.com'
$port=587
$attachments='c:\gpresult.html'
$useSsl=$true
$anonymousMode=$false
function sendEmail{
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$emailFrom,
[Parameter(Mandatory)][string]$emailPassword,
[Parameter(Mandatory)][string[]]$emailTo,
[Parameter(Mandatory=$false)][string[]]$cc,
[Parameter(Mandatory=$false)]$subject="Test Email to Validate SMTP",
[Parameter(Mandatory=$false)]$body="This is a test email.<br><br>Please disregard",
[Parameter(Mandatory=$false)]$smtpServer=$null,
[Parameter(Mandatory=$false)]$port=587,
[Parameter(Mandatory=$false)]$attachments,
[Parameter(Mandatory=$false)][bool]$useSsl=$true,
[Parameter(Mandatory=$false)][bool]$anonymous=$false
)
$commonSmtpPorts=@(25,587,465,2525)
function Check-NetConnection($server,$port,$timeout=100,$verbose=$false) {
$tcp = New-Object System.Net.Sockets.TcpClient;
try {
$connect=$tcp.BeginConnect($server,$port,$null,$null)
$wait = $connect.AsyncWaitHandle.WaitOne($timeout,$false)
if(!$wait){
$tcp.Close()
if($verbose){
Write-Host "Connection Timeout" -ForegroundColor Red
}
Return $false
}else{
$error.Clear()
$null=$tcp.EndConnect($connect) # Dispose of the connection to release memory
if(!$?){
if($verbose){
write-host $error[0].Exception.Message -ForegroundColor Red
}
$tcp.Close()
return $false
}
$tcp.Close()
Return $true
}
} catch {
return $false
}
}
function getMxRecord($emailAddress){
$regexDomain="\@(.*)$"
$domain=.{[void]($emailAddress -match $regexDomain);$matches[1]}
$mxDomain=(resolve-dnsname $domain -type mx|sort -Property Preference|select -First 1).NameExchange
$detectedSmtp=switch -Wildcard ($mxDomain){ # need to build up this list
"*outlook.com" {"smtp.office365.com";break}
"*google.com" {"smtp.gmail.com";break}
"*yahoodns.net" {'smtp.mail.yahoo.com';break}
"*inbox.com" {'my.inbox.com;break'}
"*mail.com" {'smtp.mail.com';break}
"*icloud.com" {'smtp.mail.me.com';break}
"*zoho.com" {'smtp.zoho.com';break}
default {$mxDomain}
}
if($mxDomain){
write-host "Detected MX Record`t: $mxDomain`r`nKnown SMTP Server`t: $detectedSmtp"
return $detectedSmtp
}
else{
write-warning "MX record not available for $emailAddress"
return $null
}
}
if($emailFrom -match '@' -and $emailPassword){
$encryptedPass=ConvertTo-SecureString -String $emailPassword -AsPlainText -Force
$emailCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $emailFrom,$encryptedPass
}elseif($anonymous){
$nullPassword = ConvertTo-SecureString 'null' -asplaintext -force
$emailCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList 'NT AUTHORITY\ANONYMOUS LOGON', $pass
}elseif($emailPassword){
$emailCred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $emailFrom,$emailPassword
[string]$emailFrom=$emailTo|select -First 1
}else{
$emailCred=$false
}
$detectedSmtpServer=if($emailFrom -match '@' -and !$anonymous){getMxRecord $emailFrom}else{$null}
$smtpServer=if($smtpServer){
if($smtpServer -eq $detectedSmtpServer){
Write-host "Detected SMTP server matches the provided value: $smtpServer"
}else{
write-warning "Detected SMTP server $detectedSmtpServer does not match given values. Program will use the provided value: $smtpServer"
}
$smtpServer
}else{
write-host "Using detected SMTP server $detectedSmtpServer"
$detectedSmtpServer
}
$secureSmtpParams = @{
From = $emailFrom
To = $emailTo
Subject = $subject
Body = $body
BodyAsHtml = $true
DeliveryNotificationOption = 'OnFailure','OnSuccess'
Port = $port
UseSSL = $useSsl
}
$relaySmtpParams=@{
From = $emailFrom
To = $emailTo
Subject = $subject
Body = $body
BodyAsHtml = $true
DeliveryNotificationOption = 'OnFailure', 'OnSuccess'
Port = 25
UseSSL = $useSsl
}
if ($port -ne 25){
write-host "Secure SMTP Parameters detected."
$emailParams=$secureSmtpParams
}else{
write-host "Unsecured SMTP Parameters detected."
$emailParams=$relaySmtpParams
}
write-host "$($emailParams|out-string)"
try{
# Pre-empt this error:
# Send-MailMessage : Unable to read data from the transport connection: net_io_connectionclosed.
$requiredTls='Tls12'
$availableSslProtocols=[enum]::getnames([net.securityprotocoltype])
if([Net.ServicePointManager]::SecurityProtocol -notin $requiredTls -and $requiredTls -in $availableSslProtocols){
[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::$requiredTls
}
$sendmailCommand="Send-MailMessage `@emailParams -SmtpServer $smtpServer $(if($cc){"-cc $cc"}) $(if($emailCred){"-Credential `$emailCred"}) $(if($attachments){"-Attachments `$attachments"}) -ErrorAction Stop"
write-host $sendmailCommand
Invoke-Expression $sendmailCommand
write-host "Email has been sent to $emailTo successfully"
return $true;
}
catch{
#$errorMessage = $_.Exception.Message
#$failedItem = $_.Exception.ItemName
#write-host "$errorMessage`r`n$failedItem" -ForegroundColor Yellow
Write-Warning "Initial attempt failed!`r`n$_`r`nNow scanning open ports..."
$openPorts=$commonSmtpPorts|?{Check-NetConnection $smtpServer $_}
write-host "$smtpServer has these SMTP ports opened: $(if($openPorts){$openPorts}else{'None'})"
if($detectedSmtpServer -ne $smtpServer){
try{
write-host "Program now attempts to use the detected SMTP Server: $detectedSmtpServer"
Invoke-Expression "Send-MailMessage `@emailParams -SmtpServer $detectedSmtpServer $(if($attachments){"-Attachments $attachments"}) -ErrorAction Stop"
write-host "Email has been sent to $emailTo successfully via alternative SMTP Server: $detectedSmtpServer" -ForegroundColor Green
return $true;
}catch{
write-host $error[0].Exception.Message -ForegroundColor Yellow
return $false
}
}else{
return $false
}
}
}
sendemail -emailFrom $emailFrom `
-emailPassword $emailPassword `
-emailTo $emailTo `
-cc $null `
-subject $subject `
-body $body `
-smtpServer $smtpServer `
-port $port `
-attachments $attachments `
-useSsl $useSsl `
-anonymous $anonymousMode
Version 0.02
# sendEmail.ps1
# Version 0.02
# This iteration includes the workaround for anonymous email relays
<#
# Examples:
# sendEmail [email protected] '' [email protected] -cc $null test testEmail -smtpServer 'relay.contoso.com' -port 25 -useSsl $false -anonymous $true
# sendEmail -emailFrom $EmailUser -emailPassword $emailPassword `
-emailTo '[email protected]' -cc $null `
-subject "Test Email to Validate SMTP" -body "This is a test email.<br><br>Please disregard" `
-smtpServer $smtpServer -port $port -attachments $attachments -useSsl $true
#>
$username="[email protected]"
$password="PASSWORD"
$emailFrom="[email protected]"
$emailTo="[email protected]"
$subject="Test Email to Validate SMTP"
$body="This is a test email.<br><br>Please disregard"
$smtpServer
$port=587
$attachments='c:\gpresult.html'
$useSsl=$true
<# Usage:
sendEmail -username $username `
-password $password `
-emailFrom $emailFrom `
-EmailTo $emailTo -CC $null `
-Subject $subject -Body $message `
-SMTPServer $smtpServer `
-Port $port `
-Attachments $null `
-usessl $useSsl
#>
function sendEmail{
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$userName,
[Parameter(Mandatory)][string]$password,
[Parameter(Mandatory)][string]$emailFrom,
[Parameter(Mandatory)][string[]]$emailTo,
[Parameter(Mandatory=$false)][string[]]$cc,
[Parameter(Mandatory=$false)]$subject="Test Email to Validate SMTP",
[Parameter(Mandatory=$false)]$body="This is a test email.<br><br>Please disregard",
[Parameter(Mandatory=$false)]$smtpServer=$null,
[Parameter(Mandatory=$false)]$port=587,
[Parameter(Mandatory=$false)]$attachments,
[Parameter(Mandatory=$false)]$useSsl=$true,
[Parameter(Mandatory=$false)]$anonymous=$false
)
$commonSmtpPorts=@(25,587,465,2525)
$useSsl=[System.Convert]::ToBoolean($useSsl)
function Check-NetConnection($server,$port,$timeout=100,$verbose=$false) {
$tcp = New-Object System.Net.Sockets.TcpClient;
try {
$connect=$tcp.BeginConnect($server,$port,$null,$null)
$wait = $connect.AsyncWaitHandle.WaitOne($timeout,$false)
if(!$wait){
$tcp.Close()
if($verbose){
Write-Host "Connection Timeout" -ForegroundColor Red
}
Return $false
}else{
$error.Clear()
$null=$tcp.EndConnect($connect) # Dispose of the connection to release memory
if(!$?){
if($verbose){
write-host $error[0].Exception.Message -ForegroundColor Red
}
$tcp.Close()
return $false
}
$tcp.Close()
Return $true
}
} catch {
return $false
}
}
function getMxRecord($emailAddress){
$regexDomain="\@(.*)$"
$domain=.{[void]($emailAddress -match $regexDomain);$matches[1]}
$mxDomain=(resolve-dnsname $domain -type mx|sort -Property Preference|select -First 1).NameExchange
$detectedSmtp=switch -Wildcard ($mxDomain){ # need to build up this list
"*outlook.com" {"smtp.office365.com";break}
"*google.com" {"smtp.gmail.com";break}
"*yahoodns.net" {'smtp.mail.yahoo.com';break}
"*inbox.com" {'my.inbox.com;break'}
"*mail.com" {'smtp.mail.com';break}
"*icloud.com" {'smtp.mail.me.com';break}
"*zoho.com" {'smtp.zoho.com';break}
default {$mxDomain}
}
if($mxDomain){
write-host "Detected MX Record`t: $mxDomain`r`nKnown SMTP Server`t: $detectedSmtp"
return $detectedSmtp
}
else{
write-warning "MX record not available for $emailAddress"
return $null
}
}
if($userName -and $password){
$encryptedPass=ConvertTo-SecureString -String $password -AsPlainText -Force
$emailCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $userName,$encryptedPass
}elseif($anonymous){
$nullPassword = ConvertTo-SecureString 'null' -asplaintext -force
$emailCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList 'NT AUTHORITY\ANONYMOUS LOGON', $pass
}elseif($emailPassword){
$emailCred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $emailFrom,$emailPassword
[string]$emailFrom=$emailTo|select -First 1
}else{
$emailCred=$null
}
$detectedSmtpServer=if($username -match '@' -and !$anonymous){getMxRecord $username}else{$null}
$smtpServer=if($smtpServer){
if($smtpServer -eq $detectedSmtpServer){
Write-host "Detected SMTP server matches the provided value: $smtpServer"
}else{
write-warning "Detected SMTP server $detectedSmtpServer does not match given values. Program will use the provided value: $smtpServer"
}
$smtpServer
}else{
write-host "Using detected SMTP server $detectedSmtpServer"
$detectedSmtpServer
}
$reconstructedUsername=if($emailFrom -match '@'){$emailFrom}elseif($userName -match '\\'){
$x=[regex]::match($userName,'(.*)\\(.*)').Captures.Groups;
$x[2].Value+'@'+$x[1].value+'.com'
}elseif($userName -match '@'){$userName}
$secureSmtpParams = @{
From = $reconstructedUsername
To = $emailTo
Subject = $subject
Body = $body
BodyAsHtml = $true
DeliveryNotificationOption = 'OnFailure','OnSuccess'
Port = $port
UseSSL = $useSsl
}
$relaySmtpParams=@{
From = $reconstructedUsername
To = $emailTo
Subject = $subject
Body = $body
BodyAsHtml = $true
DeliveryNotificationOption = 'OnFailure', 'OnSuccess'
Port = 25
UseSSL = $useSsl
}
if ($port -ne 25){
write-host "Secure SMTP Parameters detected."
$emailParams=$secureSmtpParams
}else{
write-host "Unsecured SMTP Parameters detected."
$emailParams=$relaySmtpParams
}
write-host "$($emailParams|out-string)"
try{
$sendmailCommand="Send-MailMessage `@emailParams -SmtpServer $smtpServer $(if($cc){"-cc $cc"}) $(if($emailCred){"-Credential `$emailCred"}) $(if($attachments){"-Attachments `$attachments"}) -ErrorAction Stop"
write-host $sendmailCommand
Invoke-Expression $sendmailCommand
write-host "Email has been sent to $emailTo successfully"
return $true;
}
catch{
#$errorMessage = $_.Exception.Message
#$failedItem = $_.Exception.ItemName
#write-host "$errorMessage`r`n$failedItem" -ForegroundColor Yellow
Write-Warning "Initial attempt failed!`r`n$_`r`nNow scanning open ports..."
$openPorts=$commonSmtpPorts|?{Check-NetConnection $smtpServer $_}
write-host "$smtpServer has these SMTP ports opened: $(if($openPorts){$openPorts}else{'None'})"
if($detectedSmtpServer -ne $smtpServer){
try{
write-host "Program now attempts to use the detected SMTP Server: $detectedSmtpServer"
Invoke-Expression "Send-MailMessage `@emailParams -SmtpServer $detectedSmtpServer $(if($attachments){"-Attachments $attachments"}) -ErrorAction Stop"
write-host "Email has been sent to $emailTo successfully via alternative SMTP Server: $detectedSmtpServer" -ForegroundColor Green
return $true;
}catch{
write-host $error[0].Exception.Message -ForegroundColor Yellow
return $false
}
}else{
return $false
}
}
}
Old Version
$emailFrom="[email protected]"
$emailPassword="PASSWORD"
$emailTo="[email protected]"
$subject="Test Email to Validate SMTP"
$body="This is a test email.<br><br>Please disregard"
$smtpServer
$port=587
$attachments='c:\gpresult.html'
$useSsl=$true
function sendEmail{
[CmdletBinding()]
param(
[Parameter(Mandatory)]$emailFrom,
[Parameter(Mandatory)]$emailPassword,
[Parameter(Mandatory)][string[]]$emailTo,
[Parameter(Mandatory=$false)][string[]]$cc,
[Parameter(Mandatory=$false)]$subject="Test Email to Validate SMTP",
[Parameter(Mandatory=$false)]$body="This is a test email.<br><br>Please disregard",
[Parameter(Mandatory=$false)]$smtpServer=$null,
[Parameter(Mandatory=$false)]$port=587,
[Parameter(Mandatory=$false)]$attachments,
[Parameter(Mandatory=$false)]$useSsl=$true
)
$commonSmtpPorts=@(25,587,465,2525)
function Check-NetConnection($server,$port,$timeout=100,$verbose=$false) {
$tcp = New-Object System.Net.Sockets.TcpClient;
try {
$connect=$tcp.BeginConnect($server,$port,$null,$null)
$wait = $connect.AsyncWaitHandle.WaitOne($timeout,$false)
if(!$wait){
$tcp.Close()
if($verbose){
Write-Host "Connection Timeout" -ForegroundColor Red
}
Return $false
}else{
$error.Clear()
$null=$tcp.EndConnect($connect) # Dispose of the connection to release memory
if(!$?){
if($verbose){
write-host $error[0].Exception.Message -ForegroundColor Red
}
$tcp.Close()
return $false
}
$tcp.Close()
Return $true
}
} catch {
return $false
}
}
function getMxRecord($emailAddress){
$regexDomain="\@(.*)$"
$domain=.{[void]($emailAddress -match $regexDomain);$matches[1]}
$mxDomain=(resolve-dnsname $domain -type mx|sort -Property Preference|select -First 1).NameExchange
$detectedSmtp=switch -Wildcard ($mxDomain){ # need to build up this list
"*outlook.com" {"smtp.office365.com";break}
"*google.com" {"smtp.gmail.com";break}
"*yahoodns.net" {'smtp.mail.yahoo.com';break}
"*inbox.com" {'my.inbox.com;break'}
"*mail.com" {'smtp.mail.com';break}
"*icloud.com" {'smtp.mail.me.com';break}
"*zoho.com" {'smtp.zoho.com';break}
default {$mxDomain}
}
if($mxDomain){
write-host "Detected MX Record`t: $mxDomain`r`nKnown SMTP Server`t: $detectedSmtp"
return $detectedSmtp
}
else{
write-warning "MX record not available for $emailAddress"
return $null
}
}
$encryptedPass=ConvertTo-SecureString -String $emailPassword -AsPlainText -Force
if($emailPassword){
$emailCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $emailFrom,$encryptedPass
}else{
$emailCred=$false
}
$detectedSmtpServer=getMxRecord $emailFrom
$smtpServer=if($smtpServer){
if($smtpServer -eq $detectedSmtpServer){
Write-host "Detected SMTP server matches the provided value: $smtpServer"
}else{
write-warning "Detected SMTP server $detectedSmtpServer does not match given values. Program will use the provided value: $smtpServer"
}
$smtpServer
}else{
write-host "Using detected SMTP server $detectedSmtpServer"
$detectedSmtpServer
}
$secureSmtpParams = @{
From = $emailFrom
To = $emailTo
Subject = $subject
Body = $body
BodyAsHtml = $true
DeliveryNotificationOption = 'OnFailure','OnSuccess'
Port = $port
UseSSL = $useSsl
}
$relaySmtpParams=@{
From = $emailFrom
To = $emailTo
Subject = $subject
Body = $body
BodyAsHtml = $true
DeliveryNotificationOption = 'OnFailure', 'OnSuccess'
Port = 25
UseSSL = $useSsl
}
if ($port -ne 25){
write-host "Secure SMTP Parameters detected."
$emailParams=$secureSmtpParams
}else{
write-host "Unsecured SMTP Parameters detected."
$emailParams=$relaySmtpParams
}
try{
Invoke-Expression "Send-MailMessage `@emailParams -SmtpServer $smtpServer $(if($cc){"-cc $cc"}) $(if($emailCred){"-Credential `$emailCred"}) $(if($attachments){"-Attachments `$attachments"}) -ErrorAction Stop"
write-host "Email has been sent to $emailTo successfully"
return $true;
}
catch{
$errorMessage = $_.Exception.Message
$failedItem = $_.Exception.ItemName
$openPorts=$commonSmtpPorts|?{Check-NetConnection $smtpServer $_}
write-host "$smtpServer has these SMTP ports opened: $($openPorts)"
write-host "$errorMessage`r`n$failedItem" -ForegroundColor Yellow
if($detectedSmtpServer -ne $smtpServer){
try{
write-host "Program now attempts to use the detected SMTP Server: $detectedSmtpServer"
Invoke-Expression "Send-MailMessage `@emailParams -SmtpServer $detectedSmtpServer $(if($attachments){"-Attachments $attachments"}) -ErrorAction Stop"
write-host "Email has been sent to $emailTo successfully via alternative SMTP Server: $detectedSmtpServer" -ForegroundColor Green
return $true;
}catch{
write-host $error[0].Exception.Message -ForegroundColor Yellow
return $false
}
}else{
return $false
}
}
}
sendTestEmail -emailFrom $EmailUser -emailPassword $emailPassword `
-emailTo '[email protected]' -cc $null `
-subject "Test Email to Validate SMTP" -body "This is a test email.<br><br>Please disregard" `
-smtpServer $smtpServer -port $port -attachments $attachments -useSsl $true
Deprecated version
# User input global parameters
$emailAccount="$env:serviceEmail"
$emailPassword='$env:serverEmailPassword'
$subject="Test Email"
$body="This is a test email.<br><br>Please disregard"
$port=587
# Autogenerated variables
$encryptedPass=ConvertTo-SecureString -String $emailPassword -AsPlainText -Force
$emailCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $emailAccount,$encryptedPass
function sendEmail{
[CmdletBinding()]
param(
$from,
[Parameter(Mandatory)]$to,
[Parameter(Mandatory=$false)]$cc,
$subject,
$body,
$credential = $emailCred,
$port='587'
)
# Resolve the smtp server dynamically
$regexDomain="\@(.*)$"
$domain=.{[void]($from -match $regexDomain);$matches[1]}
$mxDomain=.{$result=(resolve-dnsname $domain -type mx).NameExchange
if ($result.gettype() -eq [String]){return $result}else{return $result[0]}
}
$smtpServer= switch -Wildcard ($mxDomain){ # need to build up this list
"*outlook.com" {"smtp.office365.com"}
"*google.com" {"smtp.gmail.com"}
"*yahoodns.net" {'smtp.mail.yahoo.com'}
"*inbox.com" {'my.inbox.com'}
"*mail.com" {'smtp.mail.com'}
"*icloud.com" {'smtp.mail.me.com'}
"*zoho.com" {'smtp.zoho.com'}
default {"smtp.$domain"}
}
# Populate the cmdlet parameters
$emailParams = @{
From = $from
To = $to
Subject = $subject
Body = $body
BodyAsHtml = $true
DeliveryNotificationOption = 'OnFailure', 'OnSuccess'
SmtpServer = $smtpServer
Port = $port
UseSSL = $true
Credential = $emailCred
}
# Invoke the PowerShell sendmail cmdlet
try{
invoke-expression "Send-MailMessage `@emailParams $(if($cc){-Cc $cc}) -ErrorAction Stop"
write-host "Email has been sent to $to successfully"
return $true;
}
catch{
$errorMessage = $_.Exception.Message
$failedItem = $_.Exception.ItemName
write-host "Error: email has NOT been sent. Here are the errors:`r`n$errorMessage`r`n$failedItem"
return $false
}
<# Note: this error would occur with Google mail if Block Unsecured Apps has not been disabled: https://myaccount.google.com/intro/security?hl=en
Send-MailMessage : The SMTP server requires a secure connection or the client was not authenticated. The server
response was: 5.7.57 SMTP; Client was not authenticated to send anonymous mail during MAIL FROM
[BYAPR07CA0055.namprd07.prod.outlook.com]
At line:1 char:1
+ Send-MailMessage @mailParams
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpExcept
ion
+ FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage
#>
}
sendEmail -from $emailAccount -to "[email protected]" -subject $subject -body $body -credential $emailCred -port $port
Simple Mail Relay
# Send-Email-Via-Relay.ps1
# PowerShell 2.0 Compatible
function sendEmailViaRelay{
# Define log location
$hostname=$ENV:computername
$dateStamp = Get-Date -Format "yyyy-MM-dd-hhmmss"
$scriptName=$MyInvocation.MyCommand.Path
$scriptPath=Split-Path -Path $scriptName
$logPath="$scriptPath`\filecopy_logs\$hostname"
$logFile="$logPath`\$dateStamp.txt"
# Define sendmail variables
$from = "[email protected]"
$to = "[email protected]"
$cc = "[email protected]"
$subject = "$hostname is ready at time stamp: $dateStamp."
$body = "Please check the log at this location: $logFile"
$smtpServer = "relay.kimconnect.com"
# This is the Windows' version of sendmail command
Send-MailMessage -From $from -to $to -Cc $cc -Subject $subject -Body $body -SmtpServer $smtpServer -DeliveryNotificationOption OnSuccess
}
sendEmailViaRelay;
# Change these values to reflect your liking
$from = "[email protected]"
$to = "[email protected]"
$cc = "[email protected]"
$username="kim"
$attachment = "C:\users\$username\Desktop\project1.xlsx"
$subject = "Opening Our First Kung Fu Studio"
$body = "Blah blah... Enough talk. Let's fight!"
$smtpServer = "kimconnect.mail.protection.outlook.com"
$smtpPort = "587"
# This is the Windows' version of sendmail command
Send-MailMessage -From $from -to $to -Cc $cc -Subject $subject -Body $body -SmtpServer $smtpServer -port $smtpPort -UseSsl -Credential (Get-Credential) -Attachments $attachment –DeliveryNotificationOption OnSuccess
Troubleshooting notes:
Sample Error:
Send-MailMessage : Unable to read data from the transport connection: net_io_connectionclosed.
At line:1 char:5
+ Send-MailMessage @mailParam
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpExcept
ion
+ FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage
Office365 Considerations:
- Authentication: username and password must be valid and correct
- Mailbox: a licensed Office 365 mailbox is required
- Transport Layer Security (TLS): TLS 1.1 is required
- Port: Port 587 is standard. StartTLS port 465 is not allowed. Relaying port 25, if used, must be unblocked as outbound from source networks
- Microsoft requires that each smart-host configuration or send connector setting must use only the assigned host record (e.g. domain-com12345.mail.
protection.outlook.com). Verify this record at: https://admin.microsoft. com/AdminPortal/Home#/Domains - To avoid emails being marked as spam when sending from source servers, edit the SPF TXT record to match this value: v=spf1 ip4:[SOURCE_IPs_HERE] include:spf.protection.
outlook.com ~all - Third-party filtering service should be routing to the correct smart-host record as shown in (a). For instance, barracudanetworks should route to the correct smtp server as ‘domain-com12345.mail.
protection.outlook.com’. Here’s an example of allowance for ClickDimensions and Autotask at URL . com/ecp/Antispam/ EditConnectionFiltering -
In email relaying cases, connectors should be setup to specify the source(s). This can be done by authenticating to Office.com using a Global Admin account > Navigate to Exchange Admin Center (Admin > Exchange) > Mail flow > Connectors > Check the list of connectors set up for your organization. If there are no connectors listed from your organization’s email server to Office 365, create one by clicking on the ‘+’ sign > Set From = Public IP address of the Email Relaying Computer (or source subnet), Set To = Office 365 > Next > Next > Save