Bulk creation of mailboxes on Microsoft Exchange Server 2007/2010/2013/2016

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.

Automatically create Exchange mailboxes for users using bulk creation via PowerShell.

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:


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:

User_1,User 1,user1@domain
User_2,User 2,user2@domain
User_3,User 3,user3@domain


 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)

Tools for Exchange Server

34 thoughts on “Bulk creation of mailboxes on Microsoft Exchange Server 2007/2010/2013/2016

    • I’d be happy to help. Though I need to know what exactly didn’t work. Did you get any error? At which point?

    • You can use any value that’s a unique identifier for an OU, which includes: Name, Canonical name, Distinguished name, or GUID.

  1. 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.

  2. 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

  3. 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}}

    • 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:
      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!

    • 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,

    • 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,

  4. 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!

  5. 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.


  6. 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!

  7. 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

  8. Thanks a lot for this walkthrough!

    I actually added a few other New-Mailbox parameters. Worked really well.


  9. 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,

  10. 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:

    Testing Test,ttesting,deer.com/Users,DEER,[email protected]

    Kindy assist to check the problem


    • 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,

  11. 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 use UPN 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
    -UserPrincipalName $_.UserPrincipalName.
    In other words – the string after the $_. part in the command must be the same as the name of the CSV column.

  12. Hi,

    I have a list of 130 shared mailboxes that I must create. So I created a CSV file like this:


    John Smith,jsmith,domain.com/accounts/shared,mailbox database A,[email protected]

    Mark Flone,mflone,domain.com/accounts/shared,mailbox database A,[email protected]


    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?


Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>


CodeTwo sp. z o.o. sp. k. is a controller of your personal data.
See our Privacy Policy to learn more.