robocopy unable to find specified path - email

#Variables
$logfile = "\\hermamora\Public\Plex Backup\Logs\Plex_Backup_Log_$(get-date -format "yyyyMMdd").txt"
function log($string, $color)
{
if ($Color -eq $null) {$color = "white"}
Write-Host $string -ForegroundColor $color
$string | Out-File -Filepath $logfile -Append
}
function Main {
robocopy Q:\ L:\ /v /mir /z /r:1 /w:5
}
$main = Main
#Arguments for Email
$From = "FROMADDRESS"
$To = "TOADDRESS"
#$Attachment = $logfile
$Subject = "Plex Backup Success"
$Body = "Here is the log of the Plex DB Backup, It was able to complete successfully"
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
$login = "USERNAME"
$password = "PASSWORD" | ConvertTo-SecureString -AsPlainText -Force
$credentials = New-Object System.Management.Automation.Pscredential -Argumentlist $login,$password
#Main Script
#Sets up Drives for Easy copy
subst L: "\\hermamora\Public\Plex Backup\Backup"
subst Q: "C:\Users\ztownes\AppData\Local\Plex Media Server"
#Stops Plex and Copies DB
taskkill /IM "Plex Media Server.exe"
Start-Sleep -Seconds 15
log $main
Start-Sleep -Seconds 15
Start-process "C:\Program Files (x86)\Plex\Plex Media Server\Plex Media Server.exe"
#Removes Drives for unclutering
subst /d L:
subst /d Q:
Start-Sleep -Seconds 5
#Sends Email
Send-MailMessage -From $From -To $To -Cc $Cc -Subject $Subject -Body $Body -SmtpServer $SMTPServer -Port $SMTPPort -UseSsl -Credential $credentials -Attachments $logfile
Start-Sleep -Seconds 5
Whenever I try to run this code it is unable to find the drives L: and Q: for robocopy. I am able to see the drives in Windows Explorer. I have an almost identical script for PowerShell that runs this with no problem. For obvious security reasons I have removed the email addresses and passwords from the email arguments.

Related

PowerShell Email Attachment: Could not find file 'D:\20201124131044\TRACS-20201124034849\error.log environment.log RACS-20201124034849.sterr.stdout

