Exchange custom attributes on groups automatically with PowerShell
Scenario:
Set Exchange custom attributes on groups automatically with PowerShell.
In general the below script add an Exchange custom attribute on distribution and security groups. I am working on a custom delegation model on all our systems so the local IT Admins will have the least possible permissions to perform their work without any interruption. Mail enabled distribution and security groups are included in the list of the objects in Microsoft Exchange to be delegated. Based on the delegation model that we want to achieve, we need to utilise an exchange custom attribute so we will be able to perform filtering on Exchange Online (Office365).
As all changes in a hybrid environment need to be done on Exchange On-premise and then synchronised to Office 365, the script first connects on Exchange On-premise server. The next step is to define the Organizational Units in Active Directory for each country in variables and also retrieve all mail enabled groups in our system from Exchange and save them in another variable. After that the script will proceed with some checks so it will know if it will proceed with a change or not on the exchange customer attributes. If the attributes does not much, in this case CustomAttribute4, or the value in null then it will proceed to set the custom attribute to the one specified.
As you will see, I am also changing two more exchange attributes before I change the exchange custom attribute. The first attribute, MemberJoinRestriction, does not allow anyone to join without manager of the group to add the member or approve the join request. The second attributes, MemberDepartRestriction, does not allow members to leave from the group if without group manager to approve it, the group manager to remove the member
You will see that I use ForceUpgrade parameter when I setting up the custom attribute. The reason I am using this parameter is to upgrade the groups created on previous versions of exchange and when you perform change on them it will ask you to upgrade them. With this parameter it will upgrade them and the perform the change.
All the changes that will be performed, they will be sent to me so I will be able to know what has been done. If there are no changes, no email will be sent. Error report is also configured at the end of the script so I there is any error during the run it will inform me and send me the errors that appeared. I use the below script on a schedule basis and performs the changes automatically daily.
You can download the script here or copy it from below.
Let me know your thoughts and comment below if you need anything.
Related Links:
- Send Email using PowerShell
- Email error variable in PowerShell
- Encrypt password with key using PowerShell
- New-PSSession – Microsoft Docs
- Import-PSSession – Microsoft Docs
- Get-Content – Microsoft Docs
- ConvertTo-SecureString – Microsoft Docs
- New-Object – Microsoft Docs
- Get-DistributionGroup – Microsoft TechNet
- Set-DistributionGroup – Microsoft TechNet
- Send-MailMessage – Microsoft Docs
- Get-Date – Microsoft Docs
Solution / Script:
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://exchange-server.domain.com/PowerShell/ -Authentication Kerberos
Import-PSSession $Session
$File = "C:\Scripts\Password.txt"
$Key = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32)
$EmailUser = "Script-User@domain.com"
$Password = Get-Content $File | ConvertTo-SecureString -Key $Key
$EmailCredentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $EmailUser,$Password
$To = 'User1@domain.com'
$From = 'Script-User@domain.com'
$EmailResult = ""
$CYGroups = @("domain.com/Offices/Cyprus/Groups/DistributionGroups",
"domain.com/Offices/Cyprus/Groups/SecurityGroups")
$CNGroups = @("domain.com/Offices/China/Groups/DistributionGroups",
"domain.com/Offices/China/Groups/SecurityGroups")
$DEGroups = @("domain.com/Offices/Germany/Groups/DistributionGroups",
"domain.com/Offices/Germany/Groups/SecurityGroups")
$GRGroups = @("domain.com/Offices/Greece/Groups/DistributionGroups",
"domain.com/Offices/Greece/Groups/SecurityGroups")
$INGroups = @("domain.com/Offices/India/Groups/DistributionGroups",
"domain.com/Offices/India/Groups/SecurityGroups")
$UKGroups = @("domain.com/Offices/UnitedKingdom/Groups/DistributionGroups",
"domain.com/Offices/UnitedKingdom/Groups/SecurityGroups")
$AllGroups = Get-DistributionGroup -OrganizationalUnit "domain.com/Offices" -ResultSize Unlimited
foreach ($Group in $AllGroups) {
if ($Group.MemberJoinRestriction -eq "Open") {
Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -MemberJoinRestriction "Closed" -ForceUpgrade
}
if ($Group.MemberDepartRestriction -eq "Open") {
Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -MemberDepartRestriction "Closed" -ForceUpgrade
}
if (($CYGroups -contains $Group.OrganizationalUnit) -and ($Group.CustomAttribute4 -ne "Cyprus")) {
Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -CustomAttribute4 "Cyprus" -ForceUpgrade
$EmailTemp = @"
<tr>
<td class="colorm">$Group</td>
<td>Cyprus</td>
</tr>
"@
$EmailResult = $EmailResult + "`r`n" + $EmailTemp
}
elseif (($CNGroups -contains $Group.OrganizationalUnit) -and ($Group.CustomAttribute4 -ne "China")) {
Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -CustomAttribute4 "China" -ForceUpgrade
$EmailTemp = @"
<tr>
<td class="colorm">$Group</td>
<td>China</td>
</tr>
"@
$EmailResult = $EmailResult + "`r`n" + $EmailTemp
}
elseif (($DEGroups -contains $Group.OrganizationalUnit) -and ($Group.CustomAttribute4 -ne "Germany")) {
Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -CustomAttribute4 "Germany" -ForceUpgrade
$EmailTemp = @"
<tr>
<td class="colorm">$Group</td>
<td>Germany</td>
</tr>
"@
$EmailResult = $EmailResult + "`r`n" + $EmailTemp
}
elseif (($GRGroups -contains $Group.OrganizationalUnit) -and ($Group.CustomAttribute4 -ne "Greece")) {
Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -CustomAttribute4 "Greece" -ForceUpgrade
$EmailTemp = @"
<tr>
<td class="colorm">$Group</td>
<td>Greece</td>
</tr>
"@
$EmailResult = $EmailResult + "`r`n" + $EmailTemp
}
elseif (($INGroups -contains $Group.OrganizationalUnit) -and ($Group.CustomAttribute4 -ne "India")) {
Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -CustomAttribute4 "India" -ForceUpgrade
$EmailTemp = @"
<tr>
<td class="colorm">$Group</td>
<td>India</td>
</tr>
"@
$EmailResult = $EmailResult + "`r`n" + $EmailTemp
}
elseif (($UKGroups -contains $Group.OrganizationalUnit) -and ($Group.CustomAttribute4 -ne "United Kingdom")) {
Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -CustomAttribute4 "United Kingdom" -ForceUpgrade
$EmailTemp = @"
<tr>
<td class="colorm">$Group</td>
<td>United Kingdom</td>
</tr>
"@
$EmailResult = $EmailResult + "`r`n" + $EmailTemp
}
}
$EmailUp = @"
<style>
body { font-family:Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif !important; color:#434242;}
TABLE { font-family:Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif !important; border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
TR {border-width: 1px;padding: 10px;border-style: solid;border-color: white; }
TD {font-family:Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif !important; border-width: 1px;padding: 10px;border-style: solid;border-color: white; background-color:#C3DDDB;}
.colorm {background-color:#58A09E; color:white;}
.colort{background-color:#58A09E; padding:20px; color:white; font-weight:bold;}
.colorn{background-color:transparent;}
</style>
<body>
<h3>Script has been completed successfully</h3>
<h4>CustomAttribute4 has been set for the below groups</h4>
<table>
<tr>
<td class="colort">Group Name</td>
<td class="colort">Custom Attribute4 Value</td>
</tr>
"@
$EmailDown = @"
</table>
</body>
"@
$Email = $EmailUp + $EmailResult + $EmailDown
if ($EmailResult -ne "") {
send-mailmessage `
-To $To `
-Subject "Distribution Groups CustomAttribute4 Report $(Get-Date -format dd/MM/yyyy)" `
-Body $Email `
-BodyAsHtml `
-Priority high `
-UseSsl `
-Port 587 `
-SmtpServer 'smtp.office365.com' `
-From $From `
-Credential $EmailCredentials
}
if ($error -ne $null) {
foreach ($value in $error) {
$ErrorEmailTemp = @"
<tr>
<td class="colorm">$value</td>
</tr>
"@
$ErrorEmailResult = $ErrorEmailResult + "`r`n" + $ErrorEmailTemp
}
$ErrorEmailUp = @"
<style>
body { font-family:Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif !important; color:#434242;}
TABLE { font-family:Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif !important; border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
TR {border-width: 1px;padding: 10px;border-style: solid;border-color: white; }
TD {font-family:Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif !important; border-width: 1px;padding: 10px;border-style: solid;border-color: white; background-color:#C3DDDB;}
.colorm {background-color:#58A09E; color:white;}
.colort{background-color:#58A09E; padding:20px; color:white; font-weight:bold;}
.colorn{background-color:transparent;}
</style>
<body>
<h3 style="color:#BD3337 !important;"> WARNING!!!</h3>
<p>There were errors while setting up CustomAttribute4 on Groups</p>
<p>Please check the errors and act accordingly</p>
<table>
"@
$ErrorEmailDown = @"
</table>
</body>
"@
$ErrorEmail = $ErrorEmailUp + $ErrorEmailResult + $ErrorEmailDown
send-mailmessage `
-To $To `
-Subject "Distribution Groups CustomAttribute4 Report $(Get-Date -format dd/MM/yyyy) - WARNING" `
-Body $ErrorEmail `
-BodyAsHtml `
-Priority high `
-UseSsl `
-Port 587 `
-SmtpServer 'smtp.office365.com' `
-From $From `
-Credential $EmailCredentials
}
Leave a Reply