Send-SHDMailMessage

Send-SHDMailMessage

Recently the send-mailmessage was put to rest with good reason. It failed to do its job by securing the emails. It sent items via plain text and not SSL encrypted. Great for internal nothing fancy, but bad if you wanted to send data outside the world. So, I built an alternative that I use the mail message system inside windows. Let’s Send Mail With Powershell.

The Script

function Send-SHDMailMessage {
    <#
    .SYNOPSIS
        Sends an email using custom SMTP settings.
    .DESCRIPTION
        Sends an email using custom SMTP settings.
    .PARAMETER From
        As string. Name of the Email address from which it will come from. 
        Example: "David Bolding <admin@example.com>"
    .PARAMETER To
        As string. The email address too. 
        Example: "Admin@example.com"
    .PARAMETER SMTPUsername
        As string. The Username for the SMTP service you will be using. 
    .PARAMETER SMTPPassword
        As string. The Password in plain text for the smtp service you will be using. 
    .PARAMETER SMTPServer
        As string. The server name of the SMTP service you will be using. 
    .PARAMETER SMTPPort
        As string. The Server Port for the smtp serivce you will be using. 
    .PARAMETER Subject
        As string. The subject line of the email. 
    .PARAMETER Body
        As string. The body of the email as a string. Body takes default over BodyAsHtml
    .PARAMETER BodyAsHTML
        As string. The body of the email in html format. 
    .PARAMETER PlainText
        Sends the email in plain text and not ssl. 
    .PARAMETER Attachment
        As array of strings. A list of full file names for attachments. Example: "c:\temp\log.log"
    .PARAMETER CC
        Email address for a carbon copy to this email.
    .PARAMETER BCC
        Email address for a blind carbon copy of this email. 
    .PARAMETER Priority
        A validate set for High, Normal, Low. By default it will send emails out with Normal.
    .EXAMPLE
        $Message = @{
            from = "HR <HumanResources@Example.com>"
            To = "Somebody@Example.com"
            SMTPUsername = "SMTP2GoUsername"
            SMTPPassword = "SMTP2GoPassword"
            SMTPServer = "mail.smtp2go.com"
            SMTPPort = "2525"
            Subject = "Test"
            Attachment = "C:\temp\JobOffer1.pdf","C:\temp\JobOffer2.pdf"
            BodyAsHtml = @"
            <html>
            <body>
                <center><h1>Congradulation</h1></center>
                <hr>
                <p>Attached is the job offers we discussed on the phone.</p>
                <br>
                Thank you,<br><br>
                Human Resources
            </body>
            </html>
        "@
        }
        Send-SHDMail @Message
        
        Sends an email using the required information with two attachments. 
    .EXAMPLE
        $Message = @{
            from = "HR <HumanResources@Example.com>"
            To = "Somebody@Example.com"
            SMTPUsername = "SMTP2GoUsername"
            SMTPPassword = "SMTP2GoPassword"
            SMTPServer = "mail.smtp2go.com"
            SMTPPort = "2525"
            Subject = "Test"
            BodyAsHtml = @"
            <html>
            <body>
                <center><h1>Sorry, Not Sorry</h1></center>
                <hr>
                <p>Sorry you didn't get the job. Maybe next time show up with clothing on.</p>
                <br>
                Thank you,<br><br>
                Human Resources
            </body>
            </html>
        "@
        }
        Send-SHDMail @Message

        This will send out an email without any attachments. 
    .EXAMPLE
        $Message = @{
            from = "HR <HumanResources@Example.com>"
            To = "Somebody@Example.com"
            SMTPUsername = "SMTP2GoUsername"
            SMTPPassword = "SMTP2GoPassword"
            SMTPServer = "mail.smtp2go.com"
            SMTPPort = "2525"
            Subject = "Test"
            Body = "Your Hired"
        }
        Send-SHDMail @Message

        Sends out a message using just a simple text in the body. 
    .EXAMPLE
        $Message = @{
            from = "HR <HumanResources@Example.com>"
            To = "Somebody@Example.com"
            SMTPUsername = "SMTP2GoUsername"
            SMTPPassword = "SMTP2GoPassword"
            SMTPServer = "mail.smtp2go.com"
            SMTPPort = "2525"
            Subject = "Test"
            Attachment = "C:\temp\JobOffer1.pdf","C:\temp\JobOffer2.pdf"
        }
        Send-SHDMail @Message

        This will send out an email that is blank with attached items. 
    .EXAMPLE
        $Message = @{
            from = "Notify <Notify@Example.com>"
            To = "Somebody@Example.com"
            SMTPUsername = "SMTP2GoUsername"
            SMTPPassword = "SMTP2GoPassword"
            SMTPServer = "mail.smtp2go.com"
            SMTPPort = "2525"
            Subject = "$SomethingWrong"
            PlainText = $true
        }
        Send-SHDMail @Message

        This will send out an unsecured email in plain text. 
    .EXAMPLE
        $Message = @{
            from = "Notifiy <Notify@example.com>"
            To = "IT@example.com"
            SMTPUsername = "SMTPUser"
            SMTPPassword = "SMTPPassword"
            SMTPServer = "mail.example.com"
            SMTPPort = "2525"
            Subject = "Server Down"
            CC = "ITManagers@Example.com"
            BCC = "CFO@Example.com"
            PlainText = $True
            Priority = "High" 
            BodyAsHTML = @"
            <html>
                <body>
                    <center><h1>SERVER DOWN!</h1></center>
                </body>
            </html>
        "@
        }
        Send-SHDMailMessage @Message
    .OUTPUTS
        no Output. 
    .NOTES
        Author: David Bolding
        Date: 09/8/2021
    .LINK
    #>
    [cmdletbinding()]
    param (
        [parameter(Mandatory = $true)][String]$From,
        [parameter(Mandatory = $true)][String]$To,
        [parameter(Mandatory = $true)][String]$SMTPUsername,
        [parameter(Mandatory = $true)][String]$SMTPPassword,
        [parameter(Mandatory = $true)][String]$SMTPServer,
        [parameter(Mandatory = $true)][String]$SMTPPort,
        [parameter(Mandatory = $true)][String]$Subject,
        [Switch]$PlainText,
        [string]$Body,
        [String]$BodyAsHTML,
        [String[]]$Attachment,
        [string]$CC,
        [string]$BCC,
        [Validateset("High","Low","Normal")][String]$Priority
    )
    # Server Info
    $SmtpServer = $SmtpServer
    $SmtpPort = $SmtpPort

    # Creates the message object
    $Message = New-Object System.Net.Mail.MailMessage $From, $To

    If ($PSBoundParameters.ContainsKey("CC")) {
        $Message.CC.Add($CC)
    }
    If ($PSBoundParameters.ContainsKey("BCC")) {
        $Message.Bcc.Add($BCC)
    }
    If ($PSBoundParameters.ContainsKey("Priority")) {
        $Message.Priority = $Priority
    } else {
        $Message.Priority = "Normal"
    }
    # Builds the message parts
    
    $Message.Subject = $Subject
    
    if ($PSBoundParameters.ContainsKey("Body")) {
        $Message.IsBodyHTML = $false
        $Message.Body = $Body
    }
    elseif ($PSBoundParameters.ContainsKey("BodyAsHTML")) {
        $Message.IsBodyHTML = $true
        $Message.Body = $BodyAsHTML
    }
    else {
        $Message.IsBodyHTML = $false
        $Message.Body = ""
    }
    
    if ($PSBoundParameters.ContainsKey('Attachment')) {
        foreach ($attach in $Attachment) {
            $message.Attachments.Add("$Attach")
        }
    }
    
    # Construct the SMTP client object, credentials, and send
    $Smtp = New-Object Net.Mail.SmtpClient($SmtpServer, $SmtpPort)
    if ($PlainText) { 
        $Smtp.EnableSsl = $true 
    }
    else { 
        $Smtp.EnableSsl = $true 
    }
    $Smtp.Credentials = New-Object System.Net.NetworkCredential($SMTPUsername, $SMTPPassword)
    $Smtp.Send($Message)

    #Closes the message object and the smtp object. 
    $message.Dispose()
    $Smtp.Dispose()
}    
    

