Powershell attached all file from folder - powershell

I need to email and attached all file from the folder but no include any sub-folder.
I am getting error
Cannot find an overload for "Add" and the argument count: "1".
At line:11 char:1
$emailMessage.Attachments.Add($getallfiles)
below is the powershell code.
$dir = "C:\Users\myid\Documents\comparsion\src\main\resources\excelfiles\Compare_Result_Files"
$getallfiles = Get-ChildItem "$dir\*.xlsx"
$emailSmtpServer = "mailhub-au.com"
$emailMessage = New-Object System.Net.Mail.MailMessage
$emailMessage.From = "donotreply#company.com"
$emailMessage.To.Add( "myid#company.com" )
$emailMessage.Subject = "Selenium Report"
$emailMessage.IsBodyHtml = $true
$emailMessage.Body = "Test Summary Attached"
$emailMessage.Body = "$getallfiles"
$emailMessage.Attachments.Add($getallfiles)
$SMTPClient = New-Object System.Net.Mail.SmtpClient( $emailSmtpServer ,$emailSmtpServerPort )
$SMTPClient.Send($emailMessage)`

You need to loop through the files and add one at a time.
Also the Attachments.Add() method requires the full file name, not a FileInfo object. See the docs
foreach ($file in $getallfiles) {
[void]$emailMessage.Attachments.Add($file.FulllName)
}
I would also suggest adding the -File switch to Get-ChildItem to ensure you only gather files, not folders.

Related

How to filter e-mails by Flag status in EWS?

I'm using EWS and trying to find e-mail messages that are flagged for action (i.e. their Flag.FlagStatus property is "Flagged"). I have successfully filtered e-mails based on their subject and other properties, but I just can't wrap my head around how to filter them based on FlagStatus.
The problem arises when defining $searchFilter in the code below.
The line returns error
"Exception calling "FindItems" with "2" argument(s): "Validation
failed. Parameter name: searchFilter""
I've tried using other variants of SearchFilter, e.g. SearchFilter+IsEqualTo, but all return the same error.
Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"
$ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP3
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)
$service.Credentials = New-Object System.Net.NetworkCredential("username","password")
$service.Url = "https://mail.server.net/EWS/Exchange.asmx"
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
$propertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$propertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text
$searchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.ItemSchema]::Flag.FlagStatus, "Flagged")
$view = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1,0)
$messages = $inbox.FindItems($searchFilter, $view)
foreach ($item in $messages.Items) {
$item.Load($propertySet)
write-host $item.Flag.FlagStatus
write-host $item.Body.Text
}
This one works:
$searchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.ItemSchema]::Categories, "Blue Category")
This one doesn't:
$searchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.ItemSchema]::Flag.FlagStatus, "Flagged")
I'd suggest you use the Extendedproperty instead of the strongly typed one (which is derived from the ep anyway) eg
ExtendedPropertyDefinition PidTagFlagStatus = new ExtendedPropertyDefinition(0x1090, MapiPropertyType.Integer);
SearchFilter.Exists sfExits = new SearchFilter.Exists(PidTagFlagStatus);
should work to give you any messages that are flagged (eg the property exists) or you could be more specific to get followupFlagged
SearchFilter.IsEqualTo sfEqualTo = new SearchFilter.IsEqualTo(PidTagFlagStatus, 0x00000002);
in Powershell you need
$PidTagFlagStatus = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x1090, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer);
$searchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+Exists($PidTagFlagStatus)
or
$searchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo($PidTagFlagStatus, 0x00000002)

Powershell in UIPath. Throw : Unable to cast object of type 'Microsoft.Exchange.WebServices.Data.GetItemResponse' to type 'System.String'

I am trying to grab emails from Exchange using powershell in UI Path. When trying to return the items, I get the following error:
Throw : Unable to cast object of type 'Microsoft.Exchange.WebServices.Data.GetItemResponse' to type 'System.String'.
Even when I change the TypeArgument in UI Path. Currently I am using the Invoke power shell activity but I get the same issues using the RunPowershellScript activity. Below is a screenshot of my sequence in UI Path, my parameters, and my powershell script, Thank you!
Param(
[parameter()]
[string]$mailbox,
[parameter()]
[string]$password
)
try{
#https://forum.uipath.com/t/get-argument-from-an-process-with-exception-in-reframework/22537/4
function test-password(){
$Creds = new-object System.Net.networkCredential -ArgumentList $mailbox, $password
$mailFolder = "Inbox"
$itemView = 3
#[Reflection.Assembly]::LoadFile("C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll")
$ExSer = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1)
$ExSer.Credentials = ($Creds)
$ExSer.Url = new-object Uri("https://outlook.office365.com/EWS/Exchange.asmx")
$ExSer.AutodiscoverUrl($mailbox, {$true})
$setMailFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($ExSer,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
$logs2 += "Successfully Connected to mailbox $mailbox"
$iv = new-object Microsoft.Exchange.WebServices.Data.ItemView($itemView)
$CustomFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And)
$ifIsRead = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::IsRead,$false)
$ifFrom = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::From,"filteremail#mycompany.com")
$CustomFilter.add($ifIsRead)
$CustomFilter.add($ifFrom)
$filteredEmails = $ExSer.FindItems($setMailFolder.Id,$CustomFilter, $iv)
$psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text;
#add-type "Microsoft.Exchange.WebServices.Data.GetItemResponse"
$ExSer.LoadPropertiesForItems($filteredEmails,$psPropertySet)
$item = $filteredEmails.Items[0]
return $mailbox, $item
}
test-password
}
catch{
Throw
}
I commented out the load dll as it seemed to work without it and was throwing a similar error when it hit it. The code seems to throw an error when it hits $Exser.LoadPropertyItems. I have also tried switching to Exchange 2007 etc. To clarify, when running purely powershell outside of UI Path, this code works just fine.
I figured it out....I was just being a dingus. It was trying to load an object, which was breaking it. If I saved it as a variable and then converted it within my script and returned what I needed as a string....guess what? It could understand the string. Below is my updated powershell.
Param(
[parameter()]
[string]$mailbox,
[parameter()]
[string]$password
)
try{
#https://forum.uipath.com/t/get-argument-from-an-process-with-exception-in-reframework/22537/4
function test-password(){
$Creds = new-object System.Net.networkCredential -ArgumentList $mailbox, $password
$mailFolder = "Inbox"
$itemView = 50
# Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"
#[Reflection.Assembly]::LoadFile("C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll")
$ExSer = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1)
$ExSer.Credentials = ($Creds)
$ExSer.Url = new-object Uri("https://outlook.office365.com/EWS/Exchange.asmx")
$ExSer.AutodiscoverUrl($mailbox, {$true})
$setMailFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($ExSer,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
$logs2 += "Successfully Connected to mailbox $mailbox"
$iv = new-object Microsoft.Exchange.WebServices.Data.ItemView($itemView)
$CustomFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And)
$ifIsRead = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::IsRead,$true)
$ifFrom = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::From,"emailtofilterby#mycompany.com")
$CustomFilter.add($ifIsRead)
$CustomFilter.add($ifFrom)
$filteredEmails = $ExSer.FindItems($setMailFolder.Id,$CustomFilter, $iv)
$psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text;
#add-type "Microsoft.Exchange.WebServices.Data.GetItemResponse"
$FilteredEmailitems = $ExSer.LoadPropertiesForItems($filteredEmails,$psPropertySet)
$EmailBody = $FilteredEmailitems.Item(0) | Select-Object -ExpandProperty Item | Select-Object -ExpandProperty Body | Select-Object -ExpandProperty Text
return $EmailBody
}
test-password
}
catch{
Throw
}

Cannot find an overload for "Add" and the argument count: "1"

I got two different scripts and combined them to check a specific folder for new file and email that file as attachment.
Here's the code combined:
Param (
$Path = "C:\path"
)
$File = Get-ChildItem $Path | Where { $_.LastWriteTime -ge [datetime]::Now.AddMinutes(-10) }
If ($File)
{
$emailSmtpServer = "smtp.xxxx.com"
$emailSmtpServerPort = "587"
$emailSmtpUser = "xxxx#xxxxxx.com"
$emailSmtpPass = "xxxxxxxx"
$emailMessage = New-Object System.Net.Mail.MailMessage
$emailMessage.From = "Xxxx Xxxx <xxxx#xxxxxx.com>"
$emailMessage.To.Add( "xxxx#xxxxxx.com" )
$emailMessage.Subject = "File Test Report"
$emailMessage.IsBodyHtml = $false
$emailMessage.Body = "Weekly Report"
$SMTPClient = New-Object System.Net.Mail.SmtpClient( $emailSmtpServer , $emailSmtpServerPort )
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential( $emailSmtpUser , $emailSmtpPass );
$attachment = $File
$emailMessage.Attachments.Add($attachment)
$SMTPClient.Send($emailMessage)
}
The code works fine, it looks for new file and sends the email except it won't attach the file and I get the following error
Cannot find an overload for "Add" and the argument count: "1".
At D:\SendEmail2.ps1:24 char:1
+ $emailMessage.Attachments.Add($attachment)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
I think it has something to do with calling the file with $attachment = $File
Can anyone help?
You probably have to create a Attachment object first and also have to deal with multiple files so replace the following lines:
$attachment = $File
$emailMessage.Attachments.Add($attachment)
with:
$File | ForEach-Object {
$filePath = $_.FullName
$attachment = new-object Net.Mail.Attachment($filePath)
$emailMessage.Attachments.Add($attachment)
}
i had the same issue as you and this fixed it.
https://community.spiceworks.com/posts/8438625
just change:
$path = "D:\FTP-COR\$($today.Year)\$($today.ToString("MM-dd-yyyy"))"
and add your credentials.
I am using PowerShell: (I use .NET so don't forget C#, please don't ask):-)
create a .csv file:
$collection | Export-Csv -Path $SaveAs -NoTypeInformation
To create the attachment object:
[System.Net.Mail.Attachment] $Attachment = [System.Net.Mail.Attachment]::new($SaveAs)
Then to attach to the message object:
$message.Attachments.Add($Attachment)
This should work. I have been using this and it's been working fine. I know it's in PowerShell, but at the core, same .NET

PowerShell EWS Save as for e-mails

How is it possible to save an e-mail on disk with the help of EWS in PowerShell? I've searched the internet and found some answers, but that's all for C# or VB.
The code I have now does everything I need, copy the e-mail to the correct folder in MS Outlook and so on, but I can't seem to figure out how to save the message in a folder ($ENV:Temp) on disk.
This can be in the format EML or MSG, that doesn't matter to me, but it needs to be saved with everything it has (body, attachments, From, To, ..).
I've tried $Mail | Out-File "$env:TEMP\test.eml", and it does indeed generate a 15 KB file but it appears to be empty when I open it with MS Outlook.
Thank you for your help.
In the meantime, I found the solution:
$Service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -ArgumentList $ExchangeVersion
$Service.Credentials = $Credentials.GetNetworkCredential()
$Service.AutodiscoverUrl($BNLMailbox)
Try {
$PowerShellPathId = Find-MailFolderIDHC #FindMailParams -Path $BNLMailboxInbox
$Inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service,$PowerShellPathId)
}
Catch {
# Exchange version not correct or path not found
throw "Move-MailsHC $($Global:Error[0].Exception.Message)"
}
$Props = [Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties
$PropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet($Props)
$PropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text
$PropertySet.Add([Microsoft.Exchange.WebServices.Data.ItemSchema]::MimeContent)
$Date = [Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived
$TimeSpan = (Get-Date).AddHours(-$HoursAgo)
$Filter = New-Object -TypeName Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThan -ArgumentList $Date,$TimeSpan
$View = New-Object Microsoft.Exchange.WebServices.Data.ItemView(100)
$View.OrderBy.add([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived,
[Microsoft.Exchange.WebServices.Data.SortDirection]::Ascending)
foreach ($Mail in $Mails.Items) {
$TmpFolder = Join-Path $env:TEMP 'Move-MailsHC'
if (-not(Test-Path $TmpFolder)) {
New-Item $TmpFolder -ItemType Directory | Out-Null
}
Write-Verbose "Save original e-mail in temp '$TmpFolder'"
$TmpMail = Join-Path $TmpFolder 'Mail.eml'
$IoFile = New-Object System.IO.FileStream($TmpMail, [System.IO.FileMode]::Create)
$IoFile.Write($Mail.MimeContent.Content, 0, $Mail.MimeContent.Content.Length)
$IoFile.Close()
Write-Verbose "Download e-mail attachments to temp '$TmpFolder'"
foreach ($A in $Mail.Attachments){
$A.Load()
$fiFile = New-Object System.IO.FileStream((Join-Path $TmpFolder $A.Name.ToString()), [System.IO.FileMode]::Create)
$fiFile.Write($A.Content, 0, $A.Content.Length)
$fiFile.Close()
Write-Verbose "Downloaded Attachment: $($A.Name.ToString())"
}
}

Cryptolocker Honeypot FileSystemWatcher

I am a novice when it comes to scripting so please bear with me. I am trying to create a script that will monitor a bait file that is added to all file shares on a server. When the script sees that the file was modified it will block access to the user that made the modification and send an email. The script seems to work ok other than the FileSystemWatcher. It will only monitor the last share. I have seen a similar post on here but was getting confused with the answer. Can someone please help me with the task of creating a FileSystemWatcher for each bait file? I would also like any input as to how I might improve upon the script in other ways. Your help is greatly appreciated.
$to = "joe#blow.com"
$File = "test.txt"
$FilePath = "C:\temp"
$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
## SEND MAIL FUNCTION
function sendMail($s, $to) {
$smtpServer = "mail.nowhere.com"
$smtpFrom = "alert#nowhere.com"
$smtpTo = $to
$messageSubject = $s[0]
$message = New-Object System.Net.Mail.MailMessage $smtpfrom, $smtpto
$message.Subject = $messageSubject
$message.IsBodyHTML = $false
$message.Body = $s[1]
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($message)
}
## Get a list of shares and Perform tasks on each location.
$cryptopaths = Get-WmiObject -Class win32_share -filter "Type=0 AND name like '%[^$]'" | ForEach ($_.Path) {
$cryptopath = $_.Path
## Copy the bait file to the share location
Copy $FilePath\$File $cryptopath\$File -Force
##Get files hash
Try {
$Origin = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes("$FilePath\$File")))
$Copy = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes("$CryptoPath\$File")))
}
##Error on reading hash
Catch {
echo "error reading $CryptoPath\$File"
}
## If files don't match, then Send messaged and quit
if (Compare-Object $Origin $Copy){
## files don't match
$subject = "Error logged on $CryptoPath\$File by $env:username on $env:computername"
$body = "The original file does not match the witness file. Aborting monitor script."
$email =#($subject,$body)
sendMail -s $email -to "ben22#nowhere.com"
Exit
}
## CREATE WATCHER ON DIRECTORY
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $CryptoPath
$watcher.Filter = $File
$watcher.IncludeSubdirectories = $false
$watcher.EnableRaisingEvents = $false
$watcher.NotifyFilter = [System.IO.NotifyFilters]::LastWrite -bor [System.IO.NotifyFilters]::FileName
}
## Execute Watcher
while($TRUE){
$result = $watcher.WaitForChanged([System.IO.WatcherChangeTypes]::Changed `
-bor [System.IO.WatcherChangeTypes]::Renamed `
-bor [System.IO.WatcherChangeTypes]::Deleted `
-bor [System.IO.WatcherChangeTypes]::Created, 1000);
if ($result.TimedOut){
continue;
}
if ($result.Name -eq $File) {
### Make sure the files do not match
try {
$FileCheck = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes("$CryptoPath\$File")))
if (Compare-Object $Origin $FileCheck){
## files don't match
$body = "Witness file $FilePath\$File on $env:computername has been modified."
}
}
catch {
## file deleted
$body = "Witness file $FilePath\$File on $env:computername has been deleted"
}
finally {
## Deny owner of changed file access to shares and disconnect their open sessions. Send email alert
Get-Acl "$CryptoPath\$File" | foreach ($_.Owner) {
Get-SmbShare | Block-SmbShareAccess –AccountName $_.Owner
Close-SmbSession –ClientUserName $_.Owner
}
$subject = "EMERGENCY ON FILE SERVER -- $FilePath\$File by $env:username on $env:computername"
$email =#($subject,$body)
sendMail -s $email -to "ben22#nowhere.com"
sendMail -s $email -to "5555555555#txt.bell.ca"
Exit
}
}
}
The problem is that you create FileSystemWatcher instances in a loop (ForEach ($_.Path) {}), but you assign them to the same variable $watcher, overwriting the previous reference each time. Once outside the loop, you work with the $watcher variable, which references the last FileSystemWatcher instance you created and that's why you are receiving notifications for the last file only.
To get this working, you should use a type that allows storing multiple references -- that is, an array. Example:
$watchers = #();
...
$watcher = New-Object System.IO.FileSystemWatcher;
...
$watchers += $watcher;
Also, I would propose to use event handler/callback/delegate-based approach instead of waiting for a change using WaitForChanged(), because waiting for multiple file system watchers would call for a parallelized solution (well, ideally). Use Register-ObjectEvent to register an event handler and see this example in particular: http://gallery.technet.microsoft.com/scriptcenter/Powershell-FileSystemWatche-dfd7084b.
PowerShellPack also has a Start-FileSystemWatcher cmdlet that wraps this all up nicely, but I'm not sure about the status of PowerShellPack in general. It should be part of the Windows 7/8 Resource Kit, though.