Administrators of MS Exchange Server 2007/2010/2013/2016 might find themselves in need of creating multiple mail-enabled user accounts at once (e.g. when migrating from an older version of Exchange). Manual creation of even a relatively small number of Active Directory users – followed by assigning a mailbox to every one of them – can take a lot of time, not to mention creating dozens or hundreds of such items. Fortunately there is a way to make this procedure automatic – at least to some extent.
1. Creating a file with the user list.
The first thing that needs to be prepared is a complete list of all new users and mailboxes in a CSV file (Comma Separated Values). The easiest way to do it would be to use Microsoft Excel, but even ordinary Notepad is able to create such a file. In the example below the users have been defined according to the following criteria:
Alias,Name,UPN
Additional values can be added here as well – virtually for every field available in the Active Directory. A detailed how-to explaining that can be found at the end of this article. The example CSV user list looks like that:
Alias,Name,UPN
User_1,User 1,user1@domain
User_2,User 2,user2@domain
User_3,User 3,user3@domain
etc.
The header of the list is very important – it cannot be omitted. Once the list is ready, it needs to be saved as a CSV file with a relatively simple name – it will be used later in the script pulling data from it. In this example it was called CreateMailboxes.csv.
2. Assigning the password.
The next step is to create a password for all the new users. Manually assigning a new password for every single user will be a great waste of time – it is better to do it automatically using the Exchange Management Shell instead. It can be achieved with the following script:
$Password=Read-Host “Enter Password” –AsSecureString
A notification asking for the password will be displayed. We can now input the desired phrase – it will become the password for all the new users from the CSV list. It can always be changed later according to individual needs.
3. Importing the CSV file and creating the mailboxes.
The final step involves importing the CSV file we have prepared earlier and creating the mailbox-enabled user accounts. To do that, we need to issue the following command in the Exchange Management Shell:
Import-CSV CreateMailboxes.csv | ForEach {New-Mailbox -Alias $_.alias -Name $_.name -userPrincipalName $_.UPN -Database “Mailbox Database” -OrganizationalUnit Users -Password $Password}
The script presented above can be modified according to specific needs. The Exchange Management Shell interprets the selected parts of this command in the following way:
- Import-CSV CreateMailboxes.csv – pulls data from the CSV file we prepared earlier. If the file was saved in a location different from the one Exchange Management Shell is running from, a full path to the CSV file needs to be included in the script as well, e.g. “c:\My Documents\CreateMailboxes.csv” (quotation marks are required).
- ForEach – retrieves data from every single line of the CSV file using the first one as the header. All the field names are treated as names of the Active Directory fields. Additional values can be easily added to the command – e.g. when we add a line Company $_.company it will force the script to search the CSV file for a column called Company and pull from it all the data for each row of our user list.
- New-Mailbox – this item is directly responsible for the creation of new mailboxes. It supports a whole range of parametres that can be definded for each user – a full list of all available values can be found on the Microsoft Technet website: New-Mailbox cmdlet syntax. The necessary values can be added to the CSV file and the script should include an additional command line matching them.
- OrganizationalUnit – this value defines the Active Directory Organizational Unit all the new users will be added to. In the example script all the users have been included in the main “Users” group. To split users between multiple AD groups, it will be necessary to create an additional column in the CSV list (called for example “OU”), and then complete the script with a command that will pull data from this very column for every single user: -org $_.OU.
- Password – assigns to each user the password retrieved from the $Password value created before.
I hope that this article will help to save a lot of time and effort that would be required while trying to manually perform all the procedures described above.
Suggested reading
Mailbox cmdlets in Exchange Online/2013
Manage users’ AD photos without PowerShell (free tool)
this didnt work for me. Can someone help please
I’d be happy to help. Though I need to know what exactly didn’t work. Did you get any error? At which point?
How to write the Organizational Unit if it’s not a top level OU?
You can use any value that’s a unique identifier for an OU, which includes: Name, Canonical name, Distinguished name, or GUID.
Sorry Adam i am still confused. are you saying i must use following? can you explain in details please?
Import-CSV CreateMailboxes.csv | ForEach {New-Mailbox -Alias $_.alias -Name $_.name -userPrincipalName $_.UPN -Database “Mailbox 02” -OrganizationalUnit Users_Testing -Password $Password=P@ssword123}
Sorry, I’m explaining it a bit more, below:
The error you have received suggests that you are using the $Password variable which is null. It cannot be null, you must assign a password before you run your script. To assign it, it is best to use this cmdlet:
$Password=Read-Host “Enter Password” –AsSecureString
– it will let you insert the password securely. After you run this one-liner, you can use your original script and it should work with no issues.Hi
I am getting following error please help me what am i doing wrong?
Cannot bind argument to parameter ‘Password’ because it is null.
+ CategoryInfo : InvalidData: (:) [New-Mailbox], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,New-Mailbox
my command looks like this.
Import-CSV CreateMailboxes.csv | ForEach {New-Mailbox -Alias $_.alias -Name $_.name -userPrincipalName $_.UPN -Database “Mailbox 02” -OrganizationalUnit Users_Testing -Password $Password}
It seems that you have not specified any password in the $Password variable. The script should run if you prepend it with
$Password = YourUltraStrongPassword
Good Day,
Below is the syntax i used with the data within the CSV file, and works great, but i have gotten a request to add a couple users (about 200) with two different smtp email addresses, so basically, for eg. user John Doe has default email [email protected] and an additional email [email protected]. how do i go about adding that within the syntax i currently use, also what do i add for the user to change their password on first logon. all within this syntax.
much appreciated. thanks.
import-CSV userdata.csv | ForEach {New-Mailbox -Alias $_.alias -Name $_.name -userPrincipalName $_.UPN -Database “Database name” -OrganizationalUnit users -Password $password}
Hi Andy,
to reset the password, add
-ResetPasswordOnNextLogon $true
switch. The additional email needs to be added with Set-Mailbox:import-CSV userdata.csv | ForEach {Set-Mailbox $_.Mailbox -EmailAddresses @{add=$_.NewEmailAddress}}
I’ve just created 800 mailbox in +- 1:30. It’s amazing!!
Thanks!
Thanks for the above information. Worked for me.
Sr.
Thank you! I found this very helpful.
Hi,
I Used your script to create New-RemoteMailbox
My script is look like that:
Import-CSV “c:\CreateMailboxes.csv” | ForEach {New-RemoteMailbox -Alias $_.alias -Name $_.name -userPrincipalName $_.UPN -FirstName $_.FirstName -LastName $_.LastName -OnPremisesOrganizationalUnit Students365 -Password $Password}
My problem is that the first name and last name are null in the user object.
the csv file is:
Alias,Name,UPN,FirstName,LastName
AlmogC,Almog Cohen,[email protected],Almog,Cohen
EranC,Eran Carmi,[email protected],Eran,Carmi
what am i doing wrong ?
Thank you !
Hi Eiran,
Make sure that the CSV file is encoded in UTF-8 (e.g. open the file in Notepad, go to File, Save as). Then try importing again, but with the encoding defined as UTF-8:
Import-CSV “c:\CreateMailboxes.csv” -Encoding:UTF8
Let me know if this helps!
Adam
Hi Adam,
Its seems like -Encoding is not exsist in exchange 2010 powershell.
the csv file encoding is UTF-8
this is the error :
Import-Csv : A parameter cannot be found that matches parameter name ‘Encoding’.
This is the script after the change:
Import-CSV “c:\CreateMailboxes.csv” -Encoding:UTF8 | ForEach {New-RemoteMailbox -Alias $_.alias -Name $_.name -userPrincipalName $_.UPN -FirstName $_.FirstName -LastName $_.LastName -OnPremisesOrganizationalUnit Students365 -Password $Password}
Hi Eiran,
Earlier, when you didn’t use the -Encoding parameter, was the file encoded in UTF-8? If not, please try saving it as UTF-8 now and import without the -Encoding parameter.
Best regards,
Adam
The encoding was UTF-8 from the beginning
Hi Eliran,
My money is on some kind of regional formatting of the CSV file (e.g. right-to-left text direction), but it’s very hard to say in this case.
Best regards,
Adam
Hi all,
I’m searching for a way to add an expiration date to user accounts through the run commands, they are below, but can’t seem to find any guidance on where to squeeze it in. Thanks for any help.
$data = import-csv $args[0]
$FQDN = $env:userdnsdomain
foreach ($i in $data){
$first = $i.First
$last = $i.Last
$rank = $i.Rank
$edipi = $i.EDIPI
$name = $last + ‘, ‘ + $first + ‘ ‘ + $XXXX + ‘ XXXX’
$alias = $first + ‘.’ + $last
$upn = $edipi + “@” + “XXX”
$ou = $i.OU
$encryptedpass = ConvertTo-SecureString -AsPlainText $i.Password -Force
$resetpass = $true
new-mailbox -Firstname $first -LastName $last -Name $name -Alias $alias -UserPrincipalName $upn -OrganizationalUnit $ou -Password $encryptedpass -ResetPasswordOnNextLogon $resetpass
}
Hi Charles,
To set an expiration date to user accounts, try following these steps:
1. Save the below script to the .ps1 format (e.g. myscript.ps1):
#Import the ActiveDirectory module so we are able to set the expiration date
Import-Module ActiveDirectory
$data = import-csv $args[0]
$FQDN = $env:userdnsdomain
#define the expiration date in the following format MM/DD/YYYY HH:MM AM/PM”
$expirationDate = “11/1/2016 3:00AM”
foreach ($i in $data){
$first = $i.First
$last = $i.Last
$rank = $i.Rank
$edipi = $i.EDIPI
$name = $last + ‘, ‘ + $first + ‘ ‘ + $XXXX + ‘ XXXX’
$alias = $first + ‘.’ + $last
$upn = $edipi + “@” + “XXX”
$ou = $i.OU
$encryptedpass = ConvertTo-SecureString -AsPlainText $i.Password -Force
$resetpass = $true
new-mailbox -Firstname $first -LastName $last -Name $name -Alias $alias -UserPrincipalName $upn -OrganizationalUnit $ou -Password $encryptedpass -ResetPasswordOnNextLogon $resetpass
#set the expiration using the previously provided date. The identity would be the $upn
Set-ADAccountExpiration -Date $expirationDate -Identity $upn
}
The first line of the script is required to import AD module, which you need later to run the cmdlet with an expiration date. Next, define the expiration date ($expirationDate). The core action is Set-ADAccountExpiration – in the –Date provide your date ($expirationDate) and in the –Identity provide user’s UPN ($upn).
2. Execute the .ps1 file containing the above script (myscript.ps1) via Exchange Management Shell.
Hope this helps!
Adam
Hi Adam,
Is it possible to put command “$Password=readhost…” in continue of “import-csv c:\newusers.csv | …”
I want to have everything in one line if it’s possible.
Thank you for quick response.
Ence
Hi all,
I wanted to ask is it possible to put static password in the same line where is command for creating mailbox? Thanks in front.
My commands are:
$Password=Read-Host “Enter Default Password” -AsSecureString
import-csv C:\NewUsers.csv | ForEach-Object {New-Mailbox -Name $_.Name -Alias $_.Alias -OrganizationalUnit $_.OrganizationalUnit -UserPrincipalName $_.UPN -Database $_.Database -Password $Password}
Hi Ence,
I’m not sure if I understand. Do you mean a standard password for all users that they cannot change?
Thank you!
Adam
Amazing. I woke up in the morning and had a mail from Developers that they need 500 accounts to do a load test. I was like whatt!!! and this came to the rescue. Super Job.. Works as expected. Thank you so much
Thanks a lot for this walkthrough!
I actually added a few other New-Mailbox parameters. Worked really well.
Thanks
Ty
I want to create exchange 2010 mailboxes using exchange 2013 powershell, but I am getting error.
The Mailbox database “dbname” isn’t on a server running Exchange 2013 or a later version. If you want to create or
enable a Exchange 2010 mailbox, or want to enable the archive or remote archive for a Exchange 2010 Sp1 mailbox,
Hi Patil,
Can you paste the command that gives you this error?
Thank you,
Adam
I am trying to create about 100 mailboxes using the command:
import-csv “C:\users\xyz\desktop\Bulk.csv” | ForEach-Object {New-Mailbox -Bulk -Name $_.Name -Alias $_.Alias -OrganizationalUnit $_.OrganizationalUnit -UserPrincipalName $_.UPN -Database $_.Database -Password $Password}
But I was always getting error:Cannot bind argument to parameter ‘Name’ because it is an empty string.
+ CategoryInfo : InvalidData: (:) [New-Mailbox], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,New-Mailbox
My CSV file looks like this:
Name,Alias,OrganizationalUnit,Database,UserPrincipalName
Testing Test,ttesting,deer.com/Users,DEER,[email protected]
Kindy assist to check the problem
Thanks.
Hi Abu,
Apologies for the late response.
The error would suggest that your CSV file headers are missing the ‘Name’ field. My suggestions:
– check if the ‘Name’ field is spelled correctly in the CSV file
– remove the -Bulk parameter from the command (it’s unnecessary and might cause errors) and run it again.
Let me know what was the result.
Best regards,
Adam
Thanks, this is helpful
Or just “Get-User | Enable-Mailbox”.
Hi Alexis!
Thanks for your feedback.
The problem lies in the way you named the user principal name column in your CSV. Its name is
UserPrincipalName
while in the PS command you useUPN
as the data source anchor.You can fix this by changing the name of the column in CSV to
UPN
or by changing the part of the PS command from:-UserPrincipalName $_.UPN
to
-UserPrincipalName $_.UserPrincipalName
.In other words – the string after the
$_.
part in the command must be the same as the name of the CSV column.Hi,
I have a list of 130 shared mailboxes that I must create. So I created a CSV file like this:
Name,Alias,OrganizationalUnit,Database,UserPrincipalName
John Smith,jsmith,domain.com/accounts/shared,mailbox database A,[email protected]
Mark Flone,mflone,domain.com/accounts/shared,mailbox database A,[email protected]
ETC…..
The list is ready and it is saved.
import-csv C:\path | New-mailbox -Shared
the Error is the following:
“Cannot bind parameter ‘Name’ to the target. Exception setting “Name”: “The property can’t be empty.”
I went into my spreadsheet and Trimmed everything, then saved and still the same error result.
Then I tried the following:
import-csv C:\temp\sharedMailboxCreationTest.csv | ForEach-Object {New-Mailbox -shared -Name $_.Name -Alias $_.Alias -OrganizationalUnit $_.OrganizationalUnit -UserPrincipalName $_.UPN -Database $_.Database}
The Error:
“Cannot bind argument to parameter ‘UserPrincipalName’ because it is an empty string.”
What am I missing here?
Alexis