Solved

Unable to get PowerShell Script to send an email with attachment

Posted on 2014-10-29
3
572 Views
Last Modified: 2014-10-30
I have a script that gets the uptime of remote servers and saves it to a csv file. It is then suppose to send the csv file via email to the recipients but that part is not working, I get the below errors when running the script. If I REM out the email portion then the script runs fine.

Thanks again for the help

Error MSG:

At C:\scripts\Get-LastBootTime.ps1:85 char:15
+ [string]$SMTP ServerName
+               ~~~~~~~~~~~~~~~~~~~~~~
Unexpected token 'ServerName' in expression or statement.
At C:\scripts\Get-LastBootTime.ps1:85 char:14
+ [string]$SMTP ServerName
+              ~
Missing closing ')' in expression.
At C:\scripts\Get-LastBootTime.ps1:86 char:1
+ )
+ ~
Unexpected token ')' in expression or statement.
At C:\scripts\Get-LastBootTime.ps1:104 char:1
+ }
+ ~
Unexpected token '}' in expression or statement.
At C:\scripts\Get-LastBootTime.ps1:80 char:20
+ [string]$Subject = $(throw "Subject parameter required."),
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Assignment expression is not valid. The left hand side of an assignment operator needs to be something that can be
assigned to like a variable or a property.
At C:\scripts\Get-LastBootTime.ps1:81 char:17
+ [string]$Body = $(throw "Bodytext parameter required."),
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Assignment expression is not valid. The left hand side of an assignment operator needs to be something that can be
assigned to like a variable or a property.
At C:\scripts\Get-LastBootTime.ps1:82 char:24
+ [string]$Senderemail = $(throw "SenderEmail Parameter required."),
+                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Assignment expression is not valid. The left hand side of an assignment operator needs to be something that can be
assigned to like a variable or a property.
At C:\scripts\Get-LastBootTime.ps1:83 char:27
+ [string]$Recipientemail = $(throw "Recipient Parameter required."),
+                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Assignment expression is not valid. The left hand side of an assignment operator needs to be something that can be
assigned to like a variable or a property.
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken

Lines in Script that are throwing the Error:

Line 85: [string]$SMTP ServerName
Line 86: )
Line 104: }
Line 80: [string]$Subject = $(throw “Subject parameter required.”),
Line 81: [string]$Body = $(throw “Bodytext parameter required.”),
Line 82: [string]$Senderemail = $(throw “SenderEmail Parameter required.”),
Line 83: [string]$Recipientemail = $(throw “Recipient Parameter required.”),

Script:

#FUNCTIONS
function Get-LastBootTime {
    [CmdletBinding()]
    [OutputType([System.String])]
    param(
        [Parameter(ValueFromPipeline=$true)][System.String[]]$server = $env:COMPUTERNAME
    )
    begin {
        function Test-PortAlive {
                        [CmdletBinding()]
            [OutputType([System.boolean])]
            param(
                [Parameter(ValueFromPipeline=$true)][System.String[]]$server
            )
            $socket = new-object Net.Sockets.TcpClient
            $connect = $socket.BeginConnect($server, 135, $null, $null) #port set to 135 (RPC)
            $NoTimeOut = $connect.AsyncWaitHandle.WaitOne(500, $false) #timeout value set to 500 ms
            if ($NoTimeOut) {
                $socket.EndConnect($connect) | Out-Null
                return $true              
            }
            else {
                return $false
            }
        }
    }
    process {      
        $BootTime = $null
        $server = $($server).toUpper()
        $alive = Test-PortAlive -server $server
        if ($alive) {
            Write-Debug "connection to $server is open on port $port"          
            $OSInfo = Get-WmiObject win32_operatingsystem -ComputerName $server #get the info with WMI
            $BootTime = $OSInfo.ConvertToDateTime($OSInfo.LastBootUpTime) #convert to datetime
            $BootTime = '{0:yyyy-MM-dd HH:mm:ss}' -f $BootTime #parse time to sortable format
            if ($BootTime) {
                Write-Debug "$server was rebooted last time at:`t$BootTime"                
                $result = "" | select "Server","LastBootTime" #creating a custom object
                $result.Server = $server
                $result.LastBootTime = $BootTime
                $result #return the $result object
            }
            else {
                Write-Debug "couldn't get boot time from server $server"
            }
        }          
        else {
            Write-Debug "Error - connection to $server is not open on port $port"          
        }
    }  
}
Function Send-Email {
}
param (
[string]$Subject = $(throw “Subject parameter required.”),
[string]$Body = $(throw “Bodytext parameter required.”),
[string]$Senderemail = $(throw “SenderEmail Parameter required.”),
[string]$Recipientemail = $(throw “Recipient Parameter required.”),
[string]$Attachment = $null,
[string]$SMTP ServerName
)
$MailMessage = New-Object System.Net.Mail.MailMessage
$SMTPClient = New-Object System.Net.Mail.smtpClient
$SMTPClient.host = $SMTP
$Recipient = New-Object System.Net.Mail.MailAddress($Recipientemail, “Recipient”)
$Sender = New-Object System.Net.Mail.MailAddress($Senderemail, “Sender”)

