Solved

Unable to get PowerShell Script to send an email with attachment

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

Is Your AD Toolbox Looking More Like a Toybox?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

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
The article will show you how you can maintain a simple logfile of all Startup and Shutdown events on Windows servers and desktops with PowerShell. The script can be easily adapted into doing more like gracefully silencing/updating your monitoring s…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

770 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