Monday, May 13, 2013
A complete script to first dump all exchange mailboxes to .csv and then enumerate all mailbox permissions.
It uses the Exchange 2010 management shell and Quest’s Active Directory Powershell modules.
Usage:
- Load the script in the ISE editor.
- Set the two global parameters
- Run the script
- first execute: dump_mailboxes (this wil generate a .csv with all mailboxes)
- then execuite: dump_all_mailbox_permission (this will generate a second .csv with all permissions. Open in Excel to filter)
echo "-"
$global_ad_domain = "AD.CUSTOMER.LOCAL"
$global_ad_short = "AD"
### Load Modules for Active Directory and Exchange 2010
if (!($QUEST_LOADED))
{
Add-PSSnapin Quest.ActiveRoles.ADManagement
Set-QADPSSnapinSettings -DefaultSizeLimit 0
$logged_on_to = $env:USERDNSDOMAIN
if (!($logged_on_to -eq "$global_ad_domain"))
{
$user = read-host "Enter username in adusername format"
$pw = read-host "Enter password" -AsSecureString
connect-QADService -service '$global_ad_domain' -ConnectionAccount $user -ConnectionPassword $pw
}
else
{
connect-QADService
}
Set-QADProgressPolicy -ShowProgress $false
$QUEST_LOADED=$TRUE
echo "quest loaded"
}
if ($EMS_loaded -eq $NULL)
{
. 'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'
echo "- Exchange Management Shell Loaded"
Connect-ExchangeServer -auto
$EMS_loaded = $true
echo "- Exchange Management Shell Connected"
}
### Functions
function dump_mailboxes
{
$output_file = "d:\temp\mailboxes.csv"
echo "Name`tAlias" >$output_file
# $mailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox
$mailboxes = Get-Mailbox -resultsize Unlimited
foreach ($mailbox in $mailboxes)
{
$Name = $mailbox.Name
$Alias = $mailbox.Alias
echo "$Name`t$Alias" >>$output_file
}
}
function dump_all_mailbox_permission
{
$output_file = "d:\temp\mailbox_permissions.csv"
$lijst = import-csv -delimiter "`t" d:\temp\mailboxes.csv
$aantal = $lijst.count
$teller = 0
write-host "Aantal functionele mailboxen: $aantal"
echo "Mailbox`tAuthType`tGroup`tSam`tType" >$output_file
foreach ($regel in $lijst)
{
$teller++
$Alias = $regel.alias
write-host "$teller / $aantal -> $Alias"
mailbox_permissions $Alias >>$output_file
}
}
function mailbox_permissions($mailbox)
{
if ($perms = get-mailboxpermission -identity "$mailbox" | where {($_.isinherited -eq $false) -and ($_.User -like "$global_ad_short\*")})
{
foreach ($perm in $perms)
{
$usr = $perm.User.tostring()
$typeusr = (get-qadobject -identity $usr -DontUseDefaultIncludedProperties).type
$usr = $usr.replace("$global_ad_short","")
$rights = $perm.AccessRights
if ($typeusr -eq "group")
{
$members = get-qadgroupmember -identity "$usr"
foreach ($member in $members)
{
$mbmrsam = $member.samaccountname
echo "$mailbox`t$typeusr`t$usr`t$mbmrsam`t$rights"
}
}
else
{
echo "$mailbox`t$typeusr`t`t$usr`t$rights"
}
}
}
}
echo "-"
Wednesday, April 27, 2011
A common usecase for the need of open relays are MFC’s (”Copiers”) because people need to scan documents and want to mail them directly to recipients on the internet.
Never apply the following to your normal connector for mailflow, as your mailserver will most certainly be used to send spam!
Create a new receive connector (Server configuration, Hub Transport) and make sure it’s bindings don’t conflict with other connectors. The name for the connector could be something like “Relay Connector MFC’s” and make sure you add the right ip-addresses or ranges.
To grant the relay access, the following line will do the trick:
Get-ReceiveConnector "Relay Connector MFC's" | Add-ADPermission -User "NT AUTHORITY\ANONYMOUS LOGON" -ExtendedRights "Ms-Exch-SMTP-Accept-Any-Recipient"
Thursday, March 3, 2011
Because i need to maintain lots of Exchange 2003 servers and there are no Exchange 2003 powershell modules, i’m writing my own.
Here’s a piece of code that handles the forwarding of mail for users.
As you know, forwarding mail for a mailbox/user involves creating a contact with an external smtp address in Active Directory. Next, that contact can be assigned to the mailbox and a forwarding mode can be selected.
This script will handle all of those functions for you.
The script uses two global variables (customize to match your own Active Directory and/or place where you want to create these forwarding contacts):
$FQDN=",DC=netherlands,DC=europe,DC=microsoft,DC=com"
$base_security_groups_container="CN=Users"
Here’s the code:
function set_forward_mail($username, $forwarding_mode, $forwarding_address)
{
# forwarding_mode
# 0 = forwarding disabled
# 1 = forward without local delivery
# 2 = forward with local delivery
if ($forwarding_mode -eq "2")
{
if (!(get-qadobject -identity "$username (forwarded by PowershellApp)"))
{
# contact doesn't exist (yet). Create now
New-QADObject -ParentContainer "$base_security_groups_container$FQDN" -type "contact" -name "$username (forwarded by PowershellApp)" -DisplayName "$username (forwarded by PowershellApp)" -ObjectAttributes @{Description="$username (forwarded by PowershellApp)";mail="$forward_address";targetAddress="SMTP:$forwarding_address";mailNickname="$username"+"_forwarded_by_PowershellApp";msExchHideFromAddressLists=$true}
# Recipient Update Service will do the rest.
# Set the forwarding mode, type 2
$forward_user_dn = (Get-QADObject -identity "$username (forwarded by PowershellApp)" | Select-Object dn).dn
set-qaduser -identity $username -objectAttributes @{deliverAndRedirect=$true;altRecipient=$forward_user_dn}
}
else
{
# contact DOES exist. Update
set-qadobject -identity "$username (forwarded by PowershellApp)" -ObjectAttributes @{Description="$username (forwarded by PowershellApp)";mail="$forward_address";targetAddress="SMTP:$forwarding_address";mailNickname="$username"+"_forwarded_by_PowershellApp";msExchHideFromAddressLists=$true}
# clear any old addresses in the list of addresses and make the new one primary
get-qadobject -identity "$username (forwarded by PowershellApp)" | Clear-QADProxyAddress | Add-QADProxyAddress -Address "SMTP:$forwarding_address" -Primary
# make sure the forwarding mode is correct, type 2
$forward_user_dn = (Get-QADObject -identity "$username (forwarded by PowershellApp)" | Select-Object dn).dn
set-qaduser -identity $username -objectAttributes @{deliverAndRedirect=$true;altRecipient=$forward_user_dn}
}
}
if ($forwarding_mode -eq "1")
{
if (!(get-qadobject -identity "$username (forwarded by PowershellApp)"))
{
# contact doesn't exist (yet). Create now
New-QADObject -ParentContainer "$base_security_groups_container$FQDN" -type "contact" -name "$username (forwarded by PowershellApp)" -DisplayName "$username (forwarded by PowershellApp)" -ObjectAttributes @{Description="$username (forwarded by PowershellApp)";mail="$forward_address";targetAddress="SMTP:$forwarding_address";mailNickname="$username"+"_forwarded_by_PowershellApp";msExchHideFromAddressLists=$true}
# Recipient Update Service will do the rest.
# Set the forwarding mode, type 2
$forward_user_dn = (Get-QADObject -identity "$username (forwarded by PowershellApp)" | Select-Object dn).dn
set-qaduser -identity $username -objectAttributes @{deliverAndRedirect=$false;altRecipient=$forward_user_dn}
}
else
{
# contact DOES exist. Update
set-qadobject -identity "$username (forwarded by PowershellApp)" -ObjectAttributes @{Description="$username (forwarded by PowershellApp)";mail="$forward_address";targetAddress="SMTP:$forwarding_address";mailNickname="$username"+"_forwarded_by_PowershellApp";msExchHideFromAddressLists=$true}
# clear any old addresses in the list of addresses and make the new one primary
get-qadobject -identity "$username (forwarded by PowershellApp)" | Clear-QADProxyAddress | Add-QADProxyAddress -Address "SMTP:$forwarding_address" -Primary
# make sure the forwarding mode is correct, type 2
$forward_user_dn = (Get-QADObject -identity "$username (forwarded by PowershellApp)" | Select-Object dn).dn
set-qaduser -identity $username -objectAttributes @{deliverAndRedirect=$false;altRecipient=$forward_user_dn}
}
}
if ($forwarding_mode -eq "0")
{
if (!(get-qadobject -identity "$username (forwarded by PowershellApp)"))
{
# contact doesn't exist, just disable forwarding
set-qaduser -identity $username -objectAttributes @{deliverAndRedirect=$false;altRecipient=""}
}
else
{
# contact DOES exist. disable forwarding and delete contact
set-qaduser -identity $username -objectAttributes @{deliverAndRedirect=$false;altRecipient=""}
Remove-QADObject -identity "$username (forwarded by PowershellApp)" -Force
}
}
}
Wednesday, December 22, 2010
As i told before, it’s not that easy to make changes with powershell to your Exchange 2003 environment as it is nowadays with Exchange 2010.
Since it was pretty hard to read certain values from Active Directory, i’m doing a pretty nasty trick: copy the values from an existing user.
Here’s how to create a mailbox for an existing user:
function add_exchange2003_mailbox_for_user($username)
{
# to keep it simple: let's copy the properties of a template user, e.g. Administrator, and create the mailboxes in the same database
$template_user = "Administrator"
$userproperties = get-qaduser -identity $template_user -IncludeAllProperties
set-qaduser -identity $username -objectAttributes @{msExchHomeServerName=$userproperties.MsExchHomeServerName}
set-qaduser -identity $username -objectAttributes @{mailnickname="$username"}
set-qaduser -identity $username -objectAttributes @{mDBUseDefaults='TRUE'}
set-qaduser -identity $username -objectAttributes @{homeMBD=$userproperties.homeMDB}
# now the Recipient Update Service will do the rest ...
}
When you’re making changes to your active directory or exchange environment with powershell, it’s a piece of cake with Windows 2008 R2 and/or Exchange 2010. All the cmdlets are there by default.
But when you’re dealing with Windows 2003 and/or Exchange 2003, it’s a whole different story.
I will be posting some of my scripts for Windows 2003 and Exchange 2003 from now on.
Because Windows 2003 has no active directory powershell module, i’m using the Quest AD Templates for that purpose (highly recommended!).
Here’s how to change the primary address for an exchange 2003 user:
function set_exchange2003_primary_address($username, $primary_smtp_address)
{
# lowercase the to-be-added address
$primary_smtp_address = $primary_smtp_address.ToLower()
# get current addresses
$userinfo = get-qaduser -identity $username
$new_proxyaddresses = $userinfo.ProxyAddresses
# lowercase all the "SMTP:" entries
foreach ($number in 0..($new_proxyaddresses.Count - 1) )
{
$address = $new_proxyaddresses[$number]
$new_proxyaddresses[$number]=$address.Replace("SMTP:", "smtp:")
}
# Next, check if the to-be-added address is allready in the list
$allready_in_list = $FALSE
foreach ($number in 0..($new_proxyaddresses.Count - 1) )
{
$address = $new_proxyaddresses[$number].ToLower()
$check = $address.CompareTo("smtp:$primary_smtp_address")
if ($check -eq 0)
{
# address is found in the list. Make it PRIMARY
$new_proxyaddresses[$number]=$address.Replace("smtp:", "SMTP:")
$allready_in_list = $TRUE
}
}
# But if it's not found, add the new adress to the list as primary
if ($allready_in_list -eq $FALSE)
{
$new_proxyaddresses += 'SMTP:'+$primary_smtp_address
}
# now write the addresses to active directory
set-qaduser -identity $username -objectAttributes @{ProxyAddresses=$new_proxyaddresses}
}
Hmm..
Guess I should have payed more attention… Why not do this:
function set_exchange2003_primary_address($username, $primary_smtp_address)
{
get-qaduser -identity $username | Add-QADProxyAddress -Address $primary_smtp_address -Primary
}
Thursday, November 11, 2010
To renew a self-signed ssl certificate on an Exchange 2007 server:
Start the Exchange Management Shell, then:
Get-ExchangeCertificate -DomainName CAS01.contoso.com
Find the certificate that contains a “W” from the list of certificates For example, select IP.WS. The “W” indicates that the certificate is assigned to IIS.
Then to clone the certificate, run the following cmdlet (the thumbprint is unique):
Get-ExchangeCertificate -Thumbprint c4248cd7065c87cb942d60f7293feb7d533a4afc | New-ExchangeCertificate
The new cloned certificate will then be stamped with a new expiration date one year after the date you run the cmdlet.
And last but not least: assign the certificate to a service:
Enable-ExchangeCertificate -Thumbprint c4248cd7065c87cb942d60f7293feb7d533a4afc -Service IIS
Monday, November 1, 2010
In addition to the import procedures, here’s how to export to .pst files:
Add an import to the queue:
New-MailboxExportRequest -Mailbox p.puk -FilePath "\\FS01\data\Backup Mailbox (PST)\p.puk.pst"
And status:
Get-MailboxExportRequest
Friday, October 29, 2010
SP1 for Exchange 2010 has a new approach for importing .pst files.
First of all make sure the group “Exchange Trusted Subsystem” has NTFS permissions on the folder which contains all the .pst files.
Second, make sure this folder has been shared. Exchange only accepts unc paths.
Third, you have to make a new role assignment to a security group.
Create a universal group called “Mailbox Import Export Access” in active directory and add the user who’s going to do the export. Next, from the Exchange Management Shell:
New-ManagementRoleAssignment -Name "Mailbox Import Export Access" -SecurityGroup "Mailbox Import Export Access" -Role "Mailbox Import Export"
All the preparations have been made.
To queue (yes queue!) the import for a user:
New-MailboxImportRequest -Mailbox p.puk -FilePath "\\FS01\data\Backup Mailbox (PST)\p.puk.pst"
You can repeat the line for other users or pipe a list of users to build a bigger queue.
The following command shows the queue and the status of all imports:
Get-MailboxImportRequest
or
get-mailboximportrequest | fl filepath,status
One drawback so far:
I haven’t been able to find a way to set the locale by default (was possible with non-SP1 by typing
-locale "nl-NL"
for Dutch users) which is really annoying since users will end up with “Inbox” instead of “Postvak In”, “Sent Items” instead of “Verzonden Items”, etc.
This can be overcome by logging in to the webmail before starting the import and set the default language from there (first question asked when logging in). But that’s still annoying.
Update 2011/03/25
I haven’t been able to test it yet but running the following command prior to the import might do the trick ….
Set-MailboxRegionalConfiguration p.puk -Language "nl-NL" -DateFormat "dd-MM-yyyy" -LocalizeDefaultFolderName:$true
or for all mailboxes
get-mailbox | set-mailboxregionalconfiguration -Language nl-NL -DateFormat "dd-MM-yyyy" -LocalizeDefaultFolderName:$true
Wednesday, September 1, 2010
In addition to the previous article, you might want to add your default locale to the import-mailbox command.
e.g.
import-mailbox -identity "hugo" -pstfolderpath "c:\pstfiles" -locale "nl-NL"
Otherwise annoying duplicate folders like Inbox/Postvak IN, Calendar/Agenda, Drafts/Concepten, etc will appear.
Wednesday, August 25, 2010
I haven’t figured out how to get proper resultcodes or errorhandling from the “Import-Mailbox” command, but you can use your transcript file for that. See my other post for that.
You’ll need some global vars, e.g.:
$your_import_file="c:\import\import.csv"
$folder_with_psts="C:\exmerge\primary database export files"
Then it’s as simple as this:
function import_mailboxes()
{
$UserDetails=Import-Csv -delimiter ";" $your_import_file
$count=0
$found=0
$notfound=0
foreach($UD in $UserDetails)
{
$count++
$username=$UD.Code.ToLower()
$full_path_to_pst=$folder_with_psts + $username + ".pst"
$FileExists = Test-Path $full_path_to_pst
if ($FileExists)
{
write-host "$count - $username - Ready to import ($full_path_to_pst)" -ForegroundColor Green
$found++
Import-Mailbox -Identity $username -PSTFolderPath $folder_with_psts
}
else
{
write-host "$count - $username - No matching pst file found!" -ForegroundColor Red
$notfound++
}
}
write-host "Summary: Found (and hopefully successfully imported): $found, Not Found: $notfound"
}
Friday, August 13, 2010
Create .csv files from all smtp email addresses in your (exchange 2003) environment.
csvde -f groups.csv -d "dc=home,dc=yourdomain,dc=local" -r "(&(objectClass=group)(mail=*))" -l "DN,displayName,proxyAddresses"
csvde -f users.csv -d "dc=home,dc=yourdomain,dc=local" -r "(&(objectClass=user)(mail=*))" -l "DN,samAccountName,displayName,mail,proxyAddresses"
csvde -f contacts.csv -d "dc=home,dc=yourdomain,dc=local" -r "(&(objectClass=contact)(mail=*))" -l "DN,displayName,targetAddress"
Tuesday, August 10, 2010
This script uses the RemoteExchange calls for Exchange 2010:
. 'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'
Connect-ExchangeServer -auto
And the function:
function enable_mailbox_for_existing_user([string]$username)
{
$check = get-aduser -Filter { samAccountName -eq $username }
if($check -eq $null)
{
write-host "- User does not exist - ERROR" -ForegroundColor Red
}
else
{
# seems like the user exists
$mailbox_test = get-user $username | select recipienttype
if ($mailbox_test.RecipientType -eq "userMailbox")
{
write-host "- User is allready mail-enabled - WARNING" -ForeGroundColor Yellow
}
if ($mailbox_test.RecipientType -eq "User")
{
Enable-Mailbox -Identity $username -Alias $username | Out-Null
write-host "- Mailbox for user created - OK" -ForeGroundColor Green
}
}
}
Wednesday, August 4, 2010
Currently, Exchange 2010 SP1 is still in beta. Among other new features it’s not longer necessary to install Outlook 2010 (64 bit!!) on your Exchange 2010 server.
For now you have to.
To import or export .pst files you need to get the right Role Assignment. From the Exchange Management Shell:
New-ManagementRoleAssignment –Role “Mailbox Import Export” –User “Administrator”
Then it’s just a matter of:
Export-Mailbox Administrator -PSTFolderPath E:\
HOWEVER
If you have all the roles (Mailbox, Client Access and Hub Transport) on the same server, you’ll run into error:
Error occurred in the step: Approving object. An unknown error has occurred., error code: -2147221219
Solution:
- Either move the Mailbox (+Outlook 2010 64bit) to a second Exchange server.
- Or change the following:
- adsiedit
- connect to..
- Well known Naming Context: Configuration
- CN=Configuration,DC=your,DC=domain,DC=local
- CN=Services,
- CN=Microsoft Exchange,
- CN=<Your Organization Name>,
- CN=Administrative Groups,
- CN=Exchange Administrative Group (FYDIBOHF23SPDLT),
- CN=Databases,
- CN=Mailbox Database 0123456789,
- Now rightclick on “CN=Mailbox Database 0123456789” (left pane), properties
- security tab
- Grant the System user the following rights: Read, Administer information store, Allow Impersonation to Personal Exchange, Create named properties in the information store, Open mail send queue, Receive as, Send as, View information store status
- Restart
This should be fixed in SP1 or even before that.
From the Exchange Management Shell:
Get-Mailboxdatabase | Add-AdPermission -User Administrator -AccessRights GenericAll
Thursday, December 10, 2009
Doing a full backup of an Exchange 2003 database was easy.
Start, run, ntbackup, backup, custom, select the exchange object, select a destination file, create a schedule and there you go: your daily scheduled database dump. This (and this is important as we’re dealing with a database) would also commit all data tot the database and purge the transaction logs.
This would then be backupped by any backup application.
More expensive backup solutions would do these kind of database tricks by default. But as i prefer to use non-intelligent, image-based backups (like V2i, Symantec Backup Exec System Recovery, or Drivesnapshot), this had to be done manually.
Doing the same with Exchange 2007 took me some time to find out. Here’s how.
You’ll need Service Pack 2 for Exchange 2007. This includes a plugin for Windows Backup (wbadmin.exe, the successor of ntbackup) so that it’s Exchange-aware.
Please note that Windows Backup can only create backup on a volume basis (complete drive letters or mountpoints only)! That’s why my Exchange 2007 servers have a dedicated drive for the Exchange Database + System files + Transaction Logs. This keeps the backups as small as possible, without extra data. Allthough it’s better to have the Transaction Logs on another drive aswell in case of serious recovery, but i’m going to test that later.
Backups are on a seperate partition too.
This gives the following scenario:
C: = Windows 2008 + Exchange 2007 installation
D: = dvdrom drive
E: = dedicated to: Exchange Database, System files and Transaction Logs
F: = dedicated to: Exchange backup/dump
To create the backup, the following command is used:
WBADMIN START BACKUP -backupTarget:F: -include:E: -vssfull -quiet
-vssfull is the option that purges the Transaction Logs
-quiet will not ask “are you sure?” but still shows some output (you might want to pipe this to a file as some sort of log)
This can be scheduled with Windows Task Scheduler (Server manager, Configuration, Task Scheduler, Task Scheduler Library).
Only one instance of the backup is kept on F:, but that’s no problem as all partitions are backed up by the regular backup.
Monday, September 14, 2009
Having problems with sending mail?
You might want to try to simulate a smtp session to see what goes wrong exactly.
Start a msdos prompt and type:
C:\WINDOWS>telnet smtp.xs4all.nl 25
Your smtp may be different offcourse.
Trying 194.109.6.51...
Connected to smtp.xs4all.nl.
Escape character is '^]'.
220 smtp-vbr11.xs4all.nl ESMTP Sendmail 8.13.8/8.13.8; Mon, 14 Sep 2009 15:03:50 +0200 (CEST)
Type “helo” followed by your domain
helo bogusdomain.nl
250 smtp-vbr11.xs4all.nl Hello xxxxxxxxx [a.b.c.d], pleased to meet you
Type “mail from:” followed by your email address
mail from:[email protected]
250 2.1.0 [email protected]... Sender ok
Type “rcpt to:” followed by your email address
rcpt to:[email protected]
553 5.3.0 [email protected]... Relaying denied,Authenticate with your username and password first
Now we see what is wrong here. This server doesn’t allow me to relay.
Type “quit” to exit.
quit
221 2.0.0 smtp-vbr11.xs4all.nl closing connection
Connection closed by foreign host.
If you didn’t get an error after “rcpt-to:”, continue with:
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
hello hugo
.
250 2.0.0 Ok: queued as 60D2A4A24A
quit
221 2.0.0 Bye
Mail should arrive now.
Wednesday, September 9, 2009
Sometimes you just want people not to show up in your address list.
Here’s a simple vbs script that does the trick.
REM On Error Resume Next
groep = inputbox("Which group?")
set objRootDSE = GetObject("LDAP://RootDSE")
strdomainname = objRootDSE.Get("defaultNamingContext")
set objgroup = getobject("LDAP://cn=" + groep + ",cn=users," + strdomainname)
objgroup.GetInfo
arrmember = objgroup.GetEx("member")
for each objmember in arrmember
set objuser = getobject("LDAP://" + objmember)
objuser.MSExchHideFromAddressLists = TRUE
objuser.SetInfo
next
Friday, August 14, 2009
SSL, the basics:
A SSL certifcate enables secure communication (encryption) between client and server. For this to work, there are 3 checks performed by your client (which can be a computer, pda, smartphone, etc):
- Date of the certificate. Is it valid? Isn’t the certificate expired yet?
- Trusted Authority. In short: which trusted company sold this certificate? e.g. Verisign, Thawte, etc. Your client has a list of well-known and trusted companys. If this company is on the list, this certificate can be trusted also.
- The common name. If the common name on the certificate is www.domain1.com and you want to visit webmail.domain1.com through ssl, check 3 fails.
Exchange 2007 and SSL
After installing Exchange 2007, a self-signed SSL certificate is installed by default. This SSL certificate is used to secure communication between both Internet clients (Exchange ActiveSync, Outlook Web Access, Outlook Anywhere, POP3 and IMAP4) and internal clients (Outlook 2007) to the Client Access server.
Exchange Server 2007 also introduces a new Exchange web service called the Autodiscover service. The autodiscover service is used to configure Outlook 2007 clients. More specifically, the Autodiscover service is used by Outlook 2007 client features such as the Availability service (free/busy), Auto Account Setup (automatic profile creation), Out of Office (OOF), Offline Address Book (OAB), and Unified Messaging (UM). This means that in order for these features to work correctly, the Autodiscover service must be properly configured. Since the Autodiscover service is a web-based service, it’s located on the Client Access server (CAS). And since it’s a webbased service, it needs an SSL certificate that is accepted by all clients, internal but also on the internet.
We now have one problem.
As the common name of the server is different, based on where you reside at that moment, you’ll need a SSL certificate with at least 5 different common names, e.g.
- the netbios name of the computer, lets say: “EXCH2K7SRV02”
- the fully qualified domain name in the local network; EXCH2k7SRV02.domain1.local
- the fully qualified domain name on internet; webmail.domain1.com
- the fully qualified domain name for the autodiscovery in the local network; autodiscover.domain1.local
- the fully qualified domain name for the autodiscovery on internet; autodiscover.domain1.com
SAN certificate
With Exchange Server 2007 a new type of certificate is introduced; it’s called a subject alternative name (SAN) certificate. The interesting thing about a SAN certificate is that it allows us to include multiple FQDNs (aka common names) in one single certificate.
So in case you wondered: this SAN certificate has nothing to do with your SAN storage. It’s something different.
Request a SAN certificate
Start the Exchange 2007 Management Shell
In the Powershell we type:
[PS] C:\Windows\System32> New-ExchangeCertificate -DomainName EXCH2k7SRV02, EXCH2k7SRV02.domain1.local, webmail.domain1.com, autodiscover.domain1.local, autodiscover.domain1.com -FriendlyName Domain1SSLCertificate -GenerateRequest:$True -Keysize 1024 -path c:\certreq.txt -privatekeyExportable:$true -subjectName "c=US, o=My Company, CN=domain1.com" -privatekeyExportable:$true
As you see, with the “-DomainName” parameter, i’m requesting a certificate for 5 Subject Alternative Names which makes it a SAN certificate.
Make the “-FriendlyName” something obvious. And remember it, you’ll need it later!
I mark the private key as exportable (”-privatekeyExportable:$true”) in order to re-use the certificate whenever i want to transfer it to another server. I know this is less secure, but i’ve been in a lot of situations where customers didn’t remember where they bought the certificate or didn’t have the appropriate login info etc. So that’s why.
In the “-subjectName”, specify your country “c=US”, organisation “o=My Company” and the domain you are working with “CN=domain1.com”.
As you see (”-path”) the request is stored in a file called c:\certreq.txt. The content of this file is required to actually request the certificate at your SSL reseller or your own active directory CA.
Import the SAN certificate
Once you’ve got the certificate, save it to c:\certnew.cer.
In the Exchange Management Shell type:
[PS] C:\Windows\System32> Import-ExchangeCertificate -path c:\certnew.cer -friendlyname "Domain1SSLCertificate"
So this is where you’ll need that friendlyname again.
After his command you’ll see a “thumbprint” on your screen. My example: “795E704F73D47F6053A493961CB23DB349731141”
The certificate is now imported.
If you forgot the thumbprint, you can look it up by typing:
[PS] C:\Windows\System32> Get-ExchangeCertificate -DomainName "EXCH2K702"
All you have to do right now is activate the certificate for the required Exchange services. Do this by typing:
[PS] C:\Windows\System32> Enable-ExchangeCertificate -thumbprint 795E704F73D47F6053A493961CB23DB349731141 -services "IIS,POP,IMAP"