I am trying to send out an email with only the attachments that exist in the directory. There are three sets of files i am monitoring: error.log, environment.log and a .stdout. I want to check whether each one of the files exist and if they do then add it in a list and send it out as attachments. I dont want to do anything if the files dont exist. I attempted to loop through the list of files (this is in windows) and then if the files exist send them out. My code below:
$PSEmailServer = "xxxxxxxxxxx"
$Password ="xxxxxxxxx"
$mypassword = ConvertTo-SecureString $Password -AsPlainText -Force
$mycredential = New-Object System.Management.Automation.PSCredential ("xxxxx", $mypassword)
$EmailSubject ="test"
$filepath ="D:\20201124131044\TRACS-20201124034849\"
$files = #('error.log','environment.log','TRACS-20201124034849.sterr.stdout')
$FromEmail ="xxxxxxxxxx"
if(($files | foreach{Test-path $filepath }) -contains $True){
$newfile = $filepath + $files
Send-MailMessage -From $FromEmail -To "xxxxxxx" -Subject $EmailSubject -Body "test" -Credential $mycredential -Attachments $newfile
}
else {
echo "nothing"
exit
}
when i run the above i get the following error:
Send-MailMessage : Could not find file 'D:\20201124131044\TRACS-20201124034849\error.log environment.log TRACS-20201124034849.sterr.stdout'. At C:\Users\Downloads\powershell.ps1:22 char:1
+ Send-MailMessage -From $FromEmail -To "xxxxxxx" -Subje ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Send-MailMessage], FileNotFoundException
+ FullyQualifiedErrorId : > System.IO.FileNotFoundException,Microsoft.PowerShell.Commands.SendMailMessage
I think I need to iterate the list to attach each filename to the it's filepath and then store it in a list and then send out the email? Please advise.
You can simply use -contains or -in to find filenames in an array.
Also, I would recommend using splatting for the parameters to Send-MailMessage:
$filepath = "D:\20201124131044\TRACS-20201124034849"
$files = 'error.log','environment.log','TRACS-20201124034849.sterr.stdout'
# find files with names that can be found in the $files array
$attachments = #(Get-ChildItem -Path $filepath -File | Where-Object { $files -contains $_.Name })
# if we have any files to send
if ($attachments.Count) {
$Password = "xxxxxxxxx"
$mypassword = ConvertTo-SecureString $Password -AsPlainText -Force
$mycredential = New-Object System.Management.Automation.PSCredential ("xxxxx", $mypassword)
# use splatting for better readability
$mailParams = #{
To = "xxxxxxx"
From = "xxxxxxxxxx"
Subject = "test"
Body = "test"
Credential = $mycredential
Attachments = $attachments.FullName
SmtpServer = "xxxxxxxxxxx"
# more parameters can be added here
}
# send the email
Send-MailMessage #mailParams
}
else {
Write-Host 'Nothing to send..'
}
Try
$PSEmailServer = "xxxxxxxxxxx"
$Password ="xxxxxxxxx"
$mypassword = ConvertTo-SecureString $Password -AsPlainText -Force
$mycredential = New-Object System.Management.Automation.PSCredential ("xxxxx", $mypassword)
$EmailSubject ="test"
$attachments = Get-ChildItem "D:\20201124131044\TRACS-20201124034849" | Where-Object {$_.Name -match "error.log|environment.log|TRACS-20201124034849.sterr.stdout"}
$FromEmail ="xxxxxxxxxx"
if($attachments){
Send-MailMessage -From $FromEmail -To "xxxxxxx" -Subject $EmailSubject -Body "test" -Credential $mycredential -Attachments $attachements
}
else {
echo "nothing"
exit
}

Powershell Script to send email after validation

I have a Powershell script that logs the result to a text file (this is working fine), now I need to update it to send email instead of a Log file (see actual script below). I'm kind of a new to powershell, hopefully you can help me out.
# details of the script
# if a file "FILE.400" is found and check the modified date, it will send a log file (txt file)
# need to update the script, to send email instead of a log file
$svr=$env:ComputerName
$date=[datetime]::Today.ToString('MM-dd-yyyy')
$filename = "FILE.400"
$DestLogs1 = "E:\sample\pfupdatedfin-$date.txt"
$DestLogs2 = "E:\sample\pfoutdatedfin-$date.txt"
$SrcPath = "E:\sample\$filename"
If ((Get-ChildItem $SrcPath).LastWriteTime -gt $date)
{
$date | Out-File $DestLogs1
Write-Output "Found latest FILE.400 file" | Out-File $DestLogs1 -Append
(Get-ChildItem -Recurse -Path $SrcPath).LastWriteTime | Out-File $DestLogs1 -Append
}
Else
{
Write-Output "FILE.400 - is not updated, please verify " | Out-File $DestLogs2
(Get-ChildItem -Recurse -Path $SrcPath).LastWriteTime | Out-File $DestLogs2 -Append
}
Send-MailMessageis pretty easy to use. The online documentation for cmdlets is very easy to find. Just enter the name of the cmdlet in your favorite search engine. Or use the Get-Help cmdlet. Here is an example how to use it just fille the Variables reasonably :
Send-MailMessage -From $From -To $To -Subject $Subject -Body $Body -SmtpServer $SMTPServer -Port $SMTPPort -Credential $Credential # -UseSsl:$UseSsl
-useSsl is a switch so it is not necessary unless it's $true. If you want to provide a variable to a switch parameter, don't use a whitespace but a : in between.
Credentials in Powershell are stored in credential objects. You can't just use a plain text password. However don't think they are stored extremly save since the password can be easly extracted if you know how. Here is how you create the necessary credential object:
$SecPw = ConvertTo-SecureString -AsPlainText $Password -Force
$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName,$SecPw
the script is working as expected, in my Home network
$svr=$env:ComputerName
$date=[datetime]::Today.ToString('MM-dd-yyyy')
$filename = "FILE.400"
$DestLogs1 = "E:\sample\pfupdatedfin-$date.txt"
$DestLogs2 = "E:\sample\pfoutdatedfin-$date.txt"
$SrcPath = "E:\sample\$filename"
# email settings
$MyEmail = "myemail#gmail.com"
$SMTP = "smtp.gmail.com"
$To = "samplereceiver#gmail.com"
$Subject1 = "JDA-Alert || Found FILE.400 file - Successful"
$Body1 = "JDA-Alert || Found FILE.400 file - Successful"
$Subject2 = "JDA-Alert || FILE.400 file - Outdated File"
$Body2 = "JDA-Alert || FILE.400 file - Outdated File"
$Creds = (Get-Credential -Credential "$MyEmail")
If ((Get-ChildItem $SrcPath).LastWriteTime -gt $date)
{
Start-Sleep 2
Send-MailMessage -To $To -From $MyEmail -Subject $Subject1 -Body $Body1 -SmtpServer $SMTP -Credential $Creds -UseSsl -Port 587 -DeliveryNotificationOption Never
}
Else
{
Start-Sleep 2
Send-MailMessage -To $To -From $MyEmail -Subject $Subject2 -Body $Body2 -SmtpServer $SMTP -Credential $Creds -UseSsl -Port 587 -DeliveryNotificationOption Never
}

