diff --git a/WebsitePanel/Lib/References/Microsoft/Microsoft.Exchange.Data.Common.dll b/WebsitePanel/Lib/References/Microsoft/Microsoft.Exchange.Data.Common.dll
new file mode 100644
index 00000000..6357f145
Binary files /dev/null and b/WebsitePanel/Lib/References/Microsoft/Microsoft.Exchange.Data.Common.dll differ
diff --git a/WebsitePanel/Lib/References/Microsoft/Microsoft.Exchange.Data.Transport.dll b/WebsitePanel/Lib/References/Microsoft/Microsoft.Exchange.Data.Transport.dll
new file mode 100644
index 00000000..971c863e
Binary files /dev/null and b/WebsitePanel/Lib/References/Microsoft/Microsoft.Exchange.Data.Transport.dll differ
diff --git a/WebsitePanel/Sources/WSPTransportAgent/App.config b/WebsitePanel/Sources/WSPTransportAgent/App.config
new file mode 100644
index 00000000..f3d7ccd1
--- /dev/null
+++ b/WebsitePanel/Sources/WSPTransportAgent/App.config
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WebsitePanel/Sources/WSPTransportAgent/Properties/AssemblyInfo.cs b/WebsitePanel/Sources/WSPTransportAgent/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..2235d8fb
--- /dev/null
+++ b/WebsitePanel/Sources/WSPTransportAgent/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("WSPTransportAgent")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("WSPTransportAgent")]
+[assembly: AssemblyCopyright("Copyright © 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("e28cac4e-9660-4174-8010-c6a00c81bf57")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/WebsitePanel/Sources/WSPTransportAgent/WSPRoutingAgent.cs b/WebsitePanel/Sources/WSPTransportAgent/WSPRoutingAgent.cs
new file mode 100644
index 00000000..84fe075b
--- /dev/null
+++ b/WebsitePanel/Sources/WSPTransportAgent/WSPRoutingAgent.cs
@@ -0,0 +1,260 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+using System.IO;
+using System.Configuration;
+using System.Collections.ObjectModel;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Xml;
+using Microsoft.Exchange.Data.Transport;
+using Microsoft.Exchange.Data.Transport.Routing;
+using Microsoft.Exchange.Data.Mime;
+using System.DirectoryServices;
+
+
+namespace WSPTransportAgent
+{
+ public class WSPRoutingAgentFactory : RoutingAgentFactory
+ {
+ public override RoutingAgent CreateAgent(SmtpServer server)
+ {
+ return new WSPRoutingAgent(server);
+ }
+ }
+
+ public class WSPRoutingAgent : RoutingAgent
+ {
+ private string routingDomain;
+ private bool enableVerboseLogging;
+ private string logFile;
+ private Hashtable htAcceptedDomains;
+ private bool blockInternalInterTenantOOF;
+
+ public WSPRoutingAgent(SmtpServer server)
+ {
+ //subscribe to different events
+ loadConfiguration();
+
+ WriteLine("WSPRoutingAgent Registration started");
+ loadAcceptedDomains(server);
+ //GetAcceptedDomains();
+ WriteLine("\trouting Domain: " + routingDomain);
+
+ base.OnResolvedMessage += new ResolvedMessageEventHandler(WSPRoutingAgent_OnResolvedMessage);
+
+ WriteLine("WSPRoutingAgent Registration completed");
+ }
+
+ private void loadConfiguration()
+ {
+ this.routingDomain = ".tmpdefault";
+ this.enableVerboseLogging = true;
+ this.logFile = "C:\\WSP.LOG";
+
+ try
+ {
+ ExeConfigurationFileMap map = new ExeConfigurationFileMap();
+ map.ExeConfigFilename = System.Reflection.Assembly.GetExecutingAssembly().Location + ".config";
+ Configuration libConfig = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
+ AppSettingsSection section = (libConfig.GetSection("appSettings") as AppSettingsSection);
+
+ this.routingDomain = section.Settings["routingDomain"].Value;
+ this.enableVerboseLogging = (section.Settings["enableVerboseLogging"].Value == "true");
+ this.blockInternalInterTenantOOF = (section.Settings["blockInternalInterTenantOOF"].Value == "true");
+ this.logFile = section.Settings["logFile"].Value;
+ }
+ catch (Exception ex)
+ {
+ WriteLine("\t[Error] " + ex.Message);
+ LogErrorToEventLog("[Error] [loadConfiguration] Error :" + ex.Message);
+ }
+
+
+ }
+
+
+ private void loadAcceptedDomains(SmtpServer server)
+ {
+ try
+ {
+ if (htAcceptedDomains == null)
+ this.htAcceptedDomains = new Hashtable();
+ else
+ this.htAcceptedDomains.Clear();
+
+ foreach (AcceptedDomain domain in server.AcceptedDomains)
+ {
+ htAcceptedDomains.Add(domain.ToString(), "1");
+ WriteLine("\tAccepted Domain: " + domain.ToString());
+ }
+ }
+ catch (Exception ex)
+ {
+ WriteLine("\t[Error] " + ex.Message);
+ LogErrorToEventLog("[Error] [loadAcceptedDomains] Error :" + ex.Message);
+ }
+ }
+
+
+ void WSPRoutingAgent_OnResolvedMessage(ResolvedMessageEventSource source, QueuedMessageEventArgs e)
+ {
+ try
+ {
+
+ WriteLine("Start WSPRoutingAgent_OnResolvedMessage");
+
+ WriteLine("\tFromAddress: " + e.MailItem.FromAddress.ToString());
+ WriteLine("\tSubject: " + e.MailItem.Message.Subject.ToString());
+ WriteLine("\tMapiMessageClass: " + e.MailItem.Message.MapiMessageClass.ToString());
+
+ MimeDocument mdMimeDoc = e.MailItem.Message.MimeDocument;
+ HeaderList hlHeaderlist = mdMimeDoc.RootPart.Headers;
+ Header mhProcHeader = hlHeaderlist.FindFirst("X-WSP");
+
+ if (mhProcHeader == null)
+ {
+ WriteLine("\tTouched: " + "No");
+
+ if (!e.MailItem.Message.IsSystemMessage)
+ {
+ bool touched = false;
+
+ if (e.MailItem.FromAddress.DomainPart != null)
+ {
+ foreach (EnvelopeRecipient recp in e.MailItem.Recipients)
+ {
+ WriteLine("\t\tTo: " + recp.Address.ToString().ToLower());
+ if (IsMessageBetweenTenants(e.MailItem.FromAddress.DomainPart.ToLower(), recp.Address.DomainPart.ToLower()))
+ {
+ WriteLine("\t\tMessage routed to domain: " + recp.Address.DomainPart.ToLower() + routingDomain);
+ RoutingDomain myRoutingDomain = new RoutingDomain(recp.Address.DomainPart.ToLower() + routingDomain);
+ RoutingOverride myRoutingOverride = new RoutingOverride(myRoutingDomain, DeliveryQueueDomain.UseOverrideDomain);
+ source.SetRoutingOverride(recp, myRoutingOverride);
+ touched = true;
+ }
+ }
+ }
+ else
+ {
+ if ((e.MailItem.Message.MapiMessageClass.ToString() == "IPM.Note.Rules.OofTemplate.Microsoft") &
+ blockInternalInterTenantOOF)
+ {
+ WriteLine("\t\tOOF From: " + e.MailItem.Message.From.SmtpAddress);
+ if (e.MailItem.Message.From.SmtpAddress.Contains("@"))
+ {
+ string[] tmp = e.MailItem.Message.From.SmtpAddress.Split('@');
+ foreach (EnvelopeRecipient recp in e.MailItem.Recipients)
+ {
+ WriteLine("\t\tTo: " + recp.Address.ToString().ToLower());
+ if (IsMessageBetweenTenants(tmp[1].ToLower(), recp.Address.DomainPart.ToLower()))
+ {
+ WriteLine("\t\tRemove: " + recp.Address.DomainPart.ToLower());
+ e.MailItem.Recipients.Remove(recp);
+ }
+ }
+ }
+ }
+ }
+
+ if (touched)
+ {
+ MimeNode lhLasterHeader = hlHeaderlist.LastChild;
+ TextHeader nhNewHeader = new TextHeader("X-WSP", "Logged00");
+ hlHeaderlist.InsertBefore(nhNewHeader, lhLasterHeader);
+ }
+ }
+ else
+ WriteLine("\tSystem Message");
+ }
+ else
+ WriteLine("\tTouched: " + "Yes");
+
+ }
+
+ catch (Exception ex)
+ {
+ WriteLine("\t[Error] Error :" + ex.Message);
+ LogErrorToEventLog("[Error] [OnResolvedMessage] Error :" + ex.Message);
+ }
+
+ WriteLine("End WSPRoutingAgent_OnResolvedMessage");
+ }
+
+ private bool IsMessageBetweenTenants(string senderDomain, string recipientDomain)
+ {
+ if (senderDomain == recipientDomain) return false;
+
+ if ((htAcceptedDomains[senderDomain] != null) &&
+ (htAcceptedDomains[recipientDomain] != null))
+ return true;
+
+ return false;
+ }
+
+ /*
+ private void GetAcceptedDomains()
+ {
+ try
+ {
+ htAcceptedDomains.Clear();
+ DirectoryEntry rdRootDSE = new DirectoryEntry("LDAP://RootDSE");
+ DirectoryEntry cfConfigPartition = new DirectoryEntry("LDAP://" + rdRootDSE.Properties["configurationnamingcontext"].Value);
+ DirectorySearcher cfConfigPartitionSearch = new DirectorySearcher(cfConfigPartition);
+ cfConfigPartitionSearch.Filter = "(objectClass=msExchAcceptedDomain)";
+ cfConfigPartitionSearch.SearchScope = SearchScope.Subtree;
+ SearchResultCollection srSearchResults = cfConfigPartitionSearch.FindAll();
+
+ foreach (SearchResult srSearchResult in srSearchResults)
+ {
+ DirectoryEntry acDomain = srSearchResult.GetDirectoryEntry();
+ htAcceptedDomains.Add(acDomain.Properties["msexchaccepteddomainname"].Value.ToString().ToLower(), "1");
+ WriteLine("\tAccepted Domain :" + acDomain.Properties["msexchaccepteddomainname"].Value.ToString().ToLower());
+ }
+ }
+ catch (Exception ex)
+ {
+ WriteLine("\tError :" + ex.Message);
+ EventLog.WriteEntry("WSP Transport Agent", ex.Message, EventLogEntryType.Error);
+ }
+ }
+ */
+
+
+ private void WriteLine(string Line)
+ {
+ if (!enableVerboseLogging) return;
+
+ try
+ {
+ StreamWriter writer = new StreamWriter(logFile, true, System.Text.Encoding.ASCII);
+ writer.WriteLine("[" + DateTime.Now.ToString() + "]" + Line);
+ writer.Close();
+ }
+ catch (Exception e)
+ {
+
+ }
+ }
+
+
+ private void LogErrorToEventLog(string Line)
+ {
+ try
+ {
+ if (EventLog.SourceExists("WSPTransportAgent"))
+ {
+ EventLog.WriteEntry("WSPTransportAgent", Line, EventLogEntryType.Error);
+ }
+ }
+ catch (Exception ex)
+ {
+ WriteLine("[Error] WritingEventLog :" + ex.Message);
+ }
+ }
+
+
+ }
+
+}
diff --git a/WebsitePanel/Sources/WSPTransportAgent/WSPTransportAgent.csproj b/WebsitePanel/Sources/WSPTransportAgent/WSPTransportAgent.csproj
new file mode 100644
index 00000000..47bfc898
--- /dev/null
+++ b/WebsitePanel/Sources/WSPTransportAgent/WSPTransportAgent.csproj
@@ -0,0 +1,62 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {D959F137-A56F-4F4E-BA80-599FBE3700E3}
+ Library
+ Properties
+ WSPTransportAgent
+ WSPTransportAgent
+ v4.0
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\Lib\References\Microsoft\Microsoft.Exchange.Data.Common.dll
+
+
+ ..\..\Lib\References\Microsoft\Microsoft.Exchange.Data.Transport.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WebsitePanel/Sources/WSPTransportAgent/WSPTransportAgent.reg b/WebsitePanel/Sources/WSPTransportAgent/WSPTransportAgent.reg
new file mode 100644
index 00000000..755c888a
--- /dev/null
+++ b/WebsitePanel/Sources/WSPTransportAgent/WSPTransportAgent.reg
@@ -0,0 +1,15 @@
+Windows Registry Editor Version 5.00
+
+[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\MEACPTransportAgent]
+"MaxSize"=dword:00080000
+"AutoBackupLogFiles"=dword:00000000
+"Retention"=dword:00000000
+
+[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\MEACPTransportAgent\MEACPTransportAgent]
+"EventMessageFile"=hex(2):43,00,3a,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,\
+ 00,73,00,5c,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,2e,00,\
+ 4e,00,45,00,54,00,5c,00,46,00,72,00,61,00,6d,00,65,00,77,00,6f,00,72,00,6b,\
+ 00,36,00,34,00,5c,00,76,00,34,00,2e,00,30,00,2e,00,33,00,30,00,33,00,31,00,\
+ 39,00,5c,00,45,00,76,00,65,00,6e,00,74,00,4c,00,6f,00,67,00,4d,00,65,00,73,\
+ 00,73,00,61,00,67,00,65,00,73,00,2e,00,64,00,6c,00,6c,00,00,00
+
diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.sln b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.sln
index fb708ef8..a88f65b6 100644
--- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.sln
+++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.sln
@@ -43,6 +43,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebsitePanel.Plugins.PayPal
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebsitePanel.Templates", "WebsitePanel.Templates\WebsitePanel.Templates.csproj", "{387FA0EF-3927-45FF-8F8F-BCCD735540C6}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WSPTransportAgent", "WSPTransportAgent\WSPTransportAgent.csproj", "{D959F137-A56F-4F4E-BA80-599FBE3700E3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -107,6 +109,10 @@ Global
{387FA0EF-3927-45FF-8F8F-BCCD735540C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{387FA0EF-3927-45FF-8F8F-BCCD735540C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{387FA0EF-3927-45FF-8F8F-BCCD735540C6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D959F137-A56F-4F4E-BA80-599FBE3700E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D959F137-A56F-4F4E-BA80-599FBE3700E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D959F137-A56F-4F4E-BA80-599FBE3700E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D959F137-A56F-4F4E-BA80-599FBE3700E3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj b/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj
index 30bb5548..2f0e726b 100644
--- a/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj
+++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/WebsitePanel.WebPortal.csproj
@@ -106,6 +106,7 @@
+