DeleteContent not deleting items correctly/at all - powershell

To preface this all, I am running this script in the US against a US mailbox server. The mail that I am wanting to delete is also mail that I have exported to a PST.
The mailbox Export uses a ContentFilter while a deleteContent uses a SearchQuery. These 2 acts of grabing information seem to act very different to me.
I have successfully been able to export the mail I want to a PST, however deleting the content has been posing a huge problem.
I am trying to delete mailbox items that are before the current get-date using the code below. I swear I have been following Microsoft's documentation on this, however nothing is working for me.
$date = (get-date -hour 00 minute 00 second 00).ToShortDateString()
Search-Mailbox -Identity "id" -SearchQuery "Received:<$($date)" -deleteContent -force
This is not working. I am getting an error:
The property keyword isn't supported.
+ CategoryInfo : InvalidArgument: (:) [], ParserException
Please see edits below as I have fixed my string, however the issue still persists. It seems as though the < is what is messing up the query.
EDIT
"Received:<'$date'" - This executes when I specify it as my SearchQuery however no results come back.
It seems like the < is what is messing up my query. Once I remove the < and leave the query as "Received:'$date'" it deletes all emails from todays date.
Also, it appears that the time is offset by 5 hours when doing this. I am in the US and the mailbox server I am running this on is in the US, yet it is still acting like it could be using UTC time. How do I fix this? More importantely though, why isn't my less than working.
EDIT 2:
I have also attempted to do querys such as "Received -lt '$date'" this is not working also.

Try: $date.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
While the above will get you an ISO 8601 datetime, it doesn't look like the search query is using the full thing. I did find that the below syntax seem to work at least for the date part:
$date = (get-date).Date.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
Search-Mailbox -Identity "id" -SearchQuery "Received<$date" -deleteContent -force
The SearchQuery argument is using KQL, which is documented at: http://msdn.microsoft.com/en-us/library/office/ee558911(v=office.15).aspx
Unfortunately since it seems Exchange is ignoring the time part, I'm guessing that this is going to be limited to filtering at UTC midnight. Looking at the docs, there is shorthand that will give you the same results:
Search-Mailbox -Identity "id" -SearchQuery "Received<today" -deleteContent -force

Related

Set Expiry Date with CSV containing DD-MMM-YYYY format

Our HR Department's Termination system sends us a report at intermittent intervals of people who are leaving/people who have left.
Import-Csv -Path \C\Users\Leaver.csv | ForEach-Object {
$EmployeeNumber = $_.EmployeeNumber
$TerminationDate = $_.TerminationDate
$objADUser = (Get-ADUser -Filter {employeeid -eq $EmployeeNumber}).samAccountName
}
The report that HR give us doesn't have their sAMAccountName or even their email. Fortunately, it does have their Employee ID. I'm using this in the script to get their SAM name since I figure that's easier to work with.
Problem is, the termination date they give is actually the last day they work, not the first day of non-work.
Normally I'd have
Set-ADAccountExpiration -Identity $objADUser -DateTime "$TerminationDate"
But that means they can't work on their last day. I also can't add a time like "23:59:59" as Powershell doesn't seem to like that with a variable.
There's also the fact that the date format is in DD-MMM-YYYY (EG 01-Jan-2000) which does make it difficult to work with.
Anyone know what the best syntax to use here is?

Working with unusual date formats in Powershell?

