Showing posts with label Scripting. Show all posts
Showing posts with label Scripting. Show all posts

Wednesday, January 11, 2012

Using Rich HTML with Send-MailMessage

By:Rik Hoffelder
The Send-MailMessage CMDLET can be a useful tool in many ways. However it has some limitations that can be easily overcome with a little PowerShell scripting and HTML tags. I was recently asked by a customer for some ideas to help automate a notification message when a new employee joins the company. This was to be a part of a larger auto-user provisioning script that would send a welcome message to the new employee with various company information and helpful links. This particular task was performed manually by an administrator using a custom template in Outlook (.OFT file). Our mission was to convert the OFT and manual process into something we could do with Send-MailMessage.

Before I go too much further into the solution I want to thank and credit my customer, Paul Savage of McCarthy Building Companies, for pulling this all together and sharing his code with us. Thank you Paul!

First it is important to understand that Send-MailMessage allows you to use HTML in the message body using the –HtmlAsBody switch. Next we take advantage of the Get-Content and Out-String cmdlets to build the Body parameter of the message. This allows us to create a txt file with HTML tags that contain the message content and provide the same formatting that was used in the body of the OFT. So with the assistance of Paul's Sharepoint Developer we were able to create the message body text file as shown below:

Body.Txt

<style>

.colorchange {

    color:#4F81BD;

}

</style>

<html xmlns="http://www.w3.org/1999/xhtml">

<body>

<p style="font-family:Tahoma, Geneva, sans-serif; font-size:10pt">Welcome to Company Name Here!&nbsp; We are glad you are here!&nbsp;&nbsp; Below are some helpful items to get you started.</p>

<p style="font-family:Tahoma, Geneva, sans-serif; font-size:10pt">Our company provides a library of documents to help you with your daily tasks and responsibilities <a href="http://intranet.company.com/employee%20%documents ">by clicking here.</a>.</p>

<p style="font-family:Tahoma, Geneva, sans-serif; font-size:10pt">The <a href=" http://intranet.company.com/hr">Human Resources Policies Manual</a> should be thoroughly reviewed.&nbsp; By replying, you are acknowledging receipt and consent to the Policies outlined in the Manual.</p>

<p style="font-family:Tahoma, Geneva, sans-serif; font-size:10pt">In addition to policies noted above, please take a moment to review and understand a few additional guidelines when using our Information Systems.&nbsp; They are: </p>

<p style="font-family:Tahoma, Geneva, sans-serif; font-size:10pt">&nbsp;1.&nbsp; Use of the Mass Distribution Function Company E-Mail System- <a href="http://intranet.company.com/hr/Mass+Email+Distribution.doc">http:// intranet.company.com/hr/Mass+Email+Distribution.doc</a><br />

&nbsp;2.&nbsp; Spam E-Mails- <a href="http:// intranet.company.com/hr/Email-SPAM-Filtering-Service.aspx">http:// intranet.company.com/hr/Email-SPAM-Filtering-Service.aspx</a> <br />

<p style="font-family:Tahoma, Geneva, sans-serif; font-size:10pt">Again, the intent of these policies and procedures are to provide for necessary safeguards that protect all employees interests and our company.&nbsp;&nbsp; If you have any questions on the policies or procedures, feel free to contact the I.T. Help Desk at 800-555-1234.&nbsp; They will forward your questions to the appropriate personnel who can assist you.</p>

<p style="font-family:Tahoma, Geneva, sans-serif; font-size:10pt">Thank you and welcome aboard!</p>

<p style="font-family:Tahoma, Geneva, sans-serif; font-size:10pt"><b>Jane Doe</b> | <span class="colorchange">Director</span></p>

<p style="font-family:Tahoma, Geneva, sans-serif; font-size:8pt; color:#808080">Human Resources | Company Name, Inc.<br/>(800) 555-1234</p>

</body>

</html>

Next we reference the body file in the script as shown below:

SendWelcomeEmail.PS1

$messageParameters = @{

Subject = "Welcome Aboard!"

Body = Get-Content "C:\body.txt" | out-string

From = "Welcome@company.com"

To = "NewEmployee@company.com"

SmtpServer = "smtp.company.com"

}

Send-MailMessage @messageParameters –BodyAsHtml

With a little bit of tweaking you can easily pass a variable to the script by adding the following:

