├── Database ├── MtaDB │ ├── ScriptDb.exe │ ├── MANTA_MTA │ │ ├── Create DB.sql │ │ └── Tables │ │ │ ├── man_mta_transactionStatus.sql │ │ │ ├── man_evn_type.sql │ │ │ ├── man_rle_ruleType.sql │ │ │ ├── man_evn_bounceCode.sql │ │ │ ├── man_evn_bounceType.sql │ │ │ ├── man_mta_sendStatus.sql │ │ │ ├── man_rle_patternType.sql │ │ │ ├── man_evn_bounceRuleCriteriaType.sql │ │ │ ├── man_ip_groupMembership.sql │ │ │ ├── man_rle_rule.sql │ │ │ ├── man_ip_group.sql │ │ │ ├── man_evn_bounceEvent.sql │ │ │ ├── man_evn_bounceRule.sql │ │ │ ├── man_mta_sendMeta.sql │ │ │ ├── man_mta_fblAddress.sql │ │ │ ├── man_cfg_localDomain.sql │ │ │ ├── man_cfg_relayingPermittedIp.sql │ │ │ ├── man_rle_mxPattern.sql │ │ │ ├── man_evn_event.sql │ │ │ ├── man_mta_msg.sql │ │ │ ├── man_ip_ipAddress.sql │ │ │ ├── man_cfg_para.sql │ │ │ ├── man_mta_send.sql │ │ │ ├── man_mta_transaction.sql │ │ │ └── man_mta_queue.sql │ └── ScriptDb.exe.config ├── Datasets │ ├── DataSets.exe │ └── MANTA_MTA │ │ ├── man_cfg_para.txt │ │ ├── man_cfg_para.xml │ │ ├── man_evn_type.txt │ │ ├── man_evn_type.xml │ │ ├── man_ip_group.txt │ │ ├── man_ip_group.xml │ │ ├── man_mta_msg.txt │ │ ├── man_mta_msg.xml │ │ ├── man_mta_send.txt │ │ ├── man_mta_send.xml │ │ ├── man_rle_rule.txt │ │ ├── man_rle_rule.xml │ │ ├── man_evn_event.txt │ │ ├── man_evn_event.xml │ │ ├── man_mta_queue.txt │ │ ├── man_mta_queue.xml │ │ ├── man_ip_ipAddress.txt │ │ ├── man_ip_ipAddress.xml │ │ ├── man_rle_mxPattern.txt │ │ ├── man_rle_mxPattern.xml │ │ ├── man_rle_ruleType.txt │ │ ├── man_rle_ruleType.xml │ │ ├── man_cfg_localDomain.txt │ │ ├── man_cfg_localDomain.xml │ │ ├── man_evn_bounceCode.txt │ │ ├── man_evn_bounceCode.xml │ │ ├── man_evn_bounceEvent.txt │ │ ├── man_evn_bounceEvent.xml │ │ ├── man_evn_bounceRule.txt │ │ ├── man_evn_bounceRule.xml │ │ ├── man_evn_bounceType.txt │ │ ├── man_evn_bounceType.xml │ │ ├── man_mta_fblAddress.txt │ │ ├── man_mta_fblAddress.xml │ │ ├── man_mta_sendStatus.txt │ │ ├── man_mta_sendStatus.xml │ │ ├── man_mta_transaction.txt │ │ ├── man_mta_transaction.xml │ │ ├── man_rle_patternType.txt │ │ ├── man_rle_patternType.xml │ │ ├── man_ip_groupMembership.txt │ │ ├── man_ip_groupMembership.xml │ │ ├── man_mta_transactionStatus.txt │ │ ├── man_mta_transactionStatus.xml │ │ ├── man_cfg_relayingPermittedIp.txt │ │ ├── man_cfg_relayingPermittedIp.xml │ │ ├── man_evn_bounceRuleCriteriaType.txt │ │ └── man_evn_bounceRuleCriteriaType.xml └── SQL Scripts │ └── select bounceRules.sql ├── OpenManta.Data ├── App.config ├── MantaDB.cs ├── FeedbackLoopEmailAddressDB.cs ├── MtaMessageDB.cs ├── Properties │ └── AssemblyInfo.cs ├── CfgRelayingPermittedIP.cs ├── OpenManta.Data.csproj ├── OutboundRuleDB.cs └── VirtualMtaDB.cs ├── OpenManta.Web ├── favicon.ico ├── img │ └── manta-logo.png ├── Views │ ├── Home │ │ └── Index.cshtml │ ├── OutboundRules │ │ ├── Delete.cshtml │ │ └── Index.cshtml │ ├── Sends │ │ ├── Pause.cshtml │ │ ├── Resume.cshtml │ │ ├── Discard.cshtml │ │ ├── GetMessageResultCsv.cshtml │ │ ├── VirtualMTA.cshtml │ │ ├── Overview.cshtml │ │ ├── Deferred.cshtml │ │ ├── Failed.cshtml │ │ ├── Bounces.cshtml │ │ └── _ReportLayout.cshtml │ ├── RabbitMQ │ │ └── Index.cshtml │ ├── ServerStatus │ │ └── Index.cshtml │ ├── VirtualMta │ │ ├── Edit.cshtml │ │ └── EditGroup.cshtml │ ├── Bounces │ │ └── Index.cshtml │ └── Web.config ├── Global.asax ├── AppendSendMetadata.ashx ├── Content │ ├── fonts │ │ ├── ArchivoNarrow-Bold.ttf │ │ ├── ArchivoNarrow-Italic.ttf │ │ ├── ArchivoNarrow-Regular.ttf │ │ └── ArchivoNarrow-BoldItalic.ttf │ └── fonts.css ├── bower.json ├── App_Start │ ├── FilterConfig.cs │ ├── WebApiConfig.cs │ ├── RouteConfig.cs │ └── BundleConfig.cs ├── Controllers │ ├── ServerStatusController.cs │ ├── HomeController.cs │ ├── BouncesController.cs │ ├── SettingsController.cs │ ├── RabbitMQController.cs │ ├── OutboundRulesController.cs │ ├── VirtualMtaController.cs │ ├── API │ │ └── v1 │ │ │ ├── OutboundRulesController.cs │ │ │ └── SettingsController.cs │ └── DashboardController.cs ├── Models │ ├── API │ │ └── v1 │ │ │ ├── OutboundRulesViewModels.cs │ │ │ ├── VirtualMtaViewModels.cs │ │ │ └── SettingsViewModels.cs │ ├── RabbitMqModel.cs │ ├── BounceModel.cs │ ├── OutboundRules.cs │ └── SettingsModel.cs ├── Global.asax.cs ├── Properties │ ├── PublishProfiles │ │ └── MantaMTA.pubxml │ └── AssemblyInfo.cs ├── WebInterface.csproj.user ├── packages.config ├── Web.Debug.config ├── Web.Release.config └── AppendSendMetadata.ashx.cs ├── OpenManta.Framework ├── MyClass.cs ├── IStopRequired.cs ├── packages.config ├── Log4net.config ├── Smtp │ └── MantaOutboundClientResult.cs ├── Properties │ └── AssemblyInfo.cs ├── BounceRulesManager.cs ├── MantaCoreEvents.cs ├── RabbitMq │ ├── RabbitMqInboundStagingHandler.cs │ ├── RabbitMqInboundQueueManager.cs │ └── RabbitMqOutboundQueueManager.cs ├── DNSManager.cs ├── ServiceNotAvailableManager.cs ├── ServiceContractManager.cs └── Serialisation.cs ├── .gitignore ├── Readme.md ├── packages └── repositories.config ├── OpenManta.Core ├── RabbitMqPriority.cs ├── MantaAbuseEvent.cs ├── MantaTimedOutInQueueEvent.cs ├── LocalDomain.cs ├── MxRecordSrc.cs ├── OutboundMxPatternType.cs ├── SendStatus.cs ├── SmtpTransportMIME.cs ├── EntityBaseClasses.cs ├── MantaBounceEvent.cs ├── MessageDestination.cs ├── BounceRuleCriteriaType.cs ├── OutboundRuleType.cs ├── BouncePair.cs ├── Send.cs ├── BounceIdentifier.cs ├── MessageHeader.cs ├── OutboundRule.cs ├── TransactionStatus.cs ├── OutboundMxPattern.cs ├── MantaEvent.cs ├── BounceRulesCollection.cs ├── Properties │ └── AssemblyInfo.cs ├── MantaEventType.cs ├── MantaBounceType.cs ├── MXRecord.cs ├── MtaMessage.cs ├── _ExtensionMethods.cs ├── MessageHeaderCollection.cs ├── VirtualMTA.cs ├── MtaQueuedMessage.cs ├── EmailProcessingResult.cs ├── MantaBounceCode.cs ├── BodyPart.cs └── VirtualMtaGroup.cs ├── OpenManta.Service ├── Program.cs ├── App.config ├── OpenMantaService.Designer.cs ├── OpenMantaServiceInstaller.cs ├── Properties │ └── AssemblyInfo.cs └── OpenMantaService.cs ├── OpenManta.Console ├── App.config ├── Properties │ └── AssemblyInfo.cs └── Program.cs ├── OpenManta.WebLib ├── BO │ ├── SendMetadataClasses.cs │ ├── SendWaitingInfo.cs │ ├── BounceInfo.cs │ ├── VirtualMtaSendInfo.cs │ └── SendTransaction.cs ├── WebInterfaceParameters.cs ├── Properties │ └── AssemblyInfo.cs ├── DAL │ └── VirtualMtaTransactionDB.cs ├── VirtualMtaWebManager.cs └── OutboundRuleWebManager.cs └── LICENCE.md /Database/MtaDB/ScriptDb.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/MtaDB/ScriptDb.exe -------------------------------------------------------------------------------- /OpenManta.Data/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /OpenManta.Web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/OpenManta.Web/favicon.ico -------------------------------------------------------------------------------- /Database/Datasets/DataSets.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/DataSets.exe -------------------------------------------------------------------------------- /OpenManta.Web/img/manta-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/OpenManta.Web/img/manta-logo.png -------------------------------------------------------------------------------- /OpenManta.Web/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Index"; 3 | Response.Redirect("/dashboard/"); 4 | } -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Create DB.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/MtaDB/MANTA_MTA/Create DB.sql -------------------------------------------------------------------------------- /OpenManta.Web/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="WebInterface.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_cfg_para.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_cfg_para.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_cfg_para.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_cfg_para.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_type.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_type.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_type.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_type.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_ip_group.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_ip_group.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_ip_group.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_ip_group.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_msg.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_msg.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_msg.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_msg.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_send.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_send.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_send.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_send.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_rle_rule.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_rle_rule.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_rle_rule.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_rle_rule.xml -------------------------------------------------------------------------------- /OpenManta.Web/Views/OutboundRules/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Delete"; 3 | Response.Redirect("~/OutboundRules"); 4 | } 5 | -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_event.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_event.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_event.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_event.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_queue.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_queue.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_queue.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_queue.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_ip_ipAddress.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_ip_ipAddress.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_ip_ipAddress.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_ip_ipAddress.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_rle_mxPattern.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_rle_mxPattern.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_rle_mxPattern.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_rle_mxPattern.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_rle_ruleType.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_rle_ruleType.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_rle_ruleType.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_rle_ruleType.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_cfg_localDomain.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_cfg_localDomain.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_cfg_localDomain.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_cfg_localDomain.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_bounceCode.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_bounceCode.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_bounceCode.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_bounceCode.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_bounceEvent.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_bounceEvent.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_bounceEvent.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_bounceEvent.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_bounceRule.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_bounceRule.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_bounceRule.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_bounceRule.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_bounceType.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_bounceType.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_bounceType.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_bounceType.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_fblAddress.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_fblAddress.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_fblAddress.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_fblAddress.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_sendStatus.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_sendStatus.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_sendStatus.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_sendStatus.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_transaction.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_transaction.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_transaction.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_transaction.xml -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_rle_patternType.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_rle_patternType.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_rle_patternType.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_rle_patternType.xml -------------------------------------------------------------------------------- /OpenManta.Web/AppendSendMetadata.ashx: -------------------------------------------------------------------------------- 1 | <%@ WebHandler Language="C#" CodeBehind="AppendSendMetadata.ashx.cs" Class="WebInterface.AppendSendMetadata" %> 2 | -------------------------------------------------------------------------------- /OpenManta.Web/Content/fonts/ArchivoNarrow-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/OpenManta.Web/Content/fonts/ArchivoNarrow-Bold.ttf -------------------------------------------------------------------------------- /OpenManta.Web/Content/fonts/ArchivoNarrow-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/OpenManta.Web/Content/fonts/ArchivoNarrow-Italic.ttf -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_ip_groupMembership.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_ip_groupMembership.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_ip_groupMembership.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_ip_groupMembership.xml -------------------------------------------------------------------------------- /OpenManta.Web/Content/fonts/ArchivoNarrow-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/OpenManta.Web/Content/fonts/ArchivoNarrow-Regular.ttf -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_transactionStatus.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_transactionStatus.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_mta_transactionStatus.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_mta_transactionStatus.xml -------------------------------------------------------------------------------- /OpenManta.Web/Content/fonts/ArchivoNarrow-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/OpenManta.Web/Content/fonts/ArchivoNarrow-BoldItalic.ttf -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_cfg_relayingPermittedIp.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_cfg_relayingPermittedIp.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_cfg_relayingPermittedIp.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_cfg_relayingPermittedIp.xml -------------------------------------------------------------------------------- /OpenManta.Web/Views/Sends/Pause.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = null; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /OpenManta.Web/Views/Sends/Resume.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = null; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_bounceRuleCriteriaType.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_bounceRuleCriteriaType.txt -------------------------------------------------------------------------------- /Database/Datasets/MANTA_MTA/man_evn_bounceRuleCriteriaType.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenManta/MantaMTA/HEAD/Database/Datasets/MANTA_MTA/man_evn_bounceRuleCriteriaType.xml -------------------------------------------------------------------------------- /OpenManta.Web/Views/Sends/Discard.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = null; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /OpenManta.Framework/MyClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Manta.Framework 4 | { 5 | public class MyClass 6 | { 7 | public MyClass () 8 | { 9 | } 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | *.suo 3 | */bin/* 4 | */obj/* 5 | *.psess 6 | *.vspx 7 | Database/MtaDB/scriptDb.log 8 | /packages/ 9 | /.vs/ 10 | *.userprefs 11 | OpenManta.Web/bower_components/ 12 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # [MantaMTA](http://manta.io/) 2 | 3 | Production-ready open-source MTA for .NET. 4 | 5 | ## Backstory 6 | 7 | MantaMTA was developed by Colony101 to support their [Sentori](http://www.sentori.co.uk/) email system. 8 | -------------------------------------------------------------------------------- /packages/repositories.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_mta_transactionStatus.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_mta_transactionStatus]( 2 | [mta_transactionStatus_id] [int] NOT NULL, 3 | [mta_transactionStatus_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL 4 | ) ON [PRIMARY] 5 | 6 | GO 7 | 8 | -------------------------------------------------------------------------------- /OpenManta.Core/RabbitMqPriority.cs: -------------------------------------------------------------------------------- 1 | namespace OpenManta.Core 2 | { 3 | /// 4 | /// Priority for messages in RabbitMQ queues. 5 | /// 6 | public enum RabbitMqPriority : byte 7 | { 8 | Low = 0, 9 | Normal = 1, 10 | High = 2 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_evn_type.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_evn_type]( 2 | [evn_type_id] [int] NOT NULL, 3 | [evn_type_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [evn_type_description] [nvarchar](250) COLLATE Latin1_General_CI_AS NULL 5 | ) ON [PRIMARY] 6 | 7 | GO 8 | 9 | -------------------------------------------------------------------------------- /OpenManta.Framework/IStopRequired.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Framework 4 | { 5 | /// 6 | /// Interface is for objects that need to be stopped when the MTA is stopping. 7 | /// 8 | internal interface IStopRequired 9 | { 10 | void Stop(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /OpenManta.Core/MantaAbuseEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Manta Spam Complaint (Abuse) event. The result of an email coming back from a feedback loop with an ISP. 7 | /// 8 | public class MantaAbuseEvent : MantaEvent 9 | { 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /OpenManta.Framework/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_rle_ruleType.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_rle_ruleType]( 2 | [rle_ruleType_id] [int] NOT NULL, 3 | [rle_ruleType_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [rle_ruleType_description] [nvarchar](250) COLLATE Latin1_General_CI_AS NULL 5 | ) ON [PRIMARY] 6 | 7 | GO 8 | 9 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_evn_bounceCode.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_evn_bounceCode]( 2 | [evn_bounceCode_id] [int] NOT NULL, 3 | [evn_bounceCode_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [evn_bounceCode_description] [nvarchar](250) COLLATE Latin1_General_CI_AS NULL 5 | ) ON [PRIMARY] 6 | 7 | GO 8 | 9 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_evn_bounceType.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_evn_bounceType]( 2 | [evn_bounceType_id] [int] NOT NULL, 3 | [evn_bounceType_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [evn_bounceType_description] [nvarchar](250) COLLATE Latin1_General_CI_AS NULL 5 | ) ON [PRIMARY] 6 | 7 | GO 8 | 9 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_mta_sendStatus.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_mta_sendStatus]( 2 | [mta_sendStatus_id] [int] NOT NULL, 3 | [mta_sendStatus_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [mta_sendStatus_description] [nvarchar](250) COLLATE Latin1_General_CI_AS NULL 5 | ) ON [PRIMARY] 6 | 7 | GO 8 | 9 | -------------------------------------------------------------------------------- /Database/MtaDB/ScriptDb.exe.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_rle_patternType.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_rle_patternType]( 2 | [rle_patternType_id] [int] NOT NULL, 3 | [rle_patternType_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [rle_patternType_description] [nvarchar](250) COLLATE Latin1_General_CI_AS NULL 5 | ) ON [PRIMARY] 6 | 7 | GO 8 | 9 | -------------------------------------------------------------------------------- /OpenManta.Core/MantaTimedOutInQueueEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Manta Timed Out In Queue event. The result of an email failing to be delivered within the maximum allowed time. 7 | /// 8 | public class MantaTimedOutInQueueEvent : MantaEvent 9 | { 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /OpenManta.Service/Program.cs: -------------------------------------------------------------------------------- 1 | using System.ServiceProcess; 2 | 3 | namespace OpenManta.Service 4 | { 5 | static class Program 6 | { 7 | /// 8 | /// The main entry point for the application. 9 | /// 10 | static void Main() 11 | { 12 | ServiceBase.Run(new OpenMantaService()); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /OpenManta.Core/LocalDomain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Holds a local domain object. 7 | /// 8 | public class LocalDomain : NamedEntity 9 | { 10 | /// 11 | /// Local domains hostname. 12 | /// 13 | public string Hostname { get; set; } 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /OpenManta.Web/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openmanta.web", 3 | "homepage": "https://github.com/OpenManta/MantaMTA", 4 | "description": "", 5 | "main": "", 6 | "license": "MIT", 7 | "private": true, 8 | "devDependencies": { 9 | "jquery": "jquery#1.9.1", 10 | "gbelmm-jqplot": "gbelmm-jqplot#1.0.9", 11 | "bootstrap": "bootstrap#2.3.2" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /OpenManta.Web/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace WebInterface 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | //filters.Add(new RequireHttpsAttribute()); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_evn_bounceRuleCriteriaType.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_evn_bounceRuleCriteriaType]( 2 | [evn_bounceRuleCriteriaType_id] [int] NOT NULL, 3 | [evn_bounceRuleCriteriaType_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [evn_bounceRuleCriteriaType_description] [nvarchar](250) COLLATE Latin1_General_CI_AS NULL 5 | ) ON [PRIMARY] 6 | 7 | GO 8 | 9 | -------------------------------------------------------------------------------- /OpenManta.Web/Controllers/ServerStatusController.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Mvc; 2 | using WebInterface.Models; 3 | 4 | namespace WebInterface.Controllers 5 | { 6 | public class ServerStatusController : Controller 7 | { 8 | // 9 | // GET: /ServerStatus/ 10 | public ActionResult Index() 11 | { 12 | return View(new ServerStatusModel()); 13 | } 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /OpenManta.Core/MxRecordSrc.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Identifies where the MX record came from. 7 | /// 8 | public enum MxRecordSrc 9 | { 10 | Unknown = 0, 11 | /// 12 | /// MX record exists in DNS. 13 | /// 14 | MX = 1, 15 | /// 16 | /// No MX record in DNS, using A instead. 17 | /// 18 | A = 2 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /OpenManta.Web/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | 7 | namespace WebInterface.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | // 12 | // GET: /Home/ 13 | 14 | public ActionResult Index() 15 | { 16 | return View(); 17 | } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /OpenManta.Core/OutboundMxPatternType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Identifies the type of pattern to match with. 7 | /// 8 | public enum OutboundMxPatternType : int 9 | { 10 | /// 11 | /// Value is a regular expression. 12 | /// 13 | Regex = 1, 14 | /// 15 | /// Value is a comma delimited list of string to equals. 16 | /// 17 | CommaDelimited = 2 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /OpenManta.Core/SendStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | public enum SendStatus : int 6 | { 7 | /// 8 | /// The send is active; Emails can be sent. 9 | /// 10 | Active = 1, 11 | /// 12 | /// The send is paused; Emails shouldn't be sent yet. 13 | /// 14 | Paused = 2, 15 | /// 16 | /// The send is cancelled; Emails should never be sent. 17 | /// 18 | Discard = 3 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /OpenManta.Core/SmtpTransportMIME.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// ESMTP 8BITMIMETYPE 7 | /// This is used to determine what format to send/receive a messages body in. 8 | /// 9 | public enum SmtpTransportMIME : int 10 | { 11 | /// 12 | /// ASCII (7bit) 13 | /// 14 | _7BitASCII = 1, 15 | /// 16 | /// UTF-8 without byte order mark. 17 | /// 18 | _8BitUTF = 2 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /OpenManta.Core/EntityBaseClasses.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | public abstract class BaseEntity 6 | { 7 | public T ID { get; set; } 8 | } 9 | 10 | public abstract class BaseEntity : BaseEntity 11 | { 12 | } 13 | 14 | public abstract class NamedEntity : BaseEntity 15 | { 16 | public string Name { get; set; } 17 | public string Description { get; set; } 18 | } 19 | 20 | public abstract class NamedEntity : NamedEntity 21 | { 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /OpenManta.Console/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 10 | 11 | 12 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /OpenManta.Service/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /OpenManta.Web/Views/RabbitMQ/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "RabbitMQ"; 3 | Layout = "~/Views/_Layout.cshtml"; 4 | } 5 | 6 |