$MailMessage.Sender = $Sender
$MailMessage.From = $Sender
$MailMessage.Subject = $Subject
$MailMessage.To.add($Recipient)
$MailMessage.Body = $Body
Write-Debug “Attachment is $Attachment”
if ($Attachment) {
Write-Debug “Entered attachment block”
$MailMessage.attachments.add($Attachment)
}
$SMTPClient.Send($MailMessage)
}

#VARIABLES
#$DebugPreference = "continue" #uncomment to get debug info
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath #path to the directory in which the script is run.
$servers = "$dir\TestServers.txt" #last boot time will be retrieved on all the servers given in this file.
$CSVPath = "$dir\LastBootTimes.csv" #results will be exported to csv to a file with this path

#Add this to the #VARIABLES section (and modify according to your needs)
$Subject = “Server Uptime Report”
$Body = “Server Uptime Report”
$Senderemail = “ServerUpTime@test.com”
$Recipientemail = "test@test.com”
$SMTP = “STMP ServerName”

#SCRIPT MAIN
clear
$BootTimes = @(gc $servers | Get-LastBootTime) #create and populate array with the last boot times of the given servers.
$BootTimes = $BootTimes | Sort-Object -Property "LastBootTime" #Sort array by last boot time
$BootTimes #Prints the $bootTimes array to the console
$BootTimes | Export-Csv $CSVPath -NoTypeInformation -Force #Export the results to CSV

#Add this to the end of the #SCRIPT MAIN section
Send-Email -subject $subject -body $Body -senderemail $senderemail -recipientemail $recipientemail -SMTP $SMTP -attachment $CSVPath
0
Comment
Question by:robertarenson
3 Comments
 
LVL 13

Expert Comment

by:frankhelk
ID: 40410864
My solution may be a bit off topic, but ... I use the good old command line tool BLAT for many years not to accomplish such tasks. It would make little difference if you use Poweshell's internals or a transient command for such a task ...

BLAT is full of options to compose mails and works very well. See here for details and d/l. Available in both x86 and x64 flavour.
0
 
LVL 10

Accepted Solution

by:
JoeKlimis earned 500 total points
ID: 40410922
I have found the bugs in your code see below