I am working on a GUI-based Powershell tool to help users easily find out when their AD password is going to expire. Due to Covid restrictions, most users and not on-site and rely on VPN to connect to AD. A by-product of this is that many do not see the automatic pop-up in Windows to remind them of them to set a new password soon. Those that are on-site see the notification OK. It's a not a group-policy problem. The tool will be will be rolled-out in two different languages - one representing the 'mothership' (where is English is not normally spoken) and English for all other countries.
Some of the (mostly) Eastern European countries use a short date format that reads like 'd.M.yyyy.' - according to settings menu when one changes the 'Region' setting in Windows.
The tool calculates the difference between today and the expiry data and outputs the number of days to a text field. The actual expiry is display correctly in its own text field.
Some of the source code behind it all...
$thisUser = [Environment]::UserName
#make string
"net user " + $thisUser + " /domain"
#make cmd string
$fetch_net_user = "net user " + $thisUser + " /domain"
#execute command and store to variable
$net_user_data_array = Invoke-Expression $fetch_net_user
#Gets password expiry date (with header)
$password_expiry_with_header = $net_user_data_array[11]
#extracts only the date and assigns to new variable (the hours and minutes) can be ignored)
$password_expiry_as_string = $password_expiry_with_header.Split(' ')[-2]
# Home countries - works OK
try{
$password_expiry_as_dateTime = [datetime]::ParseExact($password_expiry_as_string, 'dd.MM.yyyy', $null)
}
# Others - works OK
catch{
$password_expiry_as_dateTime = [datetime]::ParseExact($password_expiry_as_string, 'dd/MM/yyyy', $null)
# where problem occurs
catch{
$password_expiry_as_dateTime = [datetime]::ParseExact($password_expiry_as_string, 'd.M.yyyy.', $null)
}
finally{
#show GUI error window...
}
#fetch date... converted to yesterday to fix an off-by-one bug!
$today = Get-Date
$rightNow = $today.AddDays(-1)
#calc days left
$daysRemaining = (New-TimeSpan -Start $rightNow -End $password_expiry_as_dateTime).Day
# some other code follows, manipulating date values etc. Works with most date formats.
When executed the script will throw several errors.
The first is...
Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime."
Others will follow such as
You cannot call a method on a null-valued expression.
As the difference between today and the expiry date cannot be calulated.
Is there any easy fix for this? I'd rather avoid having to write a long list of 'if' statments for each country/culture. Thanks!
I'm sure the code could be a little bit more elegant, and that will be addressed in a later version. Right now, getting it to work some of the more obscure date formats is my priority.
Something else that I should stress is that this tool works in a 'read only' capacity. No 'Set-Item' commands are used.
Regards,
WL
You have 2 problems:
Multiple date formats used interchangeably
Trailing dots on some strings
The first problem can be solved by passing multiple format strings to ParseExact() - it'll try each in order until it successfully parses the input string (or reaches the end of the list):
[datetime]::ParseExact($password_expiry_as_string, [string[]]#('dd.MM.yyyy', 'dd/MM/yyyy', 'dd.M.yyyy', 'd.M.yyyy'), $null, [System.Globalization.DateTimeStyles]::None)
The second problem can be solved by trimming trailing dots:
[datetime]::ParseExact($password_expiry_as_string.TrimEnd('.'), [string[]]#('dd.MM.yyyy', 'dd/MM/yyyy', 'dd.M.yyyy', 'd.M.yyyy'), $null, [System.Globalization.DateTimeStyles]::None)

How to create specific user log files in PowerShell?

I know there are question that is already answered however those are the log files I don't need and I can't get it to work. This part of PowerShell is something I didn't learned yet. I'm trying to do the following: I wrote a script to create users, mailboxes, folders etc however I want to enable a log file, just simple and plain.
Something only certain people can access and where the log files have the following info, for example: PSmith created on 01/29/2019 the user account JDoe.
How can I do this? I tried a lot found online however I have to rewrite my whole script for some to work.
Easiest option: you can enable transcript which would log every single command that is entered at the console potentially creating a huge file but you would have to filter for the specific messages yourself.
There are tools like microsoft orchestrator that would run your script and log the results automatically but those are expensive other than that you would pretty much have to build the logging yourself.
My suggestion would be to send the message to the windows event logs. This way you dont have to manage the log files, windows does it for you with date and time stamps. This would also make it audit and query friendly.
I believe you need something like this, if not please provide more code.
$creator = (get-aduser $env:username | Select Name).Name
$date = get-date -UFormat "%d/%m/%Y"
I believe you have the $user in your script.
$log = $creator + "created on " + $date + " the user account " + $user.Name
Out-File $log "C:\temp\log.csv"

How to use dynamic dates in a Search-Mailbox query?

I have this PowerShell snippet to delete e-mail between 2 dates:
Search-Mailbox -Identity <username> -SearchQuery '(Received:09/20/2012..10/12/2012)' -deletecontent
I want to make it dynamic so that it deletes e-mail older than 6 months. How can I calculate the date of 6 months ago to use in this snippet?
I have tried:
$date = (Get-Date).AddMonths(-6)
Search-Mailbox -Identity Sales -SearchQuery '(Received:<$date)' -DeleteContent
but it shows the error message:
The property keyword isn't supported.
$date is a System.DateTime object. When converted to a string it will show both date and time information which is dependent on your regional settings. This is what mine looks like:
PS M:\Scripts> $date = (Get-Date).AddMonths(-6)
PS M:\Scripts> $date
Sunday, March 27, 2016 9:30:20 AM
PS M:\Scripts> "$date"
03/27/2016 09:30:20
That last line does not meet the standards required by KQL (Keyword Query Language)
YYYY-MM-DD
YYYY-MM-DDThh:mm:ss
YYYY-MM-DDThh:mm:ssZ
YYYY-MM-DDThh:mm:ssfrZ
Since you just want the date portion lets just get that.
(Get-Date).AddMonths(-6).ToShortDateString()
3/27/2016
While that does not use hyphens, in my case, it appears the syntax allows for it in your test cases. There are oodles of ways to format dates in PowerShell. Here is one that conforms to the syntax in TechNet
(Get-Date).AddMonths(-6).ToString("yyyy-MM-dd")
2016-03-27
Point is you have to do something that will satisfy your query syntax. Test some string without -deletecontent first or just write the string to console to see what it looks like.
For a span of time you would use one of the above suggestions and, assuming you save those string results in variables, it would look something like this:
-SearchQuery '(Received:$fromDate..$toDate)'

Exchange 2010 powershell weirdness

About 3 or 4 times a week a clever spammer gets a message through my Sonicwall ESA and I need to scrub it from the exchange server. I'm network admin at a school, and students are suckers for that stuff. I run the following command as a global admin on my exchange server power shell:
Get-Mailbox -ResultSize Unlimited | Search-Mailbox -SearchQuery 'Subject:"Re-Please Update Your Password‏"' -DeleteContent
The odd thing is, about 99 out of 100 times it works. Within a few minutes the message with the aforementioned email disappears from my inbox and I go about my day. Once in a while, like today with the exact command listed above, I get a stubborn email that just won't go. At first I thought it was choking on the dash, so I changed the command to:
Get-Mailbox -ResultSize Unlimited | Search-Mailbox -SearchQuery 'Subject:"Please Update Your Password‏"' -DeleteContent
Still no joy. I'm not getting any errors, the command appears to run like normal. Anyone else run into this before? Any pointers?
Thanks.
-Bishop
I've had similar issues, tho they were more obvious (multiple [8-12] spaces). So instead of running the command over and over increasing the spaces in the query or configuring an expression for every case, I just grabbed the subjectline itself.
find the message in your mailbox, pull the subject into a variable, use that as the Searchquery.
-FS