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

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)'

Related

Powershell Convert Date format in a CSV

I have a CSV file with the following data
"Date","Time","Name","SourceIP","DestinationIP"
"Sep 1","03:55:57","mmt-5","172.16.48.158","22.22.22.22"
"Sep 1","03:55:57","mmt-5","172.16.48.158","22.22.22.22"
"Sep 1","03:55:57","mmt-5","172.16.48.158","22.22.22.22"
"Sep 1","03:55:57","mmt-5","172.16.48.158","22.22.22.22"
I would like to convert the date into something more usable like 09-01-2016 (the year would be the current year).
How can I accomplish this?
That's easy using the [DateTime] class's ParseExact method. You supply the string that is a date, you tell it how the date is formatted, and you provide a culture or provider or something, but I always just use $null.
[datetime]::ParseExact("Sep 1","MMM d",$null)
That comes out to:
Thursday, September 1, 2016 12:00:00 AM
So you could just do something like:
$Array | ForEach{[datetime]::ParseExact($_.Date,"MMM d",$null)}
And that would convert each entry's Date property to a valid [datetime] object. Then you just format it however you want:
$Array | ForEach{[datetime]::ParseExact($_.Date,"MMM d",$null).ToString("M-d-yyyy")}
That would output:
9-1-2016
Or for the exact thing you asked for use "MM-dd-yyyy" to get 09-01-2016.
Edit: Thanks to wOxxOm for educating me about the third parameter's necessity when dealing with non-localized date formats! So, if this needs to be localized for other cultures, you will need to include that last parameter. That can be done as such:
$Culture = [cultureinfo]::GetCultureInfoByIetfLanguageTag('en-US')
$Array | ForEach{[datetime]::ParseExact($_.Date,"MMM d",$Culture).ToString("MM-dd-yyyy")}
Edit2: Ok, to replace your current Date field with this information you could pass the array to the Select command, and create a new Date property on the fly, and discard the original, then pass that to Export-CSV:
$Array | Select *,#{l='Date';e={[datetime]::ParseExact($_.Date,"MMM d",$null).ToString("M-d-yyyy")}} -Exclude Date | Export-CSV D-Sample-2.csv -NoType

Working with dates in extensionAttributes and Get-Date

I'm attempting to use Active Directory extensionAttributes to keep track of certain dates (like start date, termination date, etc) so that I can trigger certain actions when that date occurs.
I'm having an issue with the different variations that a date can be entered in (M/D/YY, MM/DD/YY, MM/DD/YYYY, etc). For example, I can use Get-Date to output to a format of M/D/YYYY, but I run into issues when someone enters MM/DD/YY.
Is there a way to make this work so that it can accept other variations (as long as it's month/date/year)?
Here are a couple of lines from the script in question. This runs once a day, and checks for new users starting the following day.
$StartingOn = (Get-Date).AddDays(1).ToShortDateString()
$NewUserCheck = Get-QADUser -DontUseDefaultIncludedProperties -IncludedProperties extensionAttribute11 | where { $_.extensionAttribute11 -eq $StartingOn }
Notice how it only returns as long as the date equals the Get-Date output. It was the only way I was able to get this to work properly. Even at that, if someone typed in 07/20/15, the output would return nothing.
Don't try to compare date strings. Use DateTime comparison which won't care about formatting details e.g.:
$StartingOn = (Get-Date).AddDays(1)
$NewUserCheck = Get-QADUser -DontUseDefaultIncludedProperties -IncludedProperties extensionAttribute11 |
Where { [DateTime]($_.extensionAttribute11) -eq $StartingOn}

DeleteContent not deleting items correctly/at all

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

Powershell (exchange message search)

I've literally just C+P this code into my PowerShell, related to this question I asked on Super User.
It gives me exactly what I'm looking for but only for today's emails, can someone tell me how to add a a filter for emails the last two months for example? I looked through the code and I can't see anything related to data range so there might be another cmdlet that needs to be ran?
From a cursory glance at the script you linked, the individual emails appear to be iterated through in a foreach loop that uses the output of Get-MessageTrace as the collection of objects to iterate through. According to this documentation, Get-MessageTrace has a -StartDate and -EndDate parameter that you can specify a range of dates with.
So you just need to use those parameters to get a longer range of dates. Here's an untested example of what you'll probably need to do for the past two months:
Get-MessageTrace -StartDate (Get-Date).AddMonths(-2) -EndDate (Get-Date)
Edit: According to the parameter documentation, you may have to do some additional formatting after getting the date. I'm unfortunately not somewhere where I can test this, but here's what it says:
Use the short date format defined in the Regional Options settings for the computer on which the command is run. For example, if the computer is configured to use the short date format mm/dd/yyyy, enter 03/01/2010 to specify March 1, 2010. You can enter the date only, or you can enter the date and time of day. If you enter the date and time of day, you must enclose the argument in quotation marks ("), for example, "10/05/2010 5:00 PM".
This may not be necessary since you're already passing a DateTime object (the output of Get-Date) instead of a string... but worth mentioning, if you simply want to hard-code a string instead of getting the current time.

Powershell Variable issue and changing date format

I have a very odd thing happening in Powershell.
Here is the code:
add-pssnapin windows.serverbackup
$wbs = Get-Wbsummary
$lastbackuptime = $wbs.lastBackupTime
$solution = "Windows Server Backup"
$surl = "https://REDACTED:1338/REDACTED.asp?querysolution=$solution&querylastbackuptime=$lastbackuptime"
write-host $surl
write-host $lastbackuptime
Here is what is output when I run this
https://REDACTED:1338/REDACTED.asp?querysolution=Windows Server Backup&querylastbackuptime=05/07/2013 05:04:12
07/05/2013 05:04:12
Why is powershell swapping the date around when made as part of another variable but not when I output the variable on its own?!
This is a special case with casting a datetime object. When you simply print the date as a string using write-host, that will be equal to running $lastbackuptime.toString(). This method uses the culture of you're computer. In my case, the culture in Region settings for Windows is Norway, so I get the "european" dateformat: dd/mm/yyyy.
However, when you include $lastbackuptime inside a string, it performs a cast to a string-object. In PowerShell(or .Net) it was decided that when casting a datetime-object, it should use a standard format to convert it to string so that the code would run the same no matter what culture the computer was configured with. That's why casting gives you the US format, while toString() and Write-Host gives the "european" format
Ex:
[16:07:43] PS-ADMIN C:\> $d.tostring()
07.05.2013 16:04:17
[16:13:05] PS-ADMIN C:\> write-host $d
07.05.2013 16:04:17
[16:13:12] PS-ADMIN C:\> [string]$d
05/07/2013 16:04:17
To specify the format your datetime should be displayed, you can do something like this:
[16:14:28] PS-ADMIN C:\> $d.tostring("dd/MM/yyyy")
07.05.2013
[16:14:34] PS-ADMIN C:\> "examplestring $($d.tostring("dd/MM/yyyy"))"
examplestring 07.05.2013
Read more here
Check your regional settings, specifically the Short Date & Long Date formats.
On my system, Short Date is MM/dd/yyyy and and Long Date is dddd, MMMM dd,yyyy. Then, running a simplified version of your example:
>$lastbackuptime = get-date;
>$lastbackuptime
Tuesday, May 07, 2013 10:07:42
>$url="http://whatever/redacted.asp?time=$lastbackuptime";
>$url
http://whatever/redacted.asp?time=05/07/2013 10:07:42
When used on its own, the Long Date format is used in returning the date, but when concatenated with (or expanded inside) another string the Short Date format is used.