RabbitMQ Queues

7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | @foreach (WebInterface.Models.RabbitMqQueue q in Model) 16 | { 17 | 18 | 19 | 20 | 21 | 22 | } 23 |
QueueStateMessages
@q.Name@q.State@q.Messages.ToString("N0")
24 | -------------------------------------------------------------------------------- /OpenManta.Core/MantaBounceEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Manta Bounce Event Notification. 7 | /// 8 | public class MantaBounceEvent : MantaEvent 9 | { 10 | /// 11 | /// The type of bounce. 12 | /// 13 | public BouncePair BounceInfo; 14 | /// 15 | /// The text of the failure message. (Up to the number of characters configured.) 16 | /// 17 | public string Message { get; set; } 18 | } 19 | 20 | } 21 | 22 | -------------------------------------------------------------------------------- /OpenManta.Core/MessageDestination.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Specifies where the Message being received should go. 7 | /// 8 | public enum MessageDestination 9 | { 10 | /// 11 | /// Default value. 12 | /// 13 | Unknown = 0, 14 | /// 15 | /// Message is for delivery on this server. 16 | /// 17 | Self = 1, 18 | /// 19 | /// Message should be relayed. 20 | /// 21 | Relay = 2 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /OpenManta.Web/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Http; 5 | 6 | namespace WebInterface 7 | { 8 | public static class WebApiConfig 9 | { 10 | public static void Register(HttpConfiguration config) 11 | { 12 | config.MapHttpAttributeRoutes(); 13 | 14 | config.Routes.MapHttpRoute( 15 | name: "DefaultApi", 16 | routeTemplate: "api/{controller}/{id}", 17 | defaults: new { id = RouteParameter.Optional } 18 | ); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_ip_groupMembership.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_ip_groupMembership]( 2 | [ip_group_id] [int] NOT NULL, 3 | [ip_ipAddress_id] [int] NOT NULL 4 | ) ON [PRIMARY] 5 | 6 | GO 7 | 8 | ALTER TABLE [dbo].[man_ip_groupMembership] ADD CONSTRAINT [PK_man_ip_groupMembership] PRIMARY KEY CLUSTERED 9 | ( 10 | [ip_group_id] ASC, 11 | [ip_ipAddress_id] ASC 12 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 13 | GO 14 | 15 | -------------------------------------------------------------------------------- /OpenManta.WebLib/BO/SendMetadataClasses.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace OpenManta.WebLib.BO 8 | { 9 | public class SendMetadata 10 | { 11 | public string Name { get; set; } 12 | public string Value { get; set; } 13 | } 14 | 15 | public class SendMetadataCollection : List 16 | { 17 | public SendMetadataCollection() { } 18 | public SendMetadataCollection(IEnumerable collection) : base(collection) { } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /OpenManta.Data/MantaDB.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | using System.Data.SqlClient; 3 | 4 | namespace OpenManta.Data 5 | { 6 | /// 7 | /// Functions to help with database stuff. 8 | /// 9 | public static class MantaDB 10 | { 11 | /// 12 | /// Gets a SqlConnection to the MantaMTA Database 13 | /// 14 | /// Sql connection 15 | public static SqlConnection GetSqlConnection() 16 | { 17 | return new SqlConnection(ConfigurationManager.ConnectionStrings["SqlServer"].ConnectionString); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_rle_rule.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_rle_rule]( 2 | [rle_mxPattern_id] [int] NOT NULL, 3 | [rle_ruleType_id] [int] NOT NULL, 4 | [rle_rule_value] [nvarchar](250) COLLATE Latin1_General_CI_AS NOT NULL 5 | ) ON [PRIMARY] 6 | 7 | GO 8 | 9 | ALTER TABLE [dbo].[man_rle_rule] ADD CONSTRAINT [PK_sm_rle_rule] PRIMARY KEY CLUSTERED 10 | ( 11 | [rle_mxPattern_id] ASC, 12 | [rle_ruleType_id] ASC 13 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 14 | GO 15 | 16 | -------------------------------------------------------------------------------- /OpenManta.Web/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace WebInterface 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_ip_group.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_ip_group]( 2 | [ip_group_id] [int] IDENTITY(1,1) NOT NULL, 3 | [ip_group_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [ip_group_description] [nvarchar](250) COLLATE Latin1_General_CI_AS NULL 5 | ) ON [PRIMARY] 6 | 7 | GO 8 | 9 | ALTER TABLE [dbo].[man_ip_group] ADD CONSTRAINT [PK_man_ip_group] PRIMARY KEY CLUSTERED 10 | ( 11 | [ip_group_id] ASC 12 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 13 | GO 14 | 15 | -------------------------------------------------------------------------------- /OpenManta.WebLib/WebInterfaceParameters.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace OpenManta.WebLib 3 | { 4 | public static class WebInterfaceParameters 5 | { 6 | /// 7 | /// ID that signifies that an OutboundRulePattern is new. 8 | /// 9 | public const int OUTBOUND_RULES_NEW_PATTERN_ID = 0; 10 | 11 | /// 12 | /// ID that signifies that a Virtual MTA is new. 13 | /// 14 | public const int VIRTUALMTA_NEW_ID = 0; 15 | 16 | /// 17 | /// ID that signifies that a Virtual MTA Group is new. 18 | /// 19 | public const int VIRTUALMTAGROUP_NEW_ID = 0; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /OpenManta.Core/BounceRuleCriteriaType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Used to identify how to use a Bounce Rule's Criteria property. 7 | /// 8 | public enum BounceRuleCriteriaType : int 9 | { 10 | /// 11 | /// Default value. 12 | /// 13 | Unknown = 0, 14 | /// 15 | /// The criteria is a Regex pattern to run against the message. 16 | /// 17 | RegularExpressionPattern = 1, 18 | /// 19 | /// The criteria is a string that may appear within the message. 20 | /// 21 | StringMatch = 2 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /OpenManta.Core/OutboundRuleType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Identifies a Type of outbound rule. 7 | /// 8 | public enum OutboundRuleType : int 9 | { 10 | /// 11 | /// Rule holds the maximum simultaneous connections value. 12 | /// 13 | MaxConnections = 1, 14 | /// 15 | /// Rule holds the maximum messages per connections value. 16 | /// 17 | MaxMessagesConnection = 2, 18 | /// 19 | /// Rule holds the maximum messages per hour, all connections. 20 | /// 21 | MaxMessagesPerHour = 3 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /OpenManta.Web/Models/API/v1/OutboundRulesViewModels.cs: -------------------------------------------------------------------------------- 1 | using OpenManta.Core; 2 | 3 | namespace WebInterface.Models.API.v1 4 | { 5 | public class UpdateOutboundRuleViewModel 6 | { 7 | public int PatternID { get; set; } 8 | public string Name { get; set; } 9 | public string Description { get; set; } 10 | public int? VirtualMTA { get; set; } 11 | public OutboundMxPatternType Type { get; set; } 12 | public string PatternValue { get; set; } 13 | public int MaxConnections { get; set; } 14 | public int MaxMessagesConn { get; set; } 15 | public int MaxMessagesHour { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_evn_bounceEvent.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_evn_bounceEvent]( 2 | [evn_event_id] [int] NOT NULL, 3 | [evn_bounceCode_id] [int] NOT NULL, 4 | [evn_bounceType_id] [int] NOT NULL, 5 | [evn_bounceEvent_message] [nvarchar](max) COLLATE Latin1_General_CI_AS NOT NULL 6 | ) ON [PRIMARY] 7 | 8 | GO 9 | 10 | ALTER TABLE [dbo].[man_evn_bounceEvent] ADD CONSTRAINT [PK_man_evn_bounceEvent] PRIMARY KEY CLUSTERED 11 | ( 12 | [evn_event_id] ASC 13 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 14 | GO 15 | 16 | -------------------------------------------------------------------------------- /OpenManta.Core/BouncePair.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Holds information about an SMTP code returned by a server as a bounce. 7 | /// 8 | public struct BouncePair 9 | { 10 | /// 11 | /// The MantaBounceCode for the Bounce. 12 | /// 13 | public MantaBounceCode BounceCode; 14 | /// 15 | /// The MentaBounceType for the Bounce. 16 | /// 17 | public MantaBounceType BounceType; 18 | 19 | public override string ToString() 20 | { 21 | return String.Format("BounceType: {0}, BounceCode: {1}", this.BounceType, this.BounceCode); 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_evn_bounceRule.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_evn_bounceRule]( 2 | [evn_bounceRule_id] [int] NOT NULL, 3 | [evn_bounceRule_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [evn_bounceRule_description] [nvarchar](250) COLLATE Latin1_General_CI_AS NULL, 5 | [evn_bounceRule_executionOrder] [int] NOT NULL, 6 | [evn_bounceRule_isBuiltIn] [bit] NOT NULL, 7 | [evn_bounceRuleCriteriaType_id] [int] NOT NULL, 8 | [evn_bounceRule_criteria] [nvarchar](max) COLLATE Latin1_General_CI_AS NOT NULL, 9 | [evn_bounceRule_mantaBounceType] [int] NOT NULL, 10 | [evn_bounceRule_mantaBounceCode] [int] NOT NULL 11 | ) ON [PRIMARY] 12 | 13 | GO 14 | 15 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_mta_sendMeta.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_mta_sendMeta]( 2 | [mta_send_internalId] [int] NOT NULL, 3 | [mta_sendMeta_name] [nvarchar](max) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [mta_sendMeta_value] [nvarchar](max) COLLATE Latin1_General_CI_AS NOT NULL 5 | ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 6 | 7 | GO 8 | 9 | CREATE NONCLUSTERED INDEX [IX_man_mta_sendMeta] ON [dbo].[man_mta_sendMeta] 10 | ( 11 | [mta_send_internalId] ASC 12 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 13 | GO 14 | 15 | -------------------------------------------------------------------------------- /OpenManta.Web/Views/Sends/GetMessageResultCsv.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/_Layout.cshtml"; 3 | } 4 | 5 | 6 | 7 | @foreach (System.Data.DataColumn column in ((System.Data.DataTable)Model).Columns) 8 | { 9 | 10 | } 11 | 12 | 13 | 14 | @foreach (System.Data.DataRow row in ((System.Data.DataTable)Model).Rows) 15 | { 16 | 17 | @foreach (System.Data.DataColumn column in ((System.Data.DataTable)Model).Columns) 18 | { 19 | 20 | } 21 | 22 | } 23 | 24 | 25 |
@column.ColumnName
@row[column.ColumnName]
-------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_mta_fblAddress.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_mta_fblAddress]( 2 | [mta_fblAddress_address] [nvarchar](320) COLLATE Latin1_General_CI_AS NOT NULL, 3 | [mta_fblAddress_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [mta_fblAddress_description] [nvarchar](250) COLLATE Latin1_General_CI_AS NULL 5 | ) ON [PRIMARY] 6 | 7 | GO 8 | 9 | ALTER TABLE [dbo].[man_mta_fblAddress] ADD CONSTRAINT [PK_man_mta_fblAddress] PRIMARY KEY CLUSTERED 10 | ( 11 | [mta_fblAddress_address] ASC 12 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 13 | GO 14 | 15 | -------------------------------------------------------------------------------- /OpenManta.Web/Models/RabbitMqModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace WebInterface.Models 4 | { 5 | /// 6 | /// Holds information about a RabbitMQ queue. 7 | /// 8 | public class RabbitMqQueue 9 | { 10 | /// 11 | /// Name of the Queue. 12 | /// 13 | public string Name { get; set; } 14 | /// 15 | /// Messages in the queue. 16 | /// 17 | public long Messages { get; set;} 18 | /// 19 | /// State of the queue. 20 | /// 21 | public string State { get; set; } 22 | } 23 | 24 | public class RabbitMqQueueModel : List 25 | { 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /OpenManta.Web/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Http; 2 | using System.Web.Mvc; 3 | using System.Web.Optimization; 4 | using System.Web.Routing; 5 | 6 | namespace WebInterface 7 | { 8 | // Note: For instructions on enabling IIS6 or IIS7 classic mode, 9 | // visit http://go.microsoft.com/?LinkId=9394801 10 | public class MvcApplication : System.Web.HttpApplication 11 | { 12 | protected void Application_Start() 13 | { 14 | AreaRegistration.RegisterAllAreas(); 15 | 16 | GlobalConfiguration.Configure(WebApiConfig.Register); 17 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 18 | RouteConfig.RegisterRoutes(RouteTable.Routes); 19 | BundleConfig.RegisterBundles(BundleTable.Bundles); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_cfg_localDomain.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_cfg_localDomain]( 2 | [cfg_localDomain_id] [int] IDENTITY(1,1) NOT NULL, 3 | [cfg_localDomain_domain] [nvarchar](255) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [cfg_localDomain_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NULL, 5 | [cfg_localDomain_description] [nvarchar](250) COLLATE Latin1_General_CI_AS NULL 6 | ) ON [PRIMARY] 7 | 8 | GO 9 | 10 | ALTER TABLE [dbo].[man_cfg_localDomain] ADD CONSTRAINT [PK_man_cfg_localDomain] PRIMARY KEY CLUSTERED 11 | ( 12 | [cfg_localDomain_id] ASC 13 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 14 | GO 15 | 16 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_cfg_relayingPermittedIp.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_cfg_relayingPermittedIp]( 2 | [cfg_relayingPermittedIp_ip] [varchar](45) COLLATE Latin1_General_CI_AS NOT NULL, 3 | [cfg_relayingPermittedIp_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NULL, 4 | [cfg_relayingPermittedIp_description] [nvarchar](250) COLLATE Latin1_General_CI_AS NULL 5 | ) ON [PRIMARY] 6 | 7 | GO 8 | 9 | ALTER TABLE [dbo].[man_cfg_relayingPermittedIp] ADD CONSTRAINT [PK_man_cfg_relayingPermittedIps] PRIMARY KEY CLUSTERED 10 | ( 11 | [cfg_relayingPermittedIp_ip] ASC 12 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 13 | GO 14 | 15 | -------------------------------------------------------------------------------- /OpenManta.Core/Send.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | public class Send : BaseEntity 6 | { 7 | /// 8 | /// An Internal ID for the sendID. 9 | /// 10 | public int InternalID { get; set; } 11 | 12 | /// 13 | /// The current Status of this Send. 14 | /// 15 | public SendStatus SendStatus { get; set; } 16 | 17 | /// 18 | /// This is used to record when this instance of this class was accessed. Used by 19 | /// the SendIDManager to clean up it's internal cache. 20 | /// 21 | public DateTime LastAccessedTimestamp { get; set; } 22 | 23 | /// 24 | /// Timestamp Send was created. 25 | /// 26 | public DateTime CreatedTimestamp { get; set; } 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /OpenManta.Core/BounceIdentifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// How Manta identified an email as being a bounce, e.g. did a Bounce Rule match its content or was an NDR code found? 7 | /// 8 | public enum BounceIdentifier 9 | { 10 | /// 11 | /// Wasn't a bounce. 12 | /// 13 | NotIdentifiedAsABounce = 0, 14 | /// 15 | /// No Manta ReturnPath was found. 16 | /// 17 | UnknownReturnPath, 18 | /// 19 | /// A Bounce Rule matched the content. 20 | /// 21 | BounceRule, 22 | /// 23 | /// A Non-Delivery Report code was found. 24 | /// 25 | NdrCode, 26 | /// 27 | /// An SMTP code was found. 28 | /// 29 | SmtpCode 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_rle_mxPattern.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_rle_mxPattern]( 2 | [rle_mxPattern_id] [int] IDENTITY(1,1) NOT NULL, 3 | [rle_mxPattern_name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [rle_mxPattern_description] [nvarchar](250) COLLATE Latin1_General_CI_AS NULL, 5 | [rle_patternType_id] [int] NOT NULL, 6 | [rle_mxPattern_value] [nvarchar](250) COLLATE Latin1_General_CI_AS NOT NULL, 7 | [ip_ipAddress_id] [int] NULL 8 | ) ON [PRIMARY] 9 | 10 | GO 11 | 12 | ALTER TABLE [dbo].[man_rle_mxPattern] ADD CONSTRAINT [PK_man_rle_mxPattern] PRIMARY KEY CLUSTERED 13 | ( 14 | [rle_mxPattern_id] ASC 15 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 16 | GO 17 | 18 | -------------------------------------------------------------------------------- /OpenManta.Core/MessageHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace OpenManta.Core 5 | { 6 | /// 7 | /// Class represents an Email message header. 8 | /// 9 | public class MessageHeader 10 | { 11 | /// 12 | /// Name of the message header. 13 | /// 14 | public string Name { get; set; } 15 | 16 | /// 17 | /// Message header value. 18 | /// 19 | public string Value { get; set; } 20 | 21 | /// 22 | /// Create a new MessageHeader object. 23 | /// 24 | /// Name of the Header. 25 | /// Headers value. 26 | public MessageHeader(string name, string value) 27 | { 28 | Name = name.Trim(); 29 | Value = value.Trim(); 30 | } 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /OpenManta.Core/OutboundRule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Holds a rule for outbound clients. 7 | /// 8 | public class OutboundRule 9 | { 10 | /// 11 | /// ID of the pattern that this rule should be used with. 12 | /// 13 | public int OutboundMxPatternID { get; set; } 14 | 15 | /// 16 | /// Identifies the type of this rule. 17 | /// 18 | public OutboundRuleType Type { get; set; } 19 | 20 | /// 21 | /// The value of this rule. 22 | /// 23 | public string Value { get; set; } 24 | 25 | public OutboundRule(int outbounbMxPatternID, OutboundRuleType type, string value) 26 | { 27 | this.OutboundMxPatternID = outbounbMxPatternID; 28 | this.Type = type; 29 | this.Value = value; 30 | } 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_evn_event.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_evn_event]( 2 | [evn_event_id] [int] IDENTITY(1,1) NOT NULL, 3 | [evn_type_id] [int] NOT NULL, 4 | [evn_event_timestamp] [datetime] NOT NULL, 5 | [evn_event_emailAddress] [nvarchar](320) COLLATE Latin1_General_CI_AS NOT NULL, 6 | [snd_send_id] [nvarchar](20) COLLATE Latin1_General_CI_AS NOT NULL, 7 | [evn_event_forwarded] [bit] NOT NULL 8 | ) ON [PRIMARY] 9 | 10 | GO 11 | 12 | ALTER TABLE [dbo].[man_evn_event] ADD CONSTRAINT [DF_man_evn_event_evn_event_forwarded] DEFAULT ((0)) FOR [evn_event_forwarded] 13 | GO 14 | 15 | ALTER TABLE [dbo].[man_evn_event] ADD CONSTRAINT [PK_man_evn_bounce] PRIMARY KEY CLUSTERED 16 | ( 17 | [evn_event_id] ASC 18 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 19 | GO 20 | 21 | -------------------------------------------------------------------------------- /OpenManta.Web/Models/BounceModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using OpenManta.WebLib.BO; 3 | 4 | namespace WebInterface.Models 5 | { 6 | /// 7 | /// Model for the bounce page. 8 | /// 9 | public class BounceModel 10 | { 11 | /// 12 | /// Holds the bounce info. 13 | /// 14 | public BounceInfo[] BounceInfo { get; set; } 15 | 16 | /// 17 | /// Holds the current page number. 18 | /// 19 | public int CurrentPage { get; set; } 20 | 21 | /// 22 | /// Holds the total pages required to view all bounce info. 23 | /// 24 | public int PageCount { get; set; } 25 | 26 | /// 27 | /// Holds the deferred attempts count. 28 | /// 29 | public long DeferredCount { get; set; } 30 | 31 | /// 32 | /// Holds the rejected attepts count. 33 | /// 34 | public long RejectedCount { get; set; } 35 | } 36 | } -------------------------------------------------------------------------------- /OpenManta.Core/TransactionStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Specifies the status of a Transaction. 7 | /// 8 | public enum TransactionStatus : int 9 | { 10 | /// 11 | /// 12 | /// 13 | Unknown = 0, 14 | /// 15 | /// Message delivery attempted failed. 16 | /// 17 | Deferred = 1, 18 | /// 19 | /// Message has failed and cannot be delivered. 20 | /// 21 | Failed = 2, 22 | /// 23 | /// Message was in the queue for to long and has timed out. 24 | /// 25 | TimedOut = 3, 26 | /// 27 | /// Message was successfully devlivered. 28 | /// 29 | Success = 4, 30 | /// 31 | /// Message was throttled. 32 | /// 33 | Throttled = 5, 34 | /// 35 | /// Message was discarded in queue. 36 | /// 37 | Discarded = 6 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /OpenManta.Core/OutboundMxPattern.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Holds an outbound MX pattern, this is used to match against 7 | /// an MX servers host name in it's MX record. 8 | /// 9 | public class OutboundMxPattern : NamedEntity 10 | { 11 | /// 12 | /// The type of this pattern. 13 | /// 14 | public OutboundMxPatternType Type { get; set; } 15 | 16 | /// 17 | /// The value to use for matching the MX Record hostname. 18 | /// 19 | public string Value { get; set; } 20 | 21 | /// 22 | /// If has value, only apply this pattern against sending from 23 | /// specified IP address. 24 | /// 25 | public int? LimitedToOutboundIpAddressID { get; set; } 26 | 27 | public OutboundMxPattern() 28 | { 29 | // Default to Regex match all. 30 | this.Type = OutboundMxPatternType.Regex; 31 | this.Value = "."; 32 | } 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /OpenManta.Web/Content/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Archivo Narrow'; 3 | font-style: normal; 4 | font-weight: 400; 5 | src: local('Archivo Narrow Regular'), local('ArchivoNarrow-Regular'), url(/content/fonts/ArchivoNarrow-Regular.ttf) format('woff'); 6 | } 7 | @font-face { 8 | font-family: 'Archivo Narrow'; 9 | font-style: normal; 10 | font-weight: 700; 11 | src: local('Archivo Narrow Bold'), local('ArchivoNarrow-Bold'), url(/content/fonts/ArchivoNarrow-Bold.ttf) format('woff'); 12 | } 13 | @font-face { 14 | font-family: 'Archivo Narrow'; 15 | font-style: italic; 16 | font-weight: 400; 17 | src: local('Archivo Narrow Italic'), local('ArchivoNarrow-Italic'), url(/content/fonts/ArchivoNarrow-Italic.ttf) format('woff'); 18 | } 19 | @font-face { 20 | font-family: 'Archivo Narrow'; 21 | font-style: italic; 22 | font-weight: 700; 23 | src: local('Archivo Narrow Bold Italic'), local('ArchivoNarrow-BoldItalic'), url(/content/fonts/ArchivoNarrow-BoldItalic.ttf) format('woff'); 24 | } -------------------------------------------------------------------------------- /OpenManta.Data/FeedbackLoopEmailAddressDB.cs: -------------------------------------------------------------------------------- 1 | using System.Data.SqlClient; 2 | 3 | namespace OpenManta.Data 4 | { 5 | public static class FeedbackLoopEmailAddressDB 6 | { 7 | /// 8 | /// Checks an address to see if it appears in the list of feedback loop addresses. 9 | /// 10 | /// Address to check. 11 | /// TRUE if exists, FALSE if not. 12 | public static bool IsFeedbackLoopEmailAddress(string address) 13 | { 14 | using (SqlConnection conn = MantaDB.GetSqlConnection()) 15 | { 16 | SqlCommand cmd = conn.CreateCommand(); 17 | cmd.CommandText = @" 18 | SELECT 1 19 | FROM man_mta_fblAddress 20 | WHERE mta_fblAddress_address = @address"; 21 | cmd.Parameters.AddWithValue("@address", address); 22 | conn.Open(); 23 | object result = cmd.ExecuteScalar(); 24 | if (result == null) 25 | return false; 26 | 27 | return true; 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /OpenManta.Framework/Log4net.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /OpenManta.Web/Controllers/BouncesController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using WebInterface.Models; 7 | using OpenManta.WebLib.DAL; 8 | 9 | namespace WebInterface.Controllers 10 | { 11 | public class BouncesController : Controller 12 | { 13 | // 14 | // GET: /Bounces/ 15 | public ActionResult Index(int? page = 1, int? pageSize = 25) 16 | { 17 | long deferred, rejected = 0; 18 | TransactionDB.GetBounceDeferredAndRejected(out deferred, out rejected); 19 | return View(new BounceModel 20 | { 21 | BounceInfo =TransactionDB.GetBounceInfo(null, page.Value, pageSize.Value), 22 | CurrentPage = page.Value, 23 | PageCount = (int)Math.Ceiling(Convert.ToDouble(TransactionDB.GetBounceCount(null)) / pageSize.Value), 24 | DeferredCount = deferred, 25 | RejectedCount = rejected 26 | }); 27 | } 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Database/SQL Scripts/select bounceRules.sql: -------------------------------------------------------------------------------- 1 | /********************************************** 2 | MANTA - Select info about Bounce Rules 3 | ***********************************************/ 4 | 5 | select 6 | rle.evn_bounceRule_id, 7 | rle.evn_bounceRule_name, 8 | rle.evn_bounceRule_executionOrder, 9 | rct.evn_bounceRuleCriteriaType_name, 10 | rle.evn_bounceRule_criteria, 11 | CONVERT(NVARCHAR, rle.evn_bounceRule_mantaBounceType) + ') ' + bnt.evn_bounceType_name, 12 | CONVERT(NVARCHAR, rle.evn_bounceRule_mantaBounceCode) + ') ' + bnc.evn_bounceCode_name 13 | from 14 | man_evn_bounceRule as rle 15 | left join man_evn_bounceRuleCriteriaType as rct 16 | on rle.evn_bounceRuleCriteriaType_id = rct.evn_bounceRuleCriteriaType_id 17 | left join man_evn_bounceType as bnt 18 | on rle.evn_bounceRule_mantaBounceType = bnt.evn_bounceType_id 19 | left join man_evn_bounceCode as bnc 20 | on rle.evn_bounceRule_mantaBounceCode = bnc.evn_bounceCode_id 21 | order by 22 | rle.evn_bounceRule_executionOrder -------------------------------------------------------------------------------- /OpenManta.Core/MantaEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// An Event from Manta indicating an issue sending an email. Could be a bounce or an abuse complaint. 7 | /// 8 | public class MantaEvent : BaseEntity 9 | { 10 | /// 11 | /// The type of event that this is. 12 | /// 13 | public MantaEventType EventType { get; set; } 14 | 15 | /// 16 | /// The email address that this message was sent to. 17 | /// 18 | public string EmailAddress { get; set; } 19 | 20 | /// 21 | /// The identifier for the send. 22 | /// 23 | public string SendID { get; set; } 24 | 25 | /// 26 | /// The date and time the event was recorded. 27 | /// 28 | public DateTime EventTime { get; set; } 29 | 30 | /// 31 | /// Will be set to true when event has been forwarded. 32 | /// 33 | public bool Forwarded { get; set; } 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /OpenManta.Core/BounceRulesCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace OpenManta.Core 5 | { 6 | /// 7 | /// Holds a collection of BounceRule objects. 8 | /// 9 | public class BounceRulesCollection : List 10 | { 11 | /// 12 | /// When the BounceRules were last loaded into this collection. 13 | /// If this is "too old", the collection will reload them to ensure configuration changes are used. 14 | /// 15 | public DateTime LoadedTimestampUtc { get; set; } 16 | 17 | /// 18 | /// Standard constructor for a BounceRulesCollection. 19 | /// 20 | public BounceRulesCollection() : base() { } 21 | 22 | /// 23 | /// Allows copying of a BounceRulesCollection or the creation of one from a collection of Rules, 24 | /// e.g. a List<BounceRule>. 25 | /// 26 | /// 27 | public BounceRulesCollection(IEnumerable collection) : base(collection) { } 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /OpenManta.Service/OpenMantaService.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace OpenManta.Service 2 | { 3 | partial class OpenMantaService 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | // 32 | // MantaMTA 33 | // 34 | this.ServiceName = "M"; 35 | 36 | } 37 | 38 | #endregion 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /OpenManta.Service/OpenMantaServiceInstaller.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Configuration.Install; 3 | using System.ServiceProcess; 4 | 5 | namespace OpenManta.Service 6 | { 7 | [RunInstaller(true)] 8 | public class OpenMantaServiceInstaller : Installer 9 | { 10 | /// 11 | /// Public Constructor for WindowsServiceInstaller. 12 | /// - Put all of your Initialization code here. 13 | /// 14 | public OpenMantaServiceInstaller() 15 | { 16 | this.Installers.Add(new ServiceProcessInstaller 17 | { 18 | Account = ServiceAccount.LocalService, 19 | Username = null, 20 | Password = null 21 | }); 22 | this.Installers.Add(new ServiceInstaller { 23 | ServiceName = "OpenManta", 24 | Description = "The OpenManta mail transfer agent", 25 | DisplayName = "OpenManta", 26 | StartType = ServiceStartMode.Automatic 27 | }); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /OpenManta.Web/Models/OutboundRules.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using OpenManta.Core; 3 | 4 | namespace WebInterface.Models 5 | { 6 | /// 7 | /// Holds the Model for the Outbound Rules page. 8 | /// 9 | public class OutboundRuleModel 10 | { 11 | /// 12 | /// Collection of the Outbound Rules 13 | /// 14 | public IList OutboundRules { get; set; } 15 | 16 | /// 17 | /// The MX pattern that the rules relate to. 18 | /// 19 | public OutboundMxPattern Pattern { get; set; } 20 | 21 | /// 22 | /// Holds a list of all the outbound Virtual MTAs. 23 | /// 24 | public IList VirtualMtaCollection { get; set; } 25 | 26 | public OutboundRuleModel( IList outboundRuleCollection, OutboundMxPattern pattern, IList virtualMtaCollection) 27 | { 28 | OutboundRules = outboundRuleCollection; 29 | Pattern = pattern; 30 | VirtualMtaCollection = virtualMtaCollection; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /OpenManta.Framework/Smtp/MantaOutboundClientResult.cs: -------------------------------------------------------------------------------- 1 | using OpenManta.Core; 2 | 3 | namespace OpenManta.Framework.Smtp 4 | { 5 | public enum MantaOutboundClientResult : int 6 | { 7 | MaxConnections = -3, 8 | MaxMessages = -2, 9 | ClientAlreadyInUse = -1, 10 | Success = 0, 11 | FailedToConnect = 1, 12 | ServiceNotAvalible = 2, 13 | RejectedByRemoteServer = 3 14 | } 15 | 16 | public class MantaOutboundClientSendResult 17 | { 18 | public MantaOutboundClientResult MantaOutboundClientResult { get; set; } 19 | public string Message { get; set; } 20 | public VirtualMTA VirtualMTA { get; set; } 21 | public MXRecord MXRecord { get; set; } 22 | 23 | public MantaOutboundClientSendResult(MantaOutboundClientResult result, string message, VirtualMTA vmta = null, MXRecord mx = null) 24 | { 25 | MantaOutboundClientResult = result; 26 | Message = message; 27 | VirtualMTA = vmta; 28 | MXRecord = mx; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /OpenManta.Data/MtaMessageDB.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace OpenManta.Data 5 | { 6 | public static class MtaMessageDB 7 | { 8 | /// 9 | /// Delimiter user for RCPT addresses. 10 | /// 11 | private const string _RcptToDelimiter = ","; 12 | 13 | public static async Task GetMailFrom(Guid messageId) 14 | { 15 | using (var conn = MantaDB.GetSqlConnection()) 16 | { 17 | var cmd = conn.CreateCommand(); 18 | cmd.CommandText = @"SELECT TOP 1 mta_msg_mailFrom 19 | FROM man_mta_msg 20 | WHERE mta_msg_id = @msgId"; 21 | cmd.Parameters.AddWithValue("@msgId", messageId); 22 | await conn.OpenAsync().ConfigureAwait(false); 23 | var result = await cmd.ExecuteScalarAsync().ConfigureAwait(false); 24 | if (result == null) 25 | return string.Empty; 26 | return result.ToString(); 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /OpenManta.Web/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Optimization; 2 | 3 | namespace WebInterface 4 | { 5 | public class BundleConfig 6 | { 7 | public static void RegisterBundles(BundleCollection bundles) 8 | { 9 | BundleTable.EnableOptimizations = false; 10 | 11 | // Scripts 12 | bundles.Add(new ScriptBundle("~/resources/js/jquery").Include("~/bower_components/jquery/jquery.js")); 13 | bundles.Add(new ScriptBundle("~/resources/js/bootstrap").Include("~/bower_components/bootstrap/docs/assets/js/bootstrap.js")); 14 | bundles.Add(new ScriptBundle("~/resources/js/jqplot").Include("~/bower_components/gbelmm-jqplot/src/core/jquery.jqplot.js")); 15 | 16 | 17 | // Styles 18 | bundles.Add (new StyleBundle ("~/resources/css/bootstrap").Include ("~/bower_components/bootstrap/docs/assets/css/bootstrap.css", 19 | "~/bower_components/bootstrap/docs/assets/css/bootstrap-responsive.css", 20 | "~/Content/app.css", 21 | "~/Content/fonts.css")); 22 | bundles.Add(new ScriptBundle("~/resources/css/jqplot").Include("~/bower_components/gbelmm-jqplot/src/core/jquery.jqplot.css")); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /OpenManta.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle ("manta.Core")] 8 | [assembly: AssemblyDescription ("")] 9 | [assembly: AssemblyConfiguration ("")] 10 | [assembly: AssemblyCompany ("")] 11 | [assembly: AssemblyProduct ("")] 12 | [assembly: AssemblyCopyright ("dan")] 13 | [assembly: AssemblyTrademark ("")] 14 | [assembly: AssemblyCulture ("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion ("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | 28 | -------------------------------------------------------------------------------- /OpenManta.Data/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle ("Manta.Data")] 8 | [assembly: AssemblyDescription ("")] 9 | [assembly: AssemblyConfiguration ("")] 10 | [assembly: AssemblyCompany ("")] 11 | [assembly: AssemblyProduct ("")] 12 | [assembly: AssemblyCopyright ("dan")] 13 | [assembly: AssemblyTrademark ("")] 14 | [assembly: AssemblyCulture ("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion ("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | 28 | -------------------------------------------------------------------------------- /OpenManta.Web/Properties/PublishProfiles/MantaMTA.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | FileSystem 9 | Release 10 | Any CPU 11 | 12 | True 13 | True 14 | True 15 | False 16 | DonotMerge 17 | False 18 | c:\temp\mantamta 19 | True 20 | 21 | -------------------------------------------------------------------------------- /OpenManta.Framework/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle ("Manta.Framework")] 8 | [assembly: AssemblyDescription ("")] 9 | [assembly: AssemblyConfiguration ("")] 10 | [assembly: AssemblyCompany ("")] 11 | [assembly: AssemblyProduct ("")] 12 | [assembly: AssemblyCopyright ("dan")] 13 | [assembly: AssemblyTrademark ("")] 14 | [assembly: AssemblyCulture ("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion ("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | 28 | // Log4net config file location 29 | [assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4net.config", Watch = true)] 30 | -------------------------------------------------------------------------------- /OpenManta.Core/MantaEventType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// This identifies the type of an event. 7 | /// 8 | public enum MantaEventType : int 9 | { 10 | /// 11 | /// Event of a Type unknown 12 | /// 13 | Unknown = 0, 14 | /// 15 | /// Event occurs when delivery of a message is unsuccessful. 16 | /// 17 | Bounce = 1, 18 | /// 19 | /// This event occurs so that you can remove the address that generated the complaint from your database or 20 | /// stop sending to it. You can also use this event to maintain statistical information on the number of spam 21 | /// complaints created by each campaign. Continuing to send to an address that has complained about spam can 22 | /// have a negative effect on your deliverability. 23 | /// 24 | Abuse = 3, 25 | /// 26 | /// Event occurs when a message has been in Manta's outbound queue over the value 27 | /// without it being successfully accepted by a remote MTA. Manta stops attempting to send it and creates a TimedOutInQueue Event. 28 | /// 29 | TimedOutInQueue = 4 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_mta_msg.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_mta_msg]( 2 | [mta_msg_id] [uniqueidentifier] NOT NULL, 3 | [mta_send_internalId] [int] NOT NULL, 4 | [mta_msg_rcptTo] [nvarchar](max) COLLATE Latin1_General_CI_AS NOT NULL, 5 | [mta_msg_mailFrom] [nvarchar](max) COLLATE Latin1_General_CI_AS NOT NULL 6 | ) ON [PRIMARY] 7 | 8 | GO 9 | 10 | CREATE UNIQUE CLUSTERED INDEX [mta_msg_id] ON [dbo].[man_mta_msg] 11 | ( 12 | [mta_msg_id] ASC 13 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 14 | GO 15 | 16 | ALTER TABLE [dbo].[man_mta_msg] ADD CONSTRAINT [PK_man_mta_msg] PRIMARY KEY NONCLUSTERED 17 | ( 18 | [mta_msg_id] ASC 19 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 20 | GO 21 | 22 | CREATE NONCLUSTERED INDEX [SendInternalID] ON [dbo].[man_mta_msg] 23 | ( 24 | [mta_send_internalId] ASC 25 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 26 | GO 27 | 28 | -------------------------------------------------------------------------------- /OpenManta.Web/Views/ServerStatus/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Server Status"; 3 | Layout = "~/Views/_Layout.cshtml"; 4 | } 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
NameDirectoryFilesUsed SpaceAvailable Space
Drop@Model.DropDir.Path@Model.DropDir.FileCount.ToString("N0")@Model.DropDir.UsedSpace@Model.DropDir.FreeSpace
Logs@Model.LogDir.Path@Model.LogDir.FileCount.ToString("N0")@Model.LogDir.UsedSpace@Model.LogDir.FreeSpace
Queue@Model.QueueDir.Path@Model.QueueDir.FileCount.ToString("N0")@Model.QueueDir.UsedSpace@Model.QueueDir.FreeSpace
44 | 45 |

Manta Reset Scheduled Task Log Tail.

46 | -------------------------------------------------------------------------------- /OpenManta.Core/MantaBounceType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Identifies the type of bounce. 7 | /// 8 | public enum MantaBounceType : int 9 | { 10 | /// 11 | /// Default value. 12 | /// 13 | Unknown = 0, 14 | /// 15 | /// A hard bounce is where the ISP is explicitly saying that this email address is not valid. 16 | /// Typically this is a "user does not exist" error message. 17 | /// 18 | Hard = 1, 19 | /// 20 | /// A soft bounce is an error condition, which if it continues, the email address should be considered 21 | /// invalid. An example is a "DNS Failure" (MantaBounceCode 21) bounce message. This can happen because the domain 22 | /// name no longer exists, or this could happen because the DNS registration expired and will be renewed 23 | /// tomorrow, or there was a temporary DNS lookup error. If the "DNS failure" messages persist, then we 24 | /// know the address is bad. 25 | /// 26 | Soft = 2, 27 | /// 28 | /// The email was rejected as spam. Instead of removing the email addresses from your list, you would 29 | /// want to solve whatever caused the blocking and restore delivery to these addresses. 30 | /// 31 | Spam = 3 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /OpenManta.Web/WebInterface.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MantaMTA 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | SpecificPage 13 | True 14 | False 15 | False 16 | False 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | False 26 | True 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /OpenManta.Framework/BounceRulesManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using OpenManta.Core; 4 | using OpenManta.Data; 5 | 6 | namespace OpenManta.Framework 7 | { 8 | internal partial class BounceRulesManager 9 | { 10 | /// 11 | /// Holds a singleton instance of the BounceRulesManager. 12 | /// 13 | public static BounceRulesManager Instance { get { return _Instance; } } 14 | private static readonly BounceRulesManager _Instance = new BounceRulesManager(); 15 | private BounceRulesManager() { } 16 | 17 | private static BounceRulesCollection _bounceRules = null; 18 | public static BounceRulesCollection BounceRules 19 | { 20 | get 21 | { 22 | if (_bounceRules == null || _bounceRules.LoadedTimestampUtc.AddMinutes(5) < DateTime.UtcNow) 23 | { 24 | // Would be nice to write to a log that we're updating. 25 | _bounceRules = EventDB.GetBounceRules(); 26 | 27 | // Ensure the Rules are in the correct order. 28 | _bounceRules = new BounceRulesCollection(_bounceRules.OrderBy(r => r.ExecutionOrder)); 29 | 30 | // Only set the LoadedTimestamp value after we're done assigning new values to _bounceRules. 31 | _bounceRules.LoadedTimestampUtc = DateTime.UtcNow; 32 | } 33 | 34 | return _bounceRules; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /OpenManta.Web/Controllers/SettingsController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using OpenManta.Data; 7 | using WebInterface.Models; 8 | 9 | namespace WebInterface.Controllers 10 | { 11 | public class SettingsController : Controller 12 | { 13 | // 14 | // GET: /Settings/ 15 | public ActionResult Index() 16 | { 17 | return View(new SettingsModel 18 | { 19 | ClientIdleTimeout = CfgPara.GetClientIdleTimeout(), 20 | DaysToKeepSmtpLogsFor = CfgPara.GetDaysToKeepSmtpLogsFor(), 21 | DefaultVirtualMtaGroupID = CfgPara.GetDefaultVirtualMtaGroupID(), 22 | VirtualMtaGroupCollection = VirtualMtaGroupDB.GetVirtualMtaGroups(), 23 | EventForwardingUrl = CfgPara.GetEventForwardingHttpPostUrl(), 24 | LocalDomains = CfgLocalDomains.GetLocalDomainsArray(), 25 | MaxTimeInQueue = CfgPara.GetMaxTimeInQueueMinutes(), 26 | ReceiveTimeout = CfgPara.GetReceiveTimeout(), 27 | RelayingPermittedIPs = CfgRelayingPermittedIP.GetRelayingPermittedIPAddresses(), 28 | RetryInterval = CfgPara.GetRetryIntervalBaseMinutes(), 29 | ReturnPathDomain = CfgPara.GetReturnPathDomain(), 30 | SendTimeout = CfgPara.GetSendTimeout() 31 | }); 32 | } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_ip_ipAddress.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_ip_ipAddress]( 2 | [ip_ipAddress_id] [int] IDENTITY(1,1) NOT NULL, 3 | [ip_ipAddress_ipAddress] [varchar](45) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [ip_ipAddress_hostname] [varchar](255) COLLATE Latin1_General_CI_AS NULL, 5 | [ip_ipAddress_isInbound] [bit] NULL, 6 | [ip_ipAddress_isOutbound] [bit] NULL, 7 | CONSTRAINT [UK_c101_ip_ipAddress_ipAddress] UNIQUE NONCLUSTERED 8 | ( 9 | [ip_ipAddress_ipAddress] ASC 10 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 11 | ) ON [PRIMARY] 12 | 13 | GO 14 | 15 | ALTER TABLE [dbo].[man_ip_ipAddress] ADD CONSTRAINT [PK_man_ip_ipAddress_id] PRIMARY KEY CLUSTERED 16 | ( 17 | [ip_ipAddress_id] ASC 18 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 19 | GO 20 | 21 | ALTER TABLE [dbo].[man_ip_ipAddress] ADD CONSTRAINT [UK_c101_ip_ipAddress_ipAddress] UNIQUE NONCLUSTERED 22 | ( 23 | [ip_ipAddress_ipAddress] ASC 24 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 25 | GO 26 | 27 | -------------------------------------------------------------------------------- /OpenManta.Web/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /OpenManta.Web/Views/Sends/VirtualMTA.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = Model.SendID + " > Virtual MTA"; 3 | Layout = "~/Views/Sends/_ReportLayout.cshtml"; 4 | } 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | @foreach (OpenManta.WebLib.BO.VirtualMtaSendInfo vmta in Model.VirtualMtaSendInfo) 20 | { 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | } 31 | 32 |
VirtualMTAAcceptedAccepted %RejectedRejected %Throttled %Deferred %
@vmta.Hostname
@vmta.IPAddress
@vmta.Accepted.ToString("N0")@vmta.AcceptedPercent.ToString("N2")%@vmta.Rejected.ToString("N0")@vmta.RejectedPercent.ToString("N2")%@vmta.ThrottledPercent.ToString("N2")%@vmta.DeferredPercent.ToString("N2")%
-------------------------------------------------------------------------------- /OpenManta.Web/Views/Sends/Overview.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = Model.SendID + " > Overview"; 3 | Layout = "~/Views/Sends/_ReportLayout.cshtml"; 4 | } 5 | 6 |
7 |
8 |
9 |
Total Emails
10 |

@Model.SendInfo.TotalMessages.ToString("N0")

11 |
12 |
13 |
14 |
15 |
Accepted
16 |

@Model.SendInfo.Accepted.ToString("N0")

17 |
18 |
19 |
20 |
21 |
Rejected
22 |

@Model.SendInfo.Rejected.ToString("N0")

23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
Currently Waiting
31 |

@Model.SendInfo.Waiting.ToString("N0")

32 |
33 |
34 |
35 |
36 |
Throttled
37 |

@Model.SendInfo.ThrottledPercent.ToString("N2")%

38 |
39 |
40 |
41 |
42 |
Deferred
43 |

@Model.SendInfo.DeferredPercent.ToString("N2")%

44 |
45 |
46 |
-------------------------------------------------------------------------------- /OpenManta.Core/MXRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | public class MXRecord 6 | { 7 | /// 8 | /// The hostname or IP address of a MX 9 | /// 10 | public string Host { get; set; } 11 | 12 | /// 13 | /// The preference of the MX 14 | /// 15 | public int Preference { get; set; } 16 | 17 | /// 18 | /// The TTL seconds 19 | /// 20 | private uint TTL { get; set; } 21 | 22 | /// 23 | /// The date/time that this record was got. 24 | /// 25 | private DateTime LookupTimestamp { get; set; } 26 | 27 | /// 28 | /// Return true if Time To Live has passed. RIP. 29 | /// 30 | public bool Dead 31 | { 32 | get 33 | { 34 | // If the TTL added to the lookup date is over specified date time then return true. 35 | return (LookupTimestamp.AddSeconds(this.TTL) < DateTime.UtcNow); 36 | } 37 | } 38 | 39 | /// 40 | /// Identifies the source of an MX record. 41 | /// 42 | public MxRecordSrc MxRecordSrc { get; set; } 43 | 44 | public MXRecord(string host, int preference, uint ttl, MxRecordSrc mxRecordSrc) 45 | { 46 | this.Host = host; 47 | this.Preference = preference; 48 | this.TTL = ttl; 49 | this.LookupTimestamp = DateTime.UtcNow; 50 | this.MxRecordSrc = mxRecordSrc; 51 | } 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /OpenManta.Web/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /OpenManta.Web/Views/Sends/Deferred.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = Model.SendID + " > Deferrals"; 3 | Layout = "~/Views/Sends/_ReportLayout.cshtml"; 4 | } 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | @foreach (OpenManta.WebLib.BO.BounceInfo bounce in ((OpenManta.WebLib.BO.BounceInfo[])Model.BounceInfo).OrderByDescending(b=>b.LastOccurred).ThenByDescending(b=>b.Count)) 19 | { 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | } 28 | 29 |
VirtualMTARemoteResponseCountLast Occurred
@bounce.LocalHostname
@bounce.LocalIpAddress
@bounce.RemoteHostname@bounce.Message@bounce.Count.ToString("N0")@bounce.LastOccurred
30 | 31 | 46 | -------------------------------------------------------------------------------- /OpenManta.WebLib/BO/SendWaitingInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace OpenManta.WebLib.BO 5 | { 6 | /// 7 | /// Holds a next attempt number and how many messages are currently waiting for sending. 8 | /// 9 | public class SendWaitingInfo 10 | { 11 | /// 12 | /// The next attempt number. 13 | /// 14 | public int AttemptNumber { get; set; } 15 | 16 | /// 17 | /// The number of Emails waiting to make there next attempt. 18 | /// 19 | public int EmailsWaiting { get; set; } 20 | } 21 | 22 | /// 23 | /// Holds a collection of SendWaitingInfo. 24 | /// 25 | public class SendWaitingInfoCollection : List 26 | { 27 | public SendWaitingInfoCollection() { } 28 | public SendWaitingInfoCollection(IEnumerable collection) : base(collection) { } 29 | } 30 | 31 | public class SendWaitingByDomainItem 32 | { 33 | public string Domain { get; set; } 34 | public int Waiting { get; set; } 35 | public DateTime NextAttempt { get; set; } 36 | } 37 | 38 | public class SendWaitingByDomainCollection : List 39 | { 40 | public SendWaitingByDomainCollection() { } 41 | public SendWaitingByDomainCollection(IEnumerable collection) : base(collection) { } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /OpenManta.WebLib/BO/BounceInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenManta.Core; 7 | 8 | namespace OpenManta.WebLib.BO 9 | { 10 | /// 11 | /// Holds information about a bounce. 12 | /// 13 | public class BounceInfo 14 | { 15 | /// 16 | /// The TransactionStatus that the bounce relates to. 17 | /// 18 | public TransactionStatus TransactionStatus { get; set; } 19 | /// 20 | /// The bounce message. 21 | /// 22 | public string Message { get; set; } 23 | /// 24 | /// The remote MX hostname or IP if no hostname. 25 | /// 26 | public string RemoteHostname { get; set; } 27 | /// 28 | /// The hostname of the IP address that the bounce relates to. 29 | /// 30 | public string LocalHostname { get; set; } 31 | /// 32 | /// The IP Address that the bounce relates to. 33 | /// 34 | public string LocalIpAddress { get; set; } 35 | /// 36 | /// The amount of times that this bounce has happened. 37 | /// 38 | public long Count { get; set; } 39 | /// 40 | /// Timestamp of the time this bounce last happened. 41 | /// 42 | public DateTime LastOccurred { get; set; } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /OpenManta.Core/MtaMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace OpenManta.Core 5 | { 6 | /// 7 | /// Represents an Inbound Email that is going to be queued for relaying, but has not yet been. 8 | /// 9 | public class MtaMessage : BaseEntity 10 | { 11 | /// 12 | /// ID of the RabbitMQ delivery that this message represents. 13 | /// 14 | public ulong RabbitMqDeliveryTag { get; set; } 15 | 16 | /// 17 | /// Priority of this message in RabbitMQ. 18 | /// 19 | public RabbitMqPriority RabbitMqPriority { get; set; } 20 | 21 | /// 22 | /// The VirtualMTA group that the message should be sent through. 23 | /// 24 | public int VirtualMTAGroupID { get; set; } 25 | 26 | /// 27 | /// Internal ID that identifies the Send that this 28 | /// message is part of. 29 | /// 30 | public int InternalSendID { get; set; } 31 | 32 | /// 33 | /// The Mail From to used when sending this message. 34 | /// May be NULL for NullSender 35 | /// 36 | public string MailFrom { get; set; } 37 | 38 | /// 39 | /// Array of Rcpt To's for this message. 40 | /// 41 | public string[] RcptTo { get; set; } 42 | 43 | /// 44 | /// The raw Email itself. 45 | /// 46 | public string Message { get; set; } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_cfg_para.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_cfg_para]( 2 | [cfg_para_dropFolder] [nvarchar](255) COLLATE Latin1_General_CI_AS NOT NULL, 3 | [cfg_para_queueFolder] [nvarchar](255) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [cfg_para_logFolder] [nvarchar](255) COLLATE Latin1_General_CI_AS NOT NULL, 5 | [cfg_para_listenPorts] [nvarchar](255) COLLATE Latin1_General_CI_AS NOT NULL, 6 | [cfg_para_retryIntervalMinutes] [int] NOT NULL, 7 | [cfg_para_maxTimeInQueueMinutes] [int] NOT NULL, 8 | [cfg_para_defaultIpGroupId] [int] NOT NULL, 9 | [cfg_para_clientIdleTimeout] [int] NOT NULL, 10 | [cfg_para_receiveTimeout] [int] NOT NULL, 11 | [cfg_para_sendTimeout] [int] NOT NULL, 12 | [cfg_para_returnPathDomain_id] [int] NOT NULL, 13 | [cfg_para_maxDaysToKeepSmtpLogs] [int] NOT NULL, 14 | [cfg_para_eventForwardingHttpPostUrl] [nvarchar](max) COLLATE Latin1_General_CI_AS NOT NULL, 15 | [cfg_para_keepBounceFilesFlag] [bit] NOT NULL, 16 | [cfg_para_pickupDirectoryEnabled] [bit] NOT NULL, 17 | [cfg_para_pickupDirectory] [nvarchar](max) COLLATE Latin1_General_CI_AS NOT NULL, 18 | [cfg_para_rabbitMqEnabled] [bit] NOT NULL, 19 | [cfg_para_rabbitMqUsername] [nvarchar](max) COLLATE Latin1_General_CI_AS NOT NULL, 20 | [cfg_para_rabbitMqPassword] [nvarchar](max) COLLATE Latin1_General_CI_AS NOT NULL, 21 | [cfg_para_rabbitMqHostname] [nvarchar](max) COLLATE Latin1_General_CI_AS NOT NULL 22 | ) ON [PRIMARY] 23 | 24 | GO 25 | 26 | -------------------------------------------------------------------------------- /OpenManta.Web/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /OpenManta.Core/_ExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Text; 3 | 4 | namespace OpenManta.Core 5 | { 6 | /// 7 | /// Extension methods for the StringReader class. 8 | /// 9 | public static class StringReaderExtensions 10 | { 11 | /// 12 | /// Reads up until a "\r\n" (CRLF), unlike the built-in ReadLine() which considers "\r", "\n", and "\r\n" as marking the end of a line. 13 | /// 14 | /// 15 | public static string ReadToCrLf(this StringReader reader) 16 | { 17 | int c = reader.Read(); 18 | 19 | // Are we at the end of the string? 20 | if (c == -1) 21 | return null; 22 | 23 | 24 | StringBuilder sb = new StringBuilder(); 25 | 26 | // Move through the string one character at a time and checking we haven't reached the end 27 | // as indicated by a "\r\n" (CRLF). 28 | do 29 | { 30 | char ch = (char)c; 31 | 32 | // If the current character is a CR and the next character is an LF then 33 | // we've found the end of the line. 34 | if (ch == '\r' && ((char)reader.Peek() == '\n')) 35 | { 36 | // Advance the cursor to the second part of the CRLF so the next Read() will be 37 | // from after it. 38 | reader.Read(); 39 | 40 | return sb.ToString(); 41 | } 42 | else 43 | { 44 | sb.Append(ch); 45 | } 46 | } while ((c = reader.Read()) != -1); 47 | 48 | 49 | return sb.ToString(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_mta_send.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_mta_send]( 2 | [mta_send_internalId] [int] NOT NULL, 3 | [mta_send_id] [nvarchar](20) COLLATE Latin1_General_CI_AS NOT NULL, 4 | [mta_sendStatus_id] [int] NOT NULL, 5 | [mta_send_createdTimestamp] [datetime] NOT NULL, 6 | [mta_send_messages] [int] NOT NULL, 7 | [mta_send_accepted] [int] NOT NULL, 8 | [mta_send_rejected] [int] NOT NULL 9 | ) ON [PRIMARY] 10 | 11 | GO 12 | 13 | ALTER TABLE [dbo].[man_mta_send] ADD CONSTRAINT [DF_man_mta_send_mta_send_messages] DEFAULT ((0)) FOR [mta_send_messages] 14 | GO 15 | 16 | ALTER TABLE [dbo].[man_mta_send] ADD CONSTRAINT [DF_man_mta_send_mta_send_accepted] DEFAULT ((0)) FOR [mta_send_accepted] 17 | GO 18 | 19 | ALTER TABLE [dbo].[man_mta_send] ADD CONSTRAINT [DF_man_mta_send_mta_send_rejected] DEFAULT ((0)) FOR [mta_send_rejected] 20 | GO 21 | 22 | ALTER TABLE [dbo].[man_mta_send] ADD CONSTRAINT [PK_man_mta_send] PRIMARY KEY CLUSTERED 23 | ( 24 | [mta_send_internalId] ASC 25 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 26 | GO 27 | 28 | CREATE UNIQUE NONCLUSTERED INDEX [SendID] ON [dbo].[man_mta_send] 29 | ( 30 | [mta_send_id] ASC 31 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 32 | GO 33 | 34 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_mta_transaction.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_mta_transaction]( 2 | [mta_msg_id] [uniqueidentifier] NOT NULL, 3 | [ip_ipAddress_id] [int] NULL, 4 | [mta_transaction_timestamp] [datetime] NOT NULL, 5 | [mta_transactionStatus_id] [int] NOT NULL, 6 | [mta_transaction_serverResponse] [nvarchar](max) COLLATE Latin1_General_CI_AS NOT NULL, 7 | [mta_transaction_serverHostname] [nvarchar](max) COLLATE Latin1_General_CI_AS NULL 8 | ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 9 | 10 | GO 11 | 12 | CREATE CLUSTERED INDEX [IX_man_mta_transaction] ON [dbo].[man_mta_transaction] 13 | ( 14 | [mta_msg_id] ASC 15 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 16 | GO 17 | 18 | CREATE NONCLUSTERED INDEX [Status] ON [dbo].[man_mta_transaction] 19 | ( 20 | [mta_msg_id] ASC, 21 | [mta_transactionStatus_id] ASC 22 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 23 | GO 24 | 25 | CREATE NONCLUSTERED INDEX [Timestamp] ON [dbo].[man_mta_transaction] 26 | ( 27 | [mta_transaction_timestamp] ASC 28 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 29 | GO 30 | 31 | -------------------------------------------------------------------------------- /OpenManta.Web/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WebInterface")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WebInterface")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3346e810-ce08-4307-8679-50f362c0768e")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /OpenManta.Core/MessageHeaderCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace OpenManta.Core 6 | { 7 | /// 8 | /// Holds a collection of Email message headers. 9 | /// 10 | public class MessageHeaderCollection : List 11 | { 12 | public MessageHeaderCollection() { } 13 | public MessageHeaderCollection(IEnumerable collection) : base(collection) { } 14 | 15 | 16 | /// 17 | /// Retrieves all MessageHeaders found with the Name provided in . 18 | /// Search is case-insensitive. 19 | /// 20 | /// The Name of the header to find. The case of it is not important. 21 | /// A MessageHeaderCollection of matches, if any. 22 | public MessageHeaderCollection GetAll(string header) 23 | { 24 | return new MessageHeaderCollection(this.Where(h => h.Name.Equals(header, StringComparison.OrdinalIgnoreCase))); 25 | } 26 | 27 | 28 | /// 29 | /// Retrives the first MessageHeader found with the Name provided in . 30 | /// 31 | /// The Name of the header to find. The case of it is not important. 32 | /// A MessageHeader object for the first match, else null if no matches were found. 33 | public MessageHeader GetFirstOrDefault(string header) 34 | { 35 | return this.FirstOrDefault(h => h.Name.Equals(header, StringComparison.OrdinalIgnoreCase)); 36 | } 37 | } 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /OpenManta.Framework/MantaCoreEvents.cs: -------------------------------------------------------------------------------- 1 | using OpenManta.Framework.RabbitMq; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace OpenManta.Framework 6 | { 7 | public static class MantaCoreEvents 8 | { 9 | /// 10 | /// List of all the objects that need to be stopped. 11 | /// 12 | private static List _StopRequiredTasks = new List(); 13 | 14 | /// 15 | /// Registers an instance of a class that implements IStopRequired. 16 | /// 17 | /// Thing that needs to be stopped. 18 | internal static void RegisterStopRequiredInstance(IStopRequired instance) 19 | { 20 | _StopRequiredTasks.Add(instance); 21 | } 22 | 23 | /// 24 | /// This should be called when the MTA is stopping as it will stop stuff that needs stopping. 25 | /// 26 | public static void InvokeMantaCoreStopping() 27 | { 28 | Logging.Debug("InvokeMantaCoreStopping Started."); 29 | 30 | // Loop through the things that need stopping and stop them :) 31 | Parallel.ForEach(_StopRequiredTasks, instance => 32 | { 33 | Logging.Debug("InvokeMantaCoreStopping > " + instance.GetType()); 34 | instance.Stop(); 35 | }); 36 | 37 | // Close the RabbitMQ connection when were done. 38 | RabbitMqManager.LocalhostConnection.Close(); 39 | 40 | Logging.Debug("InvokeMantaCoreStopping Finished."); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /OpenManta.Console/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MTA-Console")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MTA-Console")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3b067fb8-1178-4635-98b2-df1aeb7921ee")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /OpenManta.Web/AppendSendMetadata.ashx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using OpenManta.Core; 6 | using OpenManta.Framework; 7 | using OpenManta.WebLib; 8 | using OpenManta.WebLib.DAL; 9 | using OpenManta.WebLib.BO; 10 | 11 | namespace WebInterface 12 | { 13 | /// 14 | /// Summary description for AppendSendMetadata 15 | /// 16 | public class AppendSendMetadata : IHttpHandler 17 | { 18 | 19 | public void ProcessRequest(HttpContext context) 20 | { 21 | context.Response.ContentType = "text/plain"; 22 | 23 | string[] relayingIPs = MtaParameters.IPsToAllowRelaying; 24 | if(!relayingIPs.Contains(context.Request.UserHostAddress)) 25 | { 26 | context.Response.Write("Forbidden"); 27 | return; 28 | } 29 | 30 | 31 | string sendID = context.Request.QueryString["SendID"]; 32 | string name = context.Request.QueryString["Name"]; 33 | string value = context.Request.QueryString["Value"]; 34 | 35 | if (string.IsNullOrWhiteSpace(sendID) || string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(value)) 36 | { 37 | context.Response.Write("bad"); 38 | return; 39 | } 40 | 41 | Send snd = SendManager.Instance.GetSend(sendID); 42 | SendDB.SaveSendMetadata(snd.InternalID, new SendMetadata { 43 | Name = name, 44 | Value = value 45 | }); 46 | 47 | 48 | context.Response.Write("ok"); 49 | } 50 | 51 | public bool IsReusable 52 | { 53 | get 54 | { 55 | return true; 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /OpenManta.WebLib/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WebInterfaceLib")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WebInterfaceLib")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("90035cfd-0099-4ef7-abfb-0337ce9782a7")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Database/MtaDB/MANTA_MTA/Tables/man_mta_queue.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[man_mta_queue]( 2 | [mta_msg_id] [uniqueidentifier] NOT NULL, 3 | [mta_queue_queuedTimestamp] [datetime] NOT NULL, 4 | [mta_queue_attemptSendAfter] [datetime] NOT NULL, 5 | [mta_queue_isPickupLocked] [bit] NOT NULL, 6 | [mta_queue_dataPath] [nvarchar](max) COLLATE Latin1_General_CI_AS NULL, 7 | [mta_queue_data] [nvarchar](max) COLLATE Latin1_General_CI_AS NULL, 8 | [ip_group_id] [int] NOT NULL, 9 | [mta_send_internalId] [int] NOT NULL 10 | ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 11 | 12 | GO 13 | 14 | CREATE NONCLUSTERED INDEX [AttemptSendAfter] ON [dbo].[man_mta_queue] 15 | ( 16 | [mta_queue_attemptSendAfter] ASC 17 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 18 | GO 19 | 20 | CREATE NONCLUSTERED INDEX [NonClusteredIndex-20141117-122722] ON [dbo].[man_mta_queue] 21 | ( 22 | [mta_queue_attemptSendAfter] ASC, 23 | [mta_queue_isPickupLocked] ASC 24 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 25 | GO 26 | 27 | ALTER TABLE [dbo].[man_mta_queue] ADD CONSTRAINT [PK_man_mta_queue_1] PRIMARY KEY CLUSTERED 28 | ( 29 | [mta_msg_id] ASC 30 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 31 | GO 32 | 33 | -------------------------------------------------------------------------------- /OpenManta.Service/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("OpenManta Service")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("OpenManta Service")] 13 | [assembly: AssemblyCopyright("Copyright © 2013-2016 Colony101 UK Ltd")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e1675b1c-7552-416c-8603-5d6f128fbb25")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("0.1.*")] 36 | [assembly: AssemblyFileVersion("0.1.0.0")] 37 | -------------------------------------------------------------------------------- /OpenManta.WebLib/DAL/VirtualMtaTransactionDB.cs: -------------------------------------------------------------------------------- 1 | using System.Data.SqlClient; 2 | using OpenManta.Core; 3 | using OpenManta.WebLib.BO; 4 | using OpenManta.Data; 5 | 6 | namespace OpenManta.WebLib.DAL 7 | { 8 | public static class VirtualMtaTransactionDB 9 | { 10 | /// 11 | /// Gets a summary of a virtual MTAs transaction history. 12 | /// 13 | /// 14 | /// 15 | public static SendTransactionSummaryCollection GetSendSummaryForIpAddress(int ipAddressId) 16 | { 17 | using (SqlConnection conn = MantaDB.GetSqlConnection()) 18 | { 19 | SqlCommand cmd = conn.CreateCommand(); 20 | cmd.CommandText = @"SELECT mta_transactionStatus_id, COUNT(*) AS 'Count' 21 | FROM man_mta_transaction 22 | WHERE ip_ipAddress_id = @ipAddressId 23 | GROUP BY mta_transactionStatus_id"; 24 | cmd.Parameters.AddWithValue("@ipAddressId", ipAddressId); 25 | return new SendTransactionSummaryCollection(DataRetrieval.GetCollectionFromDatabase(cmd, CreateAndFillSendTransactionSummaryFromRecord)); 26 | } 27 | } 28 | 29 | /// 30 | /// Creates a SendTransactionSummary from the DataRecord. 31 | /// 32 | /// The record of the data. 33 | /// A filled SendTransactionSummary object. 34 | private static SendTransactionSummary CreateAndFillSendTransactionSummaryFromRecord(System.Data.IDataRecord record) 35 | { 36 | return new SendTransactionSummary((TransactionStatus)record.GetInt64("mta_transactionStatus_id"), record.GetInt64("count")); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /OpenManta.Web/Views/Sends/Failed.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = Model.SendID + " > Failed"; 3 | Layout = "~/Views/Sends/_ReportLayout.cshtml"; 4 | } 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | @foreach(OpenManta.WebLib.BO.BounceInfo bounce in Model.BounceInfo) 18 | { 19 | 20 | 21 | @switch (bounce.TransactionStatus) 22 | { 23 | case OpenManta.Core.TransactionStatus.Discarded: 24 | 25 | break; 26 | case OpenManta.Core.TransactionStatus.Failed: 27 | 28 | break; 29 | case OpenManta.Core.TransactionStatus.TimedOut: 30 | 31 | break; 32 | } 33 | 34 | 35 | 36 | 37 | } 38 | 39 |
VirtualMTAStatusRemoteResponseCount
@bounce.LocalHostname
@bounce.LocalIpAddress
DiscardedRejectedTimed Out In Queue@bounce.RemoteHostname@bounce.Message@bounce.Count.ToString("N0")
40 | 41 | -------------------------------------------------------------------------------- /OpenManta.Web/Controllers/RabbitMQController.cs: -------------------------------------------------------------------------------- 1 | using OpenManta.Core; 2 | using OpenManta.Framework; 3 | using Newtonsoft.Json.Linq; 4 | using System.IO; 5 | using System.Net; 6 | using System.Web.Mvc; 7 | using System.Linq; 8 | using System.Collections.Generic; 9 | using WebInterface.Models; 10 | 11 | namespace WebInterface.Controllers 12 | { 13 | public class RabbitMQController : Controller 14 | { 15 | // 16 | // GET: /RabbitMQ/ 17 | public ActionResult Index() 18 | { 19 | RabbitMqQueueModel model = new RabbitMqQueueModel(); 20 | // Connect to Rabbit MQ and grab basic queue counts. 21 | HttpWebRequest request = HttpWebRequest.CreateHttp("http://localhost:15672/api/queues"); 22 | request.Credentials = new NetworkCredential(MtaParameters.RabbitMQ.Username, MtaParameters.RabbitMQ.Password); 23 | using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 24 | { 25 | 26 | string json = new StreamReader(response.GetResponseStream()).ReadToEnd(); 27 | JArray rabbitQueues = JArray.Parse(json); 28 | foreach (JToken q in rabbitQueues.Children()) 29 | { 30 | JEnumerable qProperties = q.Children(); 31 | string queueName = (string)qProperties.First(x => x.Name.Equals("name")).Value; 32 | if (queueName.StartsWith("manta_mta_")) 33 | { 34 | model.Add(new RabbitMqQueue { 35 | Name = queueName, 36 | Messages = (long)qProperties.First(x=>x.Name.Equals("messages")).Value, 37 | State = (string)qProperties.First(x => x.Name.Equals("state")).Value 38 | }); 39 | } 40 | } 41 | } 42 | return View(model); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /OpenManta.Core/VirtualMTA.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Net; 4 | using System.Net.Sockets; 5 | 6 | namespace OpenManta.Core 7 | { 8 | public class VirtualMTA : BaseEntity 9 | { 10 | /// 11 | /// The Hostname of specified for this IP Address. 12 | /// 13 | public string Hostname { get; set; } 14 | 15 | /// 16 | /// The .Net IP Address object for this Virtual MTA. 17 | /// 18 | public IPAddress IPAddress {get;set;} 19 | 20 | /// 21 | /// If true the IP address can be used for receiving. 22 | /// 23 | public bool IsSmtpInbound { get; set; } 24 | 25 | /// 26 | /// If true the IP address can be used for sending. 27 | /// 28 | public bool IsSmtpOutbound { get; set; } 29 | 30 | /// 31 | /// Holds the information regarding how often this IP has been used. 32 | /// This is used for load balancing the IPs in a pool, it is never saved to the database. 33 | /// string = mx record hostname (lowercase). 34 | /// int = count of times used. 35 | /// 36 | internal ConcurrentDictionary SendsCounter = new ConcurrentDictionary(); 37 | 38 | /// 39 | /// Creates a new TcpClient for this Virtual MTA. 40 | /// 41 | /// 42 | /// 43 | public TcpClient CreateTcpClient(int port) 44 | { 45 | return new TcpClient(new IPEndPoint(this.IPAddress, port)); 46 | } 47 | 48 | /// 49 | /// Constructor sets defaults. 50 | /// 51 | public VirtualMTA() 52 | { 53 | this.IsSmtpInbound = true; 54 | this.IsSmtpOutbound = true; 55 | } 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /OpenManta.Core/MtaQueuedMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace OpenManta.Core 5 | { 6 | /// 7 | /// Holds a QUEUED MtaMesage 8 | /// 9 | public class MtaQueuedMessage : MtaMessage 10 | { 11 | /// 12 | /// Timestamp of the earliest the first/next attempt to send the message should be made. 13 | /// 14 | public DateTime AttemptSendAfterUtc { get; set; } 15 | 16 | /// 17 | /// Number of times that this message has been queued. 18 | /// 19 | public int DeferredCount { get; set; } 20 | 21 | /// 22 | /// 23 | /// 24 | public bool IsHandled { get; set; } 25 | 26 | /// 27 | /// Timestamp of when the message was originally queued. 28 | /// 29 | public DateTime QueuedTimestampUtc { get; set; } 30 | 31 | /// 32 | /// Create a new MtaOutboundMessage from the InboundMessage. 33 | /// 34 | /// Inbound message to create this outbound message from. 35 | /// The outbound message. 36 | public static MtaQueuedMessage CreateNew(MtaMessage inbound) 37 | { 38 | return new MtaQueuedMessage 39 | { 40 | DeferredCount = 0, 41 | InternalSendID = inbound.InternalSendID, 42 | MailFrom = inbound.MailFrom, 43 | Message = inbound.Message, 44 | ID = inbound.ID, 45 | AttemptSendAfterUtc = DateTime.UtcNow, 46 | QueuedTimestampUtc = DateTime.UtcNow, 47 | RcptTo = inbound.RcptTo, 48 | VirtualMTAGroupID = inbound.VirtualMTAGroupID, 49 | IsHandled = false, 50 | RabbitMqPriority = inbound.RabbitMqPriority 51 | }; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /OpenManta.Web/Controllers/OutboundRulesController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using WebInterface.Models; 7 | using OpenManta.Core; 8 | using OpenManta.Data; 9 | using OpenManta.Framework; 10 | using OpenManta.WebLib; 11 | 12 | namespace WebInterface.Controllers 13 | { 14 | public class OutboundRulesController : Controller 15 | { 16 | // 17 | // GET: /OutboundRules/ 18 | public ActionResult Index() 19 | { 20 | return View(OutboundRuleDB.GetOutboundRulePatterns()); 21 | } 22 | 23 | // 24 | // GET: /OutboundRules/Edit?id= 25 | public ActionResult Edit(int id = WebInterfaceParameters.OUTBOUND_RULES_NEW_PATTERN_ID) 26 | { 27 | OutboundMxPattern pattern = null; 28 | IList rules = null; 29 | 30 | if (id != WebInterfaceParameters.OUTBOUND_RULES_NEW_PATTERN_ID) 31 | { 32 | pattern = OutboundRuleDB.GetOutboundRulePatterns().Single(p => p.ID == id); 33 | rules = OutboundRuleDB.GetOutboundRules().Where(r => r.OutboundMxPatternID == id).ToList(); 34 | } 35 | else 36 | { 37 | pattern = new OutboundMxPattern(); 38 | rules = OutboundRuleDB.GetOutboundRules ().Where (r => r.OutboundMxPatternID == MtaParameters.OUTBOUND_RULES_DEFAULT_PATTERN_ID).ToList (); 39 | } 40 | 41 | 42 | IList vMtas = VirtualMtaDB.GetVirtualMtas(); 43 | return View(new OutboundRuleModel(rules, pattern, vMtas)); 44 | } 45 | 46 | // 47 | // GET: /OutboundRules/Delete?patternID= 48 | public ActionResult Delete(int patternID) 49 | { 50 | OutboundRuleWebManager.Delete(patternID); 51 | return View(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /OpenManta.Web/Views/Sends/Bounces.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = Model.SendID + " > Bounces"; 3 | Layout = "~/Views/Sends/_ReportLayout.cshtml"; 4 | } 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | @foreach(OpenManta.WebLib.BO.BounceInfo bounce in Model.BounceInfo) 18 | { 19 | 20 | 21 | @switch (bounce.TransactionStatus) 22 | { 23 | case OpenManta.Core.TransactionStatus.Deferred: 24 | 25 | break; 26 | case OpenManta.Core.TransactionStatus.Discarded: 27 | 28 | break; 29 | case OpenManta.Core.TransactionStatus.Failed: 30 | 31 | break; 32 | case OpenManta.Core.TransactionStatus.TimedOut: 33 | 34 | break; 35 | } 36 | 37 | 38 | 39 | 40 | } 41 | 42 |
VirtualMTAStatusRemoteResponseCount
@bounce.LocalHostname
@bounce.LocalIpAddress
DeferredDiscardedRejectedTimed Out In Queue@bounce.RemoteHostname@bounce.Message@bounce.Count.ToString("N0")
43 | 44 | -------------------------------------------------------------------------------- /OpenManta.WebLib/VirtualMtaWebManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using OpenManta.Data; 3 | using OpenManta.Core; 4 | 5 | namespace OpenManta.WebLib 6 | { 7 | public static class VirtualMtaWebManager 8 | { 9 | /// 10 | /// Get a collection of all of the Virtual MTA Groups. 11 | /// 12 | /// 13 | public static IList GetAllVirtualMtaGroups() 14 | { 15 | IList ipGroups = VirtualMtaGroupDB.GetVirtualMtaGroups(); 16 | 17 | // Get all the groups Virtual MTAs. 18 | foreach (VirtualMtaGroup grp in ipGroups) 19 | { 20 | grp.VirtualMtaCollection = VirtualMtaDB.GetVirtualMtasInVirtualMtaGroup(grp.ID); 21 | } 22 | 23 | return ipGroups; 24 | } 25 | 26 | /// 27 | /// Gets a single Virtual MTA Group. 28 | /// 29 | /// ID of the Virtual MTA Group to get. 30 | /// The Virtual MTA Group or NULL if none exist with ID 31 | public static VirtualMtaGroup GetVirtualMtaGroup(int id) 32 | { 33 | VirtualMtaGroup grp = VirtualMtaGroupDB.GetVirtualMtaGroup(id); 34 | grp.VirtualMtaCollection = VirtualMtaDB.GetVirtualMtasInVirtualMtaGroup(grp.ID); 35 | return grp; 36 | } 37 | 38 | /// 39 | /// Saves the Virtual MTA Group. 40 | /// 41 | /// Virtual MTA Group to save. 42 | public static void Save(VirtualMtaGroup grp) 43 | { 44 | VirtualMtaGroupDB.Save(grp); 45 | } 46 | 47 | /// 48 | /// Deletes a Virtual MTA Group. 49 | /// 50 | /// ID of the group to delete. 51 | public static void DeleteGroup(int id) 52 | { 53 | VirtualMtaGroupDB.Delete(id); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /OpenManta.Core/EmailProcessingResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Indicates the result of processing an email, e.g. it was a bounce and we could identify what type of bounce, or it was a Feedback Abuse email. 7 | /// Also includes some error situations. 8 | /// 9 | public enum EmailProcessingResult 10 | { 11 | /// 12 | /// Used by the EmailProcessingDetails class to indicate when processing of an email hasn't gone far enough for a suitable EmailProcessingResult value to have been set. 13 | /// Some methods use EmailProcessingDetails objects as parameters, but don't set the .ProcessingResult property of them as they're too low level for it to mean anything at the point they run. 14 | /// 15 | NotYetSet = -1, 16 | /// 17 | /// Default value. 18 | /// 19 | Unknown = 0, 20 | /// 21 | /// Email successfully processed - was abuse. 22 | /// 23 | SuccessAbuse = 1, 24 | /// 25 | /// Email successfully processed - was a bounce. 26 | /// 27 | SuccessBounce = 2, 28 | /// 29 | /// Email successfully processed - wasn't an abuse or bounce email; likely to be junk. 30 | /// 31 | SuccessNoAction = 3, 32 | /// 33 | /// Error processing email - problem with content. 34 | /// 35 | ErrorContent = 4, 36 | /// 37 | /// Error processing email - file doesn't exist. 38 | /// 39 | ErrorNoFile = 5, 40 | /// 41 | /// Error processing email - no reason given. 42 | /// 43 | ErrorNoReason = 6, 44 | /// 45 | /// No return path was found as such we identify 46 | /// email address or send. 47 | /// 48 | ErrorNoReturnPath = 7 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /OpenManta.Web/Views/VirtualMta/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = (Model.ID == OpenManta.WebLib.WebInterfaceParameters.VIRTUALMTA_NEW_ID ? "Create" : "Edit") + " Virtual MTA"; 3 | Layout = "~/Views/_Layout.cshtml"; 4 | } 5 | 6 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 49 | 50 | 51 |
IP Address
Hostname
Accept Inbound Email
Send Outbound Email
46 | @(Model.ID == OpenManta.WebLib.WebInterfaceParameters.VIRTUALMTA_NEW_ID ? "Create" : "Update") 47 | Cancel 48 |
52 | -------------------------------------------------------------------------------- /OpenManta.Data/CfgRelayingPermittedIP.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Data.SqlClient; 3 | using System.Net; 4 | 5 | namespace OpenManta.Data 6 | { 7 | public static class CfgRelayingPermittedIP 8 | { 9 | /// 10 | /// Gets an array of the IP addresses that are permitted to use this server for relaying from the database. 11 | /// 12 | /// 13 | public static string[] GetRelayingPermittedIPAddresses() 14 | { 15 | using (SqlConnection conn = MantaDB.GetSqlConnection()) 16 | { 17 | SqlCommand cmd = conn.CreateCommand(); 18 | cmd.CommandText = @" 19 | SELECT cfg_relayingPermittedIp_ip 20 | FROM man_cfg_relayingPermittedIp"; 21 | conn.Open(); 22 | ArrayList results = new ArrayList(); 23 | SqlDataReader reader = cmd.ExecuteReader(); 24 | while (reader.Read()) 25 | results.Add(reader.GetString("cfg_relayingPermittedIp_ip")); 26 | 27 | return (string[])results.ToArray(typeof(string)); 28 | } 29 | } 30 | 31 | /// 32 | /// Saves the array of IP Address that are allowed to relay messages through MantaMTA. 33 | /// Overwrites the existing addresses. 34 | /// 35 | /// IP Addresses to allow relaying for. 36 | public static void SetRelayingPermittedIPAddresses(IPAddress[] addresses) 37 | { 38 | using (SqlConnection conn = MantaDB.GetSqlConnection()) 39 | { 40 | SqlCommand cmd = conn.CreateCommand(); 41 | cmd.CommandText = @"DELETE FROM man_cfg_relayingPermittedIp"; 42 | foreach (IPAddress addr in addresses) 43 | { 44 | cmd.CommandText += System.Environment.NewLine + "INSERT INTO man_cfg_relayingPermittedIp(cfg_relayingPermittedIp_ip) VALUES ( '" + addr.ToString() + "' )"; 45 | } 46 | conn.Open(); 47 | cmd.ExecuteNonQuery(); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /OpenManta.Web/Controllers/VirtualMtaController.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Web.Mvc; 3 | using OpenManta.Data; 4 | using OpenManta.Core; 5 | using WebInterface.Models; 6 | using OpenManta.WebLib; 7 | 8 | namespace WebInterface.Controllers 9 | { 10 | public class VirtualMtaController : Controller 11 | { 12 | // 13 | // GET: /VirtualMta/ 14 | public ActionResult Index() 15 | { 16 | var ips = VirtualMtaDB.GetVirtualMtas(); 17 | var summary = new List(); 18 | var ipGroups = VirtualMtaWebManager.GetAllVirtualMtaGroups(); 19 | foreach (var address in ips) 20 | { 21 | summary.Add(new VirtualMTASummary 22 | { 23 | IpAddress = address, 24 | SendTransactionSummaryCollection = OpenManta.WebLib.DAL.VirtualMtaTransactionDB.GetSendSummaryForIpAddress(address.ID) 25 | }); 26 | } 27 | return View(new VirtualMtaPageModel { VirtualMTASummaryCollection = summary.ToArray(), IpGroups = ipGroups }); 28 | } 29 | 30 | // 31 | // GET: /VirtualMta/Edit 32 | public ActionResult Edit(int id = WebInterfaceParameters.VIRTUALMTA_NEW_ID) 33 | { 34 | if (id == WebInterfaceParameters.VIRTUALMTA_NEW_ID) 35 | return View(new VirtualMTA()); 36 | return View(VirtualMtaDB.GetVirtualMta(id)); 37 | } 38 | 39 | // 40 | // GET: /VirtualMta/EditGroup 41 | public ActionResult EditGroup(int id = WebInterfaceParameters.VIRTUALMTAGROUP_NEW_ID) 42 | { 43 | VirtualMtaGroup grp = null; 44 | if (id == WebInterfaceParameters.VIRTUALMTAGROUP_NEW_ID) 45 | grp = new VirtualMtaGroup(); 46 | else 47 | grp = VirtualMtaWebManager.GetVirtualMtaGroup(id); 48 | 49 | return View(new VirtualMtaGroupCreateEditModel 50 | { 51 | VirtualMtaGroup = grp, 52 | VirtualMTACollection = VirtualMtaDB.GetVirtualMtas() 53 | }); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /OpenManta.Console/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.ExceptionServices; 4 | using OpenManta.Core; 5 | using OpenManta.Framework; 6 | 7 | namespace OpenManta.Console 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | Logging.Info("MTA Started"); 14 | 15 | AppDomain.CurrentDomain.FirstChanceException += delegate(object sender, FirstChanceExceptionEventArgs e) 16 | { 17 | Logging.Warn("", e.Exception); 18 | }; 19 | 20 | IList ipAddresses = VirtualMtaManager.GetVirtualMtasForListeningOn(); 21 | 22 | // Array will hold all instances of SmtpServer, one for each port we will be listening on. 23 | List smtpServers = new List(); 24 | 25 | // Create the SmtpServers 26 | for (int c = 0; c < ipAddresses.Count; c++) 27 | { 28 | VirtualMTA ipAddress = ipAddresses[c]; 29 | for (int i = 0; i < MtaParameters.ServerListeningPorts.Length; i++) 30 | smtpServers.Add(new SmtpServer(ipAddress.IPAddress, MtaParameters.ServerListeningPorts[i])); 31 | } 32 | 33 | // Start the SMTP Client. 34 | MessageSender.Instance.Start(); 35 | // Start the events (bounce/abuse) handler. 36 | EventsFileHandler.Instance.Start(); 37 | 38 | QueueManager.Instance.Start(); 39 | OpenManta.Framework.RabbitMq.RabbitMqInboundStagingHandler.Instance.Start(); 40 | 41 | bool quit = false; 42 | while (!quit) 43 | { 44 | ConsoleKeyInfo key = System.Console.ReadKey(true); 45 | if (key.KeyChar == 'q' || key.KeyChar == 'Q') 46 | quit = true; 47 | } 48 | 49 | // Need to wait while servers & client shutdown. 50 | MantaCoreEvents.InvokeMantaCoreStopping(); 51 | foreach (SmtpServer s in smtpServers) 52 | s.Dispose (); 53 | 54 | Logging.Info("MTA Stopped"); 55 | System.Console.WriteLine("Press any key to continue"); 56 | System.Console.ReadKey(true); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /OpenManta.Service/OpenMantaService.cs: -------------------------------------------------------------------------------- 1 | using OpenManta.Framework; 2 | using OpenManta.Framework.RabbitMq; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ServiceProcess; 6 | 7 | namespace OpenManta.Service 8 | { 9 | public partial class OpenMantaService : ServiceBase 10 | { 11 | // Array will hold all instances of SmtpServer, one for each port we will be listening on. 12 | private readonly IList SmtpServers = new List(); 13 | 14 | public OpenMantaService() 15 | { 16 | InitializeComponent(); 17 | } 18 | 19 | protected override void OnStart(string[] args) 20 | { 21 | Logging.Info("Starting OpenManta Service."); 22 | AppDomain.CurrentDomain.UnhandledException += delegate(object sender, UnhandledExceptionEventArgs e) 23 | { 24 | Exception ex = (Exception)e.ExceptionObject; 25 | Logging.Fatal(ex.Message, ex); 26 | }; 27 | 28 | RabbitMqInboundStagingHandler.Instance.Start(); 29 | 30 | // Start the RabbitMQ Bulk inserter. 31 | QueueManager.Instance.Start(); 32 | 33 | // Create the SmtpServers 34 | foreach(var vmta in VirtualMtaManager.GetVirtualMtasForListeningOn()) 35 | { 36 | foreach(var port in MtaParameters.ServerListeningPorts) 37 | SmtpServers.Add(new SmtpServer(vmta.IPAddress, port)); 38 | } 39 | 40 | // Start the SMTP Client. 41 | MessageSender.Instance.Start(); 42 | 43 | // Start the events (bounce/abuse) handler. 44 | EventsFileHandler.Instance.Start(); 45 | 46 | Logging.Info("OpenManta Service has started."); 47 | } 48 | 49 | protected override void OnStop() 50 | { 51 | Logging.Info("Stopping OpenManta Service"); 52 | 53 | // Need to wait while servers & client shutdown. 54 | MantaCoreEvents.InvokeMantaCoreStopping(); 55 | foreach (var smtp in SmtpServers) 56 | smtp.Dispose(); 57 | 58 | Logging.Info("OpenManta Service has stopped."); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /OpenManta.Web/Controllers/API/v1/OutboundRulesController.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Web.Http; 3 | using OpenManta.Core; 4 | using OpenManta.Data; 5 | using OpenManta.WebLib; 6 | using WebInterface.Models.API.v1; 7 | 8 | namespace WebInterface.Controllers.API.v1 9 | { 10 | /// 11 | /// Summary description for OutboundRules API 12 | /// 13 | [RoutePrefix("api/v1/OutboundRules")] 14 | public class OutboundRulesController : ApiController 15 | { 16 | [HttpPost] 17 | [Route("Update")] 18 | public bool Update(UpdateOutboundRuleViewModel viewModel) 19 | { 20 | if (viewModel.VirtualMTA == -1) 21 | viewModel.VirtualMTA = null; 22 | 23 | OutboundMxPattern pattern = null; 24 | if (viewModel.PatternID == WebInterfaceParameters.OUTBOUND_RULES_NEW_PATTERN_ID) 25 | pattern = new OutboundMxPattern(); 26 | else 27 | pattern = OutboundRuleDB.GetOutboundRulePatterns().SingleOrDefault(p => p.ID == viewModel.PatternID); 28 | if (pattern == null) 29 | return false; 30 | 31 | pattern.Description = viewModel.Description.Trim(); 32 | pattern.LimitedToOutboundIpAddressID = viewModel.VirtualMTA; 33 | pattern.Name = viewModel.Name.Trim(); 34 | pattern.Type = viewModel.Type; 35 | pattern.Value = viewModel.PatternValue; 36 | pattern.ID = OutboundRuleWebManager.Save(pattern); 37 | 38 | OutboundRuleWebManager.Save(new OutboundRule(pattern.ID, OutboundRuleType.MaxConnections, viewModel.MaxConnections.ToString())); 39 | OutboundRuleWebManager.Save(new OutboundRule(pattern.ID, OutboundRuleType.MaxMessagesConnection, viewModel.MaxMessagesConn.ToString())); 40 | OutboundRuleWebManager.Save(new OutboundRule(pattern.ID, OutboundRuleType.MaxMessagesPerHour, viewModel.MaxMessagesHour.ToString())); 41 | 42 | return true; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /OpenManta.Web/Views/Sends/_ReportLayout.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/_Layout.cshtml"; 3 | PageData["OverviewUrl"] = "/sends/overview"; 4 | PageData["SpeedUrl"] = "/sends/speed"; 5 | PageData["VmtaUrl"] = "/sends/virtualmta"; 6 | PageData["BounceUrl"] = "/sends/bounces"; 7 | PageData["DeferredUrl"] = "/sends/deferred"; 8 | PageData["FailedUrl"] = "/sends/failed"; 9 | } 10 | 11 | 22 | 23 |
24 | 32 |
33 | 34 | @RenderBody() 35 | 36 |
37 | 41 |
-------------------------------------------------------------------------------- /OpenManta.Core/MantaBounceCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenManta.Core 4 | { 5 | /// 6 | /// Manta notification bounce code. 7 | /// These identify the type of bounce that has occurred. 8 | /// 9 | public enum MantaBounceCode : int 10 | { 11 | /// 12 | /// Default value. 13 | /// 14 | Unknown = 0, 15 | /// 16 | /// Not actually a bounce. Gives code processing a bounce a way of finding that it's not actually looking at a bounce, e.g. when finding a 17 | /// 18 | NotABounce = 1, 19 | /// 20 | /// There is no email account for the email address specified. 21 | /// 22 | BadEmailAddress = 11, 23 | General = 20, 24 | DnsFailure = 21, 25 | MailboxFull = 22, 26 | MessageSizeTooLarge = 23, 27 | UnableToConnect = 29, 28 | ServiceUnavailable = 30, 29 | /// 30 | /// A bounce that we're unable to identify a reason for. 31 | /// 32 | BounceUnknown = 40, 33 | /// 34 | /// Sending server appears on a blocking list. 35 | /// 36 | KnownSpammer = 51, 37 | /// 38 | /// The content of the email has been identified as spam. 39 | /// 40 | SpamDetected = 52, 41 | AttachmentDetected = 53, 42 | RelayDenied = 54, 43 | /// 44 | /// Used when a receiving MTA has indicated we're sending too many emails to them. 45 | /// 46 | RateLimitedByReceivingMta = 55, 47 | /// 48 | /// Indicates the receiving server reported an error with the sending address provided by Manta. 49 | /// 50 | ConfigurationErrorWithSendingAddress = 56, 51 | /// 52 | /// The receiving MTA has blocked the IP address. Contact them to have it removed. 53 | /// 54 | PermanentlyBlockedByReceivingMta = 57, 55 | /// 56 | /// The receiving MTA has placed a temporary block on the IP address, but will automatically remove it after a short period. 57 | /// 58 | TemporarilyBlockedByReceivingMta = 58 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /OpenManta.Web/Models/API/v1/VirtualMtaViewModels.cs: -------------------------------------------------------------------------------- 1 | namespace WebInterface.Models.API.v1 2 | { 3 | /// 4 | /// Summary description for SaveVirtualMtaViewModel 5 | /// 6 | public class SaveVirtualMtaViewModel 7 | { 8 | /// 9 | /// ID of the virtual MTA. 10 | /// 11 | public int Id { get; set; } 12 | 13 | /// 14 | /// Hostname of the Virtual MTA. 15 | /// 16 | public string HostName { get; set; } 17 | 18 | /// 19 | /// IP Address of the Virtual MTA. 20 | /// 21 | public string IpAddress { get; set; } 22 | 23 | /// 24 | /// TRUE if the Virtual MTA can accept inbound Email. 25 | /// 26 | public bool Inbound { get; set; } 27 | 28 | /// 29 | /// TRUE if the Virtal MTA can send outbound Email. 30 | /// 31 | public bool Outbound { get; set; } 32 | } 33 | 34 | public class DeleteVirtualMtaViewModel 35 | { 36 | /// 37 | /// ID of the Virtual MTA to delete. 38 | /// 39 | public int Id { get; set; } 40 | } 41 | 42 | public class SaveVirtualMtaGroupViewModel 43 | { 44 | /// 45 | /// ID of the Virtual MTA Group to save. 46 | /// 47 | public int Id { get; set; } 48 | 49 | /// 50 | /// Name of the Virtual MTA Group. 51 | /// 52 | public string Name { get; set; } 53 | 54 | /// 55 | /// Description of the Virtual MTA Group. 56 | /// 57 | public string Description { get; set; } 58 | 59 | /// 60 | /// ID's of the VirtualMTAs that the Group should contain. 61 | /// 62 | public int[] MtaIDs { get; set; } 63 | } 64 | 65 | public class DeleteVirtualMtaGroupViewModel 66 | { 67 | /// 68 | /// ID of the Virtual MTA Group to delete. 69 | /// 70 | public int Id { get; set; } 71 | } 72 | } -------------------------------------------------------------------------------- /OpenManta.Web/Models/API/v1/SettingsViewModels.cs: -------------------------------------------------------------------------------- 1 | namespace WebInterface.Models.API.v1 2 | { 3 | /// 4 | /// Summary description for UpdateSettingsViewModel 5 | /// 6 | public class UpdateSettingsViewModel 7 | { 8 | /// 9 | /// Seconds before connection idle timeout. 10 | /// 11 | public int ClientIdleTimeout { get; set; } 12 | 13 | /// 14 | /// Seconds before connection receive timeout. 15 | /// 16 | public int ReceiveTimeout { get; set; } 17 | 18 | /// 19 | /// Seconds before connection send timeout. 20 | /// 21 | public int SendTimeout { get; set; } 22 | 23 | /// 24 | /// ID of the VirtualMTA Group to use if not specified in email headers. 25 | /// 26 | public int DefaultVirtualMtaGroupID { get; set; } 27 | 28 | /// 29 | /// URL to post events to. 30 | /// 31 | public string EventUrl { get; set; } 32 | 33 | /// 34 | /// Days to keep smtp logs defore deleing them. 35 | /// 36 | public int DaysToKeepSmtpLogsFor { get; set; } 37 | 38 | /// 39 | /// Max time in hours that an email can be in the queue for before it is timed out. 40 | /// 41 | public int MaxTimeInQueueHours { get; set; } 42 | 43 | /// 44 | /// The time in minutes to use as the base for the retry interval calculation. 45 | /// 46 | public int RetryIntervalBase { get; set; } 47 | 48 | /// 49 | /// Array of the IP Addresses that are allowed to relay through MantaMTA. 50 | /// 51 | public string[] IpAddressesForRelaying { get; set; } 52 | 53 | /// 54 | /// ID of the local domain that should be used as the hostname for the returnpath if none is specified in the email headers. 55 | /// 56 | public int ReturnPathLocalDomainID { get; set; } 57 | 58 | /// 59 | /// Array of the localdomains. 60 | /// 61 | public string[] LocalDomains { get; set; } 62 | } 63 | } -------------------------------------------------------------------------------- /OpenManta.Web/Views/Bounces/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Bounces"; 3 | Layout = "~/Views/_Layout.cshtml"; 4 | } 5 | 6 | 9 | 10 |
11 |
12 |
13 |
Deferred
14 |

@Model.DeferredCount.ToString("N0")

15 |
16 |
17 |
18 |
19 |
Rejected
20 |

@Model.RejectedCount.ToString("N0")

21 |
22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | @foreach(OpenManta.WebLib.BO.BounceInfo bounce in Model.BounceInfo) 38 | { 39 | 40 | 41 | @switch (bounce.TransactionStatus) 42 | { 43 | case OpenManta.Core.TransactionStatus.Deferred: 44 | 45 | break; 46 | case OpenManta.Core.TransactionStatus.Discarded: 47 | 48 | break; 49 | case OpenManta.Core.TransactionStatus.Failed: 50 | 51 | break; 52 | case OpenManta.Core.TransactionStatus.TimedOut: 53 | 54 | break; 55 | } 56 | 57 | 58 | 59 | 60 | 61 | } 62 | 63 |
VirtualMTAStatusRemoteResponseCountLast Occurred
@bounce.LocalHostname
@bounce.LocalIpAddress
DeferredDiscardedRejectedTimed Out In Queue@bounce.RemoteHostname@bounce.Message@bounce.Count.ToString("N0")@bounce.LastOccurred
64 | 65 | 80 | 81 | -------------------------------------------------------------------------------- /OpenManta.Web/Views/VirtualMta/EditGroup.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = (Model.VirtualMtaGroup.ID == OpenManta.WebLib.WebInterfaceParameters.VIRTUALMTAGROUP_NEW_ID ? "Create" : "Edit") + " Virtual MTA Group"; 3 | Layout = "~/Views/_Layout.cshtml"; 4 | } 5 | 6 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 56 | 57 | 58 | 59 | 60 | 61 | 65 | 66 | 67 |
Name
Description
Virtual MTAs 49 | @foreach(OpenManta.Core.VirtualMTA vmta in Model.VirtualMTACollection) 50 | { 51 | 54 | } 55 |
62 | @(Model.VirtualMtaGroup.ID == OpenManta.WebLib.WebInterfaceParameters.VIRTUALMTAGROUP_NEW_ID ? "Create" : "Update") 63 | Cancel 64 |
68 | -------------------------------------------------------------------------------- /OpenManta.Web/Views/OutboundRules/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Outbound Rules"; 3 | Layout = "~/Views/_Layout.cshtml"; 4 | } 5 | 6 | 17 | 18 |

Outbound Rules 19 | 20 |

21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | @foreach (OpenManta.Core.OutboundMxPattern outboundRule in Model) 34 | { 35 | 36 | 37 | 38 | 48 | 57 | 63 | 64 | } 65 | 66 |
NameDescriptionPatternVirtual MTA
@outboundRule.Name@outboundRule.Description@switch (outboundRule.Type) 39 | { 40 | case OpenManta.Core.OutboundMxPatternType.CommaDelimited: 41 | @:List 42 | break; 43 | case OpenManta.Core.OutboundMxPatternType.Regex: 44 | @:Regex 45 | break; 46 | } 47 |  @outboundRule.Value@if (!outboundRule.LimitedToOutboundIpAddressID.HasValue) 49 | { 50 | @:All 51 | } 52 | else 53 | { 54 | @OpenManta.Data.VirtualMtaDB.GetVirtualMta(outboundRule.LimitedToOutboundIpAddressID.Value).Hostname 55 | } 56 | 58 |
59 | Edit 60 | 61 |
62 |
-------------------------------------------------------------------------------- /OpenManta.WebLib/OutboundRuleWebManager.cs: -------------------------------------------------------------------------------- 1 | using OpenManta.Core; 2 | 3 | namespace OpenManta.WebLib 4 | { 5 | public static class OutboundRuleWebManager 6 | { 7 | /// 8 | /// Creates a new MX Pattern and it's default rules. 9 | /// 10 | /// Name of the pattern. 11 | /// Description of the pattern. 12 | /// The Type of the pattern. 13 | /// The pattern value. 14 | /// IP Address to limit the outbound rule to, or null if applies to all IP's. 15 | /// ID of the MX Pattern. 16 | public static int CreatePattern(string name, string description, OutboundMxPatternType type, string pattern, int? ipAddress) 17 | { 18 | OutboundMxPattern mxPattern = new OutboundMxPattern 19 | { 20 | Description = description, 21 | Name = name, 22 | Type = type, 23 | Value = pattern, 24 | LimitedToOutboundIpAddressID = ipAddress 25 | }; 26 | 27 | mxPattern.ID = Save(mxPattern); 28 | 29 | // Create the three types of rule. 30 | Save(new OutboundRule(mxPattern.ID, OutboundRuleType.MaxConnections, "-1")); 31 | Save(new OutboundRule(mxPattern.ID, OutboundRuleType.MaxMessagesConnection, "-1")); 32 | Save(new OutboundRule(mxPattern.ID, OutboundRuleType.MaxMessagesPerHour, "-1")); 33 | 34 | return mxPattern.ID; 35 | } 36 | 37 | /// 38 | /// Deletes the specified Outbound Rule pattern and all of it's rules. 39 | /// 40 | /// ID of the MX Pattern to delete. 41 | public static void Delete(int mxPatternID) 42 | { 43 | DAL.OutboundRulesDB.Delete(mxPatternID); 44 | } 45 | 46 | /// 47 | /// Saves the OutboundMxPattern. 48 | /// 49 | /// Pattern to save. 50 | /// ID of the pattern. 51 | public static int Save(OutboundMxPattern pattern) 52 | { 53 | return DAL.OutboundRulesDB.Save(pattern); 54 | } 55 | 56 | /// 57 | /// Saves the OutboundRule. 58 | /// 59 | /// The rule to save. 60 | public static void Save(OutboundRule rule) 61 | { 62 | DAL.OutboundRulesDB.Save(rule); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /OpenManta.Web/Controllers/DashboardController.cs: -------------------------------------------------------------------------------- 1 | using OpenManta.Core; 2 | using OpenManta.Framework; 3 | using Newtonsoft.Json.Linq; 4 | using System; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Net; 8 | using System.Web.Mvc; 9 | using WebInterface.Models; 10 | using OpenManta.WebLib.DAL; 11 | 12 | namespace WebInterface.Controllers 13 | { 14 | public class DashboardController : Controller 15 | { 16 | // 17 | // GET: /Dashboard/ 18 | public ActionResult Index() 19 | { 20 | DashboardModel model = new DashboardModel 21 | { 22 | SendTransactionSummaryCollection = TransactionDB.GetLastHourTransactionSummary(), 23 | Waiting = SendDB.GetQueueCount(new SendStatus[] { SendStatus.Active, SendStatus.Discard }), 24 | Paused =SendDB.GetQueueCount(new SendStatus[] { SendStatus.Paused }), 25 | BounceInfo = TransactionDB.GetLastHourBounceInfo(3), 26 | SendSpeedInfo = TransactionDB.GetLastHourSendSpeedInfo() 27 | }; 28 | 29 | try 30 | { 31 | // Connect to Rabbit MQ and grab basic queue counts. 32 | HttpWebRequest request = HttpWebRequest.CreateHttp("http://localhost:15672/api/queues"); 33 | request.Credentials = new NetworkCredential(MtaParameters.RabbitMQ.Username, MtaParameters.RabbitMQ.Password); 34 | using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 35 | { 36 | 37 | string json = new StreamReader(response.GetResponseStream()).ReadToEnd(); 38 | JArray rabbitQueues = JArray.Parse(json); 39 | foreach (JToken q in rabbitQueues.Children()) 40 | { 41 | JEnumerable qProperties = q.Children(); 42 | string queueName = (string)qProperties.First(x => x.Name.Equals("name")).Value; 43 | if (queueName.StartsWith("manta_mta_")) 44 | { 45 | long messages = (long)qProperties.First(x => x.Name.Equals("messages", System.StringComparison.OrdinalIgnoreCase)).Value; 46 | if (queueName.IndexOf("_inbound") > 0) 47 | model.RabbitMqInbound += messages; 48 | else if (queueName.IndexOf("_outbound_") > 0) 49 | model.RabbitMqTotalOutbound += messages; 50 | } 51 | } 52 | } 53 | } 54 | catch(Exception) 55 | { 56 | model.RabbitMqInbound = int.MinValue; 57 | model.RabbitMqTotalOutbound = int.MinValue; 58 | } 59 | 60 | 61 | return View(model); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /OpenManta.Web/Models/SettingsModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using OpenManta.Core; 3 | 4 | namespace WebInterface.Models 5 | { 6 | /// 7 | /// Model for the Settings page. 8 | /// 9 | public class SettingsModel 10 | { 11 | /// 12 | /// Time in seconds before connection idle timeout. 13 | /// 14 | public int ClientIdleTimeout { get; set; } 15 | 16 | /// 17 | /// The amount of days SMTP logs should be kept for before deleting. 18 | /// 19 | public int DaysToKeepSmtpLogsFor { get; set; } 20 | 21 | /// 22 | /// The ID of the Virtual MTA Group to use if none is specified in an emails header. 23 | /// 24 | public int DefaultVirtualMtaGroupID { get; set; } 25 | 26 | /// 27 | /// Collection of all the Virtual MTA Groups that Manta knows about. 28 | /// 29 | public IList VirtualMtaGroupCollection { get; set; } 30 | 31 | /// 32 | /// The URL to forward events to. 33 | /// 34 | public string EventForwardingUrl { get; set; } 35 | 36 | /// 37 | /// Collection of the LocalDomains that Manta uses. 38 | /// 39 | public IList LocalDomains { get; set; } 40 | 41 | /// 42 | /// Maximum time in minutes that any message should be allowed to spend in the queue before timeing out. 43 | /// 44 | public int MaxTimeInQueue { get; set; } 45 | 46 | /// 47 | /// Array of the IP Addresses that are allowed to relay through Manta. 48 | /// 49 | public string[] RelayingPermittedIPs { get; set; } 50 | 51 | /// 52 | /// Time in seconds before SMTP client should timeout when waiting for a response. 53 | /// 54 | public int ReceiveTimeout { get; set; } 55 | 56 | /// 57 | /// The base minutes to use for the retry interval calculation. 58 | /// 59 | public int RetryInterval { get; set; } 60 | 61 | /// 62 | /// The default hostname that should be used for returnpath domains if not set in email header. 63 | /// 64 | public string ReturnPathDomain { get; set; } 65 | 66 | /// 67 | /// The time in seconds to wait before timing out and SMTP client transmittion. 68 | /// 69 | public int SendTimeout { get; set; } 70 | } 71 | } -------------------------------------------------------------------------------- /OpenManta.Framework/RabbitMq/RabbitMqInboundStagingHandler.cs: -------------------------------------------------------------------------------- 1 | using OpenManta.Core; 2 | using RabbitMQ.Client.Events; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace OpenManta.Framework.RabbitMq 7 | { 8 | public class RabbitMqInboundStagingHandler : IStopRequired 9 | { 10 | private const int STAGING_DEQUEUE_TASKS = 25; 11 | public int _StartedThreads = 0; 12 | private static RabbitMqInboundStagingHandler _Instance = new RabbitMqInboundStagingHandler(); 13 | private bool IsStopping = false; 14 | private RabbitMqInboundStagingHandler() 15 | { 16 | MantaCoreEvents.RegisterStopRequiredInstance(this); 17 | } 18 | 19 | public static RabbitMqInboundStagingHandler Instance { get { return _Instance; } } 20 | public void Start() 21 | { 22 | Parallel.For(0, STAGING_DEQUEUE_TASKS, (i) => { 23 | var t = new System.Threading.Thread(new System.Threading.ThreadStart(HandleDequeue)); 24 | t.Start(); 25 | }); 26 | } 27 | 28 | public void Stop() 29 | { 30 | IsStopping = true; 31 | } 32 | 33 | private void HandleDequeue() 34 | { 35 | while(!IsStopping) 36 | { 37 | BasicDeliverEventArgs ea = RabbitMq.RabbitMqManager.Dequeue(RabbitMqManager.RabbitMqQueue.InboundStaging, 1, 100).FirstOrDefault(); 38 | if(ea == null) 39 | { 40 | //await Task.Delay(1000); 41 | System.Threading.Thread.Sleep(1000); 42 | continue; 43 | } 44 | 45 | MtaQueuedMessage qmsg = Serialisation.Deserialise(ea.Body).Result; 46 | MtaMessage msg = new MtaMessage 47 | { 48 | ID = qmsg.ID, 49 | InternalSendID = qmsg.InternalSendID, 50 | MailFrom = qmsg.MailFrom, 51 | RcptTo = qmsg.RcptTo, 52 | VirtualMTAGroupID = qmsg.VirtualMTAGroupID 53 | }; 54 | 55 | RabbitMqManager.Publish(msg, RabbitMqManager.RabbitMqQueue.Inbound, true, qmsg.RabbitMqPriority).Wait(); 56 | RabbitMqManager.Publish(qmsg, RabbitMqManager.RabbitMqQueue.OutboundWaiting, true, qmsg.RabbitMqPriority).Wait(); 57 | RabbitMqManager.Ack(RabbitMqManager.RabbitMqQueue.InboundStaging, ea.DeliveryTag, false); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /OpenManta.Core/BodyPart.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Mime; 3 | using System.Text; 4 | 5 | namespace OpenManta.Core 6 | { 7 | /// 8 | /// A single part of a MimeMessage that contains part of the content. This could be 9 | /// simply a container for other BodyParts or actual meaningful content as in plain text, 10 | /// HTML code, an image, etc. 11 | /// 12 | public class BodyPart 13 | { 14 | /// 15 | /// All the headers for this BodyPart. 16 | /// 17 | public MessageHeaderCollection Headers { get; set; } 18 | /// 19 | /// Holds the boundary 20 | /// 21 | public string Boundary { get; set; } 22 | /// 23 | /// The content type of the body part. 24 | /// 25 | public ContentType ContentType { get; set; } 26 | /// 27 | /// The Transfer encoding for the body part. 28 | /// 29 | public TransferEncoding TransferEncoding { get; set; } 30 | /// 31 | /// The Transfer encoded body - might not be legible without being decoded (so call 32 | /// GetDecodedBody() to have that appropriately decoded). 33 | /// 34 | public string EncodedBody { get; set; } 35 | /// 36 | /// A collection of MimeMessageBodyPart objects that make up the email. 37 | /// 38 | public BodyPart[] BodyParts{ get; set; } 39 | /// 40 | /// If true then this body part contains a MIME Message. 41 | /// 42 | public bool HasChildMimeMessage 43 | { 44 | get 45 | { 46 | if (ContentType == null || string.IsNullOrWhiteSpace(ContentType.MediaType)) 47 | return false; 48 | 49 | return ContentType.MediaType.Equals("message/rfc822", StringComparison.OrdinalIgnoreCase); 50 | } 51 | } 52 | /// 53 | /// Returns a child MIME Message if one exists, else null. 54 | /// 55 | public MimeMessage ChildMimeMessage 56 | { 57 | get 58 | { 59 | if (!HasChildMimeMessage) 60 | return null; 61 | 62 | return MimeMessage.Parse(this.GetDecodedBody()); 63 | } 64 | } 65 | /// 66 | /// Get this Body Part decoded. 67 | /// 68 | /// Body part body with Transport Encoding decoded. 69 | public string GetDecodedBody() 70 | { 71 | string tmp = EncodedBody; 72 | 73 | if (TransferEncoding == TransferEncoding.Base64) 74 | { 75 | tmp = UTF8Encoding.Default.GetString(Convert.FromBase64String(tmp)); 76 | } 77 | return tmp; 78 | } 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /OpenManta.Framework/DNSManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Linq; 4 | using OpenManta.Core; 5 | 6 | namespace OpenManta.Framework 7 | { 8 | [Serializable] 9 | internal class DNSDomainNotFoundException : Exception { } 10 | 11 | internal static class DNSManager 12 | { 13 | /// 14 | /// Holds a thread safe collection of MX Records so we don't need to query the DNS API every time. 15 | /// 16 | private static ConcurrentDictionary _Records = new ConcurrentDictionary(); 17 | 18 | /// 19 | /// Gets an Array of MX Records for the specified domain. If none found returns null. 20 | /// 21 | /// 22 | /// 23 | public static MXRecord[] GetMXRecords(string domain) 24 | { 25 | // Make sure the domain is all lower. 26 | domain = domain.ToLower(); 27 | 28 | // This is what we'll be returning. 29 | MXRecord[] mxRecords = null; 30 | 31 | // Try and get DNS from internal cache. 32 | if (DNSManager._Records.TryGetValue(domain, out mxRecords)) 33 | { 34 | // Found cached records. 35 | // Make sure they haven't expired. 36 | if (mxRecords.Count((MXRecord mx) => mx.Dead) < 1) 37 | return mxRecords; 38 | } 39 | 40 | string[] records = null; 41 | 42 | try 43 | { 44 | // Get the records from DNS 45 | records = dnsapi.GetMXRecords(domain); 46 | } 47 | catch (DNSDomainNotFoundException) 48 | { 49 | // Ensure records is null. 50 | records = null; 51 | } 52 | 53 | // No MX records for domain. 54 | if (records == null) 55 | { 56 | // If there are no MX records use the hostname as per SMTP RFC. 57 | MXRecord[] mxs = new MXRecord[] 58 | { 59 | new MXRecord(domain, 10, 300u, MxRecordSrc.A) 60 | }; 61 | _Records.AddOrUpdate(domain, mxs, (string key, MXRecord[] existing) => mxs); 62 | return mxs; 63 | } 64 | 65 | mxRecords = new MXRecord[records.Length]; 66 | for (int i = 0; i < mxRecords.Length; i++) 67 | { 68 | string[] split = records[i].Split(new char[] { ',' }); 69 | if(split.Length == 3) 70 | mxRecords[i] = new MXRecord(split[1], int.Parse(split[0]), uint.Parse(split[2]), MxRecordSrc.MX); 71 | } 72 | 73 | // Order by preferance 74 | mxRecords = ( 75 | from mx in mxRecords 76 | where mx != null 77 | orderby mx.Preference 78 | select mx).ToArray(); 79 | DNSManager._Records.TryAdd(domain, mxRecords); 80 | return mxRecords; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /OpenManta.Core/VirtualMtaGroup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace OpenManta.Core 6 | { 7 | /// 8 | /// Represents a grouping of IP Address that can be used by the MTA for 9 | /// sending of messages. 10 | /// 11 | public class VirtualMtaGroup : NamedEntity 12 | { 13 | /// 14 | /// Collection of the Virtual MTAs that make up this group. 15 | /// 16 | public IList VirtualMtaCollection { get; set; } 17 | 18 | /// 19 | /// Timestamp of when this MtaIPGroup instance was created; used for caching. 20 | /// 21 | public DateTime CreatedTimestamp = DateTime.UtcNow; 22 | 23 | /// 24 | /// Gets a random IP from the collection. 25 | /// This should be improved to take into account messages sent in last ?. 26 | /// 27 | /// 28 | public VirtualMTA GetRandomIP() 29 | { 30 | // There are no IP addresses in the group so return null. 31 | if (VirtualMtaCollection == null) 32 | return null; 33 | 34 | return VirtualMtaCollection.OrderBy(x => new Random().Next()).FirstOrDefault(); 35 | } 36 | 37 | /// 38 | /// Object used for locking in GetIpAddressForSending method. 39 | /// 40 | private static object _SyncLock = new object(); 41 | 42 | /// 43 | /// Gets an IP Address. Uses to load balance accross all IPs in group. 44 | /// 45 | /// MXRecord of the host wanting to send to. 46 | /// MtaIpAddress or NULL if none in group. 47 | public VirtualMTA GetVirtualMtasForSending(MXRecord mxRecord) 48 | { 49 | lock (_SyncLock) 50 | { 51 | string key = mxRecord.Host.ToLowerInvariant(); 52 | 53 | // Get the IP address that has sent the least to the mx host. 54 | VirtualMTA vMTA = VirtualMtaCollection.OrderBy(ipAddr => ipAddr.SendsCounter.GetOrAdd(key, 0)).FirstOrDefault(); 55 | 56 | // Get the current sends count. 57 | int currentSends = 0; 58 | if (!vMTA.SendsCounter.TryGetValue(key, out currentSends)) 59 | return null; 60 | 61 | // Increment the sends count to include this one. 62 | vMTA.SendsCounter.AddOrUpdate(key, currentSends + 1, new Func(delegate(string k, int value) { return value + 1; })); 63 | 64 | // Return the IP Address. 65 | return vMTA; 66 | } 67 | } 68 | 69 | /// 70 | /// Constuctor sets defaults. 71 | /// 72 | public VirtualMtaGroup() 73 | { 74 | this.VirtualMtaCollection = new List(); 75 | } 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /OpenManta.WebLib/BO/VirtualMtaSendInfo.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace OpenManta.WebLib.BO 3 | { 4 | /// 5 | /// Holds information abount a Virtual MTA and what it has done in a send. 6 | /// 7 | public class VirtualMtaSendInfo : OpenManta.Core.VirtualMTA 8 | { 9 | /// 10 | /// The amount of messages accepted by a remote MX. 11 | /// 12 | public long Accepted { get; set; } 13 | 14 | /// 15 | /// The amount of messages rejected by a remote MX. 16 | /// 17 | public long Rejected { get; set; } 18 | 19 | /// 20 | /// The amount of attempts to send a message that where throttled by MantaMTA. 21 | /// 22 | public long Throttled { get; set; } 23 | 24 | /// 25 | /// The amount of attempts to send a message that where deferred by the remote MX. 26 | /// 27 | public long Deferred { get; set; } 28 | 29 | /// 30 | /// The amount of attempts to send messages that where made. 31 | /// 32 | private long Attempts 33 | { 34 | get 35 | { 36 | return Accepted + Deferred + Rejected + Throttled; 37 | } 38 | } 39 | 40 | /// 41 | /// The percentage of attempts that where accepted. 42 | /// 43 | public double AcceptedPercent 44 | { 45 | get 46 | { 47 | if (Attempts < 1) 48 | return 0; 49 | return (100d / (Attempts - Throttled - Deferred)) * Accepted; 50 | } 51 | } 52 | 53 | /// 54 | /// The percentage of attempts that where deferred by the remote MX. 55 | /// 56 | public double DeferredPercent 57 | { 58 | get 59 | { 60 | if (Attempts < 1) 61 | return 0; 62 | return (100d / Attempts) * Deferred; 63 | } 64 | } 65 | 66 | /// 67 | /// The percentage of attempts that where throttled by MantaMTA. 68 | /// 69 | public double ThrottledPercent 70 | { 71 | get 72 | { 73 | if (Attempts < 1) 74 | return 0; 75 | return (100d / Attempts) * Throttled; 76 | } 77 | } 78 | 79 | /// 80 | /// The percentage of attempts that where rejected by the remote MX. 81 | /// 82 | public double RejectedPercent 83 | { 84 | get 85 | { 86 | if (Attempts < 1) 87 | return 0; 88 | return (100d / (Attempts - Throttled - Deferred)) * Rejected; 89 | } 90 | } 91 | 92 | public VirtualMtaSendInfo() 93 | { 94 | Accepted = 0; 95 | Rejected = 0; 96 | Throttled = 0; 97 | Deferred = 0; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /OpenManta.Framework/ServiceNotAvailableManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | 4 | namespace OpenManta.Framework 5 | { 6 | /// 7 | /// 421 Service not available likley means that an IP is being blocked. 8 | /// This manager helps us by keeping tack of these and we can use it to 9 | /// only send a maximum of 1 message/minute from IPs that seem to be blocked. 10 | /// 11 | internal static class ServiceNotAvailableManager 12 | { 13 | /// 14 | /// Dictionary 15 | /// 16 | public static ConcurrentDictionary> _ServiceUnavailableLog = new ConcurrentDictionary>(); 17 | 18 | /// 19 | /// Add a service unavailable event. 20 | /// 21 | /// 22 | /// 23 | /// 24 | public static void Add(string ip, string mxHostname, DateTime lastFail) 25 | { 26 | mxHostname = mxHostname.ToLower(); 27 | _ServiceUnavailableLog.TryAdd(ip, new ConcurrentDictionary()); 28 | ConcurrentDictionary ipServices = _ServiceUnavailableLog[ip]; 29 | ipServices.AddOrUpdate(mxHostname, lastFail, delegate(string key, DateTime existingValue) 30 | { 31 | // We should only use the "new" timestamp if it's a later date that the existing value. 32 | // If the existing value is "newer" then a different thread updated already with better data. 33 | if (existingValue > lastFail) 34 | return existingValue; 35 | return lastFail; 36 | }); 37 | } 38 | 39 | 40 | private static readonly TimeSpan ServiceUnavailableTimeSpan = new TimeSpan(0, 0, 30); 41 | /// 42 | /// Check to see if the MX hostname has denied the specified IP access within the last 1 minute. 43 | /// 44 | /// IP to check 45 | /// Hostname of the MX to check 46 | /// TRUE if service is unavailable 47 | public static bool IsServiceUnavailable(string ip, string mxHostname) 48 | { 49 | mxHostname = mxHostname.ToLower(); 50 | ConcurrentDictionary ipServices = null; 51 | if (_ServiceUnavailableLog.TryGetValue(ip, out ipServices)) 52 | { 53 | DateTime lastFail = DateTime.MinValue; 54 | 55 | if (ipServices.TryGetValue(mxHostname, out lastFail)) 56 | { 57 | if ((DateTime.UtcNow - lastFail) < ServiceUnavailableTimeSpan) 58 | return true; 59 | } 60 | } 61 | 62 | return false; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /OpenManta.Framework/ServiceContractManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ServiceModel; 3 | 4 | namespace OpenManta.Framework 5 | { 6 | /// 7 | /// Make working with WCF Services nicer. 8 | /// 9 | public static class ServiceContractManager 10 | { 11 | /// 12 | /// Holds the send point addresses of contracts. 13 | /// 14 | public struct ServiceAddresses 15 | { 16 | /// 17 | /// The send manager endpoint. 18 | /// 19 | public const string SendManager = "SendManager"; 20 | } 21 | 22 | /// 23 | /// Base endpoint address. 24 | /// 25 | private const string _baseAddress = "net.pipe://localhost/MantaMTA"; 26 | 27 | /// 28 | /// Creates a ServiceHost using the specified parameters. 29 | /// 30 | /// Type that implements contact. 31 | /// Type of the contact that is implemented 32 | /// Endpoint address. 33 | /// EventHandler for service host Faulted 34 | /// ServiceHost 35 | public static ServiceHost CreateServiceHost(Type serviceType, Type implementedContract, string address, EventHandler faultedAction) 36 | { 37 | // Create the service host. 38 | ServiceHost serviceHost = new ServiceHost( 39 | serviceType, 40 | new Uri[] { new Uri(_baseAddress) } 41 | ); 42 | 43 | // Attatch it to an endpoint. 44 | serviceHost.AddServiceEndpoint(implementedContract, new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), address); 45 | 46 | // Add the faulted event handler. 47 | serviceHost.Faulted += faultedAction; 48 | 49 | // Return the service. 50 | return serviceHost; 51 | } 52 | 53 | /// 54 | /// Get a service channel. 55 | /// 56 | /// Typeof the contact to get channel for. 57 | /// Service Contract. 58 | public static T GetServiceChannel() 59 | { 60 | // Workout the endpoint address needed for contact. 61 | string serviceAddress = string.Empty; 62 | 63 | // If couldn't workout the endpoint then contact isn't implemented. 64 | if (string.IsNullOrWhiteSpace(serviceAddress)) 65 | throw new NotImplementedException(); 66 | 67 | // Create the ChannelFactory 68 | ChannelFactory pipeFactory = new ChannelFactory(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress(_baseAddress + "/" + serviceAddress)); 69 | // And finally get the channel to the service contract. 70 | return pipeFactory.CreateChannel(); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /OpenManta.Web/Controllers/API/v1/SettingsController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Web.Http; 6 | using OpenManta.Core; 7 | using OpenManta.Data; 8 | using WebInterface.Models.API.v1; 9 | 10 | namespace WebInterface.Controllers.API.v1 11 | { 12 | /// 13 | /// Summary description for Settings API 14 | /// 15 | [RoutePrefix("api/v1/Settings")] 16 | public class SettingsController : ApiController 17 | { 18 | /// 19 | /// Saves the settings. 20 | /// 21 | /// 22 | /// TRUE if updated or FALSE if update failed. 23 | [HttpPost] 24 | [Route("Update")] 25 | public bool Update(UpdateSettingsViewModel viewModel) 26 | { 27 | if (viewModel.ClientIdleTimeout < 0 || 28 | viewModel.ReceiveTimeout < 0 || 29 | viewModel.SendTimeout < 0) 30 | return false; 31 | 32 | List relayingIps = new List(); 33 | foreach (string str in viewModel.IpAddressesForRelaying) 34 | { 35 | relayingIps.Add(IPAddress.Parse(str)); 36 | } 37 | 38 | CfgPara.SetClientIdleTimeout(viewModel.ClientIdleTimeout); 39 | CfgPara.SetReceiveTimeout(viewModel.ReceiveTimeout); 40 | CfgPara.SetSendTimeout(viewModel.SendTimeout); 41 | CfgPara.SetDefaultVirtualMtaGroupID(viewModel.DefaultVirtualMtaGroupID); 42 | CfgPara.SetEventForwardingHttpPostUrl(viewModel.EventUrl); 43 | CfgPara.SetDaysToKeepSmtpLogsFor(viewModel.DaysToKeepSmtpLogsFor); 44 | CfgPara.SetMaxTimeInQueueMinutes(viewModel.MaxTimeInQueueHours * 60); 45 | CfgPara.SetRetryIntervalBaseMinutes(viewModel.RetryIntervalBase); 46 | CfgRelayingPermittedIP.SetRelayingPermittedIPAddresses(relayingIps.ToArray()); 47 | CfgPara.SetReturnPathLocalDomain(viewModel.ReturnPathLocalDomainID); 48 | 49 | var domains = CfgLocalDomains.GetLocalDomainsArray(); 50 | CfgLocalDomains.ClearLocalDomains(); 51 | foreach (string localDomain in viewModel.LocalDomains) 52 | { 53 | if (string.IsNullOrWhiteSpace(localDomain)) 54 | continue; 55 | LocalDomain ld = domains.SingleOrDefault(d => d.Hostname.Equals(localDomain, StringComparison.OrdinalIgnoreCase)); 56 | if (ld == null) 57 | ld = new LocalDomain { Hostname = localDomain.Trim() }; 58 | CfgLocalDomains.Save(ld); 59 | } 60 | 61 | return true; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /OpenManta.Data/OpenManta.Data.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {91B948F6-C85D-4846-9356-F54EB66AE280} 7 | Library 8 | OpenManta.Data 9 | OpenManta.Data 10 | v4.5 11 | 12 | 13 | true 14 | full 15 | false 16 | bin\Debug 17 | DEBUG; 18 | prompt 19 | 4 20 | false 21 | 22 | 23 | full 24 | true 25 | bin\Release 26 | prompt 27 | 4 28 | false 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | {34989F0C-49A3-4017-A8D6-3EB00B4A9487} 59 | OpenManta.Core 60 | 61 | 62 | -------------------------------------------------------------------------------- /OpenManta.Framework/RabbitMq/RabbitMqInboundQueueManager.cs: -------------------------------------------------------------------------------- 1 | using OpenManta.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | using RabbitMQ.Client.Events; 6 | 7 | namespace OpenManta.Framework.RabbitMq 8 | { 9 | internal static class RabbitMqInboundQueueManager 10 | { 11 | /// 12 | /// Dequeues a collection of inbound messages from RabbitMQ. 13 | /// 14 | /// The maximum amount of messages to dequeue. 15 | /// The dequeue messages. 16 | public static async Task> Dequeue(int maxItems) 17 | { 18 | List items = RabbitMqManager.Dequeue(RabbitMqManager.RabbitMqQueue.Inbound, maxItems, 1 * 1000); 19 | IList messages = new List(); 20 | if (items.Count == 0) 21 | return messages; 22 | 23 | foreach (BasicDeliverEventArgs ea in items) 24 | { 25 | MtaMessage msg = await Serialisation.Deserialise(ea.Body); 26 | msg.RabbitMqDeliveryTag = ea.DeliveryTag; 27 | messages.Add(msg); 28 | } 29 | 30 | return messages; 31 | } 32 | 33 | /// 34 | /// Enqueues the Email that we are going to relay in RabbitMQ. 35 | /// 36 | /// ID of the Message being Queued. 37 | /// ID of the Virtual MTA Group to send the Message through. 38 | /// ID of the Send the Message is apart of. 39 | /// The envelope mailfrom, should be return-path in most instances. 40 | /// The envelope rcpt to. 41 | /// The Email. 42 | /// Priority of message. 43 | /// True if the Email has been enqueued in RabbitMQ. 44 | public static async Task Enqueue(Guid messageID, int ipGroupID, int internalSendID, string mailFrom, string[] rcptTo, string message, RabbitMqPriority priority) 45 | { 46 | // Create the thing we are going to queue in RabbitMQ. 47 | var recordToSave = new MtaMessage 48 | { 49 | ID = messageID, 50 | InternalSendID = internalSendID, 51 | MailFrom = mailFrom, 52 | Message = message, 53 | RcptTo = rcptTo, 54 | VirtualMTAGroupID = ipGroupID, 55 | RabbitMqPriority = priority 56 | }; 57 | 58 | return await RabbitMqManager.Publish(MtaQueuedMessage.CreateNew(recordToSave), RabbitMqManager.RabbitMqQueue.InboundStaging, true, priority); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /OpenManta.Data/OutboundRuleDB.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Data.SqlClient; 5 | using OpenManta.Core; 6 | 7 | namespace OpenManta.Data 8 | { 9 | public static class OutboundRuleDB 10 | { 11 | /// 12 | /// Get the Outbound MX Patterns from the database. 13 | /// 14 | /// 15 | public static IList GetOutboundRulePatterns() 16 | { 17 | using (SqlConnection conn = MantaDB.GetSqlConnection()) 18 | { 19 | SqlCommand cmd = conn.CreateCommand(); 20 | cmd.CommandText = @" 21 | SELECT * 22 | FROM man_rle_mxPattern 23 | ORDER BY rle_mxPattern_id DESC"; // Order descending so default -1 is always at the bottom! 24 | 25 | return DataRetrieval.GetCollectionFromDatabase(cmd, CreateAndFillOutboundMxPattern); 26 | } 27 | } 28 | 29 | /// 30 | /// Get the Outbound Rules from the database. 31 | /// 32 | /// 33 | public static IList GetOutboundRules() 34 | { 35 | using (SqlConnection conn = MantaDB.GetSqlConnection()) 36 | { 37 | SqlCommand cmd = conn.CreateCommand(); 38 | cmd.CommandText = @" 39 | SELECT * 40 | FROM man_rle_rule"; 41 | 42 | return DataRetrieval.GetCollectionFromDatabase(cmd, CreateAndFillOutboundRule); 43 | } 44 | } 45 | 46 | /// 47 | /// Create and fill an OutboundMxPattern object from the Data Record. 48 | /// 49 | /// Datarecord containing values for the new object. 50 | /// OutboundMxPattern object. 51 | private static OutboundMxPattern CreateAndFillOutboundMxPattern(IDataRecord record) 52 | { 53 | OutboundMxPattern mxPattern = new OutboundMxPattern(); 54 | 55 | mxPattern.Description = record.GetStringOrEmpty("rle_mxPattern_description"); 56 | mxPattern.ID = record.GetInt32("rle_mxPattern_id"); 57 | mxPattern.Name = record.GetString("rle_mxPattern_name"); 58 | if (!record.IsDBNull("ip_ipAddress_id")) 59 | mxPattern.LimitedToOutboundIpAddressID = record.GetInt32("ip_ipAddress_id"); 60 | mxPattern.Type = (OutboundMxPatternType)record.GetInt32("rle_patternType_id"); 61 | mxPattern.Value = record.GetString("rle_mxPattern_value"); 62 | return mxPattern; 63 | } 64 | 65 | /// 66 | /// Create and fill an OutboundRule object from the Data Record. 67 | /// 68 | /// Datarecord containing values for the new object. 69 | /// OutboundRule object. 70 | private static OutboundRule CreateAndFillOutboundRule(IDataRecord record) 71 | { 72 | OutboundRule rule = new OutboundRule(record.GetInt32("rle_mxPattern_id"), (OutboundRuleType)record.GetInt32("rle_ruleType_id"), record.GetString("rle_rule_value")); 73 | 74 | return rule; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /OpenManta.Data/VirtualMtaDB.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Data.SqlClient; 5 | using OpenManta.Core; 6 | 7 | namespace OpenManta.Data 8 | { 9 | public static class VirtualMtaDB 10 | { 11 | /// 12 | /// Gets all of the MTA IP Addresses from the Database. 13 | /// 14 | /// 15 | public static IList GetVirtualMtas() 16 | { 17 | using (SqlConnection conn = MantaDB.GetSqlConnection()) 18 | { 19 | SqlCommand cmd = conn.CreateCommand(); 20 | cmd.CommandText = @" 21 | SELECT * 22 | FROM man_ip_ipAddress"; 23 | return DataRetrieval.GetCollectionFromDatabase(cmd, CreateAndFillVirtualMtaFromRecord); 24 | } 25 | } 26 | 27 | /// 28 | /// Gets a single MTA IP Addresses from the Database. 29 | /// 30 | /// 31 | public static VirtualMTA GetVirtualMta(int id) 32 | { 33 | using (SqlConnection conn = MantaDB.GetSqlConnection()) 34 | { 35 | SqlCommand cmd = conn.CreateCommand(); 36 | cmd.CommandText = @" 37 | SELECT * 38 | FROM man_ip_ipAddress 39 | WHERE ip_ipAddress_id = @id"; 40 | cmd.Parameters.AddWithValue("@id", id); 41 | return DataRetrieval.GetSingleObjectFromDatabase(cmd, CreateAndFillVirtualMtaFromRecord); 42 | } 43 | } 44 | 45 | /// 46 | /// Gets a collection of the Virtual MTAs that belong to a Virtual MTA Group from the database. 47 | /// 48 | /// ID of the Virtual MTA Group to get Virtual MTAs for. 49 | /// 50 | public static IList GetVirtualMtasInVirtualMtaGroup(int groupID) 51 | { 52 | using (SqlConnection conn = MantaDB.GetSqlConnection()) 53 | { 54 | SqlCommand cmd = conn.CreateCommand(); 55 | cmd.CommandText = @"SELECT * 56 | FROM man_ip_ipAddress as [ip] 57 | WHERE [ip].ip_ipAddress_id IN (SELECT [grp].ip_ipAddress_id FROM man_ip_groupMembership as [grp] WHERE [grp].ip_group_id = @groupID) "; 58 | cmd.Parameters.AddWithValue("@groupID", groupID); 59 | return DataRetrieval.GetCollectionFromDatabase(cmd, CreateAndFillVirtualMtaFromRecord); 60 | } 61 | } 62 | 63 | /// 64 | /// Creates a VirtualMTA object filled with the values from the DataRecord. 65 | /// 66 | /// 67 | /// 68 | private static VirtualMTA CreateAndFillVirtualMtaFromRecord(IDataRecord record) 69 | { 70 | VirtualMTA vmta = new VirtualMTA(); 71 | vmta.ID = record.GetInt32("ip_ipAddress_id"); 72 | vmta.Hostname = record.GetString("ip_ipAddress_hostname"); 73 | vmta.IPAddress = System.Net.IPAddress.Parse(record.GetString("ip_ipAddress_ipAddress")); 74 | vmta.IsSmtpInbound = record.GetBoolean("ip_ipAddress_isInbound"); 75 | vmta.IsSmtpOutbound = record.GetBoolean("ip_ipAddress_isOutbound"); 76 | return vmta; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /OpenManta.Web/Views/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 40 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /OpenManta.WebLib/BO/SendTransaction.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using OpenManta.Core; 4 | 5 | namespace OpenManta.WebLib.BO 6 | { 7 | /// 8 | /// Holds a Send Status transaction, this may be for a send or a vMTA. 9 | /// 10 | public class SendTransactionSummary 11 | { 12 | /// 13 | /// The TransactionStatus type that this object represents. 14 | /// 15 | public TransactionStatus Status { get; set; } 16 | 17 | /// 18 | /// The amount of time it has happened. 19 | /// 20 | public long Count { get; set; } 21 | 22 | public SendTransactionSummary() { } 23 | public SendTransactionSummary(TransactionStatus status, long count) 24 | { 25 | Status = status; 26 | Count = count; 27 | } 28 | } 29 | 30 | /// 31 | /// Collection of Send Transaction Summaries. 32 | /// 33 | public class SendTransactionSummaryCollection : List 34 | { 35 | public SendTransactionSummaryCollection() { } 36 | public SendTransactionSummaryCollection(IEnumerable collection) : base(collection) { } 37 | 38 | /// 39 | /// The amount of attempts to send that have been made. 40 | /// 41 | private long Attempts 42 | { 43 | get 44 | { 45 | return this.Sum(ts => ts.Count); 46 | } 47 | } 48 | 49 | /// 50 | /// The amount of send attempts that have resulted in the remote MX accepting the message. 51 | /// 52 | public long Accepted 53 | { 54 | get 55 | { 56 | return this.Where(ts => ts.Status == TransactionStatus.Success).Sum(ts => ts.Count); 57 | } 58 | } 59 | 60 | /// 61 | /// The amount of send attempts that resulted in the remote MX rejecting the message. 62 | /// 63 | public long Rejected 64 | { 65 | get 66 | { 67 | return this.Where(ts => ts.Status == TransactionStatus.Discarded || 68 | ts.Status == TransactionStatus.Failed || 69 | ts.Status == TransactionStatus.TimedOut).Sum(ts => ts.Count); 70 | } 71 | } 72 | 73 | /// 74 | /// The percentage of send attempts that where throttled by MantaMTA. 75 | /// 76 | public double ThrottledPercent 77 | { 78 | get 79 | { 80 | if (this.Attempts < 1) 81 | return 0; 82 | long throttled = this.Where(ts => ts.Status == TransactionStatus.Throttled).Sum(ts => ts.Count); 83 | return (100d / Attempts) * throttled; 84 | } 85 | } 86 | 87 | /// 88 | /// The percentage of send attempts that resulted in the remote server temporarily rejecting the message. 89 | /// 90 | public double DeferredPercent 91 | { 92 | get 93 | { 94 | if (this.Attempts < 1) 95 | return 0; 96 | long deferred = this.Where(ts => ts.Status == TransactionStatus.Deferred).Sum(ts => ts.Count); 97 | return (100d / Attempts) * deferred; 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /OpenManta.Framework/Serialisation.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.IO; 4 | using System.IO.Compression; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace OpenManta.Framework 9 | { 10 | /// 11 | /// Provides methods to (de)serialise .Net objects to JSON and back. 12 | /// 13 | internal static class Serialisation 14 | { 15 | /// 16 | /// Deserialises the JSON or gzipped JSON to an object of type. 17 | /// 18 | /// Type of object to deserialise to. 19 | /// JSON or gziped JSON bytes. 20 | /// An object of T, with deserialised values. 21 | public static async Task Deserialise(byte[] obj) 22 | { 23 | // Will hold the JSON to deserialise. 24 | string json = string.Empty; 25 | 26 | try 27 | { 28 | // Attempt to decompress the bytes, if exception is thrown then not compressed. 29 | using (var msCompressed = new MemoryStream(obj)) 30 | { 31 | using (var msUncompressed = new MemoryStream()) 32 | { 33 | using (var gs = new GZipStream(msCompressed, CompressionMode.Decompress)) 34 | { 35 | await gs.CopyToAsync(msUncompressed); 36 | } 37 | 38 | json = Encoding.UTF8.GetString(msUncompressed.ToArray()); 39 | } 40 | } 41 | } 42 | catch (Exception) 43 | { 44 | // Not compressed so just get the string. 45 | json = Encoding.UTF8.GetString(obj); 46 | } 47 | 48 | // Return the deserialised object. 49 | return JsonConvert.DeserializeObject(json); 50 | } 51 | 52 | /// 53 | /// Serialise the object to JSON. Will gzip the JSON by default. 54 | /// 55 | /// Object to serialise. 56 | /// If true will return compress the JSON with gzip. 57 | /// Byte array of JSON or gizped JSON. 58 | public static async Task Serialise(object obj, bool compress = true) 59 | { 60 | // Serialise the object. 61 | string json = JsonConvert.SerializeObject(obj); 62 | byte[] bytes = Encoding.UTF8.GetBytes(json); 63 | 64 | // Not compressing so just return the JSON. 65 | if (!compress) 66 | return bytes; 67 | 68 | // Do the Compression. 69 | using (var msUncompressed = new MemoryStream(bytes)) 70 | { 71 | using (var msCompressed = new MemoryStream()) 72 | { 73 | using (var gzip = new GZipStream(msCompressed, CompressionMode.Compress)) 74 | { 75 | await msUncompressed.CopyToAsync(gzip); 76 | } 77 | 78 | return msCompressed.ToArray(); 79 | } 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /OpenManta.Framework/RabbitMq/RabbitMqOutboundQueueManager.cs: -------------------------------------------------------------------------------- 1 | using OpenManta.Core; 2 | using RabbitMQ.Client.Events; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace OpenManta.Framework.RabbitMq 9 | { 10 | internal static class RabbitMqOutboundQueueManager 11 | { 12 | /// 13 | /// Dequeue a message from RabbitMQ. 14 | /// 15 | /// A dequeued message or null if there weren't any. 16 | public static async Task Dequeue() 17 | { 18 | BasicDeliverEventArgs ea = null; 19 | try 20 | { 21 | ea = RabbitMqManager.Dequeue(RabbitMqManager.RabbitMqQueue.OutboundWaiting, 1, 100).FirstOrDefault(); 22 | } 23 | catch (Exception) 24 | { 25 | ea = null; 26 | } 27 | if (ea == null) 28 | return null; 29 | 30 | MtaQueuedMessage qmsg = await Serialisation.Deserialise(ea.Body); 31 | qmsg.RabbitMqDeliveryTag = ea.DeliveryTag; 32 | qmsg.IsHandled = false; 33 | return qmsg; 34 | } 35 | 36 | /// 37 | /// Enqueue the messages in the collection for relaying. 38 | /// 39 | /// Messages to enqueue. 40 | public static void Enqueue(IList inboundMessages) 41 | { 42 | Parallel.ForEach(inboundMessages, message => { 43 | Enqueue(MtaQueuedMessage.CreateNew(message)).Wait(); 44 | }); 45 | 46 | RabbitMqManager.Ack(RabbitMqManager.RabbitMqQueue.Inbound, inboundMessages.Max(m => m.RabbitMqDeliveryTag), true); 47 | } 48 | 49 | /// 50 | /// Enqueue the message for relaying. 51 | /// 52 | /// Message to enqueue. 53 | public static async Task Enqueue(MtaQueuedMessage msg) 54 | { 55 | RabbitMqManager.RabbitMqQueue queue = RabbitMqManager.RabbitMqQueue.OutboundWaiting; 56 | 57 | int secondsUntilNextAttempt = (int)Math.Ceiling((msg.AttemptSendAfterUtc - DateTime.UtcNow).TotalSeconds); 58 | 59 | if (secondsUntilNextAttempt > 0) 60 | { 61 | if (secondsUntilNextAttempt < 10) 62 | queue = RabbitMqManager.RabbitMqQueue.OutboundWait1; 63 | else if (secondsUntilNextAttempt < 60) 64 | queue = RabbitMqManager.RabbitMqQueue.OutboundWait10; 65 | else if (secondsUntilNextAttempt < 300) 66 | queue = RabbitMqManager.RabbitMqQueue.OutboundWait60; 67 | else 68 | queue = RabbitMqManager.RabbitMqQueue.OutboundWait300; 69 | } 70 | 71 | var published = await RabbitMqManager.Publish(msg, queue, priority: msg.RabbitMqPriority); 72 | 73 | if (published) 74 | msg.IsHandled = true; 75 | 76 | return published; 77 | } 78 | /// 79 | /// Acknowledge the message as handled. 80 | /// 81 | /// The message to acknowledge. 82 | internal static void Ack(MtaQueuedMessage msg) 83 | { 84 | RabbitMqManager.Ack(RabbitMqManager.RabbitMqQueue.OutboundWaiting, msg.RabbitMqDeliveryTag, false); 85 | } 86 | } 87 | } 88 | --------------------------------------------------------------------------------