SendWelcomeEmail.PS1 NewEmp

(Example .\SendWelcomeEmail.PS1 john.doe@company.com)

Param(

    [string] $NewEmp = ""

)

function ValidateParams

{

$validInputs = $true

$errorString = ""

if ($NewEmp -eq "")

{

    $validInputs = $false

    $errorString += "`missing parameter: The employee email address parameter is required. Please enter a valid email address. Example: john.doe@company.com"

}

if (!$validInputs)

{

    Write-error "$errorString"

}

return $validInputs

}

### Validate the parameters ###

$ifValidParams = ValidateParams;

if (!$ifValidParams) { exit; }

$messageParameters = @{

Subject = "Welcome to the Company!"

Body = Get-Content "C:\body.txt" | out-string

From = "Welcome@company.com"

To = &NewEmp

SmtpServer = "smtp.company.com"

}

Send-MailMessage @messageParameters –BodyAsHtml


 

Good luck and happy scripting!




More information on PowerShell

Read more!

Friday, October 8, 2010

Bulk Create Exchange 2010 Databases

By:Rik Hoffelder


Here's a handy script I wrote to bulk create mailbox databases to follow a strict naming convention and consistent configuration. It was designed to work with Exchange 2010, however it works just as well with 2007. The intent is to help organizations maintain consistency using a simple process that can be performed by less skilled administrators.


Script itself uses several command line parameters to create the variables needed for the scripts. The following provides the script usage:


.\createdbs.ps1 2010Server NumberOfDatabases DatabaseStartNumber DatabaseDrive LogDrive WarningQuota SendQuota SendReceiveQuota DeletedItemRetention MailboxRetention Oab PfDb

The following is an example of proper usage:

.\CreateDbs.PS1 EX2010 4 1 E D 450MB 500MB Unlimited 30 14 "\Default Offline Address List" "Public Folder Database 1"

In the above example 4 databases are created on server EX2010 with the following names:

EX2010-DB01-0500
EX2010-DB02-0500
EX2010-DB03-0500
EX2010-DB04-0500

The database are created on drive E, with the log files on drive D. The mailbox store is set to issue size limit warnings at 450MB, prohibit send at 500MB, and prohibit send/receive is set to unlimited. Next deleted items are retained for 30 days, while deleted mailboxes are retained for 14. Finally the Offline Address book is set along with the public folder database used by each mailbox store.

So let's suppose we need to create 3 more databases, but this time on drive G, with the logs on drive H. Let's also set the mailbox size limit to 1GB. You would run the following:

.\CreateDbs.PS1 EX2010 3 5 G H 900MB 1GB 2GB 10 7 "\North America OAB" "Public Folder Database 2"

This would have created databases EX2010-DB05-1000, EX2010-DB06-1000, and EX2010-DB07-1000 with 10 day deleted item retention, 7 day delete mailbox retention, a warning limit of 900MB, prohibit send at 1GB and prohibit send/receive at 2 GB. The OAB would be set to North America OAB and use Public Folder Database 2.

Notice how the DBxx value began with DB05 and the last four digits are now 1000.
The DbStartNum parameter determine the beginning of the numbering scheme in the DBxx portion. The -XXXX at the end uses the ProhibitSend value to represent the mailbox send size limit, making it easy for administrators to identify where to place mailboxes by the database name. A size limit of 125MB would produce a name SERVER-DBXX-0125 and so forth.

It's simple and flexible. To run it simply copy it to a PS1 file then lanuch it from Exchange Management Shell.

CreateDatabases.PS1

### BEGIN SCRIPT ###
Param(
[string] $2010Server = "",
[decimal] $NumDatabases = "",
[decimal] $DbStartNum = "",
[string] $DbDrive = "",
[string] $LogDrive = "",
[string] $WarnQuota = "",
[string] $SendQuota = "",
[string] $SendReceiveQuota = "",
[string] $DeletedItemRetention = "",
[string] $MailboxRetention = "",
[string] $OAB = "",
[string] $PfDb = ""
)

