Shore Up
A fresh office desk being set up for a new arrival — a nameplate being placed, a ring of keys, a labelled mail slot on the wall, and an empty drawer pulled open, all laid out ready.
WindowsMailSecurity

Automate New-User Onboarding in Active Directory

Ketan Aagja10 min read
No ratings yet

Before you run this

This guide builds a PowerShell script that onboards one new employee in four steps: it creates an Active Directory user account, adds them to security groups, provisions an on-premises Exchange mailbox, and creates their home folder on a file server and sets NTFS permissions. The purpose is to replace the error-prone click-through in Active Directory Users and Computers with one repeatable, reviewable run.

It needs elevated rights. You run it from an elevated (Administrator) PowerShell session as an account that can create users in the target OU and add group members — in practice a delegated account or Domain Admin. The ActiveDirectory module (RSAT) must be installed. The mailbox step uses the Enable-Mailbox cmdlet, which lives in the Exchange Management Shell and needs Exchange RBAC rights (e.g. Recipient Management). The file-server step needs write access to the share where home folders live and permission to change ACLs there.

This creates and changes real objects. A created AD account and mailbox, added group memberships, and a new folder with permissions are all live changes the moment the script runs. None of them auto-expire. Account and mailbox creation aren't dangerous, but a wrong group membership can hand out access you didn't mean to, so treat the group list with care. I've included the undo commands at the end.

Test first. Read the whole script before running it. Run it against a test OU and a throwaget username (say, onboard-test1) on a lab domain or a test VM before you point it at your production directory. New-ADUser supports -WhatIf; use it on your first pass so nothing is written.


What I'm assuming

  • Windows Server 2019/2022, a single AD domain (example.com), and Windows PowerShell 5.1 — the version that ships with the OS.
  • An on-premises Exchange Server reachable via the Exchange Management Shell. If your mailboxes are in Exchange Online / Microsoft 365, Enable-Mailbox is not how you create them there — mailboxes are provisioned by assigning a licence, so skip that step and handle licensing in your tenant instead.
  • Home folders live on a file server under a share like \\fileserver\home\ backed by a local path such as D:\Home\.
  • You have delegated rights to the target OU and the file share.

Replace every example.com, OU=..., \\fileserver\..., and group name below with your own. They are placeholders.

The onboarding script

Save this as New-Onboard.ps1. The parameters at the top are the only things you edit per hire.

#requires -Modules ActiveDirectory
[CmdletBinding(SupportsShouldProcess = $true)]  # gives us -WhatIf / -Confirm
param(
    [Parameter(Mandatory)] [string]$GivenName,
    [Parameter(Mandatory)] [string]$Surname,
    [Parameter(Mandatory)] [string]$SamAccountName,     # the logon name, e.g. jdoe
    [string]$Department = "General",
    [string]$Title      = "",
    # --- environment specifics: EDIT THESE ---
    [string]$Domain     = "example.com",
    [string]$OU         = "OU=Staff,DC=example,DC=com",
    [string[]]$Groups   = @("All Staff", "VPN Users"),
    [string]$HomeRoot   = "D:\Home",                     # local path ON the file server
    [string]$HomeUncRoot= "\\fileserver\home",           # UNC users see
    [string]$HomeDrive  = "H:"
)

$ErrorActionPreference = "Stop"   # stop on the first failure rather than half-onboarding

$displayName = "$GivenName $Surname"
$upn         = "$SamAccountName@$Domain"
$homeUnc     = Join-Path $HomeUncRoot $SamAccountName

# Prompt once for the initial password as a SecureString (never hard-code it)
$password = Read-Host "Initial password for $SamAccountName" -AsSecureString

# 1) Create the AD account -------------------------------------------------
New-ADUser `
    -Name               $displayName `
    -GivenName          $GivenName `
    -Surname            $Surname `
    -DisplayName        $displayName `
    -SamAccountName     $SamAccountName `
    -UserPrincipalName  $upn `
    -Path               $OU `
    -Department         $Department `
    -Title              $Title `
    -AccountPassword    $password `
    -ChangePasswordAtLogon $true `
    -Enabled            $true `
    -HomeDrive          $HomeDrive `
    -HomeDirectory      $homeUnc

Write-Host "Created AD user $SamAccountName" -ForegroundColor Green

# 2) Add to groups ---------------------------------------------------------
foreach ($g in $Groups) {
    Add-ADGroupMember -Identity $g -Members $SamAccountName
    Write-Host "Added to group: $g"
}