Examples

        $Message = @{
            from = "HR <HumanResources@Example.com>"
            To = "Somebody@Example.com"
            SMTPUsername = "SMTP2GoUsername"
            SMTPPassword = "SMTP2GoPassword"
            SMTPServer = "mail.smtp2go.com"
            SMTPPort = "2525"
            Subject = "Job Offers"
            Attachment = "C:\temp\JobOffer1.pdf","C:\temp\JobOffer2.pdf"
            BodyAsHtml = @"
            <html>
            <body>
                <center><h1>Congradulation</h1></center>
                <hr>
                <p>Attached is the job offers we discussed on the phone.</p>
                <br>
                Thank you,<br><br>
                Human Resources
            </body>
            </html>
        "@
        }
        Send-SHDMail @Message

In this example, I am using the SMTP2go service to send a job offer letter to a new employee. It contains the attachment flag with two offers. Each attachment is separated with a comma as this is a list of strings. The Body is an HTML using the BodyAsHTML flag. The BodyAsHTML has some custom formatting to make it look somewhat nice.

$Message = @{
    from = "HR <HumanResources@Example.com>"
    To = "Somebody@Example.com"
    SMTPUsername = "SMTP2GoUsername"
    SMTPPassword = "SMTP2GoPassword"
    SMTPServer = "mail.smtp2go.com"
    SMTPPort = "2525"
    Subject = "Thank you"
    BodyAsHtml = @"
            <html>
            <body>
                <center><h1>Sorry, Not Sorry</h1></center>
                <hr>
                <p>Sorry you didn't get the job. Maybe next time show up with clothing on.</p>
                <br>
                Thank you,<br><br>
                Human Resources
            </body>
            </html>
        "@
}
Send-SHDMail @Message