# This function validates the scripts parameters
function ValidateParams
{
$validInputs = $true
$errorString = ""
if ($2010Server -eq "")
{
$validInputs = $false
$errorString += "`nMissing parameter: The 2010Server parameter is required. Please enter the name of the Exchange 2010 server to configure. Example KCCEX2010"
}
if ($NumDatabases -eq "")
{
$validInputs = $false
$errorString += "`nMissing parameter: The NumDatabases parameter is required. Please enter the number of mailbox databases that will be created on this Exchange 2010 server. Example 8."
}
if ($DbStartNum -eq "")
{
$validInputs = $false
$errorString += "`nMissing parameter: The DbStartNum parameter is required. Please enter the starting database number. Example 5."
}
if ($DbDrive -eq "")
{
$validInputs = $false
$errorString += "`nMissing parameter: The DbDrive parameter is required. Please enter the drive letter on which you will create mailbox databases. Example: E"
}
if ($LogDrive -eq "")
{
$validInputs = $false
$errorString += "`nMissing parameter: The LogDrive parameter is required. Please enter the drive letter on which you will create transaction logs. Example: D"
}
if ($WarnQuota -eq "")
{
$validInputs = $false
$errorString += "`nMissing parameter: The WarnQuota parameter is required. Please enter the vaule to issue mailbox size limit warning. Example: 450MB or 1.5GB"
}
if ($SendQuota -eq "")
{
$validInputs = $false
$errorString += "`nMissing parameter: The SendQuota parameter is required. Please enter the vaule to issue mailbox size limit exceeded. Example: 500MB or 1GB"
}
if ($SendReceiveQuota -eq "")
{
$validInputs = $false
$errorString += "`nMissing parameter: The SendReceiveQuota parameter is required. Please enter the vaule at which the mailbox stops accepting mail. Example: Unlimited or 550MB"
}

if ($DeletedItemRetention -eq "")
{
$validInputs = $false
$errorString += "`nMissing parameter: The DeletedItemRetention parameter is required. Please enter the vaule in days. Example: 14"
}
if ($MailboxRetention -eq "")
{
$validInputs = $false
$errorString += "`nMissing parameter: The MailboxRetention parameter is required. Please enter the vaule in days. Example: 30"
}
if ($OAB -eq "")
{
$validInputs = $false
$errorString += "`nMissing parameter: The OAB parameter is required. Please enter the name of the offline address list to be used by this mailbox database in quotes. Example: 'Corporate OAB' "
}
if ($PfDb -eq "")
{
$validInputs = $false
$errorString += "`nMissing parameter: The PfDb parameter is required. Please enter the name of the public folder database in quotes. Example: 'Pub Folders DB 1'"
}

if (!$validInputs)
{
Write-error "$errorString"
}
return $validInputs
}


### Validate the parameters ###
$ifValidParams = ValidateParams;

if (!$ifValidParams) { exit; }

### Define Script variables ###
$2010Server = $2010Server.ToUpper()
$b = $NumDatabases + $DbStartNum
$DeletedItemRetention = $DeletedItemRetention + ".00:00:00"
$MailboxRetention = $MailboxRetention + ".00:00:00"

$SendQuotaLen = $SendQuota.Length
$DBSize = $SendQuotaLen - 2
[decimal] $DBSizeNum = $SendQuota.substring(0,$DBSize)

If ($DbSizeNum -le 9) {$DbExName = [string] $DbSizeNum + "000"}
ElseIf ($DbSizeNum -ge 10 -and $DbSizeNum -le 99) {$DbExName = "00" + $DbSizeNum}
ElseIf ($DbSizeNum -ge 100) {$DbExName = "0" + $DbSizeNum}

If ($DbStartNum -gt 9) {$MdbName = $2010Server + "-DB" + $DbStartNum + "-" + $DbExName}
Else {$MdbName = $2010Server + "-DB0" + $DbStartNum + "-" + $DbExName}
$EdbFilePath = $DbDrive + ":\Exchange\Databases\" + $MdbName + "\" + $MdbName + ".EDB"
$LogFolderPath = $LogDrive + ":\Exchange\Logs\" + $MdbName
$MdbID = $2010Server + "\" + $MdbName

