Almost every company that I have ever worked for has an enormous collection of distribution lists; many are duplicates or very slight variations of other group names. This makes group communications difficult to say the least. Do you use the Network Team, Network Support Team, Network Help, or Network HQ list to get in touch with your current network group? Sure, you can check the membership, but at a large company you probably don’t know the correct individual’s names, it’s why you’re using the group address in the first place right?

Where did all these address collections come from? That is a simple question to answer, people ask for them. As a team’s management and membership changes the people in it want a way to email their group all at once. They aren’t sure about the existing lists so they ask IT to make a new one. Before you know it; the company address book is a giant mess with more groups than people in it.OutlookDlOverkill

Not only is having this many DLs confusing to use, it is a security nightmare. Security professionals are finding that controlling who can communicate with whom is almost as important as changing your password. The “Wild West” days of allowing all employees to email anybody they see fit should be coming to an end at your company. Every message that leaves your organization represents it in the marketplace. Each one is a piece of data that can be used by your competition or for nefarious reasons by dark net residents.

What’s the solution? There quite a few, from commercial DL management tools like ManageEngine and Ensim, to hiring a FTE to manage distribution. If you use Microsoft Exchange you can set security and transport rules to control access to groups and the same is true for Office 365 (How To coming soon). Personally, I think the best solution is to avoid putting them in the Global Address Book in the first place. Personal or small team DLs belong in each individual’s Outlook. Outlook calls its lists Contact Groups.

Outlook Contact Groups have a lot going for them. They’re local to the user’s Outlook profile but can be shared, they can auto update email addresses for the members, and don’t require an administrator to update them. So what’s the catch? Why doesn’t everybody use Outlook Contact groups?OutlookContactGroup

Email address distribution groups in the Global Address List are often dynamically populated.¬†If your company uses Active Directory there’s a good chance that they have filled that directory with employee details like phone numbers, email addresses, physical addresses, and more. Dynamic DLs are formed when an administrator creates a query and filter set in Exchange. This rule searches AD based on the specified parameters and inserts the matching addresses into the desired list, essentially automating the process. Outlook contact groups lack this ability and have to be manually created which is tedious and time-consuming. I believe this is the biggest obstacle to their widespread adoption.

dynamic_distribution_group

Being the crafty scripter that I am, I decided to see if I could create Outlook contact groups dynamically. Did you know that Active Directory usually contains your entire firm’s management structure? There’s a field in which you can enter an employees manager. If your HR or IT department populated this field you can view the information but there’s no way to create an email list from it. I imagined it would be useful for my company if a person could choose a supervisor from a list and end up with a contact group that contained all that manager’s employees. If you select multiple managers you can create lists that contain entire departments. Unlike most “scripts” this tool has a full GUI. Does that make it an Application? What exactly is the dividing line between script and app?

OutlookDLBuilderManagers
Manager’s List Generated From AD Query Select, Filter, and Sort

The code below is written for Windows 10 and requires the RSAT package be installed. You’ll also need to be sure the Manger’s list is done populating before you select items from it. The scroll bar will stop shrinking when it is done querying all your accounts. If you’re running this on a large distributed directory it can take up to a couple of minutes to complete. If you select a manager and click “Ok” and nothing happens then the scan wasn’t finished. Try again and wait a little longer.

THE CODE:

Import-Module ActiveDirectory
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null

$temppath = "$env:userprofile\documents\Outlook_dl_builder_selected_managers.csv"

function Get-Managers
{
Get-ADUser -properties * -Filter {(directreports -ne "$null") -and (displayname -notlike "*test*")  -and (displayname -notlike "123*")}|
Select @{n="Name";e={$_.Displayname}},@{n="Logon";e={$_.SamAccountName}},@{n="Email";e={$_.PrimarySmtpAddress}},Company,@{n="Country";e={$_.co}}|
Out-GridView -Title 'Select Managers to build Outlook Distribuiton List'-PassThru|
export-csv -Path $temppath -NoTypeInformation
} 

function Get-ADdirectReports
{
    PARAM ($SamAccountName)
    Get-Aduser -identity $SamAccountName -Properties directreports | %{
        $_.directreports | ForEach-Object -Process {

            Get-ADUser -identity $Psitem -Properties * | Select-Object -Property DisplayName, SamAccountName, Mail, @{n="ManagerName";e={(Get-ADUser -Identity $_.Manager -Properties displayName).DisplayName}}

            Get-ADdirectReports -SamAccountName $PSItem
        }
    }
}

function OutlookDL
{
    $outlook = new-object -com Outlook.Application
    $contacts = $outlook.Session.GetDefaultFolder(10)
    $dl = $contacts.Items.Add("IPM.DistLIst")
    $dl.DLName = "$groupname"
    $dl.Save()
}

function OutlookDL-Delete
{
    Try {
    $outlook = new-object -com Outlook.Application
    $contacts = $outlook.Session.GetDefaultFolder(10)
    $DL=$Contacts.Items("$groupname")
    $dl.delete()
    }
    Catch {Write-Host "No duplicate Outlook Group found"}
}

function AddContacts
{
    $outlook = new-object -com Outlook.Application
    $contacts = $outlook.Session.GetDefaultFolder(10)
    $namespace = $outlook.GetNamespace("MAPI")
    $DL=$Contacts.Items("$groupname")
    $recipient = $namespace.CreateRecipient("$employee")
    $recipient.Resolve()
    $DL.AddMember($recipient)
    $dl.Save()
   }

function DisplayDL
{
    $outlook = new-object -com Outlook.Application
    $contacts = $outlook.Session.GetDefaultFolder(10)
    $DL=$Contacts.Items("$groupname")
    $dl.display()
}

$groupname = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the name of the Outlook Contact Group to be created or updated:","Outlook Contact Group", " My Outlook Distrobution List")
OutlookDL-Delete
Get-Managers
$managers = Import-CSv -Path $temppath |select Logon -ExpandProperty Logon
$drlist = Foreach ($manager in $managers){Get-ADdirectReports -SamAccountName $manager|select-object -ExpandProperty mail}
OutlookDL
Foreach ($employee in $drlist) {AddContacts}
DisplayDL

Now that you’ve seen the technique at work you should be able to easily adjust the AD query to scan or filter for the fields that are most useful to your organization. You could also use sources other than AD, it would be simple to connect to a SQL database or import a CSV file.

Advertisements