Public/Add-UsersToDistributionLists.ps1

<#
.SYNOPSIS
Adds users to one or more distribution lists (DLs) based on an input CSV file.
 
.DESCRIPTION
This function reads an input CSV file where each row contains user email addresses and distribution list names.
It checks if the user is already a member of the group. If not, it adds the user to the group using ADSI.
The function logs all actions and errors to separate log files.
 
.PARAMETER InputFile
Path to the input CSV file containing the email addresses and group names.
 
.PARAMETER GroupColumn
The name of the column in the CSV that contains the group (DL) names (can be comma-separated).
 
.PARAMETER EmailColumn
The name of the column in the CSV that contains user email addresses.
 
.PARAMETER LogPrefix
Prefix to be used in the output log filenames.
 
.PARAMETER LogLocation
Optional. Directory where logs will be saved. Defaults to the current user profile folder.
 
.PARAMETER Domains
An array of domains to search within for resolving user and group information.
 
.EXAMPLE
Add-UsersToDistributionLists -InputFile "C:\input.csv" -GroupColumn "DLGroups" -EmailColumn "Email" -LogPrefix "DL_Add" -Domains @("test.corp.com", "lab.corp.com")
 
.NOTES
- The input CSV should contain at least two columns: one for email addresses and one for group names.
- Group names in the group column can be comma-separated.
- Membership check is done before attempting to add to avoid duplicates.
#>


function Add-UsersToDistributionLists {
    param (
        [Parameter(Mandatory = $true)]
        [string]$InputFile,

        [Parameter(Mandatory = $true)]
        [string]$GroupColumn,

        [Parameter(Mandatory = $true)]
        [string]$EmailColumn,

        [Parameter(Mandatory = $true)]
        [string]$LogPrefix,

        [Parameter(Mandatory = $false)]
        [string]$LogLocation = $env:USERPROFILE,

        [Parameter(Mandatory = $true)]
        [string[]]$Domains
    )

    begin {
        $label       = Get-Date -Format "yyyyMMdd"
        $logPath     = Join-Path $LogLocation "$LogPrefix`_$label.log"
        $csvLogPath  = Join-Path $LogLocation "$LogPrefix.csv"
        $errorLog    = Join-Path $LogLocation "AddUsers_Error_$label.log"
        $results     = @()

        "[{0}] : Script Started`n" -f (Get-Date -Format 'dd/MM/yy HH:mm:ss') | Out-File -FilePath $logPath -Encoding UTF8
    }

    process {
        try {
            $csv = Import-Csv -Path $InputFile
            foreach ($entry in $csv) {
                $email = $entry.$EmailColumn
                $groups = ($entry.$GroupColumn -split ',') | ForEach-Object { $_.Trim() } | Where-Object { $_ }

                foreach ($group in $groups) {
                    $results += [pscustomobject]@{
                        EmailAddress = $email
                        DLName       = $group
                    }

                    $timestamp = Get-Date -Format '[dd/MM/yy HH:mm:ss]'

                    # Check if user is already in group
                    $membershipCheck = Check-UserGroupMembershipByEmail -Email $email -GroupCN $group -Domains $Domains
                    
                    if ($membershipCheck) {
                        Add-Content -Path $logPath -Value "$timestamp : [$email] is already a member of [$group]"
                    }
                    else { 

                    try {
                        # Get User DN
                        $userDN = Get-ADUserByMail -Email $email -Domains $Domains
                        if (-not $userDN) {
                            "$timestamp : ERROR - User not found → $email`n" | Out-File -FilePath $errorLog -Append
                            continue
                        }

                        # Get Group DN
                        $groupObj = Get-ADGroupByCN -GroupCN $group -Domains $Domains
                        if (-not $groupObj) {
                            "$timestamp : ERROR - Group not found → $group`n" | Out-File -FilePath $errorLog -Append
                            continue
                        }

                        $groupDN = $groupObj.distinguishedName

                        # Add User to Group via ADSI
                        $userDN  = Get-ADUserByMail -Email $email -Domains $domains
                        Add-UserToGroup_ADSI -UserDN $userDN -GroupDN $groupObj

                        Add-Content -Path $logPath -Value "$timestamp : [$email] successfully added to [$group]" 
                    }
                    catch {
                        $timestamp = Get-Date -Format '[dd/MM/yy HH:mm:ss]'
                        Add-Content -Path $errorLog -Value "$timestamp : ERROR adding [$email] to [$group] → $($_.Exception.Message)"
                    }
                }
            }

        }

            $results | Export-Csv -Path $csvLogPath -NoTypeInformation -Encoding UTF8
            Add-Content -Path $logPath -Value ("[{0}] : Script Completed`n" -f (Get-Date -Format 'dd/MM/yy HH:mm:ss'))
            return "Success"
        }
        catch {
            $timestamp = Get-Date -Format '[dd/MM/yy HH:mm:ss]'
            "$timestamp : ERROR processing file → $($_.Exception.Message)`n" | Out-File -FilePath $errorLog -Append
            return "Failed"
        }
    }



    end {
        Remove-Variable -Name results, csv, entry, email, groups -ErrorAction SilentlyContinue
    }
}