Powershell: Using send-mailmessage after PSFTP in script

I have written a small script that are using PSFTP to connect to a FTP server, download some files and conclude by sending an email with a summary of downloaded files.
I get a problem with the send-mailmessage part, which fails with this error:
Send-MailMessage : The remote certificate is invalid according to the validation procedure.
When running the send-mailmessage alone, it works flawlessly, it is only when using it combined with PSFTP, it fails. I am guessing, that it is the due to having made a session with the ftpserver, that somehow interferes, but that session should be ended when we come to the send mail. I can't figure this out, can anybody help?
My script:
#--------- FTP server variables here ------
$User = "XXX"
$Pass = "XXX"
$EncryptedPass = ConvertTo-SecureString -String $Pass -asPlainText -Force
$Credentials = New-Object System.Management.Automation.PSCredential($User,$EncryptedPass)
$Server = "XXX"
#-------- Mail credentials here -----------
$User_ = "XXX"
$Pass_ = "XXX"
$EncryptedPass_ = ConvertTo-SecureString -String $Pass_ -asPlainText -Force
$Mailcredentials = New-Object System.Management.Automation.PSCredential($User_,$EncryptedPass_)
#$mailcredentials =
$Subject ="'bowkerdownload'"
$To = "XXX"
$From = "XXX"
$body = (get-content -path g:\resultout.txt) -join "`n"
$SMTP = "smtp.office365.com"
#---------File variables here --------------
$month = (Get-Date).AddMonths(-8).ToString('MMM')
$year = (Get-date).addyears(-1).ToString('yyyy')
$filesequential="_*_"
$filesize = "lc"
$filetype = ".txt"
$samlevar=($month + ''+$year + ''+$filesequential + ''+$filesize + ''+$filetype)
$filename = $samlevar.tostring()
#------ The script---------
Set-FTPConnection -Credentials $Credentials -Server $server -Session defaultftpsession -UsePassive
$Session = Get-FTPConnection -Session defaultftpsession
Get-FTPChildItem -Path /Download -filter "$filename" |
Get-FTPItem -session $Session -LocalPath g:\ -Overwrite |
Convertfrom-string -PropertyNames Kode, Status, Action, fil |
Select-Object -Property Status, action, Fil |
Out-file g:\resultout.txt;
Send-MailMessage -To $To -Subject $Subject -Body $Body -SmtpServer $SMTP -From $From -Credential $Mailcredentials -port 587 -UseSsl``