### Create Mailbox Databases Loop ###
Do {New-MailboxDatabase -Name $MdbName -Server $2010Server -EdbFilePath $EdbFilePath -LogFolderPath $LogFolderPath -OfflineAddressBook $OAB -PublicFolderDatabase $PfDb
;Mount-Database $MdbName
;Set-MailboxDatabase –Identity $MdbName –IssueWarningQuota $WarnQuota –ProhibitSendQuota $Sendquota –ProhibitSendReceiveQuota $SendReceiveQuota -DeletedItemRetention $DeletedItemRetention -MailboxRetention $MailboxRetention -RetainDeletedItemsUntilBackup $True
;$DbStartNum++
;If ($DbStartNum -gt 9) {$MdbName = $2010Server + "-DB" + $DbStartNum + "-" + $DbExName}
Else {$MdbName = $2010Server + "-DB0" + $DbStartNum + "-" + $DbExName}
;$EdbFilePath = $DbDrive + ":\Exchange\Databases\" + $MdbName + "\" + $MdbName + ".EDB"
;$LogFolderPath = $LogDrive + ":\Exchange\Logs\" + $MdbName
;$MdbID = $2010Server + "\" + $MdbName
}
Until ($DbStartNum -eq $b)
### END SCRIPT ###






More information on Exchange




Read more!

Tuesday, March 23, 2010

Cross-Forest Migration with Exchange 2010 is a piece of cake!

By:Rik Hoffelder
Overview
It has been a while since I've posted anything new on The Generation V as I have been neck deep in projects. One of them involved a cross-forest Exchange migration as part of a larger AD migration. In this project the customer was migrating Exchange 2003 in Forest A to Exchange 2010 in Forest B and they needed to do it on a budget. In other words, no third party tools if at all possible. As the title suggests, with free tools from Microsoft and built-in features of Exchange 2010, it was remarkably easy.
Over the years Microsoft has added many tools, most free, to assist in numerous management and migration tasks. For this project I used the Active Directory Migration Tool 3.1, Exchange Sync from the Exchange 2003 toolkit, CVSDE, VBScripts, and PowerShell to perform all of the tasks. This saved the customer the many thousands of dollars third party software would have cost and not necessarily made the process any easier.
I will not go into the specifics of the AD migration part of the project, just know that all user and group accounts were migrated using ADMT 3.1. I also did not use ILM 2007 FP1 SP1 to provide GAL sync as this wasn't necessary due to the relatively small size of the project (about 600 mailboxes) and the rarity of account/mailbox additions/changes/deletions in this environment during the co-existence period. Even in that case, creating new accounts or modifying DLs followed a document process I created that eliminated the need for GAL sync. I would suggest ILM for larger organizations and those that make many changes during co-existence.

Prepare Routing

Prior to the Exchange migration, I had to establish a routing method to be used during the co-existence period between Exchange forests. This is necessary because both Exchange forests must be authorative for the primary SMTP namespace of customer.com. To do this I established a proxy address of ex2003.local for Exchange 2003 and ex2010.local for Exchange 2010.

I then added ex2010.local to the Accepted Domain Hub Transport organization configuration and added %m@ex2010.local as a proxy address to each affected E-mail Address Policy. Next I added the %m@ex2003.local proxy address to each Exchange 2003 Recipient Policy and selected the "This organization is responsible for delivery …" checkbox. All recipients were updated with the new policies.

Next I created SMTP connectors in each Exchange forest to forward to the other's proxy address space. For example the Exchange 2003 SMTP connector routes @ex2010.local to the Exchange 2010 forest and vice versa.

Prepare User Accounts

