I have hundreds of Public folders, and I need to remove all existing user permissions on each folder, then add new permissions for Default and Anonymous. Some users don't exist, or are disabled.
This is the ps1 file I've written:
param (
[string] $pf='\Clients'
)
$children = Get-PublicFolder -Identity $pf –Recurse
$children | % {
$Perm = Get-PublicFolderClientPermission $_.Identity
$Perm | % {
Remove-PublicFolderClientPermission -Identity $_.Identity -User $_.User -Confirm:$false
}
Remove-PublicFolderClientPermission -Identity $_.Identity -User Default -Confirm:$false
Add-PublicFolderClientPermission -Identity $_.Identity -User Default -AccessRights Owner
Remove-PublicFolderClientPermission -Identity $_.Identity -User Anonymous -Confirm:$false
Add-PublicFolderClientPermission -Identity $_.Identity -User Anonymous -AccessRights Contributor
}
Error is:
Cannot process argument transformation on parameter 'User'. Cannot convert value
"Default" to type
"Microsoft.Exchange.Management.StoreTasks.MailboxFolderUserIdParameter".
Error: "Cannot convert hashtable to an object of the following type:
Microsoft.Exchange.Management.StoreTasks.MailboxFolderUserIdParameter.
Hashtable-to-Object conversion is not supported in restricted language mode or a
Data section."
+ CategoryInfo : InvalidData: (:) [Remove-PublicFolderClientPermission], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Remove-PublicFolderClientPermission
+ PSComputerName : outlook.office365.com
This error is for "Default", same thing happened for normal user accounts that exist.
$_.User on the 8th line doesn't parse as a user. Any thoughts?
You need to replace $_.User to $_.User.DisplayName
I know it was published a long time ago, but it is still relevant.
Same solution :
$a= Get-publicFolder \ -recurse -resultsize unlimited
$b= $a | Get-PublicFolderClientPermission
foreach ($pfper in $b) {
write-host $pfper.User.DisplayName $pfper.Identity ; Remove-PublicFolderClientPermission $pfper.Identity -User $pfper.User.DisplayName -Confirm:$false}
Get-PublicFolder \ -Recurse | Add-PublicFolderClientPermission -User Anonymous -AccessRights None
Get-PublicFolder \ -Recurse | Add-PublicFolderClientPermission -User Default -AccessRights None
Related
I'm currently trying to use powershell to change Outlook calendar permissions for a subset of users, so that they can all view calendar details of one another.
So far, I have been able to find the commands to change permissions for a single user, and for all users in the org - but have not yet established how to apply these changes to just a group.
Here is the script I found to modify permissions for all users:
foreach($user in Get-Mailbox -RecipientTypeDetails UserMailbox) {
$cal = $user.alias+”:\Calendar”
Set-MailboxFolderPermission -Identity $cal -User Default -AccessRights LimitedDetails
}
In order to apply this to just a group of users, would my modifications below be correct?
foreach($user in Get-MsolGroupMember -Identity "Name of Group") {
$cal = $user.alias+”:\Calendar”
Set-MailboxFolderPermission -Identity $cal -User Default -AccessRights LimitedDetails
}
You need to first find the group as object, because Get-MsolGroupMember doesn't have a -Identity parameter.
Then use that to get info of its users:
$groupToFind = 'DisplayName of Group'
$permissions = 'LimitedDetails'
$group = Get-MsolGroup | Where-Object { $_.DisplayName -eq $groupToFind }
if ($group) {
# get the group members (users only) and run through
Get-MsolGroupMember -GroupObjectId $group.ObjectId -MemberObjectTypes User -All | ForEach-Object {
$cal = '{0}:\Calendar' -f $_.Alias
$perms = Get-MailboxFolderPermission -Identity $cal -User Default
if ($perms.AccessRights -contains $permissions) {
Write-Host "User $($_.Alias) already has the '$permissions' permission"
}
else {
Write-Host "Setting permissions on $cal"
# for safety, first run with the -WhatIf switch. If you are satisfied with what
# is output on screen, remove or comment out that switch and run again
Set-MailboxFolderPermission -Identity $cal -User Default -AccessRights $permissions -WhatIf
}
}
}
else {
Write-Warning "Could not find group '$groupToFind'..."
}
Instead of using the Where-Object clause on Get-MsolGroup, you could also do Get-MsolGroup -SearchString $groupToFind, but beware that using -SearchString will return groups that have a display name that START with this string.
If you receive "The command completed successfully, no permissions were changed", this could mean the user first needs to get permissions on the so-called top of the information store (i.e. the mailbox folder itself):
Get-MsolGroupMember -GroupObjectId $group.ObjectId -MemberObjectTypes User -All | ForEach-Object {
$top = '{0}:\' -f $_.Alias # Top of Information Store
$cal = '{0}:\Calendar' -f $_.Alias
Add-MailboxFolderPermission -Identity $top -User Default -AccessRights FolderVisible -Confirm:$false
Set-MailboxFolderPermission -Identity $cal -User Default -AccessRights LimitedDetails -Confirm:$false
}
P.S. Because Outlook runs in cache, it takes time to reflect the changes there.
I inherited several PowerShell scripts, to place a user on LitigationHold in Exchange, as well as set the user's AD protect from accidental deletion to $true.
They all work separately, but one uses User Full name, and the other uses the SAM account name. I am trying to marry scripts so that I can just use the Full name, but I can't seem to pass the SAMAccountName .
My attempt at combining the codes:
foreach ($user in ("Name 1", "Name 2", "Name 3"))
{
$mailuser = Get-Mailbox $user -DomainController A1.Domain l -ErrorAction SilentlyContinue| Select *;
if ($mailuser -eq $null)
{
Write-Host "$user was not found. Check for misspellings."
}
else
{
if($mailuser.LitigationHoldDate -ne $null)
{
Set-Mailbox $user -LitigationHoldEnabled:$true -Confirm:$False -Force:$True -DomainController A1.Domain;
Write-Host "$user is now placed on hold.";
$userinfo = {
Get-ADUser $user -Server A1.Domain
};
Set-ADObject -Identity $userinfo.SamAccountName -ProtectedFromAccidentalDeletion:$true;
$i = Get-ADUser $user -Properties description -Server A1.Domain |
%{ $_.description } |
Set-ADUser $userinfo -Server A1.Domain -Replace #{
description="8/19/2019 - Security Hold, please contact admin before modifying `r`n | $($i)"
}
}
else{
Write-Host "$user is already on litigation hold as of $($mailuser.LitigationHoldDate) by $($mailuser.LitigationHoldOwner)."
}
}
}
To take list of Display names and get usernames:
foreach ($user in ("Name 1", "Name 2", "Name 3"))
{
$userinfo = Get-ADUser -filter { DisplayName -like $user } -Server A1.Domain ;
if ($userinfo -ne $null)
{
Get-ADUser -filter { DisplayName -like $user } -Server A1.Domain | ft SamAccountName -HideTableHeaders
}
else
{
Write-Host "$user is not available"
}
}
To Add Lit Hold into AD Description
foreach ($user in ("Name 1", "Name 2", "Name 3"))
{
$mailuser = Get-Mailbox $user -DomainController A1.Domain -ErrorAction SilentlyContinue| Select *;
if($mailuser -eq $null)
{
Write-Host "$user was not found. Check for misspellings."
}
else
{
if ($mailuser.LitigationHoldDate -eq $null)
{
$i = Get-ADUser $user -Properties description -Server A1.Domain | %{ $_.description};
Set-ADUser $user -Server A1.Domain -Replace #{
description="Security Hold, please contact the Gnome before modifying `r`n | $($i)"
}
}
else
{
Write-Host "$user is already on litigation hold as of $($mailuser.LitigationHoldDate) by $($mailuser.LitigationHoldOwner)."
}
}
}
To take a list of Display names and set Lit Hold:
foreach ($user in ("Name 1", "Name 2", "Name 3""))
{
$mailuser = Get-Mailbox $user -DomainController A1.Domain -ErrorAction SilentlyContinue| Select *;
if ($mailuser -eq $null)
{
Write-Host "$user was not found. Check for misspellings."
}
else
{
if($mailuser.LitigationHoldDate -eq $null)
{
Set-Mailbox $user -LitigationHoldEnabled:$true -Confirm:$False -Force:$True -DomainController A1.Domain ;
Write-Host "$user is now placed on hold."
}
else
{
Write-Host "$user is already on litigation hold as of $($mailuser.LitigationHoldDate) by $($mailuser.LitigationHoldOwner)."
}
}
}
To take a list of usernames and protect against accidental deletion:
"User1", "User2", "User3" | Get-aduser -Server A1.Domain | Set-ADObject -ProtectedFromAccidentalDeletion:$true
I want to account to be set to LitigationHold, AD protect from accidental deletion, also reflect security hold on description.
This is the error message I get when I run it:
FN LN is now placed on hold.
Set-ADObject : Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the argument, and then try running the
command again.
At line:9 char:25
+ Set-ADObject -Identity $userinfo.SamAccountName -ProtectedFromAccide ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Set-ADObject], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.SetADObject
Set-ADUser : A positional parameter cannot be found that accepts argument 'Get-ADUser $user -Server A1.domain '.
At line:12 char:1
+ Set-ADUser $userinfo -Server A1.domain -Replace # ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-ADUser], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.ActiveDirectory.Management.Commands.SetADUser
I was trying to see if I can bypass the -Identify flag by giving it the user full name, but Set-ADObject will only take an object, not a string.
--edit 3--
Replying to #Seth about -Identity flag is a parameter:
changed part of the code to give -Identity an ADObject:
$userinfo = Get-ADUser {DisplayName -like $user} -Server A1.domain};
Set-ADObject $userinfo -ProtectedFromAccidentalDeletion:$true;
The error message is as follows:
Get-ADUser : Cannot evaluate parameter 'Identity' because its argument is specified as a script block and there is no input. A script block cannot be
evaluated without input.
At line:8 char:26
+ $userinfo = Get-ADUser {DisplayName -like $user} -Server A1.domain ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : MetadataError: (:) [Get-ADUser], ParameterBindingException
+ FullyQualifiedErrorId : ScriptBlockArgumentNoInput,Microsoft.ActiveDirectory.Management.Commands.GetADUser
Set-ADObject : Cannot evaluate parameter 'Identity' because its argument is specified as a script block and there is no input. A script block cannot be
evaluated without input.
At line:9 char:15
+ Set-ADObject $userinfo -ProtectedFromAccidentalDeletion:$true;
+ ~~~~~~~~~
+ CategoryInfo : MetadataError: (:) [Set-ADObject], ParameterBindingException
+ FullyQualifiedErrorId : ScriptBlockArgumentNoInput,Microsoft.ActiveDirectory.Management.Commands.SetADObject
Set-ADUser : A positional parameter cannot be found that accepts argument 'Get-ADUser {DisplayName -like $user} -Server A1.domain'.
At line:12 char:1
+ Set-ADUser $userinfo -Server A1.domain -Replace # ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-ADUser], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.ActiveDirectory.Management.Commands.SetADUser
I think at this point the issue boils down to: Set-ADUser uses SamAccountName, and I can't seem to parse out the SamAccountName from the user ADObject. I can get the SamAccountName by calling a table from the ADObject, but it will not pass into Set-ADUser correctly.
You're currently not doing any verification on whenever you actually get a proper ADUser object. You simply assume that the assignment to $i/$userinfo will be successful. Your $name contains the display name for a user. So for example it would be "John Doe".
This works for Get-Mailbox because it supports Name, Alias, Distinguished name (DN), Canonical DN, <domain name>\<account name>, Email address, GUID, LegacyExchangeDN, SamAccountName, User ID or user principal name (UPN) as values for Identity. It has to do this to an extend because some values might or might not be available to identify a mailbox. Get-ADUser on the other hand has a much more strict approach only supporting distinguished name, GUID (objectGUID), security identifier (objectSid), SAM account name (sAMAccountName). Hence using the display name to find an AD account isn't supported. Your colleague used a filter to just use it anyway which is one solution $userinfo = Get-ADUser -filter { DisplayName -like $user } -Server A1.Domain ;.
If you really want to go with the display name you'll need to either look for it like that or use the DistinguishedName property of the mailbox to get the owner. So you'd do something like:
$mailbox = Get-Mailbox test
$adObject = Get-AdUser -Identity $mailbox.DistinguishedName
Obviously you should check whenever the property actually exists on the mailbox object as it might be disconnected. Also rather than using $user again and again you might want to use actual object (e.g. the mailbox or AD Object) to make sure you only need to verify your search results once.
You should also be able to just use one Set-AdUser call instead of that very weird call you're currently doing. You find the user, iterate the descriptions for the user (an object only has one) and add to it. Doing something like Set-AdUser $adObject -Description "New Description | $($adObject.Description)" would be much shorter and clearer. Spreading it some more might even improve it more.
I'm trying to remove orphaned user objects from all mailboxes in our Exchange server.
When I execute this command:
get-mailboxpermission * | where {$_.User -like "S-1-5-21*"} | foreach {$_.Identity.Name}
It correctly returns a list with all the mailboxes that still have orphaned user account permissions set on them.
However, when I try to remove them by doing this:
get-mailboxpermission * | where {$_.User -like "S-1-5-21*"} | remove-mailboxpermission -identity $_.Identity.Name -user $_.User -accessrights $_.AccessRights -deny:$_.Deny
It returns this error:
Cannot bind argument to parameter 'Identity' because it is null.
+ CategoryInfo : InvalidData: (:) [Remove-MailboxPermission], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Remove-MailboxPermission
What am I doing wrong?
Thanks for any help.
$_ doesn't work like that, you need to wrap the Remove-MailboxPermission statement in ForEach-Object {}:
Get-MailboxPermission * | Where-Object {$_.User -like "S-1-5-21*"} | ForEach-Object {
Remove-MailboxPermission -Identity $_.Identity.Name -User $_.User -AccessRights $_.AccessRights -Deny:$_.Deny
}
Since Exchange doesn't seem to like nested pipelines very much, you could simply to away with the parameter arguments altogether (Remove-MailboxPermission will automatically bind the permissions from the pipeline):
Get-MailboxPermission * | Where-Object {$_.User -like "S-1-5-21*"} | Remove-MailboxPermission
I'm trying to run the command below to remove e Send On Behalf permission, but i'm getting an exception and it removes all the users that have access, instead of the one I specify in my script
$owner = "lpeter"
$remove = "jdoe"
$grantlist = Get-Mailbox $owner -DomainController tordc01 | select -ExpandProperty GrantSendOnB
$grantlist = $grantlist |?{$_.Name -ne $remove}
Set-Mailbox $owner -GrantSendOnBehalfTo $null -DomainController tordc01
$grantlist | %{
Set-Mailbox $owner -GrantSendOnBehalfTo #{Add=$_.Name} -Confirm $true
} -DomainController tordc01
here is the exception :
ForEach-Object : Cannot bind parameter 'Process'. Cannot convert the
"-DomainController" value of type "System.String" to type
"System.Management.Automation.ScriptBlock". At line:1 char:15
+ $grantlist | % <<<< {Set-Mailbox $owner -GrantSendOnBehalfTo #{Add=$_.Name} -Confirm $true} -DomainController tordc01
+ CategoryInfo : InvalidArgument: (:) [ForEach-Object], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.ForEachObjectCommand
The exception is pretty self-explanatory, you're trying to supply the -DomainController parameter to ForEach-Object, instead of to Set-Mailbox
Change the last statement to:
$grantlist | %{
Set-Mailbox $owner -GrantSendOnBehalfTo #{Add=$_.Name} -Confirm:$true -DomainController tordc01
}
I will add -AccessRights fullaccess but it only work when csv file looks like
"Name","GrantSendonBehalfTo"
"OJE01","ore.se/lk/forv/socf/NYMXX04"
When its more than one to one the csvfile dont work How to fix that ????
"Name","GrantSendonBehalfTo"
"KEU01","ore.se/lk/forv/socf/BEAXX37;ore.se/lk/forv/socf/ERC01"
Step One
Get-mailbox -ResultSize Unlimited -Identity *
| where {$_.GrantSendOnBehalfTo}
| Select-Object name,#{Name='GrantSendonBehalfTo';Expression={[string]::join(";", ($_.GrantSendonBehalfTo))}}
| Export-Csv c:\Grant.txt -Delimiter ','
Step TWO
Import-Csv C:\Grant.txt
| foreach{Add-MailboxPermission -Identity $_.Name -User $_.GrantSendonBehalfTo -AccessRights fullaccess}
Any idea?
You joined the grantees with a semicolon, so naturally you need to split those joint grantees before you can (re-)assign access:
Import-Csv C:\Grant.txt | % {
$name = $_.Name
$_.GrantSendonBehalfTo -split ';' | % {
Add-MailboxPermission -Identity $name -User $_ -AccessRights fullaccess
}
}