Search code examples
emailpowershellsend

Powershell mail message script


I'm having a problem with a script.

Every night, the server task scheduler runs a batch that creates a log on which PCs it couldn't update. This PS script then pulls the error log and sends an email notifying us of the PCs. The error log file is a .txt file and the name of the file changes everyday to reflect the date, for example, 10172016.txt.

I can get the script to email and it used to pull the log file and place it into its body; but now, it's blank and shows an error regarding "+".

Code:

clear

$smtpserver = "test.test.org"

$from="noreply@test.org"

$to="adamh@test.org"

$subject="Update Error Log for" + " " + (get-date -format d)

$message = (Get-Content -path "\\testserver\Departments\IT\Private\test\logs" + "(get-date -f mmddyyyy)" + ".txt" | Out-String )

$mailer = new-object Net.Mail.SMTPclient($smtpserver)

$msg = new-object Net.Mail.MailMessage($from,$to,$subject,$body)

$msg.IsBodyHTML = $false

$mailer.send($msg)

Please help.


Solution

  • There is (at least) a problem with your code, namely (command simplified):

    Get-Content -path "\path\to\" + "(get-date -f MMddyyyy)" + ".txt"
    

    It needs to be (note the enclosing parentheses and the absence of double quotes around the get-date command):

    Get-Content -path ("\path\to\" + (get-date -f MMddyyyy) + ".txt")
    

    PowerShell has two fundamental parsing modes - argument mode and expression mode, and understanding which is applied when is important: see Get-Help about_Parsing.

    In short: Without (...), PowerShell sees "\path\to\" + (get-date -f MMddyyyy) + ".txt" as 5 separate arguments rather than a single, synthesized string.


    Alternatively, you could use a single double-quoted string with string interpolation that uses the subexpression operator, $(...), to embed the get-date call:

    Get-Content -path "\path\to\$(get-date -f MMddyyyy).txt"
    

    Additional observations:

    • A native Send-MailMessage is available since PowerShell version 3.

    • The format string for 2-digit months is MM, not mm (the latter is minutes).

    • While using pseudo method syntax new-object Net.Mail.MailMessage($from,$to,$subject,$body) happens to work, it's better to avoid it, because it can mask a misconception of how New-Object works: The proper form is New-Object Net.Mail.MailMessage -ArgumentList $from,$to,$subject,$body; as you can see, because you're dealing with a cmdlet, it uses argument mode.