protected override void OnStart(string[] args) { Logging.Info("Starting OpenManta Service."); AppDomain.CurrentDomain.UnhandledException += delegate(object sender, UnhandledExceptionEventArgs e) { Exception ex = (Exception)e.ExceptionObject; Logging.Fatal(ex.Message, ex); }; RabbitMqInboundStagingHandler.Start(); // Start the RabbitMQ Bulk inserter. QueueManager.Instance.Start(); // Create the SmtpServers foreach (var vmta in VirtualMtaManager.GetVirtualMtasForListeningOn()) { foreach (var port in MtaParameters.ServerListeningPorts) { SmtpServers.Add(new SmtpServer(vmta.IPAddress, port)); } } // Start the SMTP Client. MessageSender.Instance.Start(); // Start the events (bounce/abuse) handler. EventsFileHandler.Instance.Start(); Logging.Info("OpenManta Service has started."); }
protected override void OnStart(string[] args) { RabbitMqInboundStagingHandler.Start(); Logging.Info("Starting Manta MTA Service."); AppDomain.CurrentDomain.UnhandledException += delegate(object sender, UnhandledExceptionEventArgs e) { Exception ex = (Exception)e.ExceptionObject; Logging.Fatal(ex.Message, ex); }; // Start the RabbitMQ Bulk inserter. QueueManager.Instance.Start(); VirtualMTACollection ipAddresses = VirtualMtaManager.GetVirtualMtasForListeningOn(); // Create the SmtpServers for (int c = 0; c < ipAddresses.Count; c++) { VirtualMTA ipAddress = ipAddresses[c]; for (int i = 0; i < MtaParameters.ServerListeningPorts.Length; i++) { _SmtpServers.Add(new SmtpServer(ipAddress.IPAddress, MtaParameters.ServerListeningPorts[i])); } } // Start the SMTP Client. MessageSender.Instance.Start(); // Start the events (bounce/abuse) handler. EventsFileHandler.Instance.Start(); Logging.Info("Manta MTA Service has started."); }
static void Main(string[] args) { Logging.Info("MTA Started"); AppDomain.CurrentDomain.FirstChanceException += delegate(object sender, FirstChanceExceptionEventArgs e) { Logging.Warn("", e.Exception); }; IList <VirtualMTA> ipAddresses = VirtualMtaManager.GetVirtualMtasForListeningOn(); // Array will hold all instances of SmtpServer, one for each port we will be listening on. List <SmtpServer> smtpServers = new List <SmtpServer>(); // Create the SmtpServers for (int c = 0; c < ipAddresses.Count; c++) { VirtualMTA ipAddress = ipAddresses[c]; for (int i = 0; i < MtaParameters.ServerListeningPorts.Length; i++) { smtpServers.Add(new SmtpServer(ipAddress.IPAddress, MtaParameters.ServerListeningPorts[i])); } } // Start the SMTP Client. MessageSender.Instance.Start(); // Start the events (bounce/abuse) handler. EventsFileHandler.Instance.Start(); QueueManager.Instance.Start(); OpenManta.Framework.RabbitMq.RabbitMqInboundStagingHandler.Start(); bool quit = false; while (!quit) { ConsoleKeyInfo key = System.Console.ReadKey(true); if (key.KeyChar == 'q' || key.KeyChar == 'Q') { quit = true; } } // Need to wait while servers & client shutdown. MantaCoreEvents.InvokeMantaCoreStopping(); foreach (SmtpServer s in smtpServers) { s.Dispose(); } Logging.Info("MTA Stopped"); System.Console.WriteLine("Press any key to continue"); System.Console.ReadKey(true); }
private async Task <bool> SendMessageAsync(MtaQueuedMessage msg) { // Check that the message next attempt after has passed. if (msg.AttemptSendAfterUtc > DateTime.UtcNow) { RabbitMqOutboundQueueManager.Enqueue(msg); await Task.Delay(50); // To prevent a tight loop within a Task thread we should sleep here. return(false); } if (await MtaTransaction.HasBeenHandledAsync(msg.ID)) { msg.IsHandled = true; return(true); } // Get the send that this message belongs to so that we can check the send state. Send snd = await SendManager.Instance.GetSendAsync(msg.InternalSendID); switch (snd.SendStatus) { // The send is being discarded so we should discard the message. case SendStatus.Discard: await msg.HandleMessageDiscardAsync(); return(false); // The send is paused, the handle pause state will delay, without deferring, the message for a while so we can move on to other messages. case SendStatus.Paused: msg.HandleSendPaused(); return(false); // Send is active so we don't need to do anything. case SendStatus.Active: break; // Unknown send state, requeue the message and log error. Cannot send! default: msg.AttemptSendAfterUtc = DateTime.UtcNow.AddMinutes(1); RabbitMqOutboundQueueManager.Enqueue(msg); Logging.Error("Failed to send message. Unknown SendStatus[" + snd.SendStatus + "]!"); return(false); } bool result; // Check the message hasn't timed out. If it has don't attempt to send it. // Need to do this here as there may be a massive backlog on the server // causing messages to be waiting for ages after there AttemptSendAfter // before picking up. The MAX_TIME_IN_QUEUE should always be enforced. if (msg.AttemptSendAfterUtc - msg.QueuedTimestampUtc > new TimeSpan(0, MtaParameters.MtaMaxTimeInQueue, 0)) { await msg.HandleDeliveryFailAsync(MtaParameters.TIMED_OUT_IN_QUEUE_MESSAGE, null, null); result = false; } else { MailAddress mailAddress = new MailAddress(msg.RcptTo[0]); MailAddress mailFrom = new MailAddress(msg.MailFrom); MXRecord[] mXRecords = DNSManager.GetMXRecords(mailAddress.Host); // If mxs is null then there are no MX records. if (mXRecords == null || mXRecords.Length < 1) { await msg.HandleDeliveryFailAsync("550 Domain Not Found.", null, null); result = false; } else if (IsMxBlacklisted(mXRecords)) { await msg.HandleDeliveryFailAsync("550 Domain blacklisted.", null, mXRecords[0]); result = false; } else { // The IP group that will be used to send the queued message. VirtualMtaGroup virtualMtaGroup = VirtualMtaManager.GetVirtualMtaGroup(msg.VirtualMTAGroupID); VirtualMTA sndIpAddress = virtualMtaGroup.GetVirtualMtasForSending(mXRecords[0]); SmtpOutboundClientDequeueResponse dequeueResponse = await SmtpClientPool.Instance.DequeueAsync(sndIpAddress, mXRecords); switch (dequeueResponse.DequeueResult) { case SmtpOutboundClientDequeueAsyncResult.Success: case SmtpOutboundClientDequeueAsyncResult.NoMxRecords: case SmtpOutboundClientDequeueAsyncResult.FailedToAddToSmtpClientQueue: case SmtpOutboundClientDequeueAsyncResult.Unknown: break; // Don't need to do anything for these results. case SmtpOutboundClientDequeueAsyncResult.FailedToConnect: await msg.HandleFailedToConnectAsync(sndIpAddress, mXRecords[0]); break; case SmtpOutboundClientDequeueAsyncResult.ServiceUnavalible: await msg.HandleServiceUnavailableAsync(sndIpAddress); break; case SmtpOutboundClientDequeueAsyncResult.Throttled: await msg.HandleDeliveryThrottleAsync(sndIpAddress, mXRecords[0]); break; case SmtpOutboundClientDequeueAsyncResult.FailedMaxConnections: msg.AttemptSendAfterUtc = DateTime.UtcNow.AddSeconds(2); RabbitMqOutboundQueueManager.Enqueue(msg); break; } SmtpOutboundClient smtpClient = dequeueResponse.SmtpOutboundClient; // If no client was dequeued then we can't currently send. // This is most likely a max connection issue. Return false but don't // log any deferal or throttle. if (smtpClient == null) { result = false; } else { try { Action <string> failedCallback = delegate(string smtpResponse) { // If smtpRespose starts with 5 then perm error should cause fail if (smtpResponse.StartsWith("5")) { msg.HandleDeliveryFailAsync(smtpResponse, sndIpAddress, smtpClient.MXRecord).Wait(); } else { // If the MX is actively denying use service access, SMTP code 421 then we should inform // the ServiceNotAvailableManager manager so it limits our attepts to this MX to 1/minute. if (smtpResponse.StartsWith("421")) { ServiceNotAvailableManager.Add(smtpClient.SmtpStream.LocalAddress.ToString(), smtpClient.MXRecord.Host, DateTime.UtcNow); msg.HandleDeliveryDeferral(smtpResponse, sndIpAddress, smtpClient.MXRecord, true); } else { // Otherwise message is deferred msg.HandleDeliveryDeferral(smtpResponse, sndIpAddress, smtpClient.MXRecord, false); } } throw new SmtpTransactionFailedException(); }; // Run each SMTP command after the last. await smtpClient.ExecHeloOrRsetAsync(failedCallback); await smtpClient.ExecMailFromAsync(mailFrom, failedCallback); await smtpClient.ExecRcptToAsync(mailAddress, failedCallback); await smtpClient.ExecDataAsync(msg.Message, failedCallback, async (response) => { await msg.HandleDeliverySuccessAsync(sndIpAddress, smtpClient.MXRecord, response); }); SmtpClientPool.Instance.Enqueue(smtpClient); result = true; } catch (SmtpTransactionFailedException) { // Exception is thrown to exit transaction, logging of deferrals/failers already handled. result = false; } catch (Exception ex) { Logging.Error("MessageSender error.", ex); if (msg != null) { msg.HandleDeliveryDeferral("Connection was established but ended abruptly.", sndIpAddress, smtpClient.MXRecord, false); } result = false; } finally { if (smtpClient != null) { smtpClient.IsActive = false; smtpClient.LastActive = DateTime.UtcNow; } } } } } return(result); }