?
Solved

Unable to get PowerShell Script to send an email with attachment

Posted on 2014-10-29
3
Medium Priority
?
668 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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 11

Accepted Solution

by:
Joe Klimis earned 2000 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

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

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

There are times when we need to generate a report on the inbox rules, where users have set up forwarding externally in their mailbox. In this article, I will be sharing a script I wrote to generate the report in CSV format.
In the absence of a fully-fledged GPO Management product like AGPM, the script in this article will provide you with a simple way to watch the domain (or a select OU) for GPOs changes and automatically take backups when policies are added, removed o…
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …

752 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