private void OnSubmittedMessageHandler(SubmittedMessageEventSource source, QueuedMessageEventArgs e) { Logger.Debug("[GenericExchangeTransportagent] [RoutingAgent] OnSubmittedMessage fired..."); var emailItem = new EmailItem(e.MailItem); _config.RoutingAgentConfig.OnSubmittedMessage.ToList().ForEach( x => { try { x.Execute(emailItem); } catch (Exception ex) { Logger.Error(ex, @"Error Executing ""OnSubmittedMessage"""); } }); if (emailItem.ShouldBeDeletedFromQueue) { source.Delete(); } }
private void OnSubmittedMessageHandler(SubmittedMessageEventSource source, QueuedMessageEventArgs e) { Logger.Debug("[GenericTransportAgent] RoutingAgent - OnSubmittedMessage fired..."); var emailItem = new EmailItem(e.MailItem); foreach (var x in Configuration.Config.RoutingAgentConfig.OnSubmittedMessage) { try { x.Execute(emailItem); } catch (Exception ex) { Logger.Error(ex, @"Error Executing ""OnSubmittedMessage"""); } } if (emailItem.ShouldBeDeletedFromQueue) { source.Delete(); } }
private void OnOnSubmittedMessage(SubmittedMessageEventSource source, QueuedMessageEventArgs queuedMessageEventArgs) { lock (_fileLock) { AgentAsyncContext agentAsyncContext = null; try { var mailItem = queuedMessageEventArgs.MailItem; agentAsyncContext = GetAgentAsyncContext(); // check the sender whitelist if (_exchangeAttachmentFilterConfig.SendersWhitelist.Any( f => Regex.IsMatch(mailItem.FromAddress.ToString(), WildcardToRegex(f)))) { return; } // maybe we will need list of recipients on single line... var recipientList = new StringBuilder(); for (var i = 0; i < mailItem.Recipients.Count; i++) { recipientList.Append(i == 0 ? mailItem.Recipients[i].Address.ToString() : "; " + mailItem.Recipients[i].Address); } var removedAttachments = new List <Attachment>(); var strippedAttachments = new List <Attachment>(); var messageRejected = false; var messageLogStringBuilder = new SysLogBuilder(); var mailItemStatusText = $"[from: {mailItem.FromAddress}] [to: {recipientList}] [method: {mailItem.InboundDeliveryMethod}] [subject: {mailItem.Message.Subject}] [size: {mailItem.MimeStreamLength.ToString("N0")}]"; messageLogStringBuilder.Log(mailItemStatusText); if (mailItem.Message.Attachments.Count == 0 && _exchangeAttachmentFilterConfig.LogAccepted) { messageLogStringBuilder.LogPadded( "ACCEPTED: [reason: no attachments]"); } else { foreach (var attachment in mailItem.Message.Attachments) { // It would be great idea to process only attachments with size greater // than some threshold, 'cos infected files are always quite small (only few kB) // But I am not sure how to get the attachment size here, ... // if (any previous) attachment rejected the message then break the processing now if (messageRejected) { break; } AttachmentFilterStatus attachmentStatus = null; if (_exchangeAttachmentFilterConfig.DsnStripOriginalMessage) { // DSN has InboundDeliveryMethod equal to DeliveryMethod.File and FromAddress is equal to <> // and DSN's original message is included as message/rfc822 attachment if (mailItem.InboundDeliveryMethod == DeliveryMethod.File && mailItem.FromAddress.ToString() == "<>" && attachment.ContentType.ToLower().Equals("message/rfc822")) { attachmentStatus = new AttachmentFilterStatus(AttachmentFilterStatusEnum.StripAttachment, "DSN original message"); } } if (attachmentStatus == null) { // default file status (by extension) attachmentStatus = FilenameFilterStatus(attachment.FileName); // is it archive? if (_exchangeAttachmentFilterConfig.ScanArchives && IsArchive(attachment.FileName)) { var archiveStatus = ProcessArchiveStream(attachment.GetContentReadStream()); if (archiveStatus.Status > attachmentStatus.Status) { attachmentStatus = archiveStatus; } } // is it OpenXml document? if (_exchangeAttachmentFilterConfig.ScanOpenXmlDocuments && IsOpenXmlDocument(attachment.FileName)) { var openXmlDocumentStatus = ProcessOpenXmlDocumentStream(attachment.GetContentReadStream()); if (openXmlDocumentStatus.Status > attachmentStatus.Status) { attachmentStatus = openXmlDocumentStatus; } } } var attachmentStatusText = $"[file: {attachment.FileName}] [type: {attachment.AttachmentType}] [content type:{attachment.ContentType}] [reason: {attachmentStatus.Reason}]"; switch (attachmentStatus.Status) { case AttachmentFilterStatusEnum.Accept: if (_exchangeAttachmentFilterConfig.LogAccepted) { messageLogStringBuilder.LogPadded($"ACCEPTED: {attachmentStatusText}"); } break; case AttachmentFilterStatusEnum.RemoveAttachment: // just mark this attachment for removement, but do not touch attachments collection now // (we are in foreach loop and need to process them all) removedAttachments.Add(attachment); if (_exchangeAttachmentFilterConfig.LogRejectedOrRemoved) { messageLogStringBuilder.LogPadded($"REMOVED: {attachmentStatusText}"); } break; case AttachmentFilterStatusEnum.StripAttachment: // just mark this attachment for removement, but do not touch attachments collection now // (we are in foreach loop and need to process them all) strippedAttachments.Add(attachment); if (_exchangeAttachmentFilterConfig.LogRejectedOrRemoved) { messageLogStringBuilder.LogPadded($"STRIPPED: {attachmentStatusText}"); } break; case AttachmentFilterStatusEnum.RejectMessage: // reject whole message if (_exchangeAttachmentFilterConfig.LogRejectedOrRemoved) { messageLogStringBuilder.LogPadded($"REJECTED: {attachmentStatusText}"); } messageRejected = true; break; } } } if (messageLogStringBuilder.MessageCount > 1) { SysLog.Log(messageLogStringBuilder); } // reject the message? if (messageRejected) { // delete the source message and do nothing more (we do not send DSN)... source.Delete(); return; } // for every attachment we marked as being removed create new txt attachment with some info why it happened... foreach (var removedAttachment in removedAttachments) { // new attachment filename var newFileName = $"{_exchangeAttachmentFilterConfig.RemovedAttachmentPrefix}{removedAttachment.FileName}.txt"; // add new attachment to the message... var newAttachment = mailItem.Message.Attachments.Add(newFileName); // ...and write content into it (info message) var newAttachmentWriter = new StreamWriter(newAttachment.GetContentWriteStream()); newAttachmentWriter.WriteLine(removedAttachment.FileName); newAttachmentWriter.WriteLine(); newAttachmentWriter.WriteLine(_exchangeAttachmentFilterConfig.RemovedAttachmentNewContent); newAttachmentWriter.Flush(); newAttachmentWriter.Close(); } // finally remove all attachments marked for removal foreach (var removedAttachment in removedAttachments) { mailItem.Message.Attachments.Remove(removedAttachment); } // ...and stripped attachments, too foreach (var strippedAttachment in strippedAttachments) { mailItem.Message.Attachments.Remove(strippedAttachment); } } catch (IOException ex) { SysLog.Log("IOException: " + ex.Message); } catch (Exception ex) { SysLog.Log("Exception: " + ex.Message); } finally { agentAsyncContext?.Complete(); } } }