Scenario: A user is a member of multiple security and distribution groups and you wish to determine which of these groups are distribution.
Script:
$1 = (Get-ADUser STEVE -Properties Memberof).memberof
$2 = $1 | %{Get-DistributionGroup $_}
Scenario: A user is a member of multiple security and distribution groups and you wish to determine which of these groups are distribution.
Script:
$1 = (Get-ADUser STEVE -Properties Memberof).memberof
$2 = $1 | %{Get-DistributionGroup $_}
Scenario: You want to schedule a task remotely via Powershell on remote systems:
Script:
$Servers = "Win2012Svr1", "Win2012Svr2","Win2012Svr3" $Servers |%{ Invoke-Command { $action = New-ScheduledTaskAction -Execute 'C:TaskClientStatsClientStats.bat' $trigger = New-ScheduledTaskTrigger -Daily -At 1am Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "ClientStats" -Description "Daily Stat Dump" -user "domainadmin" -password "adminpassword1" -runlevel Highest } -ComputerName $_ }
Scenario: You have a list of PST files that you want to import into a mailbox. You want to place the imports into a folder in the mailbox called ‘Imported’ so it doesn’t conflict with the users current mailbox folder structure.
Here is what you have:
Script: The script below will take the list of users in the csv format, loop through each user to find their PST’s. For each PST it will create a New Mailbox Import Request. Note – Make sure your properly plan space as you could potentially blow up your database/log size.
#Import the users from the CSV File $users = Import-csv C:tempusers.csv #Loop through each user $users | %{ $u = $_ | Select -ExpandProperty Name #Find the PST files for the user in this loop $files = get-childitem \FileServer1SharePSTs -file $u* -Recurse #For each PST file, Create a Mailbox Import Request $files.fullname | %{ New-mailboximportrequest $u -filepath $_ -acceptlargedataloss -baditemlimit 100000 -batchname BigImport -targetrootfolder Unarchived } }
Scenario: You try to send a message with an attachment to a recipient but you receive a bounce/undeliverable message that shows this error.
Remote Server returned ‘550 5.3.4 SMTPSEND.OverAdvertisedSize; message size exceeds fixed maximum size’
When sending the message, although the message size is close to the max message size set by Exchange, it still falls under the max message size. For Example: The maximum message size that your email servers will allow is 35MB, and the message you want to send has a size of 30MB.
Cause for the bounce: There is a message size conversion when passing off between different message relays. Sometimes this conversion can be up to a 30% increase of the original message size. For example, when the message is received in Exchange it shows 30MB. When the message is passing through the send connector, a size conversion takes place on the message and when Exchange attempts to send it through the send connector to the next message relay, it reads 38MB. This 38MB exceeds the 35MB limit set on the next message relay and it causes a bounce/undeliverable message.
You can see the size conversion in the TotalBytes field by running a command similar to the following:
get-tranpsortserver | Get-messagetrackinglog -MessageSubject “Big Attachment” -start 1/28/2015 | Sort TimeStamp | Select ServerHostname, Source , EventID, TotalBytes
*In my experience, the type of message attachment influences the size conversion for the message.
WorkaroundResolution:
The easy solution is to just zip the attachment and make it smaller and then attempt to pass it through. Else you need to increase your maximum message size limits on your message relays to account for the increase caused by the conversion. For Example, if you truly want to allow a 35MB attachment and account for a 30% message size increase, your maximum message size needs to be 45.5MB.
Scenario: You want to enable mailbox auditing on a mailbox and you want to log all actions performed by Admins, Delegates, and Owners. You also want to retrieve the audit entries into a easy to read format.
Enable Auditing on a Mailbox: By default, mailbox auditing is disabled but the audit options are already pre-set for Admin and Delegates. You will need to enable mailbox auditing and set the actions for the owner of the mailbox as well by running this command:
set-mailbox testuser1 -AuditEnabled $true -AuditOwner Update,Move,MoveToDeletedItems,SoftDelete,HardDelete,Create
To view the audit status for a mailbox:
get-mailbox testuser1 | FL *Audit*
View Audit Log entries
To view the log entries for an audit, you can run the following command-lets.
#Edit the following Variables $Mailbox = "testuser1" #Mailbox that has Auditing Enabled $hours = "48" #Hours to search back from $myDir = "C:temp" $mailto = "steve@domain.com" $MailFrom = "steve@domain.com" $ReportemailSubject = "Audit Log Results for $Mailbox" $MailServer = "smtp.domain.com" #Static Variables $reportemailsubject = "Mailbox Audit Logs for $mailbox in last $hours hours." $rawfile = "$myDirAuditLogEntries.csv" $htmlfile = "$myDirAuditLogEntries.html" $smtpsettings = @{ To = $MailTo From = $MailFrom Subject = $reportemailsubject SmtpServer = $MailServer } Write-Host "Searching $mailbox for last $hours hours." $auditlogentries = @() $identity = (Get-Mailbox $mailbox).Identity $auditlogentries = Search-MailboxAuditLog -Identity $mailbox -LogonTypes 'Delegate','Owner','Admin' -StartDate (Get-Date).AddHours(-$hours) -ShowDetails if ($($auditlogentries.Count) -gt 0) { Write-Host "Writing raw data to $rawfile" $auditlogentries | Export-CSV $rawfile -NoTypeInformation -Encoding UTF8 foreach ($entry in $auditlogentries) { $reportObj = New-Object PSObject $reportObj | Add-Member NoteProperty -Name "Mailbox" -Value $entry.MailboxResolvedOwnerName $reportObj | Add-Member NoteProperty -Name "Mailbox UPN" -Value $entry.MailboxOwnerUPN $reportObj | Add-Member NoteProperty -Name "Timestamp" -Value $entry.LastAccessed $reportObj | Add-Member NoteProperty -Name "Audit Logon Type" -Value $entry.LogonType $reportObj | Add-Member NoteProperty -Name "Accessed By" -Value $entry.LogonUserDisplayName $reportObj | Add-Member NoteProperty -Name "Operation" -Value $entry.Operation $reportObj | Add-Member NoteProperty -Name "Result" -Value $entry.OperationResult $reportObj | Add-Member NoteProperty -Name "Folder" -Value $entry.FolderPathName if ($entry.ItemSubject) { $reportObj | Add-Member NoteProperty -Name "Subject Lines" -Value $entry.ItemSubject } else { $reportObj | Add-Member NoteProperty -Name "Subject Lines" -Value $entry.SourceItemSubjectsList } $report += $reportObj } $htmlbody = $report | ConvertTo-Html -Fragment $htmlhead="<html> <style> BODY{font-family: Arial; font-size: 8pt;} H1{font-size: 22px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;} H2{font-size: 18px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;} H3{font-size: 16px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;} TABLE{border: 1px solid black; border-collapse: collapse; font-size: 8pt;} TH{border: 1px solid #969595; background: #dddddd; padding: 5px; color: #000000;} TD{border: 1px solid #969595; padding: 5px; } td.pass{background: #B7EB83;} td.warn{background: #FFF275;} td.fail{background: #FF2626; color: #ffffff;} td.info{background: #85D4FF;} </style> <body> <p>Report of mailbox audit log entries for $mailbox in the last $hours hours.</p>" $htmltail = "</body></html>" $htmlreport = $htmlhead + $htmlbody + $htmltail Write-Host "Writing report data to $htmlfile" $htmlreport | Out-File $htmlfile -Encoding UTF8 Write-Host "Sending email" Send-MailMessage @smtpsettings -Body $htmlreport -BodyAsHtml -Encoding ([System.Text.Encoding]::UTF8) -Attachments $rawfile } Write-Host "Finished."
Scenario: When connecting to Exchange PowerShell without the Exchange management tools installed, you get the following error message when trying to convert the mailbox size to another Size unit. For example: With the Exchange Management tools installed, you can run the following command successfully:
Get-MailboxStatistics user1 | Select {$_.TotalItemSize.Value.ToMB()}
But when you connect to Exchange Powershell via a session without the Exchange Management tools installed, you receive the following error:
Method Invocation failed because [Deserialized.Microsoft.Exchange.Data.ByteQuantifiedSize] does not contain a method named ‘ToMB’
Solution: To work around this problem:
#Collect Mailbox Stats $stat_o365 = get-mailbox -resultsize unlimited | Get-mailboxstatistics #Loop the stats $stat_o365 | %{ $Name = $_.displayname $TIS = [string]$_.TotalItemSize $TDIS = [string]$_.TotalDeletedItemSize #start the value manipulation $regex = [regex]"((.*))" $TISstring = [regex]::match($TIS, $regex).Groups[1] $TDISstring = [regex]::match($TDIS, $regex).Groups[1] $TISString = $TISString -replace "Bytes","" $TDISString = $TDISString -replace "Bytes","" #Convert the strings to Int $TDISValue = [INT]$TDISString $TISValue = [INT]$TISString #Add the Mailbox Size and round to the nearest MB $TotalSize = [Decimal]::Round((($TDISValue + $TISValue)/1024)/1024) }
Scenario: You want a Powershell method for finding any services that are set to start automatically but have stopped in error or by failure.
Solution: The script below looks for any Exchange servers that start with 2013* and then uses the logic “Find a Service that is set to Automatic that is currently not running and an Exit Code of the service is not 0” for each server. Then attempt to restart that service on each server. An exit code of 0 means the service was stopped manually OR stopped by Windows as it was no longer required to run. Here is a list of Error Code/Exit Code descriptions: Exit Code Descriptions
#Collect Servers into a Variable $1 = Get-exchangeserver 2013* #Collect Services that are not started due to failure or error $2 = $1 |%{Get-CimInstance win32_service -Filter "startmode = 'auto' AND state != 'running' AND Exitcode !=0 " -ComputerName $_ | select systemname, name, startname, exitcode} #View the Services that are stopped for each server $2 #Restart each failed service $2 | %{Get-service $_.Name -computername $_.SystemName | Start-service -passthru}
Scenario: You want to non-invasively search a mailbox in order to find content between a date range.
Solution: Run the following command(s):
search-mailbox userid -searchquery “kind:Email AND Received:1/1/1900..08/01/2014” -EstimateResultOnly
Note: You can remove estimateresultonly and replace with TargetMailbox and TargetFolder to export the queried contents of the mailbox to view the messages. You can also use the following KIND variables to target certain message types in your search:
Email
Meetings
Tasks
Notes
Docs
Journals
Contacts
IM
Scenario: You want a script that will perform the following:
Script:
#Define Variables $age = 180 $final_DeviceCount = @() $report = @() $file = $(((get-date).ToUniversalTime()).ToString("yyyyMMddThhmmssZ")) $filename = "C:tempeas_stat_"+$file+".csv" $today = get-date $final = @() $BreakLine = " " $stats = @("FirstSyncTime", "LastPolicyUpdateTime", "LastSyncAttemptTime", "LastSuccessSync", "DeviceType", "DeviceID", "DeviceUserAgent", "DeviceWipeSentTime", "DeviceWipeRequestTime", "DeviceWipeAckTime", "LastPingHeartbeat", "RecoveryPassword", "DeviceModel", "DeviceImei", "DeviceFriendlyName", "DeviceOS", "DeviceOSLanguage", "DevicePhoneNumber", "MailboxLogReport", "DeviceEnableOutboundSMS", "DeviceMobileOperator", "Identity", "Guid", "IsRemoteWipeSupported", "Status", "StatusNote", "DeviceAccessState", "DeviceAccessStateReason", "DeviceAccessControlRule", "DevicePolicyApplied", "DevicePolicyApplicationStatus", "LastDeviceWipeRequestor", "ClientVersion", "NumberOfFoldersSynced", "SyncStateUpgradeTime", "ClientType", "IsValid", "ObjectState" ) #Define Email Variables: $smtp = "smtp.domain.com" [string[]]$to = "steve@domain.com" $from = "MobileDeviceStats@domain.com $subject = "Mobile Device Stats using ActiveSync" #Define HTTP Style $b = "<style> BODY{ font-family: Arial; font-size: 10pt; } TABLE{ border: 1px solid black; border-collapse: collapse; } TH{ border: 1px solid black; background: #dddddd; padding: 5px; } TD{ border: 1px solid black; padding: 5px; } </style>" #=========Begin Script=========== #Calculate Mailboxes with EAS Device Partnership $MailboxesWithEASDevices = @(Get-CASMailbox -Resultsize Unlimited -erroraction SilentlyContinue | Where {$_.HasActiveSyncDevicePartnership} | Select Identity,SAMAccountName) $MailboxesWithEASDevices = $MailboxeswithEasDevices | Sort SAMAccountName #Loop Through Each Mailbox Foreach ($Mailbox in $MailboxesWithEASDevices) { $EASDeviceStats = @(Get-MobileDeviceStatistics -Mailbox $Mailbox.Identity) Write-Host "$($Mailbox.SAMAccountName) has $($EASDeviceStats.Count) device(s)" #Build the Array $ServerObj = New-Object PSObject $ServerObj | Add-Member NoteProperty -Name "Alias" -Value $Mailbox.SAMAccountName $ServerObj | Add-Member NoteProperty -Name "DeviceCount" -Value $EASDeviceStats.Count $Final_DeviceCount += $ServerObj $MailboxInfo = Get-Mailbox $Mailbox.Identity | Select DisplayName,PrimarySMTPAddress,Alias Foreach ($EASDevice in $EASDeviceStats) {$LastSuccessSync = ($EASDevice.LastSuccessSync) if ($LastSuccessSync -eq $null) { $syncAge = "Never" } else { $syncAge = ($today - $LastSuccessSync).Days } $reportObj = New-Object PSObject $reportObj | Add-Member NoteProperty -Name "DisplayName" -Value $MailboxInfo.DisplayName $reportObj | Add-Member NoteProperty -Name "EmailAddress" -Value $MailboxInfo.PrimarySMTPAddress $reportObj | Add-Member NoteProperty -Name "Alias" -Value $MailboxInfo.Alias $reportObj | Add-Member NoteProperty -Name "SyncAgeInDays" -Value $syncAge Foreach ($stat in $stats) { $reportObj | Add-Member NoteProperty -Name $stat -Value $EASDevice.$stat } $report += $reportObj } } $report | Export-csv $filename $TotalDevices = $report.count $TotalMailboxes = $MailboxesWithEASDevices.Count $AvgPerMailbox = $TotalDevices / $TotalMailboxes $LastSync180 = ($Report | Where SyncAgeInDays -ge $age).count $Top10DeviceTypes = $Report | group DeviceType | Sort Count -Descending | Select Count,Name -first 10 | ConvertTo-Html -head $b $Top10Users = $final_DeviceCount | Sort DeviceCount -Descending | Select Alias,DeviceCount -first 10 | ConvertTo-Html -head $b $PolicyApplied = $report | Group DevicePolicyApplied | Sort Count -Descending | Select Count,Name | ConvertTo-Html -head $b $body ="" $attachment = $filename $body += "<Font color=black>Attached are the Mobile Device Statistics within the entire OnPremise Exchange Organization using ActiveSync.</font><br><br><br>" $body += "<b><Font color=#00008B>Total devices:</b><Font color=black> $TotalDevices</font><br><br>" $body += "<b><Font color=#00008B>Total mailboxes that have a device:</b><Font color=black> $TotalMailboxes</font><br><br>" $body += "<b><Font color=#00008B>Average Devices Per User:</b><Font color=black> $AvgPerMailbox</font><br><br>" $body += "<b><Font color=#00008B>Devices with last sync time older than $age days:</b><Font color=black> $LastSync180</font><br><br>" $body += "<b><Font color=#00008B>ActiveSync policy applied on all mailboxes:</b> $PolicyApplied</font><br><br>" $body += "<b><Font color=#00008B>Top 10 device types:</b></font><br><br>" $body += "<Font color=black>$Top10DeviceTypes</font><br><br><br>" $body += "<b><Font color=#00008B>Top 10 users by device count:</b></font><br><br>" $body += "<Font color=#00008B>$Top10Users</font><br><br><br>" send-MailMessage -SmtpServer $smtp -To $to -From $from -Subject $subject -Body $body -BodyAsHtml -Priority high -Attachments $attachment #=========End Script===========
Scenario: When you attempt to run Get-MailboxDatabase -includePreExchange2013, you get the following error:
The Exchange server for the database object ‘DB11’ wasn’t found in Active directory Domain Services. The object may be corrupted.
You then discovered the mailbox server that used to host the database no longer exists in your organization and was forcibly removed via ADSIEdit.
Resolution: Remove the orphaned databases via ADSIEdit: