I have this very simple script to get all the searchable mailboxes. I have 2000 mailboxes but this API return only 1500 every time. Wondering if the results are paged but there is no documentation regarding it.
Import-Module "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll";
$Service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1);
#$Service.UseDefaultCredentials = $true;
$Service.Credentials = New-Object System.Net.NetworkCredential("test#test.com", "test123!");
$Service.Url ="https://exch2013.test.com/EWS/Exchange.asmx";
$Service;$m = $Service.GetSearchableMailboxes([string]::Empty,$false);
$count = 1;
#$m.SearchableMailboxes | %{$_.SmtpAddress; $count++;}#$count;
Sounds like throttling - use a paged search.
See if ECP's ediscovery search repros - if it does then its probably not an issue with your code.
There is an example of paged searches in EWSEdtior's code (you will find the code in Github). Find the form called EDiscoverySearch.cs. The call to GetSearchable Mailboxes does not do paging, however another piece of code in the same form does - you can adapt it for the call to GetSearchableMailboxes.
Related
I have a huge mailbox (~50Gb) with plenty of messages in 'Inbox' . I'm looking for moving certain messages received before particular date to another folder at the same mailbox.
I have tried to do it from Outlook Windows app but it seems too slow and I can't do it for all the messages at once. Outlook just crash.
Is there any way to perform the task from Exchange Powershell ? I can certainly create server side rule but how to apply it to the messages already in 'Inbox' ?
New-InboxRule -Name Testmove2018 -Mailbox test -MoveToFolder "MailboxName:\2018" -ReceivedAfterDate "09/01/2015"
Oleg
The Exchange Online powershell module still allows you to copy and delete messages matching a search with Search-Mailbox, but you must copy them elsewhere first. Use an empty mailbox:
# First, check your search filter using EstimateOnly or LogOnly:
Search-Mailbox myUser#domain.com -SearchQuery 'Subject:Move Me' -EstimateResultOnly
# Copy the items to a temp mailbox and delete from the primary
# (EXO does not allow copying search results to same mailbox)
# param block just for readability:
$Params = #{
Identity = 'myUser#domain.com'
SearchQuery = 'Subject:Move Me'
TargetMailbox = 'temp#domain.com'
TargetFolder = 'Temp'
DeleteContent = $true
}
$TempResult = Search-Mailbox #Params
# Now move back to original mailbox
$Params.Identity = 'temp#domain.com'
$Params.TargetMailbox = 'myUser#domain.com'
$Params.TargetFolder = 'Moved'
$MoveResult = Search-Mailbox #Params
Then just make sure the number of emails is equal. EXO can take a while to get synced up, so if it's not finding all the email to move back, just give it a while and run the second search again:
If ($TempResult.ResultItemsCount -eq $MoveResult.ResultItemsCount) {
"We're good!"
} Else {
Write-Warning "Move results not equal!"
$TempResult
$MoveResult
}
Note that this is the 'Old' method, which is already retired and may be removed in the future. The new method is supposed to be using the New-ComplianceSearch style commands, but they have some limitations and aren't built for this purpose.
In my opinion, the "easiest" way is to open the mailbox in the browser > search for what you want > scroll down to load all the messages if needed > select all > move to > "move to a different folder..."
i've a script on powershell to manage mailbox using EWS, however i'm not able to user the current filters and filter certain categories.
I would like filter categories that start by _ or * and apply to my current filters
$sfRead = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::IsRead, $True)
$WIPSubject = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.ItemSchema]::Subject, "Assigned")
$sfNot = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+Not($WIPSubject)
$sfCollection = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And)
$sfCollection.add($sfRead)
$sfCollection.add($sfNot)
If you want to do a wildcard search on the Subject then I would suggest that you use AQS for queries instead https://msdn.microsoft.com/en-us/library/office/dn579420(v=exchg.150).aspx . SearchFilters don't support wildcards you have the ContainsSubString filter which will find partial string matches https://msdn.microsoft.com/en-us/library/office/dd633645(v=exchg.80).aspx which is the closest.
I work on a team, who manage a few hundred servers. We each take primary responsibility for about 100 servers. I am the new person on the team, so I have a rule "MyServers" in outlook that makes a special sound and moves emails in to the folder "MyServers", when an email comes in with the name of one of my servers in the subject or body. Servers come and go, and the responsible person changes occasionally. I can use the GUI to modify the list, but what I want to do is use PowerShell to modify the list of servers based on a data set from a SQL query on our table of whom belongs to what. (also would be helpful when covering for someone else.)
Per PowerShell - Managing an Outlook Mailbox with PowerShell, By Joe Leibowitz, March 2013 it is possible in theory. That article and the post Hey, Scripting Guy! How Can I Tell Which Outlook Rules I Have Created? December 15, 2009 by ScriptingGuy1 have taught me how to get outlook files into PowerShell to read and or write. The post Multiple Actions for one Outlook rule in Powershell has also been helpful.
I can find several examples of creating rules, mostly around email addresses. As I did more research (below) it seems like the I want to modify 'TextRuleCondition.Text' but I am not finding any example code that gets in to reading OR modifying rule conditions for a single existing rule.
Specifying Rule Conditions
TextRuleCondition Object (Outlook)
TextRuleCondition.Text Property (Outlook)
Optimally: I would like to go to the "MyServers" rule and change the array, from what it is to a new array that I will build with PowerShell, after getting the list from a SQL table.
##source https://blogs.technet.microsoft.com/heyscriptingguy/2009/12/15/hey-scripting-guy-how-can-i-tell-which-outlook-rules-i-have-created/
## Gets outlook rules on PC
#Requires -version 2.0
Add-Type -AssemblyName microsoft.office.interop.outlook
$olFolders = “Microsoft.Office.Interop.Outlook.OlDefaultFolders” -as [type]
$outlook = New-Object -ComObject outlook.application
$namespace = $Outlook.GetNameSpace(“mapi”)
$folder = $namespace.getDefaultFolder($olFolders::olFolderInbox)
$rules = $outlook.session.DefaultStore.<Some code here gets TextRuleCondition.Text for just MyServers>
$rules ## this displays the current value
##More code inserts the array that I built earlier (not actually built, yet as I don't know what it should look like)
$rules.Save() ## this saves the changes.
Everything I have found so far programmatically creates an entire new rule from PowerShell. Nothing indicates if it is, or is not possible to modify an existing rule. My Plan "B" would be to read the existing "MyServers" rule, modify the array, and overwrite the old rule with a new one. This is problematic as it limits options, only some conditions and actions can be created programmatically.
#setup
Add-Type -AssemblyName microsoft.office.interop.outlook
$olFolders = “Microsoft.Office.Interop.Outlook.OlDefaultFolders” -as [type]
$outlook = New-Object -ComObject outlook.application
$namespace = $Outlook.GetNameSpace(“mapi”)
#get all of the rules
$rules = $outlook.Session.DefaultStore.GetRules()
#get just the rule I care about
$myRule = $rules | ? { $_.Name -eq 'My Awesome Rule' }
#build my new array of text conditions
$textValues = #('ServerA', 'NewServerB')
#replace the existing value on my rule (this is assuming you are using BodyOrSubject, you can substitute Body, Subject, etc)
$myRule.Conditions.BodyOrSubject.Text = $textValues
#save all the rules
$rules.save()
I don't appear to be able to write changes to Outlook via MAPI, the .UnRead variable is being set correctly to false within the script if you Write-Output it, but the variables don't appear to manipulate the actual .PST file. The select produces the correct emails, so read access to the .PST is fine.
Here is the code I am using to retrieve a list of unread emails from a PST folder, and set one of them to read:
$Outlook = new-object -comobject "Outlook.Application";
$Mapi = $Outlook.getnamespace("mapi");
$Pst = $Mapi.Folders.Item("Personal Folders")
$Folder = $Pst.Folders.Item("Test")
$Emails = $Folder.Items | Select UnRead, SenderEmailAddress, Subject, ReceivedTime, Body | Where {$_.Unread -eq "True"}
$Emails[1].UnRead = $false
Most examples I have seen say to place the variable in brackets, e.g.
$($Emails)[1].UnRead = $false
But this has made no difference for me.
Interestingly I get a 'method not found' error when I try to use the .delete() as well, hence I think I must be missing something.
Many thanks in advance for any advice.
Call MailItem.Save.
Do not loop through all items in a folder, use Items.Find/FindNext or Items.Restrict.
You've change property of your own object, but not on mail server
I have the following Powershell code:
$directorySearcher = New-Object System.DirectoryServices.DirectorySearcher
$directorySearche.PageSize = 100
$directorySearcher.SearchScope = [System.DirectoryServices.SearchScope]::SubTree
$searchResults = $directorySearcher.FindAll()
#$searchResults
$searchResults.Item(0).Path
If I uncomment #$searchResults then I can see hundreds of entries with "Path" and "Properties" as the objects' properties.
However when $searchResults.Item(0).Path is executed, it just says "Running script/selection. Press ctrl+break to stop." and has been like that for 10 mins so far.
Why can't I access an individual object from the SearchResultCollection ?
Turns out there were just way too many results.
I used a filter to narrow it down and now I can access individual objects since there are now only 347 results.
Before I couldn't even find out the count because there were too many.