# 3) Create the home folder and set NTFS permissions -----------------------
# Run this part ON the file server, or where $HomeRoot is a reachable path.
$homeLocal = Join-Path $HomeRoot $SamAccountName
if (-not (Test-Path $homeLocal)) {
    New-Item -Path $homeLocal -ItemType Directory | Out-Null
    # Grant the user Modify, inherited to files & subfolders: (OI)(CI)M
    icacls $homeLocal /grant ("{0}\{1}:(OI)(CI)M" -f $Domain.Split('.')[0], $SamAccountName)
    Write-Host "Home folder ready: $homeLocal"
} else {
    Write-Warning "Home folder already exists, left untouched: $homeLocal"
}

A few notes on the non-obvious bits:

  • SupportsShouldProcess plus New-ADUser's own -WhatIf support means you can run .\New-Onboard.ps1 -GivenName Test -Surname User -SamAccountName onboard-test1 -WhatIf and see what would happen without writing anything.
  • -ErrorActionPreference = "Stop" matters here: if account creation fails, you don't want the script marching on to create groups and folders for a user that doesn't exist.
  • The icacls mask (OI)(CI)M is standard: Object Inherit + Container Inherit + Modify. I use $Domain.Split('.')[0] to turn example.com into the NetBIOS name EXAMPLE — check this matches your actual NetBIOS domain name, because it isn't always the first label of the DNS name.

The mailbox step

I keep this separate because it must run in the Exchange Management Shell (or a session where you've imported the Exchange cmdlets), not the plain AD session above.

# Run in the Exchange Management Shell, after the account exists and has replicated
Enable-Mailbox -Identity "jdoe"        # -Database "MailboxDB01" is optional; omit to auto-select

Enable-Mailbox takes an existing AD user and mailbox-enables it. If you want a specific database, add -Database with your database name — confirm the exact name with Get-MailboxDatabase first. For the full parameter set, see Microsoft Learn for Enable-Mailbox. Allow for AD replication between creating the account and enabling the mailbox; if Exchange can't see the user yet, wait or target the DC you created it on.

If you're on Exchange Online, this step doesn't apply — assign a licence in the Microsoft 365 admin centre or with the Graph/Microsoft.Graph cmdlets instead.

Verify it worked

Check each piece explicitly rather than assuming:

# Account exists, in the right OU, enabled
Get-ADUser jdoe -Properties Department,HomeDirectory | Format-List Name,Enabled,DistinguishedName,HomeDirectory

# Group memberships
Get-ADPrincipalGroupMembership jdoe | Select-Object -ExpandProperty Name

# Home folder and its ACL
icacls D:\Home\jdoe

For the mailbox, in the Exchange Management Shell:

Get-Mailbox jdoe | Format-List DisplayName,Database,PrimarySmtpAddress

Have the new user attempt a logon in a test session, or use Test-ComputerSecureChannel-style checks in your environment; a mapped H: drive and a working mailbox are the real proof.

Undo / rollback

If you onboarded the wrong person or a test object, reverse it in the same order you'd expect — mailbox, then folder, then account:

# Mailbox (Exchange Management Shell): disconnects the mailbox, keeps it in the DB briefly
Disable-Mailbox jdoe -Confirm:$false

# Remove from a group you added by mistake
Remove-ADGroupMember -Identity "VPN Users" -Members jdoe -Confirm:$false

# Delete the AD account (irreversible unless AD Recycle Bin is enabled)
Remove-ADUser jdoe   # prompts for confirmation by default — good

# Remove the home folder (irreversible — data is gone)
Remove-Item D:\Home\jdoe -Recurse   # double-check the path before you hit Enter

Disable-Mailbox disconnects rather than instantly purging; the disconnected mailbox is retained per your database's deletion retention. Remove-ADUser is only recoverable if the AD Recycle Bin is enabled in your forest — otherwise it's final. And obviously, Remove-Item -Recurse on the home folder deletes the user's data with no undo, so confirm the path is the test one before you run it.

Start with -WhatIf, run it against onboard-test1, verify, then roll it out for real.

Written by
Ketan Aagja

Runs enterprise networks and security for a living, and writes Shore Up to turn two decades of hands-on Linux, Windows and mail-server work into guides you can actually use.

More about the author →

Was this article helpful?

Tap a star — no sign-in needed.

Be the first to rate this article.