Exchange - listing mailboxes in an OU with their mailbox size - powershell

I'm trying to display all the mailboxes and their sizes for all our users in our Departed OU. I seem to be very close but my command seems to be adding some padding to the results.
[PS] C:\Windows\system32>dsquery user "ou=Departed,ou=Staff,dc=COMPANY,dc=local" -limit 4 | dsget user -samid | Get-MailboxStatistics | ft DisplayName, TotalItemSize, ItemCount
And the output:
Dsquery has reached the specified limit on number of results to display; use a different value for the -limit option to
display more results.The specified mailbox " samid " doesn't exist.
+ CategoryInfo : NotSpecified: (0:Int32) [Get-MailboxStatistics], ManagementObjectNotFoundException
+ FullyQualifiedErrorId : DD7D7CEA,Microsoft.Exchange.Management.MapiTasks.GetMailboxStatistics
The specified mailbox " Eka.Tian " doesn't exist.
+ CategoryInfo : NotSpecified: (1:Int32) [Get-MailboxStatistics], ManagementObjectNotFoundException
+ FullyQualifiedErrorId : 7F701DFD,Microsoft.Exchange.Management.MapiTasks.GetMailboxStatistics
Obviously shouldnt work for the first result "samid" but "Eka.Tian" exists. Why is it adding all those spaces? Is there a way I could format the output from dsget user so it plays nice with Get-MailboxStatistics?

Why the dsquery?
get-mailbox -OrganizationalUnit "ou=Departed,ou=Staff,dc=COMPANY,dc=local" -resultsize unlimited |
get-mailboxstatistics | ft DisplayName,TotalItemSize,Itemcount

