Delete email attachment after sending powershell - windows

I have wrote a script for automated email using powershell.
The email sends however how can i configure it so that the file that is attached is moved to another folder inside the folder it was originally located?
#Searches dir for list , formats
$Attachment = Get-ChildItem -Path $dir -Filter "*$($Region.name)*" -Recurse
$AttachmentName = $Attachment.BaseName
$Subject = "$AttachmentName # $Time"
$Body = "Please find attached the file needed for $($Region.name).
Regards,
Me
"
#Actions Email
Send-MailMessage -From $Region.From -To $Region.To -CC $Region.Cc -Subject $Subject -Body $Body -SmtpServer $SMTPServer -Attachments $Attachment.FullName
Move-Item Get-ChildItem -Path $dir -Filter "*$($Region.name)*" -Recurse "C:\Users\users\Desktop\MissingImageLists\OldLists"
}

Remove your Move-Item command and replace it with:
$Attachment | Move-Item -Destination "$dir\subfolder"

Related

Powershell - extract specific items from zip then send a message (loop with message box)

I'm trying to achieve the following with this powershell script.
Copy any .zip file from folder dropfilehere to folder IN.
For each .zip file in folder "IN" open the zip file, find only the .csv file.
When .csv file is found, extract it to $dst under name DB.csv (overwrite old file).
Empty contents of folders "dropfilehere" and "IN"
Finally, when all the above is done, create a popup box with a message to the user using wscriptshell -
This is the issue. When the message is sent, the user gets 10+ popup boxes or an endless loop of them.
In the background i see cmd.exe and conhost.exe processes appearing as each popup box gets created.
I use a batch file to call the powershell script.
Powershell.exe -ExecutionPolicy Bypass -File C:\pathtoscript\call.ps1
exit
The script is:
$dst = "C:\Testing\DB"
Copy-item -Path "C:\Users\user\dropfilehere\*.zip" -destination "C:\Testing\Other\In" -Force
Foreach ($zipfile in (Get-ChildItem "C:\Testing\Other\In\*.zip" -Recurse)) {
Add-Type -Assembly System.IO.Compression.FileSystem
$zipFile = [IO.Compression.ZipFile]::OpenRead($zipfile)
$zipFile.Entries | where {$_.Name -like '*.csv'} | foreach {$FileName = $_.Name
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, "$dst\DB.csv", $true)}
$zipFile.Dispose()
Remove-Item "C:\Testing\Other\In\*" -Recurse -Force
Remove-Item "C:\Users\user\dropfilehere\*" -Recurse -Force
$org="Name of Org"
$timeout = 60 # in seconds
$ws = New-Object -ComObject "Wscript.Shell"
$intButton = $ws.Popup("A new update message here`n
Another message here.",$timeout,$org, 0)
}
exit
There is code inside your foreach loop that should be placed after it, as shown below (properly indenting your code would have made that more obvious):
Add-Type -Assembly System.IO.Compression.FileSystem
$dst = "C:\Testing\DB"
Copy-item -Path "C:\Users\user\dropfilehere\*.zip" -destination "C:\Testing\Other\In" -Force
# Process all files.
foreach ($zipfile in (Get-ChildItem "C:\Testing\Other\In\*.zip" -Recurse)) {
$zipFile = [IO.Compression.ZipFile]::OpenRead($zipfile)
$zipFile.Entries |
Where-Object { $_.Name -like '*.csv' } |
ForEach-Object {
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, "$dst\DB.csv", $true)
}
$zipFile.Dispose()
}
# Remove the folders containing the original *.zip files.
Remove-Item "C:\Testing\Other\In\*" -Recurse -Force
Remove-Item "C:\Users\user\dropfilehere\*" -Recurse -Force
# Show a message box.
$org = "Name of Org"
$timeout = 60 # in seconds
$ws = New-Object -ComObject "Wscript.Shell"
$intButton = $ws.Popup("A new update message here`nAnother message here.", $timeout, $org, 0)

Powershell Script Help (Get-Process and send output via SMTP)