In this example, we are once again using the SMTP2Go to send a rejection letter. No attachments are present on this email. The bodyashtml string is set with a nice custom HTML page.

$Message = @{
    from = "Notify <Notify@Example.com>"
    To = "Somebody@Example.com"
    SMTPUsername = "SMTP2GoUsername"
    SMTPPassword = "SMTP2GoPassword"
    SMTPServer = "mail.smtp2go.com"
    SMTPPort = "2525"
    Subject = "Server Down"
    Body = "XYZ Server Is Down"
}
Send-SHDMail @Message

In this example, we are sending out a notification email using a different user than before. We are using the same smtp2go, but you can use any server with the username and password you like. The body is a basic string with no HTML formating.

$Message = @{
    from = "Notify <Notify@Example.com>"
    To = "Somebody@Example.com"
    SMTPUsername = "SMTP2GoUsername"
    SMTPPassword = "SMTP2GoPassword"
    SMTPServer = "mail.smtp2go.com"
    SMTPPort = "2525"
    Subject = "$SomethingWrong"
    PlainText = $true
}
Send-SHDMail @Message

In this example, we are sending a notification email without a body. We are using a custom variable for the subject line. We are also sending this without the SSL encryption as some legacy systems don’t understand SSL encryption.

$Message = @{
    from = "Notifiy <Notify@example.com>"
    To = "IT@example.com"
    SMTPUsername = "SMTPUser"
    SMTPPassword = "SMTPPassword"
    SMTPServer = "mail.example.com"
    SMTPPort = "2525"
    Subject = "Server Down"
    CC = "ITManagers@Example.com"
    BCC = "CFO@Example.com"
    Priority = "High" 
    BodyAsHTML = @"
            <html>
                <body>
                    <center><h1>SERVER DOWN!</h1></center>
                </body>
            </html>
        "@
}
Send-SHDMailMessage @Message

In this example, we are Sending a Carbon copy to the IT manager and a blind carbon copy of the email to the CFO with a high priority.

Notes

  • The Body and BodyAsHTML can conflict with each other. If you do both the Body and BodyAsHTML, by default, the body will be selected. If you do not put in a body or bodyashtml, it will send the email with a body of “”.
  • This script requires you to have an SMTP service like SMTP2Go.

Conclusion

That my friends is how you Send Mail With Powershell.

Invoke File Service Integrity Check

Invoke File Service Integrity Check

This little script will allow you to check a folder location, if that folder location has x number of files, it will restart the service of your choice on a target computer. Then it will log that information and finally it will email someone this information.