I've got something for you, even though it's a little late.
You just need to adjust every Searchbase with OU and DC, the Email-Adresses at the end and the SMTP-Server, then you get an Email with a CSV-Attachment that contains every OU with Counts of active and inactive Mailboxes and a list with every mailbox and its parameters.
You can also trigger it with the Task-Scheduler of Windows, so it's an automatic report.
Add-PSSnapin Microsoft.Exchange.Management.Powershell.SnapIn;
$Kunden=Get-ADOrganizationalUnit -Filter * -SearchBase "OU=Kunden,DC=domain,DC=domain"
$leerzeile ="`n"
#Funktion für 10 GB Kontrolle
function getUber10 ($name)
{
$Uberschreit=0
$anzahluber10=0
$anzahl=0
$UserList = Get-Mailbox -OrganizationalUnit "$name" |Get-MailboxStatistics
$großen = $UserList |Select TotalItemSize
for($y=0; $y -lt $großen.Length; $y++){
if($großen[$y].totalItemSize.value.toMB() -gt 10000){
$wieoft=$großen[$y].totalItemSize.value.toMB() * 0.0001
$anzahluber10 = $anzahluber10 + [Math]::Ceiling($wieoft) - 1
}
}
$anzahluber10
}
#Liste aller Kunden mit Postfachanzahl
Get-ADOrganizationalUnit -Filter * -SearchBase "OU=Kunden, DC=domain, DC=domain" |Select-Object Name, #{n="Postfach-Anzahl";e = {(Get-ADUser -Filter {(EmailAddress -like "*#*") -and (Enabled -eq "True")} -SearchBase $_).count}},`
#{n="Deaktivierte Postfächer";e = {(Get-ADUser -Filter {Enabled -eq "False"} -SearchBase $_).count}}, #{n="10GB-Überschreitungen"; e={ getUber10 -name $_}} `
| ConvertTo-Csv -Delimiter ";" -NoTypeInformation | % {$_.Replace('"','')} | Out-File C:\ExchangeReport.csv -Append
$leerzeile | Out-File C:\ExchangeReport.csv -Append
$leerzeile | Out-File C:\ExchangeReport.csv -Append
#Liste der einzelnen Kunden mit Details der Postfächer
For($i=1; $i -lt $Kunden.Length; $i++){
$Kunde=$Kunden[$i]
$Uberschreit=0
$anzahluber10=0
$anzahl=0
$UserList = Get-Mailbox -OrganizationalUnit "$Kunde" |Get-MailboxStatistics
$großen = $UserList |Select TotalItemSize
for($x=0; $x -lt $großen.Length; $x++){
if($großen[$x].totalItemSize.value.toMB() -gt 10000){
$wieoft=$großen[$x].totalItemSize.value.toMB() * 0.0001
$anzahluber10 = $anzahluber10 + [Math]::Ceiling($wieoft) - 1
}
}
Get-ADOrganizationalUnit -Identity $Kunden[$i] |Select-Object Name, #{n="Postfach-Anzahl";e = {(Get-ADUser -Filter {(EmailAddress -like "*#*") -and (Enabled -eq "True")} -SearchBase $Kunde).count}}`
,#{n="Deaktivierte Postfächer";e = {(Get-ADUser -Filter {Enabled -eq "False"} -SearchBase $_).count}},#{n="10GB-Überschreitungen"; e={$uberschreit= $anzahluber10 ; $uberschreit}}`
| ConvertTo-Csv -Delimiter ";" -NoTypeInformation | % {$_.Replace('"','')} | Out-File C:\ExchangeReport.csv -Append
Get-Mailbox -OrganizationalUnit "$Kunde" |Select-Object #{n="Kundenname";e={Get-ADOrganizationalUnit -Identity $Kunden[$i] |Select-Object Name}}, Displayname, PrimarySmtpAddress, `
#{n="Size(MB)";e = {$Fachstat = Get-MailboxStatistics $_.name;$Fachstat.totalItemsize.value.toMB()}}, #{n="Quota";e={$Fachquot=Get-Mailbox $_.name;$Fachquot.ProhibitSendReceiveQuota}},`
#{n="Aktiv?"; e={Get-ADUser $_.DistinguishedName |select Enabled}}, #{n="Über 10GB?"; e={$uber10 = Get-MailboxStatistics $_.name; if($uber10.totalItemSize.value.toMB() -gt 10000){$uber10.IsValid}else{$uber10.IsQuarantined}}} `
| ConvertTo-Csv -Delimiter ";" -NoTypeInformation | % {$_.Replace('"','')} | % {$_.Replace('#{Name=','')} | % {$_.Replace('}','')} | % {$_.Replace('#{Enabled=','')} | Out-File C:\ExchangeReport.csv -Append
$leerzeile | Out-File C:\ExchangeReport.csv -Append
$leerzeile | Out-File C:\ExchangeReport.csv -Append
}
$Date = Get-DAte -UFormat "%d.%m.%Y"
Send-MailMessage -to "empfänger#domain.domain" -from "administrator#domain.domain" -Subject "Exchange-Report" -body "Exchange Report of $Date" -SmtpServer "External IP" -Attachments "C:\ExchangeReport.csv"
Remove-Item C:\ExchangeReport.csv
I wrote the variables etc. in German, I hope thats no problem ;)

Related

Exchange 2010 Powershell - Return Users With SendAs Permissions But Filter Disabled Users