I'm trying to make e Powershell script to check a specific service(name) with Status and StartType and additional information like time and date of the servers and server names.
List of servers from .txt is only the FQDN's.
I have the desired output in powershell but can't get it properly to send via SMTP.
In one case it doesn't show the state or won't show to processes only the names of the servers and all the information is plain text not in containers for the different servers.
Desired output :desired output in powershell need to transfer to smtp email
$ServerList = Get-Content -Path "C:\new_folder\servers.txt"
Foreach ($server in $ServerList){
$time = "---"
$time = ([WMI]'').ConvertToDateTime((gwmi win32_operatingsystem -computername $server).LocalDateTime)
$server + ', ' + $time
Get-Service -ComputerName "$server" | where-object {$_.name -like '*goge*'} | Select #{Name="server";Expression={$server}},Name,DisplayName,StartType,Status
}send-MailMessage -SmtpServer $smtp -To $to -From $from -Subject $subject -Body $body -BodyAsHtml -Priority high
Try to use this little fix, i leave comments
$ServerList = Get-Content -Path "C:\new_folder\servers.txt"
$array=#() #array which will contain result get-service
Foreach ($server in $ServerList){
$time = "---"
$time = ([WMI]'').ConvertToDateTime((gwmi win32_operatingsystem -computername $server).LocalDateTime)
$server + ', ' + $time
#add to our array result of each get-service from servers
$array+=Get-Service -ComputerName "$server" | where-object {$_.name -like '*goge*'} | Select #{Name="server";Expression={$server}},Name,DisplayName,StartType,Status
}
send-MailMessage -SmtpServer $smtp -To $to -From $from -Subject $subject -Body $array -BodyAsHtml -Priority high

powershell script to compare two text files and output should be a notification like email

I'm having a PowerShell script for comparing two text files and displaying the output:
Compare-Object $(Get-Content c:\scripts\x.txt) $(Get-Content c:\scripts\y.txt) -includeequal
But I want the output in the form of a notification, like an Email...
How can I forward the output to an Email-Body and then send it the mail?
To put the output comparison into an Email and send it over gmail, you can use the Send-MailMessage command like this:
$From = "YourEmail#gmail.com"
$To = "ToMail#Domain.com"
$Cc = "CCMail#Domain.com"
$Subject = "String Comparison"
$comparison = (Compare-Object (Get-Content c:\scripts\x.txt) (Get-Content c:\scripts\y.txt) -includeequal).InputObject
foreach($line in $comparison)
{
$Body+= $line
}
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
Send-MailMessage -From $From -to $To -Cc $Cc -Subject $Subject -Body $Body -SmtpServer $SMTPServer -port $SMTPPort -UseSsl -Credential (Get-Credential)
For more information look into Send-MailMessage and Google SMTP Config

How can I optimize this Email list powershell script

How can I configure this script so that I can repeat this mailing process for multiple addresses eg Europe, Asia without copying the code multiple times?
For example could I do something like this?:
IF $keyword "Europe" found THEN
$europe
$europe = Does the Europe stuff
THEN
IF $keyword "Asia" found THEN
$asia
etc.
Here is my code:
# Email Automation
#Defines Directory
$dir = "C:\Users\user\Desktop\myfolder"
#Sets STMP server
$SMTPServer = "10.0.0.1"
#Declares todays time and formats
$Time = (Get-Date).ToString('MM/dd/yyyy hh:mm tt')
# Europe #
#Declares the keyword used to find List
$keywordEur = "Europe"
#Searches dir for list , formats
$AttachmentEur = Get-ChildItem -Path $dir -Filter "*$keywordEur*" -Recurse
$AttachmentNameEur = $AttachmentEur.BaseName
#Defines mailing list
$FromEur = "me#email.com"
$ToEur = "you#europeemail.com"
$CcEur = "him#email.com", "her#email.com"
$SubjectEur = "$AttachmentName # $Time"
$BodyEur = "Please find attached the file needed for Europe.
Regards,
Me
"
#Actions Email
Send-MailMessage -From $FromEur -To $ToEur -CC $CcEur -Subject $SubjectEur -Body $BodyEur -SmtpServer $SMTPServerEur -Attachments $AttachmentEur.FullName
# Asia #
#Declares the keyword used to find List
$keywordAs = "Asia"
#Searches dir for list , formats
$AttachmentAs = Get-ChildItem -Path $dir -Filter "*$keywordAs*" -Recurse
$AttachmentNameAs = $AttachmentAs.BaseName
#Defines mailing list
$FromAs = "me#email.com"
$ToAs = "you#asiaemail.com"
$CcAs = "him#email.com", "her#email.com"
$SubjectAs = "$AttachmentNameAs # $Time"
$BodyAs = "Please find attached the file needed for Asia.
Regards,
Me
"
#Actions Email
Send-MailMessage -From $FromAs -To $ToAs -CC $CcAs -Subject $SubjectAs -Body $BodyAs -SmtpServer $SMTPServerAs -Attachments $AttachmentAs.FullName
Here's how you could repeat it with a ForEach loop and an object built with two hashtables for the regions:
# Email Automation
#Defines Directory
$dir = "C:\Users\user\Desktop\myfolder"
#Sets STMP server
$SMTPServer = "10.0.0.1"
#Declares todays time and formats
$Time = (Get-Date).ToString('MM/dd/yyyy hh:mm tt')
$Europe = #{
Name = 'Asia'
From = "me#email.com"
To = "you#email.com"
Cc = "him#email.com", "her#email.com"
}
$Asia = #{
Name = 'Asia'
From = "me#email.com"
To = "you#email.com"
Cc = "him#email.com", "her#email.com"
}
$Regions = #()
$Regions += New-Object PSObject -Property $Asia
$Regions += New-Object PSObject -Property $Europe
ForEach ($Region in $Regions) {
#Searches dir for list , formats
$Attachment = Get-ChildItem -Path $dir -Filter "*$($Region.name)*" -Recurse
$AttachmentName = $Attachment.BaseName
$Subject = "$AttachmentName # $Time"
$Body = "Please find attached the file needed for $($Region.name).
Regards,
Me
"
#Actions Email
Send-MailMessage -From $Region.From -To $Region.To -CC $Region.Cc -Subject $Subject -Body $Body -SmtpServer $SMTPServer -Attachments $Attachment.FullName
}
Yes there is. Since the keywords themselves are the only thing that seems to change, put your keywords in an array and wrap the entire thing in a loop:
# Email Automation
#Define Directory
$dir = "C:\Users\user\Desktop\myfolder"
#Set STMP server
$SMTPServer = "10.0.0.1"
#Declare todays time and formats
$Time = (Get-Date).ToString('MM/dd/yyyy hh:mm tt')
#Define mailing list
$From = "me#email.com"
$To = "you#email.com"
$Cc = "him#email.com", "her#email.com"
#Declares the keywords used to find attachments
$keywords = 'Europe','Asia'
foreach($keyword in $keywords){
#Searches dir for list , formats
$Attachment = Get-ChildItem -Path $dir -Filter "*$keyword*" -Recurse
$AttachmentName = $Attachment.BaseName
$Subject = "$AttachmentName # $Time"
$Body = "Please find attached the file needed for $keyword.
Regards,
Me
"
#Actions Email
Send-MailMessage -From $From -To $To -CC $Cc -Subject $Subject -Body $Body -SmtpServer $SMTPServer -Attachments $Attachment.FullName
}

