Unable to get PowerShell Script to send an email with attachment

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
robertarensonAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

frankhelkCommented:
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
Joe KlimisCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
robertarensonAuthor Commented:
Thank you so very much, that fixed my issue perfectly.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.