The Active Directory Migration Tool was used to migrate the Forest A user and group accounts into Forest B. (ADMT is also a free tool available from Microsoft's public download site http://microsoft.com/downloads). After the accounts were migrated I exported the displayName, samAccountName, mailNickname, and mail values for all mailbox-enabled users in Forest A using CSVDE as follows:

csvde -l displayName, samAccountName, mailNickname, mail -r "objectclass=user" -f c:\2003_Mailboxes.csv

This was done to use these values to mail-enable each user account in Forest B. By mail-enabling (not mailbox-enable) the Exchange 2003 users now appear in the Exchange 2010 address book allowing migrated users to communicate with unmigrated users seamlessly, thus eliminating part of the need for ILM in this project.

Before mail-enabling the Forest B users I changed the domain portion of each e-mail address to ex2003.local to use as an input value for the bulk mail-enable process. I also renamed the field in the CSV file to match the input values I used in the Exchange Management Shell cmdlet. DisplayName was changed to Name, samAccountName was changed to Identity, mailNickname was changed to Alias, and mail was changed to EmailAddress. I then ran the following cmdlet to complete the update:

Import-CSV C:\2003_Mailboxes.csv ForEach-Object –process {Enable-MailUser –Identity $_.Identity –Alias $_.Alias -EmailAddress $_.EmailAddress}

This would of course need to be manually updated for any new user accounts migrated over from Forest A.

The final step to prepare the users is run the Prepare-MoveRequest.PS1 script against the mail-enabled users. Prepare-MoveRequest.PS1 is a script created by Microsoft that updates the Forest B mail-enabled user with the MsExchMailboxGUID attribute from Forest A. This value will be used by the New-MoveRequest cmdlet to match the source Exchange 2003 mailbox to a target 2010 user. This little free script along with the –RemoteLegacy switch in the New-MoveRequest cmdlet are the new features in Exchange 2010 that help eliminate the need for third party tools in all but the most complex of cross-forest migrations.

I ran the following cmdlets in 2010 EMS, reusing the 2003.Mailboxes.CSV from the previous step:

$UserCredentials = Get-Credential

Import-CSV C:\2003_Mailboxes.csv ForEach-Object –process {Prepare-MoveRequest.ps1 -Identity $_.Identity -RemoteForestDomainController ex03.ex2003.local -RemoteForestCredential $UserCredentials –UseLocalObject}

For those new to PowerShell in general, EMS in particular, the $UserCredentials = Get-Credential cmdlet will open a dialog box requesting to enter the credentials of an account in Forest A with rights to migrate the data from Exchange 2003. Enter the credentials accordingly or the migration will fail with an error message containing 0x80004005, which means access denied in the entire Microsoft world.

Prepare Distribution Groups

Next I had to mail-enable the distribution groups migrated from Forest A. The ADMT will migrate the groups and group members as a group type of Distribution but it will not bring over Exchange attributes. This required two steps, first each migrated group had to be changed to a Universal group, as they were domain local or global groups in Forest A. Distribution Groups in Exchange 2007/2010 are Universal in scope as a result domain local or global groups cannot be mail-enabled. To do this I ran the following cmdlet in Exchange 2010 Management Shell:

Import-CSV C:\groups.csv ForEach-Object –process {Set-Group –Identity &_.Name –Universal}

I then ran the following script to mail-enable the Universal groups.

Import-CSV C:\groups.csv ForEach-Object –process {Enable-DistributionGroup =Identity &_.Name}

Now keep in mind that any new users created in Forest A and added to the Forest A version of this group, will become a member of the Forest B version of the group after the user account is migrated with the "Fix Group Memberships" option selected, thus negating the need for ILM.

Prepare Public Folders & Free/Busy

This migration occurred over a period of several weeks. Users were fully migrated to Forest B, meaning they were accessing Exchange 2003 from Forest B user credentials on workstations operating in the Forest B domain. After all users, groups, and workstations were migrated, I began the mailbox migration process.

This company relies on Public Folder data in several areas to collaborate and share information. As a result I had to maintain both public folder and free/busy synchronization between Exchange forests for a period of time. To do this I used the good old Exchange Inter-Organization Replication Tool. At preset this tool is not designed for use with Exchange 2010, but version 6.5.7408 is supported with Exchange 2007. I thought what the heck there isn't that much difference in public folder functionality between 2007 and 2010 so I gave it a try … in my lab first of course. What do you know, the darn thing worked and it worked very well.

To get it up and running I followed the steps outlined in this article: http://technet.microsoft.com/en-us/library/ee307369(EXCHG.80).aspx. It took a couple hours to get it fully functional in the customer environment, but it did the job very well and cost nothing but billable time! Hey I gotta eat too, right?


Migrating the Mailboxes

This is another area where Exchange 2010 really shines. The New-MoveRequest cmdlet offers a command-line only switch –RemoteLegacy. This switch tells Move Request to migrate a mailbox from a different Exchange 2003 or 2007 forest. It uses the MsExchMailboxGUID to match the source 2003/2007 mailbox in the remote forest with the target mail-enabled user in the Exchange 2010 forest, which was established earlier using Prepare-MoveRequest.PS1.


$UserCredentials = Get-Credential

New-MoveRequest –Identity migtest1 -RemoteLegacy -TargetDatabase "Mailbox Database 1" -RemoteGlobalCatalog 'ex03.ex2003.local' -TargetDeliveryDomain 'ex2010.local' -RemoteCredential $UserCredentials

When the move request completes it converts the target mail-enabled user to a mailbox-enabled user. It then deletes the source mailbox and converts the user to mail-enabled. As part of that process it adds a proxy address of @ex2010.local as the primary SMTP allowing users on the legacy forest to see the migrated mailbox in the global address list.

Finally using a group policy object I created a VB Script based user logon that creates a new Outlook profile by using a PRF file. The script checks for the presence of a specific profile name, if it doesn't find it Outlook is launched with the PRF as follows:


Path\Outlook.EXE Path\Update.PRF


It's quick it's easy and the code I used was readily available through a simple Bing search.

Final Words

I don't exactly recommend this process for large scale migrations, but for those of you operating on a budget and can't afford 10+ USD per mailbox for a one time use tool; this is will get you by. It isn't perfect, but it worked well for this project.





More information on Exchange



Read more!

Friday, November 20, 2009

Mailbox Reporter for Exchange 2007 & 2010

By:Rik Hoffelder
Exchange 2007 and 2010 brought about many great new features and functions. However Microsoft forgot about the little guy when it came to getting a quick overview of mailbox statistics via a GUI. It really made quite a few of my customers unhappy. It’s not that Exchange 2007 or 2010 do not provide this information, it is only available on individual mailbox properties in the Exchange Management Console, you cannot view all mailboxes on a given store without using the Get-MailboxStatistics cmdlet then piping the output to a file.

While this is all well and good, most Exchange Admins moving from 2000 or 2003 to 2007 aren’t familiar with PowerShell, let alone Exchange Management Shell. As a result I wrote this handy little script to replace that functionality and view all mailboxes within the organization. It’s run from Exchange Management Shell using the following command:

C:\Scripts> ./MailboxReport.PS1

It then opens the report in a web browser as shown below:



Just copy the code below and paste into a text file named MailboxReport.PS1 then run as described above. It works with Exchange 2007 or Exchange 2010. I hope you find it useful!

#Exchange Mailbox Reporter
$a = "<style>"
$a = $a + "BODY{background-color:white;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:LightBlue}"
$a = $a + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:White}"
$a = $a + "</style>"
$b = "<H2> Mailbox Summary Report </H2>"
$servers = get-mailboxserver
Foreach ($server in $servers) {
Get-MailboxStatistics -server $Server |
Where-Object {$_.DisplayName -NotMatch "^CAS_"} |
Where-Object {$_.DisplayName -NotMatch "^SystemMailbox"} |
Where-Object {$_.DisplayName -NotMatch "^Microsoft System"} |
Select-Object DisplayName, ItemCount, TotalItemSize, StorageLimitStatus, LastLogonTime, LastLogoffTime, LastLoggedOnUserAccount, ServerName, Database |
Sort-Object TotalItemSize -descending |
ConvertTo-HTML -head $a -body $b |
Out-File MailboxReport.htm
}
Invoke-Expression ./MailboxReport.htm