Send-MailMessage: Cannot validate argument on parameter 'Subject'

This error appears when running the script below:
Send-MailMessage : Cannot validate argument on parameter 'Subject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
The email still sends successfully and the subject appears correctly.
$dir = "C:\Users\user\Desktop\Lists\TodaysLists"
$SMTPServer = "192.168.1.111"
$Time = (Get-Date).ToString('MM/dd/yyyy hh:mm tt')
$japan = #{
Name = 'Japan'
From = "me#me.com
To = "you#me.com"
Cc = "him#me.com"
}
$ireland = #{
Name = 'Ireland'
From = "me#me.com
To = "you#me.com"
Cc = "him#me.com"
}
$Regions = #()
$Regions += New-Object PSObject -Property $japan
$Regions += New-Object PSObject -Property $ireland
foreach ($Region in $Regions) {
$Attachment = Get-ChildItem -Path $dir -Filter "*$($Region.Name)*" -Recurse
$AttachmentName = $Attachment.BaseName
$Subject = "$AttachmentName"
$Body = "Please find attached the Report for $($Region.Name).
Produced # $Time
Regards,
John Doe
"
Send-MailMessage -From $Region.From -To $Region.To -CC $Region.Cc -Subject $Subject -Body $Body -SmtpServer $SMTPServer -Attachments $Attachment.FullName
$Attachment | Move-Item -Destination "C:\Users\user\Desktop\Lists\oldLists"
}
My guess would be that $Attachment = Get-ChildItem -Path $dir -Filter "*$($Region.Name)*" -Recurse is not returning any files for one or more of the regions, so $Subject ends up being $null.
You could either check for that state and perhaps throw a warning instead of attempting to send the mail, or another way to work around the error (and get an email sent but with a blank subject) would be to add some other (guaranteed) text to $subject. E.g:
$Subject = "$($Region.Name): $AttachmentName"
Although then I suspect it would complain about -Attachments being null.
To add a check/throw warning, you could do the following:
foreach ($Region in $Regions) {
$Attachment = Get-ChildItem -Path $dir -Filter "*$($Region.Name)*" -Recurse
If ($Attachment) {
$AttachmentName = $Attachment.BaseName
$Subject = "$AttachmentName"
$Body = "Please find attached the Report for $($Region.Name).
Produced # $Time
Regards,
John Doe
"
Send-MailMessage -From $Region.From -To $Region.To -CC $Region.Cc -Subject $Subject -Body $Body -SmtpServer $SMTPServer -Attachments $Attachment.FullName
$Attachment | Move-Item -Destination "C:\Users\user\Desktop\Lists\oldLists"
} Else {
Write-Warning "One or more files named $($Region.Name) were not found in $dir. Mail not sent."
}
}

Resources