so I have a script that works fine that I found online and changed to suit my needs. I have pasted this script below. However, in the output there is a lot of disabled users that have permissions to the mailboxes. E.g. I'd get an Output like "Mailbox Name^Mailbox#email.com^ActiveUser ActiveUser DisabledUser" So I am wondering if there is a way to make the script skip disabled users, same way how it leaves out self permissions.
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
. $env:ExchangeInstallPath\bin\RemoteExchange.ps1
Connect-ExchangeServer -auto
$OutFile = “C:\Send_As_Permissions.txt”
“DisplayName” + “^” + “Email Address” + “^” + “Send As” | Out-File $OutFile -Force
$Mailboxes = Get-Mailbox -resultsize unlimited | Select Identity, Alias, DisplayName, DistinguishedName, WindowsEmailAddress
ForEach ($Mailbox in $Mailboxes) {
$SendAs = Get-ADPermission $Mailbox.identity | where {($_.ExtendedRights -like “*Send-As*”) -and -not ($_.User -like “NT AUTHORITY\SELF”) -and -not ($_.User -like “s-1-5-21*”)} | % {$_.User}
$Mailbox.DisplayName + “^” + $Mailbox.WindowsEmailAddress + “^” + $SendAs | Out-File $OutFile -Append
}
If you want to report on enabled mailboxes only, filter the output from Get-Mailbox on the IsMailboxEnabled property:
$Mailboxes = Get-Mailbox -resultsize unlimited | Where-Object { $_.IsMailboxEnabled } | Select ...
If you want to report on individual rights assignments for enabled accounts only, you'll have to query AD based on the value of the User property you extract:
$SendAs = Get-ADPermission $Mailbox.identity | where {($_.ExtendedRights -like “*Send-As*”) -and -not ($_.User -like “NT AUTHORITY\SELF”) -and -not ($_.User -like “s-1-5-21*”)} | % {$_.User}
$domain,$username = $SendAs.Split('\')
$ADUser = Get-ADUser -Identity $username -Server $domain
if($ADUser.Enabled){
# output to report
}

Find computers that are not members of a specific GG group

I use a script to export users that are not in specific GG groups in active directory but I want to do the same with computers.
This is the example that works with users:
$groups = 'GG_LCS_UsersType4', 'GG_LCS_UsersType3', 'GG_LCS_UsersType2', 'GG_LCS_SpecialUsers'
$whereFilter = $groups | Foreach-Object {
$g = (Get-ADGroup -server $domain $_).DistinguishedName
"{0} '{1}'" -f '$_.memberOf -notcontains',$g
}
$whereFilter = [scriptblock]::Create($whereFilter -join " -and ")
$users = (Get-ADUser -server $Domain -filter {objectclass -eq "user"} -properties memberof).where($whereFilter)
$users | Select-Object SamAccountName,Enabled |
Export-Csv "${Domain}_Users_withoutGG.csv" -NoTypeInformation -Encoding UTF8 -Append
And I tried this in order to do the same with computers, but this doesn't work:
$groups = 'GG_LCS_ComputersType2', 'GG_LCS_ComputersType3', 'GG_LCS_ComputersType4'
$whereFilter = $groups | Foreach-Object {
$g = (Get-ADGroup -server $domain $_).DistinguishedName
"{0} '{1}'" -f '$_.memberOf -notcontains',$g
}
$whereFilter = [scriptblock]::Create($whereFilter -join " -and ")
$users = (Get-ADComputer -server $Domain -filter {objectclass -eq "computer"} -properties memberof).where($whereFilter)
$users | Select-Object SamAccountName,Enabled |
Export-Csv "${Domain}_Computers_withoutGG.csv" -NoTypeInformation -Encoding UTF8 -Append
Could you help me? Thanks!
Try adding the -SearchBase
$AD = Get-ADComputer -Filter * -Properties $properties -SearchBase "DC=subdomain,DC=domain,DC=com" -Server $server
$AD | Select-Object * | Export-Csv -NoTypeInformation $filePath -Encoding UTF8

Unable to export my data to a CSV

I have some data I am trying to push out to a CSV but it keeps failing. Any advice?
Import-Module ActiveDirectory
$ExportFile = "C:\T2\Test.csv"
$MacHeading = "Mac OS: "
$MACOS = Get-ADComputer -Filter 'OperatingSystem -like "MAC*"' -Properties OperatingSystem, CanonicalName | Select Name, CanonicalName, OperatingSystem
$MACOSCount = Get-ADComputer -Filter 'OperatingSystem -like "MAC*"' | Measure-Object | %{$_.Count}
$MacHeading | Export-CSV -path $ExportFile -Append
$MACOS | Export-CSV -path $ExportFile -Append
$MACOSCount | Export-CSV -path $ExportFile -Append
My error message is:
Export-CSV : Cannot append CSV content to the following file:
C:\T2\Test.csv. The appended object does not have a property that
corresponds to the following column: Mac OS: . To continue with
mismatched properties, add the -Force parameter, and then retry the
command. At C:\T2\Test.ps1:9 char:15
+ $MacHeading | Export-CSV -path $ExportFile -Append
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (Mac OS: :String) [Export-Csv], InvalidOperationException
+ FullyQualifiedErrorId : CannotAppendCsvWithMismatchedPropertyNames,Microsoft.PowerShell.Commands.ExportCsvCommand
while you can create a csv file manually it is usually cumbersome and you will have to match the column headers when you add data manually.
In your code above you start your csv by creating a csv file with one header\column 'mac os'. macos is an objects with various properties and it does not contain a header called 'mac os' so export-csv does not know where to send the data.
also you are missing the -notypeinformation switch to export-csv without which the csv will contain an additional unneeded header with object type
you can look at doing something like this:
$comps = Get-ADComputer -Filter 'OperatingSystem -like "MAC*"' -Properties OperatingSystem, CanonicalName |
Select-Object #{N='MacHeading';e={'Mac OS'}},Name, CanonicalName, OperatingSystem
$comps |
ForEach-Object -Begin {$i = 0} -Process {$I++; $_ | Add-Member -Name ID -Value $i -MemberType NoteProperty -PassThru} |
Export-Csv -Path $path -NoTypeInformation
$comps=Get-ADComputer -Filter { OperatingSystem -Like '*MAC*' } -Properties OperatingSystem,CanonicalName
If you're willing to go without the $MacHeading (which isn't terribly useful for a CSV), you could just do this:
Get-ADComputer -Filter 'OperatingSystem -like "MAC*"' -Properties OperatingSystem, CanonicalName |
Select Name, CanonicalName, OperatingSystem |
Export-CSV -path $ExportFile -Append -NoTypeInformation
Get-ADComputer -Filter 'OperatingSystem -like "MAC*"' |
Measure-Object | %{$_.Count} |
Out-File $ExportFile -Append -Encoding ASCII
The key is to use Out-File instead of Out-CSV for the items that won't really make a CSV.

