Solved

Unable to get PowerShell Script to send an email with attachment

Posted on 2014-10-29
3
615 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 14

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

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Utilizing an array to gracefully append to a list of EmailAddresses
This script can help you clean up your user profile database by comparing profiles to Active Directory users in a particular OU, and removing the profiles that don't match.
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.

808 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