The SMTP Simulator project has been started due to a specific demand during a customer project. We needed a solution to test native transport of Exchange Server 2013 and third party addons to Exchange in an isolated lab envrionment having no internet access at all.
While it is pretty easy to send test emails using PowerShell, we wanted to create an automated service which is capable of:
The SMTP Simulator can be used with any Message Transfer Agents (MTA), not only with Exchange. Besides testing the MTA itself, we needed to test some of the following third-party solutions:
The Visual Studio solution creates a MSI installer file. The MSI package created installs the SMTP Service itself, but not the required web application (see issue #49).
Documentation is provided by the SMTP Simulator Wiki.
The code has been published as open source at Github. Feel free to fork the solution and contribute to the code.
Report any issues or feature requests at Github.
The project still has some open ends and needs some love and attention. Open issues are part of the issue tracker at Github.
Main topics are:
This script connects either to Exchange Online or to a dedicated on-premises Exchange Server to export configured mailbox delegates and SMTP forwarding configurations.
The SMTP forwarding configurations are gathered from inbox rules and from mailbox forwarding settings.
# Example 1 # Connect to the on-premises Exchange Server mx01.varunagroup.de and export delegation and SMTP forwarding information .\Get-DelegatesAndForwardingRules.ps1 -ExchangeHost mx01.varunagroup.de # Example 2 # Connect to the on-premises Exchange Server mx01.varunagroup.de, export delegation and SMTP forwarding information and get verbose information on the objects worked on .\Get-DelegatesAndForwardingRules.ps1 -ExchangeHost mx01.varunagroup.de -Verbose # Example 3 # Connect to Exchange Online and export delegation and SMTP forwarding information .\Get-DelegatesAndForwardingRules.ps1 -ExchangeOnline
Use GitHub Issues to leave comments, requests, end even bugs or issues.
The script is based on the O365-InvestigationTooling script DumpDelegatesandForwardingRules.ps1 by Brandon Koeller Find more Office 365 investigation tooling scripts at https://github.com/OfficeDev/O365-InvestigationTooling.
When migrating to new version of Exchange Servers you must move your internal SMTP relay endpoints. This can be a challeging tasks as application owners mostly ignore your requests for such changes.
You can use the information provided in the receive connector log files to identify remote clients (MTAs / MTUs) connecting to the legacy infrastructure. The assumption is that protocol logging is enabled. You can easily active protocol logging across all receive connector fo a single server using the following EMS PowerShell one-liner:
Get-ReceiveConnector -Server EX01 | Set-ReceiveConnector -ProtocolLoggingLevel Verbose
The scripts searches the log files for the connection's EHLO response which containes the remote name or remote IP-address of the system connecting to the receive connector.
You can either search
For more information read the readme.md file at Github.
You need to adjust the log file path to suit your IT infrastructure. A next releas will contain a more automatic solution.
# Search legacy Exchange servers SMTP receive log files for the last 4 days and save search results in a single CSV file .\Get-RemoteSmtpServers.ps1 -Servers SRV01,SRV02 -LegacyExchange -AddDays -4 -ToCsv
I was involved in a troubleshooting request for a hybrid mail flow issue. Before I take a closer look at the issue, let's talk about the hybrid setup.
A managed service provider runs separated on-premises Exchange Organizations for various clients. Also, the service provider runs it's own Exchange Organization in a hybrid setup with Exchange Online (EXO) utilizing centralized mail flow. Let's name the managed service provider Varunagroup, using the primary domain varunagroup.de.
The on-premises IT-Infrastructure consists of the following email components:
The following diagram illustrates the setup and the expected mail flow.
Let's name one of the clients Setebos AG, using setebos-ag.com as their primary domain.
Varunagroup's IT department activated journaling in Exchange Online, using an on-premises Journaling mailbox. After a few days, an IT administrator checked the inbox folder for journaling messages and journaling reports. The journaling inbox did not contain messages of Varounagroup senders or recipients only, but messages from client sender domains, e.g., setebos-ag.com.
In reality, the mail flow from on-premises to external recipients from any of the local Exchange organizations looked like shown in this diagram.
Why does the Variangoup journaling mailbox contain messages from Setebos senders sent to external recipients?
We choose a single message for troubleshooting purposes, originating from the Setebos.com domain, sent to a non-Varunagroup recipient.
The interesting piece of information is row 6.
You see that EXO resolves the target mail exchanger via DNS. The target is another Microsoft 365 tenant as we see an xxx.mail.protection.outlook.com host.
When checking the on-premises mail gateway connection log, we found the distracting information that the gateway resolved the target mail exchanger as xxx.mail.protection.outlook.com.
As a next step, we checked the extended message tracking log using the new Exchange Admin Center. We created a new custom query with the following search criteria:
When you troubleshoot connection issues with Exchange Online, always select the extended report. You'll receive the report as a CSV file attachment. Use the Data tab in Excel to import the CSV file. Do not access the content by simply clicking the received file attachment.
The interesting information is stored in the custom_data column for row source=SMTP and event_id=RECEIVE.
S:ProxyHop1=HE1EUR01FT049.mail.protection.outlook.com(10.152.0.221); S:ProxyHop2=AM0PRxxCAxxxx.outlook.office365.com(2603:10a6:208:fa::40); S:InboundConnectorData=Name=Inbound from [EXCHANGE ORG GUID]; ConnectorType=OnPremises; TenantId=[VARUNAGROUP GUID]; S:InboundTlsDetails=TLS=SP_PROT_TLS1_2_SERVER [...]; S:CorrelationId=d9ac6a10-8de9-4308-4205-07d865e8909b; S:MimeParts=Att/Emb/MPt:0/0/1; S:MessageValue=MediumHigh; S:Replication=AM6PRxxxxMBxxxx; S:FirstForestHop=AM0PRxxxxMBxxxx.eurprd03.prod.outlook.com; S:FromEntity=HybridOnPrem; S:Oorg=varunagroup.de; S:ProxiedClientIPAddress=81.173.212.44; S:ProxiedClientHostname=mx01.varunagroup.de; S:DeliveryPriority=Normal; S:AccountForest=EURPRxxAxxx.PROD.OUTLOOK.COM
The information in line 3 shows the actual name of the configured Varunagroup inbound connector, as shown in the Exchange Online connector configuration. The message did not enter the Varunagroup EXO tenant due to a mysterious connection, it was received by the dedicated inbound connector, configured by HCW.
The key to this question is the TLS certificate used by the centralized email gateway and the TLS common name filtering in Exchange Online.
The wildcard name *.varunagroup.de resulted in a matching string comparison for the incoming TLS common names of mx01.varunagroup.de and mx02.varunagroup.de. At the same time, the inbound connector matched the Edge Transport TLS certificate smtpo365.varunagroup.de.
Nobody knew, how the inbound connector configuration got "changed" to the wildcard name or for how long that configuration resulted in outbound messages from customer domains routed via the service provider tenant.
The solution contains two configurations.
The TLS common name behavior is by design and described in this blog post as FAQ #6(b). As a customer, you identify this as a misbehaving SMTP receive connector. But as described in the blog post, this is by design.
It is required that you understand the inbound routing behavior of Exchange Online if you have complicated outbound routing requirements. The blog post provides detailed information on how Office 365 inbound routing works and what you should be aware of.
Links
Enjoy Exchange Online.
The Skype for Business client merges contact data from different sources when displaying the contact card. The merged data is used to perform name resolution when performing a user search. In a more complex deployment scenario where an email domain name is in shared use in two in Active Directory forests you might run into a situation where the Skype for Business client tries to use the wrong target address.
Such a scenario would look like as follows.
Forest A is used as a dedicated infrastructure for developers. When logged on to the development network the users should be able to skype with colleagues currently connected to the default office client network.
Forest B is the default office client network.
Clients logged on to forest A connect to the Skype for Business infrastructure in forest B as external clients. Forest A is used for user account authentication while forest B is used for Skype for Business connection and authentication.
Forest A runs an Exchange Server 2013 organization.
Forest B runs an Exchange Server 2013 organization and a full Skype for Business 2015 server deployment.
Both Active Directory forests to not have trust of any sort established.
Such a configuration would result in forest A users trying to contact a Skype for Business user using the wrong address. Instead of using John.Doe@Sedna-Ltd.com the Skype for Business client of Jane Doe@Sedna-Ltd.com (logged on to forest A) would try to contact John.Doe@dev.Sedna-Ltd.com. As there is no endpoint defined for dev.Sedna-Ltd.com a connection could not be established. Therefore, no availability information is available and no call or chat connection could be established.
The Skype for Business client uses merged data pulled from the Skype for Business address and from the local (Forest A) Active Directory (GAL). This results in a connection attempt to John.Doe@dev.Sedna-Ltd.com.
<?xml version="1.0"?> <settings> <UseMsoSearch>false</UseMsoSearch> </settings>
Enjoy Skype for Business
This script will generate a report for Exchange 2007/2010 Public Folder Replication. It returns general information, such as the total number of public folders, total items in all public folders, the total size of all items, the top 20 largest folders, and more. Additionally, it lists each Public Folder and the replication status on each server.
By default, this script will scan the entire Exchange environment in the current domain and all public folders. This can be limited by using the -ComputerName and -FolderPath parameters.
Generate a public folder generation report for public folder \MYPUBLICFOLDER having replicas on servers MXSRV01, MXSRV02, MXSRV03
Get-PublicFolderReplicationReport.ps1 -ComputerName MXSRV01,MXSRV02,MXSRV03 -FolderPath "\MYPUBLICFOLDER" -Recurse -Subject "Public Folder Environment Report" -AsHTML -To postmaster@varunagroup.de -From postmaster@varunagroup.de -SmtpServer relay.mcsmemail.de -SendEmail
Example report
If you want to simplify the report generation, create an additional script: Run-PublicFolderReplicationReport.ps1
param( [string]$publicFolderPath = '' ) # Variables # Custom label for email subject $label = 'Exchange 2007' $recipients = 'pfreports@mcsmemail.de' $sender = 'postmaster@mcsmemail.de' # array of public folder servers to query $publicFolderServers = @('EX2007-01','EX2010-01') # SMTP server to relay mail $smtpServer = 'relay.mcsmemail.de' # Used to trigger a dedicated report for \GrFolder1\Folder1, \GrFolder1\Folder2 $granularRootFolder = @() # @("\Folder01") $subPath = '' # Check for granular folders, Added 2016-01-19 if($granularRootFolder -contains $publicFolderPath) { $subPath = $publicFolderPath $publicFolderPath = '' } # if($publicFolderPath -ne '') { Write-Host "Generating Public Folder reports for $($publicFolderPath)" # Generate report for a single public folder | Change COMPUTERNAME attribute for servers to analyse .\Get-PublicFolderReplicationReport.ps1 -ComputerName $publicFolderServers -FolderPath $publicFolderPath -Recurse -Subject "Public Folder Environment Report [$($publicFolderPath)] [$($label)]" -AsHTML -To $recipients -From $sender -SmtpServer $smtpServer -SendEmail } else { if($subPath -ne '') { $publicFolderPath = $subPath } else { $publicFolderPath = '\' } if($granularRootFolder.Count -ne 0) { Write-Host 'Following root folders will be excluded when using "\":' $($granularRootFolder) } Write-Host "Generating Public Folder reports for all folders in $($publicFolderPath)" $folders = Get-PublicFolder $publicFolderPath -GetChildren # Generate a single report for each folder in root $folderCount = ($folders | Measure-Object).Count $pfCount = 1 foreach($pf in $folders) { # Check, if folder is in list of granular folders if($granularRootFolder -notcontains $pf) { if($pf.ParentPath -eq '\') { $name = "$($pf.ParentPath)$($pf.Name)" } else { $name = "$($pf.ParentPath)\$($pf.Name)" } $activity = 'Generating Stats' $status = "Fetching $($name)" Write-Progress -Activity $activity -Status $status -PercentComplete (($pfCount/$folderCount)*100) .\Get-PublicFolderReplicationReport.ps1 -ComputerName $publicFolderServers -FolderPath $name -Recurse -Subject "Public Folder Environment Report [$($name)] [$($label)]" -AsHTML -To $recipients -From $sender -SmtpServer $smtpServer -SendEmail $pfCount++ } } }
Use the $granularRootFolder array to add root public folders which require a dedicated report for each sub-folder.
Additional credits go to Mike Walker (blog.mikewalker.me)
This Powershell script has been optimized using the ISESteroids™ add-on. Learn more about ISESteroids™ here.
Exchange Server uses Receive Connectors for providing SMTP endpoints for incoming connections. A modern Exchange Server provides a default connector on TCP port 25.
Sometimes you might have a requirement to create a new receive connector for selected incoming SMTP connections. A standard requirement is a receive connector for relaying messages to external recipients. This cannot (should not) be achieved using the default connector.
Each connector uses the RemoteIPRanges attribute to store the list of IP addresses of remote systems that can connect to that connector. The default connector utilizes the full IPv4 and IPv6 addresses ranges.
Your new receive connector requires at least a single IP address for a selected remote system that is supposed to connect to that receive connector. You can add a single IP address, address ranges, or IP addresses using CIDR notation.
The attribute RemoteIPRanges is a multi-value attribute and has a limit of IP address entries that can be added.
The maximum number of address entries that you can add to that attribute varies. You can store approximately 1,300 entries.
When you exceed the number of values you receive the following error message:
The administrative limit for this request was exceeded. + CategoryInfo : NotSpecified: (:) [Set-ReceiveConnector], AdminLimitExceededException + FullyQualifiedErrorId : [Server=EX01,RequestId=ee9d45ad-418b-4172-9235-963eca1a7830,TimeStamp=18.08.2020 20:07:54] [FailureCategory=Cmdlet-AdminLimitExceededException] AC1E336E,Microsoft.Exchange.Management.SystemConfi gurationTasks.SetReceiveConnector + PSComputerName : ex01.varunagroup.de
I have tested the number of values that can be stored in that multi-value attribute. Depending on the IP address format I was able to add 1,238 (172.80.x.y) or 1,244 (10.1.x.y) single IP addresses to the RemoteIPRanges attribute.
Plan your IP address configuration requirements carefully and avoid using single IP addresses. Preferably, you should use IP address ranges or IP address CIDR notation for networks.
Enjoy Exchange Server!