Print Timestamp of Stop and Start Services into .txt file

I want timestamp when services is stopped/restarted then output to file. The file will become as attached and send to support.
I cannot output to file as my below query seems got error.
$hostname = $env:computername
$smtpServer = 'smtpServer'
$from = "from"
$recipients = 'recipients'
$Subject = "Services Restarted Successfully on $hostname $ipv4"
$body = "This mail confirms that the service on $hostname $ipv4 is now running."
$ipv4 = (Test-Connection -ComputerName $env:computername -count 1).ipv4address.IPAddressToString
$natip = Invoke-WebRequest ifconfig.me
$timestamp = (Get-Date)
$output = D:\Testing\Restart.txt
$attachment = $output
$service = 'Apache'
Stop service
Stop-Service -name $service -Verbose
do {
Start-sleep -s 5 | Write-Output "$timestamp Services is stopped" | Out-file $output
}
until ((get-service $service).Status -eq 'Stopped')
Start service
start-Service -name $service -Verbose
do {
Start-sleep -s 5 | Write-Output "$timestamp Services is restarted" | Out-file $output
}
until ((get-service $service).Status -eq 'Running')
Send confirmation that service has restarted successfully
Start-Sleep -s 5
Send-MailMessage -To $recipients -Subject $Subject -Body $body ((gsv Apache) | out-string) -From $from -SmtpServer $smtpServer -Attachments $attachment
As stated in above comments, change your code to
Stop-Service -name $service -Verbose
do {
Start-sleep -s 5
Write-Output "$timestamp Services is stopped" | Out-file $output
} until ((get-service $service).Status -eq 'Stopped')
Actually your Start-Sleep cmledt calls output is sent to the pipeline ( Start-sleep - s 5 |...). My guess is that Start-sleep doesn't returns anything, so nothing is send to the pipeline. Based on that Write-Output is not called.
Antoher guess: Assignment to $output fails since your path is not a string, Powershell may interpret the assignment in command mode. Change it to:
$output = "D:\Testing\Restart.txt"

If file exists, send Email and run batch script

I have a script that runs every two hours to see if a file has been dropped. If it is there, I get an alert. I would like to take it a step further and run a job the move the file. So far here is what I have:
$path = "\\0.0.0.0\files\test\state\WAITING\*"
$fileexists = Test-Path $path
if ($fileexists) {
Send-MailMessage `
-From noreply#email.com `
-To tester#foo.com `
-Subject "Files Have Arrived" `
-Body "The files have arrived and are being moved to the processing folder." `
-SmtpServer 0.0.0.1
} else {
#donothing
}
I want to fit this in the ifexists:
Start-Process "cmd.exe" "/c \\0.0.0.0\files\test\MOVE.bat"
Would it be like this:
$path = "\\0.0.0.0\files\test\state\WAITING\*"
$fileexists = Test-Path $path
if ($fileexists) {
Send-MailMessage `
-From noreply#email.com `
-To tester#foo.com `
-Subject "Files Have Arrived" `
-Body "The files have arrived and are being moved to the processing folder." `
-SmtpServer 0.0.0.1
Start-Process "cmd.exe" "/c \\0.0.0.0\files\test\MOVE.bat
} else {
#donothing
}
I got it figured out
$path = "\\0.0.0.0\files\test\state\WAITING\*"
$fileexists = Test-Path $path
if ($fileexists) {
Start-Process "cmd.exe" "/c \\0.0.0.1\files\test\MOVE.bat"` | Send-MailMessage -From noreply#test.com -To tester#foo.com -Subject "Files Have Arrived" -Body "The files have arrived and are being moved to the processing folder." -SmtpServer 0.0.0.2`
} else {
#donothing
}
You can use semicolon ";" to separate commands.