PowerShell Script to Forward Email for a Bulk Set of Users

I wrote a PowerShell script for an Exchange 2007/2010 migration that will forward email for a group of users to an external SMTP recipient, while also delivering mail to the user’s inbox.  The script uses an input csv file which specifies the following: the users that need their email forwarded, the address to forward the mail to, and the name of the contact that will be created in the source domain.

The script creates the contacts, forwards the email to the contacts, enables delivery to both the source user and the target contact, and hides the contact from the GAL.
Enjoy!
#####################################################
# Bulk Contact Creation and Mail Forward Script #
# for Exchange 2007/2010 #
# Ron Williams #
# ron dot williams at mail dot com #
# 3/20/13 #
#####################################################

#INSTRUCTIONS:
# 1. Update csv file with appropriate values, make sure to the keep header row. 
# SamAccountName is the SAMaccountName from the source domain of the user 
# whose mail should forward to ext recipient.
# ForwardingAddress is the SMTP address to forward the mail to. 
# Will existing mailbox with this value as -ForwardingAddress
# FirstName is the First Name value that will be created on the contact
# LastName is the Last Name value that will be created on the contact
# 2. Run from EMS in format "C:\pathname\BulkContactForward.ps1 C:\pathname\input.csv"
# 3. Update $OU in variables section below to the OU where you want to creat the contacts.

#CSV FILE FORMAT:
# SamAccountName,ForwardingAddress,FirstName,Lastname
# joeb,joe.blow@contoso.com,Joe,Blow
# mikes,michael.smith@contoso.com,Mike,Smith

#VARIABLES
$OU="contoso.com/TestOU"