#FUNCTIONS
function Get-LastBootTime {
    [CmdletBinding()]
    [OutputType([System.String])]
    param(
        [Parameter(ValueFromPipeline=$true)][System.String[]]$server = $env:COMPUTERNAME
    )
    begin {
        function Test-PortAlive {
                        [CmdletBinding()]
            [OutputType([System.boolean])]
            param(
                [Parameter(ValueFromPipeline=$true)][System.String[]]$server
            )
            $socket = new-object Net.Sockets.TcpClient
            $connect = $socket.BeginConnect($server, 135, $null, $null) #port set to 135 (RPC)
            $NoTimeOut = $connect.AsyncWaitHandle.WaitOne(500, $false) #timeout value set to 500 ms
            if ($NoTimeOut) {
                $socket.EndConnect($connect) | Out-Null
                return $true               
            }
            else {
                return $false
            }
        }
    }
    process {      
        $BootTime = $null
        $server = $($server).toUpper() 
        $alive = Test-PortAlive -server $server
        if ($alive) {
            Write-Debug "connection to $server is open on port $port"          
            $OSInfo = Get-WmiObject win32_operatingsystem -ComputerName $server #get the info with WMI
            $BootTime = $OSInfo.ConvertToDateTime($OSInfo.LastBootUpTime) #convert to datetime
            $BootTime = '{0:yyyy-MM-dd HH:mm:ss}' -f $BootTime #parse time to sortable format
            if ($BootTime) {
                Write-Debug "$server was rebooted last time at:`t$BootTime"                
                $result = "" | select "Server","LastBootTime" #creating a custom object
                $result.Server = $server
                $result.LastBootTime = $BootTime
                $result #return the $result object
            }
            else {
                Write-Debug "couldn't get boot time from server $server"
            }
        }          
        else {
            Write-Debug "Error - connection to $server is not open on port $port"          
        }
    }  
}
Function Send-Email {
param(
[string]$Subject= $(throw "Subject parameter required."),
[string]$Body=$(throw "Bodytext parameter required."),
[string]$Senderemail=$(throw "SenderEmail Parameter required."),
[string]$Recipientemail=$(throw "Recipient Parameter required."),
[string]$Attachment=$null,
[string]$SMTP =$(throw "specify a mail server")
)
$MailMessage = New-Object System.Net.Mail.MailMessage
$SMTPClient = New-Object System.Net.Mail.smtpClient
$SMTPClient.host = $SMTP
$Recipient = New-Object System.Net.Mail.MailAddress($Recipientemail, "Recipient")
$Sender = New-Object System.Net.Mail.MailAddress($Senderemail, "Sender")

$MailMessage.Sender = $Sender
$MailMessage.From = $Sender
$MailMessage.Subject = $Subject
$MailMessage.To.add($Recipient)
$MailMessage.Body = $Body
Write-Debug "Attachment is $Attachment"
if ($Attachment) 
{
Write-Debug "Entered attachment block"
$MailMessage.attachments.add($Attachment)
}
$SMTPClient.Send($MailMessage)
}


#VARIABLES
#$DebugPreference = "continue" #uncomment to get debug info
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath #path to the directory in which the script is run.
$servers = "$dir\TestServers.txt" #last boot time will be retrieved on all the servers given in this file.
$CSVPath = "$dir\LastBootTimes.csv" #results will be exported to csv to a file with this path

#Add this to the #VARIABLES section (and modify according to your needs)
$Subject = "Server Uptime Report"
$Body = "Server Uptime Report"
$Senderemail = "ServerUpTime@test.com"
$Recipientemail = "test@test.test"
$SMTP = "STMP ServerName"

#SCRIPT MAIN
clear
$BootTimes = @(gc $servers | Get-LastBootTime) #create and populate array with the last boot times of the given servers.
$BootTimes = $BootTimes | Sort-Object -Property "LastBootTime" #Sort array by last boot time
$BootTimes #Prints the $bootTimes array to the console
$BootTimes | Export-Csv $CSVPath -NoTypeInformation -Force #Export the results to CSV

#Add this to the end of the #SCRIPT MAIN section
Send-Email -subject $subject -body $Body -senderemail $senderemail -recipientemail $recipientemail -SMTP $SMTP -attachment $CSVPath

Open in new window

0
 

Author Closing Comment

by:robertarenson
ID: 40414258
Thank you so very much, that fixed my issue perfectly.
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Utilizing an array to gracefully append to a list of EmailAddresses
This article will help you understand what HashTables are and how to use them in PowerShell.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now