format write-output in powershell comma separated

I've got a simple powershell script that searches for users that are in a group containing 'www*'. I'd like the output if possible to be
samAccountName,Group
How would I go about doing that in powershell?
$groups = Get-AdGroup -Properties * -filter * | Where {$_.name -like "www*"}
$output =
Foreach($g in $groups)
{
write-output $g.Name
write-output "----------"
get-adgroupmember -Identity $g | select-object -Property SamAccountName
}
$output | out-file -FilePath C:\Users\myuser\desktop\test3.txt -Append
Try this:
$groups = Get-AdGroup -Properties * -filter * | Where {$_.name -like "www*"}
$output =
Foreach($g in $groups)
{
write-output $g.Name
write-output "----------"
get-adgroupmember -Identity $g | select-object SamAccountName,#{Name="Group";Expression={$g.Name}}
}
$output | Export-Csv -NoTypeInformation -Path C:\Users\myuser\desktop\test3.txt -Append

Get group member names from Get-Acl and Append to CSV

I need to extract all the members of a group and then format that into Names, so I only get the Full Names like "Don Joe" is member of my-domain\UNCShareDrive
I need that to appear in my CSV after I have exported the ACL lists.
As an example:
Path FileSystemRights AccessControlType IdentityReference
---- ---------------- ----------------- -----------------
Microsoft.PowerShell.Core\FileSystem::\\fileshare\management\DK FullControl Allow MY-DOMAIN\Drev Management
Microsoft.PowerShell.Core\FileSystem::\\fileshare\management\ FullControl Allow BUILTIN\Administratorer
Microsoft.PowerShell.Core\FileSystem::\\fileshare\management\ FullControl Allow MY-DOMAIN\Drev Management
Microsoft.PowerShell.Core\FileSystem::\\fileshare\management\ FullControl Allow BUILTIN\Administratorer
**These persons has access to the drive:**
**Finding group: MY-DOMAIN\Administrators**
Name SamAccountName Mail
---- -------------- ----
Administrator Administrator Administrator#my-domain.dk
This is what I have so far done in Powershell:
$Searching = Get-ADGroup -Filter * -SearchBase "DC=my-domain,DC=local"
$mypath = "U:\mytest.csv"
if((Test-Path -Path "U:\mytest.csv" -pathtype Container) -eq $True){
Write-Host -ForegroundColor red "We found a file: $mypath --> REMOVING!`r`n"
Remove-Item $mypath -Force
}
$ShareName = "\\\sharename\D$"
$shares = Get-Childitem -path $ShareName |
Where-Object {$_.PSIsContainer} |
Get-ACL |
Select-Object Path -ExpandProperty Access |
Select Path, FileSystemRights,AccessControlType,IdentityReference |
export-csv $mypath -Delimiter ';' -NoTypeInformation -Encoding UTF8
$foldertotal = 0
Add-Content $mypath ""
Add-Content $mypath ""
Add-Content $mypath "Disse personer har adgang til share navnet"
Add-Content $mypath ""
Add-Content $mypath ""
$myLoop = ''
foreach ($testLoop in $myLoop) {
$Group = Get-ADGroup -Filter * -SearchBase "DC=my-domain,DC=local" -Properties IdentityReference |
Select-Object Name # Need only groups in $Shares - who are displayed
$myLoop += Write-Host -ForegroundColor Yellow "Finding group: $($Group.name).....`n"
$myLoop += ForEach ($Group in $share) {
Get-ADGroupMember -identity $($Group.name) -recursive |
Get-ADUser -Properties Name,SamAccountName,Mail |
Select-Object Name,SamAccountName,Mail
}
$testLoop | Out-File -filePath $mypath -append -encoding utf8
}
Write-Host -ForegroundColor Cyan "$($Group.name) is now exported to: $mypath`n"
I have also a hard time to filter out only the share path:
$shares.Replace('Microsoft.PowerShell.Core\FileSystem::', ' ') |
Out-File -filePath $mypath -append -encoding utf8
How come that this thing Works when I use User Input and not just automatically loop through it without the console prompt:
$Searching = Get-ADGroup -Filter * -SearchBase "DC=MY-DOMAIN,DC=local"
$mypath = "U:\mytest.csv"
$networkPath = "\\ShareName\D$"
$acl = Get-acl -path $networkPath
if((Test-Path -Path "U:\mytest.csv" -pathtype Container) -eq $True){
Write-Host -ForegroundColor red "We found a file: $mypath --> REMOVING!`r`n"
Remove-Item $mypath -Force
}
Write-Host -ForegroundColor Yellow "Eksempel på share: "`r`n\\ShareName\D$`r`n\\ShareTwo\\E$`r`n\\ShareName\management`r`n""
$ShareName = Read-host "Hvilket sharenavn vil du finde Access Control List fra?"
if($ShareName -eq "1"){
$Sharename = "\\ShareName\D$"
}
if($ShareName -eq "2"){
$Sharename = "\\ShareTwo\\E$"
}
if($ShareName -eq "3"){
$Sharename = "\\ShareName\management"
}
Get-Childitem -path $ShareName |
Where-Object {$_.PSIsContainer} |
Get-ACL |
Select-Object Path -ExpandProperty Access |
Select Path, FileSystemRights,AccessControlType,IdentityReference |
FT -AutoSize |
Out-File -Encoding utf8 $mypath
Add-Content $mypath ""
Add-Content $mypath ""
Add-Content $mypath "Disse personer har adgang til share navnet"
Add-Content $mypath ""
$users = get-aduser -Filter {Name -Like "*"} -Searchbase "dc=MY-DOMAIN,dc=local" -Properties MemberOf |
Where-Object { $_.Enabled -eq 'True' }
Write-Host -ForegroundColor red "Example: Drev Management`r`n"
$myGroups = Read-Host "Hvilken Gruppe vil du bruge?"
if($myGroups -eq "1"){
$myGroups = " Drev Management"
}
$Groups = Get-ADGroup -filter {Name -like $myGroups} | Select-Object Name
Add-Content $mypath "Finding group: $($group.name)"
Write-Host -ForegroundColor Yellow "Finding group: $($Group.name).....`n"
Add-Content -Path $mypath $result
ForEach ($Group in $Groups) {
Get-ADGroupMember -identity $($Group.name) -recursive |
Get-ADUser -Properties Name,SamAccountName,Mail |
Select-Object Name,SamAccountName,Mail |
FT -AutoSize |
Out-File -Append -encoding utf8 $mypath
}
Write-Host -ForegroundColor Cyan "$($Group.name) is now exported to: $mypath`n"
Your second code sample works, because it doesn't make the same mistakes as the first one.
$myLoop = ''
foreach ($testLoop in $myLoop) {
$Group = Get-ADGroup -Filter * ...
$myLoop += Write-Host ...
$myLoop += ForEach ($Group in $share) {
Get-ADGroupMember ...
}
$testLoop | Out-File -filePath $mypath -append -encoding utf8
}
You make $myLoop an empty string, then iterate over each element of $myLoop (one empty string), so you get a single loop cycle, no matter what you append to $myLoop inside the loop.
Instead of the group members you write the content of $testLoop (an empty string) to the output file.
You read AD groups into the variable $Group, and then overwrite its content when you use $Group as the loop variable in foreach ($Group in $share).
$share is emtpy, because it's never initialized anywhere. Even $shares is empty, because when you write the ACL information to the CSV, no output is left that could be assigned to the variable.
And as a side-note: you can't append Write-Host output to anything, because the cmdlet writes to the host process (i.e. the console), not a stream that could be captured or redirected.
You need to capture the ACL information in $shares before writing it to a file:
$shares = Get-Childitem -Path $ShareName |
Where-Object {$_.PSIsContainer} |
Get-ACL |
Select-Object Path -ExpandProperty Access |
Select Path, FileSystemRights,AccessControlType,IdentityReference
$shares | Export-Csv $mypath -Delimiter ';' -NoTypeInformation -Encoding UTF8
Then you can determine the members of the groups having access to shares like this:
$shares | Select-Object -Expand IdentityReference |
Select-Object -Expand Value |
ForEach-Object {
$name = $_ -replace '^DOMAIN\\' # <-- replace with actual domain name
Get-ADObject -Filter { Name -eq $name }
} |
Where-Object { $_.ObjectClass -eq 'group' } |
Get-ADGroupMember |
Get-ADUser -Properties * |
Select-Object Name, SamAccountName, Mail |
Out-File $mypath -Append -Encoding UTF8
Note that this will not resolve nested groups, and also won't distinguish between shares.
If you want to store both the group name and its members you need to add a loop to the pipeline:
$shares | Select-Object -Expand IdentityReference |
Select-Object -Expand Value |
ForEach-Object {
$name = $_ -replace '^DOMAIN\\' # <-- replace with actual domain name
Get-ADObject -Filter { Name -eq $name }
} |
Where-Object { $_.ObjectClass -eq 'group' } |
ForEach-Object {
$_
Get-ADGroupMember -Identity $_ |
Get-ADUser -Properties * |
Select-Object Name, SamAccountName, Mail
} |
Out-File $mypath -Append -Encoding UTF8