More information on Exchange


Read more!

Wednesday, November 18, 2009

Quick Exchange 2007 Server Status

By:Rik Hoffelder
Over the past few years I have accumulated several time saver and management scripts for Exchange 2007 using the Exchange Management Shell. I thought I would begin sharing some of the more generic and useful scripts. This particular script collects data from various performance counters and runs several Exchange 2007’s Test- cmdlets. It then writes the data to a HTM file and opens with the results.

The script must be run from under Exchange Management Shell and is intended to run against one server. I’ll post another version that collects from multiple servers; however it has been my experience that if you have multiple Exchange servers, you probably already have a monitoring solution. This was written from my Mom & Pop customers would need a quick, yet free, monitoring method. It offers no alerting, just basic information.

To run, simply copy and paste the following into a text file named ExchangeReport.PS1 then launch it from Exchange Management Shell by running the following command:

C:\Scripts> ./ExchangeReport.PS1

After running the code the Report.HTM file will open and present several items in tables as shown below:


Code Sample:
$a = "<style>"
$a = $a + "BODY{background-color:white;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:LightBlue}"
$a = $a + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:White}"
$a = $a + "</style>"

Get-ExchangeServer | Select-Object Name, AdminDisplayVersion, ServerRole, IsMemberofCluster | ConvertTo-HTML -head $a -body "<H2>Exchange Server Information</H2>" | Out-File Report.htm

