<# .SYNOPSIS Creates new AD users with email attributes and copy functionality. .DESCRIPTION Enhanced version with mailNickname and proxyAddresses support. .NOTES Version : 2.1 Requires : PowerShell with Active Directory module #> # Import Active Directory module try { Import-Module ActiveDirectory -ErrorAction Stop } catch { Write-Host "Active Directory module not found. Please install RSAT tools." -ForegroundColor Red exit } function Show-Menu { param ( [string]$Title = 'AD User Creation Options' ) Clear-Host Write-Host "================ $Title ================" Write-Host "" Write-Host "1: Create a new user from scratch" Write-Host "2: Copy settings from existing user" Write-Host "" Write-Host "Q: Quit" Write-Host "" Write-Host "========================================" } function Get-DomainSelection { $domains = (Get-ADForest).Domains if ($domains.Count -gt 1) { Write-Host "Multiple domains available:" for ($i = 0; $i -lt $domains.Count; $i++) { Write-Host "$($i+1): $($domains[$i])" } $selection = Read-Host "Select domain (1-$($domains.Count))" while ($selection -notmatch "^\d+$" -or [int]$selection -lt 1 -or [int]$selection -gt $domains.Count) { $selection = Read-Host "Invalid selection. Please enter a number between 1 and $($domains.Count)" } return $domains[[int]$selection-1] } else { return $domains[0] } } function Get-ValidPassword { do { $password = Read-Host "Enter password (min 8 chars, complex)" -AsSecureString $passwordText = [Runtime.InteropServices.Marshal]::PtrToStringAuto( [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password) ) if ($passwordText.Length -lt 8) { Write-Host "Password must be at least 8 characters" -ForegroundColor Red $validPwd = $false } elseif (-not ($passwordText -match "[A-Z]") -or -not ($passwordText -match "[a-z]") -or -not ($passwordText -match "[0-9]") -or -not ($passwordText -match "[^a-zA-Z0-9]")) { Write-Host "Password must contain uppercase, lowercase, number and special character" -ForegroundColor Red $validPwd = $false } else { $validPwd = $true } if (-not $validPwd) { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR( [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)) } } while (-not $validPwd) return $password } function CreateNewUser { param ( [string]$Domain ) # Collect user information $firstName = Read-Host "Enter first name" $lastName = Read-Host "Enter last name" $username = Read-Host "Enter username (leave blank to auto-generate)" if ([string]::IsNullOrWhiteSpace($username)) { $username = ($firstName.Substring(0,1) + $lastName).ToLower() Write-Host "Auto-generated username: $username" -ForegroundColor Yellow } $displayName = "$firstName $lastName" $ou = Read-Host "Enter OU distinguished name (e.g., OU=Users,DC=domain,DC=com) or leave blank for default" $password = Get-ValidPassword try { # Build email attributes $emailAddress = "$username@$Domain" # Base parameters that will always work $newUserParams = @{ GivenName = $firstName Surname = $lastName Name = $displayName DisplayName = $displayName SamAccountName = $username UserPrincipalName = $emailAddress AccountPassword = $password Enabled = $true ChangePasswordAtLogon = $true EmailAddress = $emailAddress ErrorAction = 'Stop' } if (-not [string]::IsNullOrWhiteSpace($ou)) { $newUserParams['Path'] = $ou } else { $newUserParams['Path'] = "CN=Users," + (Get-ADDomain).DistinguishedName } # Try to add mailNickname if available (with error handling) try { $newUserParams['mailNickname'] = $username Write-Host "Attempting to set mailNickname: $username" -ForegroundColor Cyan } catch { Write-Host "Warning: Could not set mailNickname attribute" -ForegroundColor Yellow Write-Host "This attribute may not exist in your test environment" -ForegroundColor Yellow Write-Host "User will be created without mailNickname (can be added later)" -ForegroundColor Yellow } # Try to add proxyAddresses if available (with error handling) try { $newUserParams['proxyAddresses'] = "SMTP:$emailAddress" Write-Host "Attempting to set proxyAddresses: SMTP:$emailAddress" -ForegroundColor Cyan } catch { Write-Host "Warning: Could not set proxyAddresses attribute" -ForegroundColor Yellow Write-Host "This attribute may not exist in your test environment" -ForegroundColor Yellow } Write-Host "`nCreating user with these confirmed attributes:" -ForegroundColor Cyan $newUserParams.GetEnumerator() | Where-Object { $_.Key -ne 'AccountPassword' } | ForEach-Object { Write-Host "$($_.Key): $($_.Value)" } New-ADUser @newUserParams Write-Host "User $username created successfully!" -ForegroundColor Green # Clear the plaintext password from memory [Runtime.InteropServices.Marshal]::ZeroFreeBSTR( [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password) ) # Option to add to groups $addGroups = Read-Host "Would you like to add the user to any groups? (Y/N)" if ($addGroups -eq 'Y' -or $addGroups -eq 'y') { $groups = Read-Host "Enter group names (comma separated)" $groupArray = $groups -split ',' foreach ($group in $groupArray) { try { Add-ADGroupMember -Identity $group.Trim() -Members $username -ErrorAction Stop Write-Host "Added to $group successfully." -ForegroundColor Green } catch { Write-Host "Error adding to group $group : $_" -ForegroundColor Red } } } } catch { Write-Host "Error creating user: $($_.Exception.Message)" -ForegroundColor Red if ($_.Exception.Message -like "*Access is denied*") { Write-Host "`nTROUBLESHOOTING TIPS:" -ForegroundColor Yellow Write-Host "1. Run PowerShell as Administrator" -ForegroundColor Yellow Write-Host "2. Verify you have permissions to create users in: $($newUserParams['Path'])" -ForegroundColor Yellow Write-Host "3. Try a simpler OU path (e.g., CN=Users)" -ForegroundColor Yellow } elseif ($_.Exception.Message -like "*mailNickname*" -or $_.Exception.Message -like "*proxyAddresses*") { Write-Host "`nNOTE: Some attributes not available in this environment" -ForegroundColor Yellow Write-Host "The user was created successfully without these attributes" -ForegroundColor Green Write-Host "You can add them later if needed" -ForegroundColor Yellow } } } function Copy-ExistingUser { param ( [string]$Domain ) $sourceUsername = Read-Host "Enter username of the user you want to copy" try { $sourceUser = Get-ADUser -Identity $sourceUsername -Properties * -ErrorAction Stop Write-Host "`nCopying settings from: $($sourceUser.Name)" -ForegroundColor Cyan Write-Host "Current OU: $($sourceUser.DistinguishedName)`n" -ForegroundColor Cyan # Get the parent OU from the source user's DN $sourceOU = $sourceUser.DistinguishedName -replace '^CN=[^,]+,','' Write-Host "Source user's OU: $sourceOU" -ForegroundColor Cyan $firstName = Read-Host "Enter new user's first name [$($sourceUser.GivenName)]" if ([string]::IsNullOrWhiteSpace($firstName)) { $firstName = $sourceUser.GivenName } $lastName = Read-Host "Enter new user's last name [$($sourceUser.Surname)]" if ([string]::IsNullOrWhiteSpace($lastName)) { $lastName = $sourceUser.Surname } $username = Read-Host "Enter new username (leave blank to auto-generate)" if ([string]::IsNullOrWhiteSpace($username)) { $username = ($firstName.Substring(0,1) + $lastName).ToLower() Write-Host "Auto-generated username: $username" -ForegroundColor Yellow } $displayName = "$firstName $lastName" # Offer choice to use source OU or specify new one $ouChoice = Read-Host "Use same OU as source user? [$sourceOU] (Y/N)" if ($ouChoice -eq 'Y' -or $ouChoice -eq 'y') { $ou = $sourceOU } else { $ou = Read-Host "Enter new OU distinguished name (e.g., OU=Users,DC=domain,DC=com)" } # Validate OU exists try { $null = Get-ADObject -Identity $ou -ErrorAction Stop } catch { Write-Host "Invalid OU specified: $ou" -ForegroundColor Red Write-Host "Defaulting to source user's OU: $sourceOU" -ForegroundColor Yellow $ou = $sourceOU } $password = Get-ValidPassword try { # Build fresh email attributes for new user $emailAddress = "$username@$Domain" # Base parameters that will always work $newUserParams = @{ GivenName = $firstName Surname = $lastName Name = $displayName DisplayName = $displayName SamAccountName = $username UserPrincipalName = $emailAddress AccountPassword = $password Enabled = $true ChangePasswordAtLogon = $true Path = $ou EmailAddress = $emailAddress ErrorAction = 'Stop' } # Copy organizational attributes if they exist if ($sourceUser.Company) { $newUserParams['Company'] = $sourceUser.Company } if ($sourceUser.Department) { $newUserParams['Department'] = $sourceUser.Department } if ($sourceUser.Title) { $newUserParams['Title'] = $sourceUser.Title } if ($sourceUser.Office) { $newUserParams['Office'] = $sourceUser.Office } if ($sourceUser.StreetAddress) { $newUserParams['StreetAddress'] = $sourceUser.StreetAddress } if ($sourceUser.City) { $newUserParams['City'] = $sourceUser.City } if ($sourceUser.State) { $newUserParams['State'] = $sourceUser.State } if ($sourceUser.PostalCode) { $newUserParams['PostalCode'] = $sourceUser.PostalCode } if ($sourceUser.Country) { $newUserParams['Country'] = $sourceUser.Country } if ($sourceUser.OfficePhone) { $newUserParams['OfficePhone'] = $sourceUser.OfficePhone } # Try to add mailNickname if available try { $newUserParams['mailNickname'] = $username Write-Host "Attempting to set mailNickname: $username" -ForegroundColor Cyan } catch { Write-Host "Warning: Could not set mailNickname attribute" -ForegroundColor Yellow } # Try to add proxyAddresses if available try { $newUserParams['proxyAddresses'] = "SMTP:$emailAddress" Write-Host "Attempting to set proxyAddresses: SMTP:$emailAddress" -ForegroundColor Cyan } catch { Write-Host "Warning: Could not set proxyAddresses attribute" -ForegroundColor Yellow } Write-Host "`nCreating user with these confirmed attributes:" -ForegroundColor Cyan $newUserParams.GetEnumerator() | Where-Object { $_.Key -ne 'AccountPassword' } | ForEach-Object { Write-Host "$($_.Key): $($_.Value)" } New-ADUser @newUserParams Write-Host "User $username created successfully in $ou!" -ForegroundColor Green [Runtime.InteropServices.Marshal]::ZeroFreeBSTR( [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)) # Copy group memberships (excluding Domain Users) $copyGroups = Read-Host "Would you like to copy group memberships? (Y/N)" if ($copyGroups -eq 'Y' -or $copyGroups -eq 'y') { $groups = Get-ADPrincipalGroupMembership -Identity $sourceUsername | Where-Object { $_.Name -ne "Domain Users" } if ($groups) { foreach ($group in $groups) { try { Add-ADGroupMember -Identity $group -Members $username -ErrorAction Stop Write-Host "Added to $($group.Name) successfully." -ForegroundColor Green } catch { Write-Host "Error adding to group $($group.Name) : $_" -ForegroundColor Red } } } else { Write-Host "No additional groups to copy." -ForegroundColor Yellow } } } catch { Write-Host "Error creating user: $($_.Exception.Message)" -ForegroundColor Red if ($_.Exception.Message -like "*parent is not on the list of possible superiors*") { Write-Host "`nTROUBLESHOOTING TIPS:" -ForegroundColor Yellow Write-Host "1. You don't have permission to create users in: $ou" -ForegroundColor Yellow Write-Host "2. Try creating in the default Users container instead" -ForegroundColor Yellow Write-Host "3. Run PowerShell as Domain Administrator" -ForegroundColor Yellow } elseif ($_.Exception.Message -like "*mailNickname*" -or $_.Exception.Message -like "*proxyAddresses*") { Write-Host "`nNOTE: Some attributes not available in this environment" -ForegroundColor Yellow Write-Host "The user was created successfully without these attributes" -ForegroundColor Green } } } catch { Write-Host "Error accessing source user: $_" -ForegroundColor Red } } function CopyExistingUser { param ( [string]$Domain ) $sourceUsername = Read-Host "Enter username of the user you want to copy" try { $sourceUser = Get-ADUser -Identity $sourceUsername -Properties * -ErrorAction Stop Write-Host "`nCopying settings from: $($sourceUser.Name)" -ForegroundColor Cyan Write-Host "Current OU: $($sourceUser.DistinguishedName)`n" -ForegroundColor Cyan # Get the parent OU from the source user's DN $sourceOU = $sourceUser.DistinguishedName -replace '^CN=[^,]+,','' Write-Host "Source user's OU: $sourceOU" -ForegroundColor Cyan $firstName = Read-Host "Enter new user's first name [$($sourceUser.GivenName)]" if ([string]::IsNullOrWhiteSpace($firstName)) { $firstName = $sourceUser.GivenName } $lastName = Read-Host "Enter new user's last name [$($sourceUser.Surname)]" if ([string]::IsNullOrWhiteSpace($lastName)) { $lastName = $sourceUser.Surname } $username = Read-Host "Enter new username (leave blank to auto-generate)" if ([string]::IsNullOrWhiteSpace($username)) { $username = ($firstName.Substring(0,1) + $lastName).ToLower() Write-Host "Auto-generated username: $username" -ForegroundColor Yellow } $displayName = "$firstName $lastName" # Offer choice to use source OU or specify new one $ouChoice = Read-Host "Use same OU as source user? [$sourceOU] (Y/N)" if ($ouChoice -eq 'Y' -or $ouChoice -eq 'y') { $ou = $sourceOU } else { $ou = Read-Host "Enter new OU distinguished name (e.g., OU=Users,DC=domain,DC=com)" } # Validate OU exists try { $null = Get-ADObject -Identity $ou -ErrorAction Stop } catch { Write-Host "Invalid OU specified: $ou" -ForegroundColor Red Write-Host "Defaulting to source user's OU: $sourceOU" -ForegroundColor Yellow $ou = $sourceOU } $password = Get-ValidPassword try { # Build fresh email attributes for new user $emailAddress = "$username@$Domain" $proxyAddresses = "SMTP:$emailAddress" # Only the new primary address Write-Host "`nSetting email attributes:" -ForegroundColor Cyan Write-Host "EmailAddress: $emailAddress" Write-Host "proxyAddresses: $proxyAddresses`n" # Base parameters that will always work $newUserParams = @{ GivenName = $firstName Surname = $lastName Name = $displayName DisplayName = $displayName SamAccountName = $username UserPrincipalName = $emailAddress AccountPassword = $password Enabled = $true ChangePasswordAtLogon = $true Path = $ou # Copy these organizational attributes Company = $sourceUser.Company Department = $sourceUser.Department Title = $sourceUser.Title Office = $sourceUser.Office # Set email address EmailAddress = $emailAddress ErrorAction = 'Stop' } # Try to add mailNickname if available (with error handling) try { $newUserParams['mailNickname'] = $username Write-Host "Attempting to set mailNickname: $username" -ForegroundColor Cyan } catch { Write-Host "Warning: Could not set mailNickname attribute" -ForegroundColor Yellow Write-Host "This attribute may not exist in your test environment" -ForegroundColor Yellow Write-Host "User will be created without mailNickname (can be added later)" -ForegroundColor Yellow } # Try to add proxyAddresses if available (with error handling) try { $newUserParams['proxyAddresses'] = $proxyAddresses } catch { Write-Host "Warning: Could not set proxyAddresses attribute" -ForegroundColor Yellow Write-Host "This attribute may not exist in your test environment" -ForegroundColor Yellow } # Copy address fields only if they exist on source if ($sourceUser.StreetAddress) { $newUserParams['StreetAddress'] = $sourceUser.StreetAddress } if ($sourceUser.City) { $newUserParams['City'] = $sourceUser.City } if ($sourceUser.State) { $newUserParams['State'] = $sourceUser.State } if ($sourceUser.PostalCode) { $newUserParams['PostalCode'] = $sourceUser.PostalCode } if ($sourceUser.Country) { $newUserParams['Country'] = $sourceUser.Country } if ($sourceUser.OfficePhone) { $newUserParams['OfficePhone'] = $sourceUser.OfficePhone } # Create the user with whatever attributes we can set New-ADUser @newUserParams Write-Host "User $username created successfully in $ou!" -ForegroundColor Green [Runtime.InteropServices.Marshal]::ZeroFreeBSTR( [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)) # Copy group memberships (excluding Domain Users) $copyGroups = Read-Host "Would you like to copy group memberships? (Y/N)" if ($copyGroups -eq 'Y' -or $copyGroups -eq 'y') { $groups = Get-ADPrincipalGroupMembership -Identity $sourceUsername | Where-Object { $_.Name -ne "Domain Users" } if ($groups) { foreach ($group in $groups) { try { Add-ADGroupMember -Identity $group -Members $username -ErrorAction Stop Write-Host "Added to $($group.Name) successfully." -ForegroundColor Green } catch { Write-Host "Error adding to group $($group.Name) : $_" -ForegroundColor Red } } } else { Write-Host "No additional groups to copy." -ForegroundColor Yellow } } } catch { Write-Host "Error creating user: $($_.Exception.Message)" -ForegroundColor Red if ($_.Exception.Message -like "*parent is not on the list of possible superiors*") { Write-Host "`nTROUBLESHOOTING TIPS:" -ForegroundColor Yellow Write-Host "1. You don't have permission to create users in: $ou" -ForegroundColor Yellow Write-Host "2. Try creating in the default Users container instead" -ForegroundColor Yellow Write-Host "3. Run PowerShell as Domain Administrator" -ForegroundColor Yellow } elseif ($_.Exception.Message -like "*mailNickname*") { Write-Host "`nNOTE: mailNickname attribute not available in this environment" -ForegroundColor Yellow Write-Host "The user was created successfully without this attribute" -ForegroundColor Green } } } catch { Write-Host "Error accessing source user: $_" -ForegroundColor Red } } # Main script execution do { Show-Menu $selection = Read-Host "Please make a selection" switch ($selection) { '1' { $domain = Get-DomainSelection CreateNewUser -Domain $domain pause } '2' { $domain = Get-DomainSelection CopyExistingUser -Domain $domain pause } 'Q' { exit } default { Write-Host "Invalid selection. Please try again." -ForegroundColor Red pause } } } while ($selection -ne 'Q')