function Invoke-FileServiceIntegrityCheck {
    <#
    .SYNOPSIS
        Checks a file path for number of files. If greater, restarts a service and emails a message and logs a log.
    .DESCRIPTION
        Checks a file path for a set number of files that are predefined by the end user. If the file count is greater, it will restart a service. It will log the results and email a person stated by the end user.
    .PARAMETER SearchPath
        Target Path to scan for file count.
    .PARAMETER FileCount
        File count that will be used to determine the request size.
    .PARAMETER ComputerName
        Target Computer Name that the service lives on.
    .PARAMETER ServiceName
        Name of the service to restart.
    .PARAMETER SendReportTo
        The email address to which the email report will be sent to.
    .PARAMETER EmailDomain
        The domain name. For example, example.local
    .PARAMETER MailServer
        The mail server to send the email from.
    .PARAMETER Recurse
        Recurses the file search path.
    .PARAMETER Credential
        The Credentials, if needed for the email server.
    .EXAMPLE
        Invoke-FileServiceIntegrityCheck -SearchPath \\server1\share -FileCount 25 -ComputerName server2 -ServiceName intergrator -SendReportTo bob@example.com -EmailDomain example.com -Mailserver mail.example.com -Credential (Get-Credential)

        Checks the folder \\server1\share to see if there is 25 or more files. If it does, it will restart the service named intergrator on server 2.
        Then it will send an bob@example.com from watcheye@example.com using mail.example.com and the credentials provided.
    .EXAMPLE
        Invoke-FileServiceIntegrityCheck -SearchPath \\server1\share -FileCount 25 -ComputerName server2 -ServiceName intergrator -SendReportTo bob@example.com -EmailDomain example.com -Mailserver mail.example.com

        Checks the folder \\server1\share to see if there is 25 or more files. If it does, it will restart the service named intergrator on server 2.
        Then it will send an bob@example.com from watcheye@example.com using mail.example.com. Email will be sent from the server. If no relay is setup, the server will reject the email.
    .INPUTS
        [none]
    .OUTPUTS
        email and log
    .NOTES
        Author: David Bolding
        Date: 10/14/2020

    .LINK
        https://github.com/rndadhdman/PS_Super_Helpdesk
    #>
    [cmdletbinding()]
    param (
        [parameter(HelpMessage = "Folder Search Path", Mandatory = $True)][string]$SearchPath,
        [parameter(HelpMessage = "File Count", Mandatory = $True)][int]$FileCount,
        [parameter(HelpMessage = "Computer That the server Lives", Mandatory = $True)][String]$ComputerName,
        [parameter(HelpMessage = "Service Name", Mandatory = $True)][String]$ServiceName,
        [parameter(HelpMessage = "Service Name", Mandatory = $True)][String]$SendReportTo,
        [parameter(HelpMessage = "Service Name", Mandatory = $True)][String]$EmailDomain,
        [parameter(HelpMessage = "Service Name", Mandatory = $True)][String]$Mailserver,
        [parameter(HelpMessage = "Recurse the Search")][switch]$Recurse
        [Parameter(HelpMessage = "Allows for custom Credential.")][System.Management.Automation.PSCredential]$Credential
    )

    #Checks Files
    if ($Recurse) { $Files = Get-ChildItem "$SearchPath" -Recurse } else { $Files = Get-ChildItem "$SearchPath" }


    if ($Files.Count -ge $FileCount) {

        $StopTime = Get-date
        Get-Service -ComputerName mtxs-lifetecapp -Name "Interlink" | Stop-Service

        sleep 30

        Get-Service -ComputerName mtxs-lifetecapp -Name "Interlink" | Start-Service
        $StartTime = Get-date

        sleep 30

        if ($Recurse) { $Files2 = Get-ChildItem "$SearchPath" -Recurse } else { $Files2 = Get-ChildItem "$SearchPath" }

        if (!(Test-Path c:\logs)) {mkdir c:\logs}

        #Gathers Log Info
        $Log = [pscustomobject]@{
            ComputerName = $ComputerName
            ServiceName = $ServiceName
            SearchPath = $SearchPath
            StopFileCount = $Files.count
            ServiceStopTime = $StopTime.ToString()
            ServiceStartTime = $StartTime.tostring()
            StartFileCount = $Files2.count
            CallingComputer = $env:COMPUTERNAME
        }

        $Log | Export-csv c:\temp\Invoke_FileServiceIntegrityCheck_log.csv -Append

        #Builds EMail
        $ErrorHtmlbody = @"
<html>
<head>
<style>
body {
    Color: #252525;
    font-family: Verdana,Arial;
    font-size:11pt;
}
h1 {
    text-align: center;
    color:#C8102E;
    Font-size: 34pt;
    font-family: Verdana, Arial;
}
</style>
</head>
<body>
<h1>$ServiceName Restarted</h1>
<hr>
<br>
Dear Watcher,<br>
<br>
During my last check there were <b>$($Files.Count)</b> files inside <i>$SearchPath</i>. The Integrator was stopped on <b>$($StopTime.tostring())</b> and started on <b>$($StartTime.tostring())</b>. There are now <b>$($files2.count)</b> in <i>$SearchPath</i>. Please investigate on why the $ServiceName failed on $ComputerName.<br>
<br>
<br>
Thank you,<br>
<i>$ServiceName WatchEye</i><br>
<br>
<hr>
</body>
</html>
"@
        if ($PSBoundParameters.ContainsKey('Credential')) {
            Send-MailMessage -To $SendReportTo -From "Service Watch Eye <WatchEye@$EmailDomain>" -Subject "$ServiceName Failure" -BodyAsHtml $ErrorHtmlbody -SmtpServer $Mailserver -Credential $Credential
        } else {
            Send-MailMessage -To $SendReportTo -From "Service Watch Eye <WatchEye@$EmailDomain>" -Subject "$ServiceName Failure" -BodyAsHtml $ErrorHtmlbody -SmtpServer $Mailserver
        }
    }

}

Example

Invoke-FileServiceIntegrityCheck -SearchPath \\server1\share -FileCount 25 -ComputerName server2 -ServiceName integrator -SendReportTo bob@example.com -EmailDomain example.com -Mailserver mail.example.com

In this example, we will search for the share on server1 if it has more than 25 files. If it does, then we will restart the integrator on server2. Finally, we will email bob@example.com with an email from watcher@example.com using the mail server mail.example.com.