Get-WmiObject Win32_service -errorAction silentlyContinue | Where-Object {$_.name -match "^msexchange."} |
select-object Name, Status ConvertTo-HTML -head $a -body "<H2>Exchange Services State</H2>" |
Out-File Report.htm -Append

Get-Queue | Select-Object Identity, MessageCount, Status, DeliveryType, NextHopDomain, LastError |
ConvertTo-HTML -head $a -body "<H2>Message Queues</H2>" |
Out-File Report.htm -Append

Get-WmiObject -query "select * from Win32_PerfFormattedData_MSExchangeTransportQueues_MSExchangeTransportQueues" |
select-object Name, ActiveRemoteDeliveryQueueLength, ActiveMailboxDeliveryQueueLength, SubmissionQueueLength, RetryMailboxDeliveryQueueLength |
ConvertTo-HTML -head $a -body "<H2>Message Queue Counters</H2>" |
Out-File Report.htm -Append

Get-WmiObject -errorAction silentlyContinue -query "Select * from Win32_PerfFormattedData_MSExchangeTransportSmtpSend_MSExchangeTransportSmtpSend" |
Select-Object MessageBytesSentPersec, MessageBytesSentTotal, MessagesSentPersec, MessagesSentTotal |
ConvertTo-HTML -head $a -body "<H2>SMTP Counters</H2>" |
Out-File Report.htm -Append

Get-WmiObject -errorAction silentlyContinue -query "Select * from Win32_PerfFormattedData_MSExchangeIS_MSExchangeIS" |
Select-Object ActiveUserCount, ActiveConnectionCount, ConnectionCount, RPCRequests, RPCPacketsPersec, RPCOperationsPersec, WriteBytesRPCClientsPersec, RPCAveragedLatency |
ConvertTo-HTML -head $a -body "<H2>Information Store Counters</H2>" |
Out-File Report.htm -Append

Get-WmiObject -errorAction silentlyContinue -query "Select * from Win32_PerfFormattedData_MSExchangeIS_MSExchangeISMailbox" |
Select-Object ClientLogons, ActiveClientLogons, MessageOpensPersec, FolderOpensPersec, AverageDeliveryTime, MessagesDeliveredPerSec, MessagesSentPersec, ReceiveQueueSize, MessagesQueuedForSubmission |
ConvertTo-HTML -head $a -body "<H2>Mailbox Store Counters</H2>" |
Out-File Report.htm -Append

Test-MAPIConnectivity | Select-Object Server, Database, Result, Latency, Error |
ConvertTo-HTML -head $a -body "<H2>MAPI Connectivity</H2>" |
Out-File Report.htm -Append

Test-OWAConnectivity | Select-Object ClientAccessServer, MailboxServer, URL, Scenario, Result, Latency, Error |
ConvertTo-HTML -head $a -body "<H2>OWA Connectivity</H2>" |
Out-File Report.htm -Append

Test-ActiveSyncConnectivity | Select-Object ClientAccessServer, MailboxServer, Scenario, Result, Latency, Error |
ConvertTo-HTML -head $a -body "<H2>ActiveSync Connectivity</H2>" |
Out-File Report.htm -Append

Test-MailFlow | Select-Object TestMailFlowResult, MessageLatencyTime, IsRemoteTest |
ConvertTo-HTML -head $a -body "<H2>Mail Flow</H2>" |
Out-File Report.htm -Append

Test-OutlookWebServices | Select-Object Id, Type, Message |
ConvertTo-HTML -head $a -body "<H2>Exchange Web Services</H2>" |
Out-File Report.htm -Append

Invoke-Expression Report.htm
#---End of Code Sample---


More information on Exchange


Read more!
Microsoft Virtualization, Citrix, XENServer, Storage, iscsi, Exchange, Virtual Desktops, XENDesktop, APPSense, Netscaler, Virtual Storage, VM, Unified Comminications, Cisco, Server Virtualization, Thin client, Server Based Computing, SBC, Application Delivery controllers, System Center, SCCM, SCVMM, SCOM, VMware, VSphere, Virtual Storage, Cloud Computing, Provisioning Server, Hypervisor, Client Hypervisor.