# Loop through the object returned by Import-Csv with each element represented by $person
foreach ($person in (Import-Csv .\input.csv))
 {
 # Check the Mailbox for the person exists
 If ((Get-Mailbox $person.SamAccountName -ErrorAction SilentlyContinue)) 
 { 
 # Check the mail contact doesn't exist and if not add it, hide it from GAL
 If (!(Get-MailContact $person.SamAccountName -ErrorAction SilentlyContinue)) 
 {
 New-MailContact -name $person.SamAccountName -Firstname `
 $person.FirstName -Lastname $person.lastname `
 -ExternalEmailAddress $person.ForwardingAddress -OrganizationalUnit $OU;
 Set-MailContact -identity $person.SamAccountName `
 -HiddenFromAddressListsEnabled $true
 Set-Contact $person.SamAccountName -Notes `
 "Created for Email Migration Coexistence"
 # Set the Forwarding Address on the Mailbox 
 Set-Mailbox $person.SamAccountName -ForwardingAddress `
 $person.ForwardingAddress -DeliverToMailboxAndForward $true 
 }
 else {write-host "The contact for", $person.SamAccountName, "already `
 exists. No furthur action on this contact will be performed."}
 }
 else {write-host "The mailbox for", $person.SamAccountName, "did not exist. `
 No furthur action on this mailbox will be performed."}
}

VBScript to Create Mail Enabled Users with Populated Mailboxes

Here is a vbscript that I wrote that will create a specified number of Exchange 2003 mail enabled TestUsers with populated mailboxes.   It really helps when creating (and recreating) lab users to test Active Directory and Exchange migrations in a Proof Of Concept (POC).  It should be run from an Exchange 2003 box in a non-production environment. 
 
Here is what it does:
1.       Creates Root level OU called TestOU
2.       Creates a specified number of users in that OU
3.       Creates mailboxes for all those users (mailbox enabled users)
4.       Waits 60 seconds
5.       Fills each mailbox with a specified number of emails using SMTP
 
Here is the syntax:
cscript scriptname.vbs (Number of Users) (SMTP Namespace specified in Recipient Policies) (Number of Emails to Create) (Name of the mailbox store) (Active Directory Domain Name)
For example, to create 50 users with 10 emails in each mailbox, here is the command:
cscript CreateRecipients.vbs 50 "domain.com" 10 "Mailbox Store (EX2003)" "domain.local"
 
 

‘This script creates an OU called TestOU in the root of the domain.
‘Then it creates the specified number of mailbox enabled users which are not disabled
‘All users have the same password
‘Then it populates their inboxes with the specified number of emails.
‘Always enclose arguments with spaces in quotes,
‘Seperate the arguments with a space
‘Should be run on the exchange 2003 server in a lab environment.
‘For help, email ron dot williams at mail dot com
‘Arguments= (number of test mailboxes)(domain name)(number of test emails to create)(name of mailbox store) (Active Directory Domain Name)
‘an example of the command used to run this script to create 50 users with 10 emails in each mailbox is:
‘cscript CreateRecipients.vbs 50 "domain.com" 10 "Mailbox Store (EX2003)" "domain.local"
 
‘Argument1 = oArgs.Item(0) = number of test users to create
‘Argument2 = oArgs.Item(1) = SMTP namespace domain name of the recipients ie "domain.com" is the domain name for TestUser1@domain.com
‘Argument3 = oArgs.Item(2) = number of test emails to create
‘Argument4 = oArgs.Item(3) = home MDBname, for example "Mailbox Store (EX2003)" this can be found in exchange System Manager next to the mailbox database
‘Argument5 = oArgs.Item(4) = Active Directory Domain Name domain name of active directory "domain.local" This may or may not be the same as the SMTP namespace.
 
 

Set

oArgs=WScript.Arguments

If

oArgs.Count < 5 Then ‘if the script is run with less than 5 arguments, it errors out.

Set objShell = Wscript.CreateObject("Wscript.Shell")

objShell.LogEvent EVENT_TYPE_ERROR, _

"Script was run with an incorrect number of arguments."

wscript.echo

"Script was run with an incorrect number of arguments."

WScript.Quit -1

End

If

 
 

‘get the domain DN from the oArgs.Item(4)argument

DomainDN =

"dc=" & Replace(oArgs.Item(4),".",",dc=")

‘Create the OU "TestOU" to house the user objects
‘on Error Resume Next

Set

objDomain = GetObject("LDAP://" & DomainDN)

Set

objOU = objDomain.Create("organizationalUnit", "ou=TestOU")

objOU.SetInfo
 

‘Create Users

On

Error Resume Next

For

CountUsers = 1 to oArgs.Item(0)

EmailName =

"Test_User" & CountUsers ‘ this will be the user principle name TestUser1 TestUser2 etc

FirstName =

"Test_"

LastName =

"User" & CountUsers

 

‘ Bind to Active Directory, TestOU container.

Set objRootLDAP = GetObject("LDAP://rootDSE")

Set objContainer = GetObject("LDAP://OU=TestOU," & _

objRootLDAP.Get(

"defaultNamingContext"))

‘ Create the actual User.

Set objNewUser = objContainer.Create("User", "cn=" & emailname)

objNewUser.Put

"sAMAccountName", EMailName

objNewUser.Put

"sn", LastName

objNewUser.Put

"givenName", FirstName

objNewUser.Put

"userPrincipalName", emailname

objNewUser.SetInfo
objNewUser.SetPassword

"Password1"

objNewUser.AccountDisabled =

False

objNewUser.SetInfo

Next

 
wscript.echo

"Created " & oArgs.Item(0) & " users."

 

‘The next section creates Mailboxes for all users in TestOU

strOU =

"OU=TestOU"

strStore = oArgs.Item(3)

Set NC = GetObject("LDAP://RootDSE")

Set oIADS = GetObject("LDAP://RootDSE")

strConfContext = NC.Get(

"defaultnamingcontext")

strADSPath =

"LDAP://" & strOU & "," & oIADS.Get("defaultNamingContext")

Set objCommand = CreateObject("ADODB.Command")

Set objConn = CreateObject("ADODB.Connection")

objConn.Open

"Provider=ADsDSOObject;"

Set objCommand.ActiveConnection = objConn

objCommand.CommandText =

"SELECT distinguishedName FROM "+"’"+strADsPath+"’"+" WHERE objectClass = ‘user’"

objCommand.Properties(

"searchscope") = 2

objCommand.Properties(

"Page Size") = 1000

Set objRecordSet = objCommand.Execute

While Not objRecordSet.EOF

Set oIADSUser = GetObject("LDAP://" & objRecordSet.Fields("distinguishedName"))

Set oMailBox = oIADSUser

oMailbox.CreateMailbox FindAnyMDB(

"CN=Configuration," & strConfContext)

oIADSUser.SetInfo
objRecordSet.MoveNext

Wend

 
 

Function FindAnyMDB(strConfigurationNC)

Dim oConnection

Dim oCommand

Dim oRecordSet

Dim strQuery

Set oConnection = CreateObject("ADODB.Connection")

set oCommand = CreateObject("ADODB.Command")

Set oRecordSet = CreateObject("ADODB.Recordset")

oConnection.Provider =

"ADsDSOObject"

oConnection.Open

"ADs Provider"

 
strQuery =

"<LDAP://" & strConfigurationNC & ">;(Name=" & strStore & ");name,adspath;subtree"

oCommand.ActiveConnection = oConnection
oCommand.CommandText = strQuery

Set oRecordSet = oCommand.Execute

If Not oRecordSet.EOF Then

oRecordSet.MoveFirst
FindAnyMDB =

CStr(oRecordSet.Fields("ADsPath").Value)

Else

FindAnyMDB =

""

End If

oRecordSet.Close
oConnection.Close

Set oRecordSet = Nothing

Set oCommand = Nothing

Set oConnection = Nothing

End Function

wscript.echo

"Mailbox enabled " & oArgs.Item(0) & " users."

 

‘wait 60 seconds

cscript.echo

"Waiting for 60 seconds…."

Wscript.Sleep 60000
wscript.echo

"Sending " & oArgs.Item(1) & " emails…"

 

‘Use SMTP to create mass emails to activate and populate the email boxes

For

CountMailboxes = 1 To oArgs.Item(0)

varDestUser =

"Test_User" & CountMailboxes &"@" & oArgs.Item(1)

For CountEmails = 1 To oArgs.Item(2)

set objEmail = CreateObject("CDO.Message")

objEmail.From =

"TestSender@MassEmailScript.com"

objEmail.To = varDestUser
objEmail.Subject =

"Testing Email Number " & CountEmails

objEmail.Textbody =

"Testing Email message body number " & CountEmails

objEmail.Send

Next

Next
 

wscript.echo

"Done! Check Active Directory Users and Computers to verify " _

&

"the existence of the TestOU and the Test_Users. Use Exchange System Manager " _

&

"to verify that mailboxes were created and populated."

 
‘Clear Arguments out of memory

set

oArgs=Nothing