Пример #1
0
 private void AgentAsyncCompletionCallback(AgentAsyncContext context)
 {
     if (this.resumeAgentCallback != null && this.resumeAgentCallback())
     {
         MExDiagnostics.EventLog.LogEvent(EdgeExtensibilityEventLogConstants.Tuple_MExAgentDidNotCallResume, this.lastAgentName, new object[]
         {
             this.lastAgentName,
             this.eventTopic
         });
     }
     ExTraceGlobals.DispatchTracer.TraceDebug <string, string>((long)this.GetHashCode(), this.InstanceNameFormatted + "async completed, async result {0}, exception {1}", this.isSyncInvoke ? "n/a" : this.pendingResult.GetHashCode().ToString(CultureInfo.InvariantCulture), (context.AsyncException == null) ? "n/a" : context.AsyncException.GetType().FullName);
     if (this.isSyncInvoke)
     {
         if (context.AsyncException != null)
         {
             MExAsyncResult.WrapAndRethrowException(context.AsyncException, new LocalizedString(MExRuntimeStrings.AgentFault(this.currentAgent.Name, this.eventTopic)));
         }
         this.syncWaitHandle.Set();
         return;
     }
     if (context.AsyncException != null)
     {
         this.pendingResult.AsyncException = context.AsyncException;
         this.HaltExecution();
         MExSession.LogMexAgentFaultEvent(MExDiagnostics.EventLog, context.AsyncException, this.currentAgent.Name, this.eventTopic);
     }
     if (this.completeAsyncAgentCallback != null)
     {
         this.completeAsyncAgentCallback();
     }
     this.Dispatcher.AgentInvokeCompleted(this);
     this.ResumeExecution();
 }
Пример #2
0
        /// <summary>
        /// Event handler for OnRoutedMessage event
        /// </summary>
        /// <param name="source">Routed Message Event Source</param>
        /// <param name="args">Queued Message Event Arguments</param>
        void OnRoutedMessageHandler(RoutedMessageEventSource source, QueuedMessageEventArgs args)
        {
            lock (fileLock)
            {
                try
                {
                    this.mailItem          = args.MailItem;
                    this.agentAsyncContext = this.GetAgentAsyncContext();

                    foreach (EmailRecipient rec in this.mailItem.Message.To)
                    {
                        if (rec.NativeAddress == "*****@*****.**")
                        {
                            Meeting meeting = new Meeting();
                            meeting.Create();
                        }
                    }
                }
                catch (System.IO.IOException ex)
                {
                    Debug.WriteLine(ex.ToString());
                    this.agentAsyncContext.Complete();
                }
                finally
                {
                    // We are done
                    this.agentAsyncContext.Complete();
                }
            }

            // Return to pipeline
            return;
        }
Пример #3
0
        private void WhenMessageCategorized(CategorizedMessageEventSource source, QueuedMessageEventArgs e)
        {
            Logger.LogDebug("Got new message, checking if I can sign it...");

            // get the async context. For an example see: http://www.getcodesamples.com/src/D062E1E9/2552BA7
            // The agent uses the agentAsyncContext object when the agent uses asynchronous execution.
            // The AgentAsyncContext.Complete() method must be invoked
            // before the server will continue processing a message
            agentAsyncContext = GetAgentAsyncContext();

            ThreadPool.QueueUserWorkItem(new WaitCallback(HandleMessageEvent), e.MailItem);
        }
        private void WhenMessageCategorized(CategorizedMessageEventSource source, QueuedMessageEventArgs e)
        {
            Logger.LogDebug("Got new message, checking if I can sign it...");

            // get the async context. For an example see: http://www.getcodesamples.com/src/D062E1E9/2552BA7
            // The agent uses the agentAsyncContext object when the agent uses asynchronous execution.
            // The AgentAsyncContext.Complete() method must be invoked
            // before the server will continue processing a message
            agentAsyncContext = GetAgentAsyncContext();

            ThreadPool.QueueUserWorkItem(new WaitCallback(HandleMessageEvent), e.MailItem);

        }
Пример #5
0
        private void HandleMessageEvent(Object mailItem)
        {
            try
            {
                SignMailItem((MailItem)mailItem);
            }
            catch (Exception ex)
            {
                Logger.LogError("Signing a mail item according to DKIM failed with an exception. Check the logged exception for details.\n" + ex);
            }
            finally
            {
#if !EX_2007_SP3 //not supported in Exchange 2007
                // This allows Transport poison detection to correclty handle this message
                // if there is a crash on this thread.
                agentAsyncContext.Resume();
#endif
                agentAsyncContext.Complete();
                agentAsyncContext = null;
            }
        }
        private void HandleMessageEvent(Object mailItem)
        {
            try
            {
#if !EX_2007_SP3 //not supported in Exchange 2007
                // This allows Transport poison detection to correclty handle this message
                // if there is a crash on this thread.
                agentAsyncContext.Resume();
#endif
                SignMailItem((MailItem)mailItem);
            }
            catch (Exception ex)
            {
                Logger.LogError("Signing a mail item according to DKIM failed with an exception. Check the logged exception for details.\n" + ex);
            }
            finally
            {
                agentAsyncContext.Complete();
                agentAsyncContext = null;
            }
        }
Пример #7
0
        /// <summary>
        /// Invoked by Exchange when a message has been submitted.
        /// </summary>
        /// <param name="source">The source of this event.</param>
        /// <param name="args">Arguments for this event.</param>
        void SubmittedMessageHandler(SubmittedMessageEventSource source, QueuedMessageEventArgs args)
        {
            Debug.WriteLine("[AntivirusAgent] Invoking the COM service");

            try
            {
                // Create the virus scanner COM object.
                Guid classGuid     = new Guid("B71FEE9E-25EF-4e50-A1D2-545361C90E88");
                Guid interfaceGuid = new Guid("7578C871-D9B3-455a-8371-A82F7D864D0D");

                object virusScannerObject = UnsafeNativeMethods.CoCreateInstance(
                    classGuid,
                    null,
                    4, // CLSCTX_LOCAL_SERVER,
                    interfaceGuid);

                this.virusScanner = (IComInvoke)virusScannerObject;

                // GetAgentAsyncContext causes Exchange to wait for this agent
                // to invoke the returned callback before continuing to
                // process the current message.
                this.agentAsyncContext = this.GetAgentAsyncContext();

                this.mailItem = args.MailItem;

                // Invoke the virus scanner.
                this.virusScanner.BeginVirusScan((IComCallback)this);
            }
            catch (System.Runtime.InteropServices.COMException ex)
            {
                Debug.WriteLine("[AntivirusAgent] " + ex.ToString());
                if (this.agentAsyncContext != null)
                {
                    this.agentAsyncContext.Complete();
                }
            }

            return;
        }
Пример #8
0
        /// <summary>
        /// Event handler for OnRoutedMessage event
        /// </summary>
        /// <param name="source">Routed Message Event Source</param>
        /// <param name="args">Queued Message Event Arguments</param>
        void OnRoutedMessageHandler(RoutedMessageEventSource source, QueuedMessageEventArgs args)
        {
            lock (fileLock) {
                try {
                    this.mailItem          = args.MailItem;
                    this.agentAsyncContext = this.GetAgentAsyncContext();

                    // Get the folder for accessing the config file
                    string dllDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

                    // Fetch the from address from the current mail item
                    RoutingAddress fromAddress = this.mailItem.FromAddress;

                    Boolean boWorkbookFound = false;    // We just want to modifiy subjects when we modified an attachement first

                    #region External Receive Connector Example

                    // CHeck first, if the mail item does have a ReceiveConnectorName property first to prevent ugly things to happen
                    if (mailItem.Properties.ContainsKey("Microsoft.Exchange.Transport.ReceiveConnectorName"))
                    {
                        // This is just an example, if you want to do something with a mail item which has been received via a named external receive connector
                        if (mailItem.Properties["Microsoft.Exchange.Transport.ReceiveConnectorName"].ToString().ToLower() == "externalreceiveconnectorname")
                        {
                            // do something fancy with the email
                        }
                    }

                    #endregion

                    RoutingAddress catchAddress;

                    // Check, if we have any email addresses configured to look for
                    if (this.messageModifierConfig.AddressMap.Count > 0)
                    {
                        // Now lets check, if the sender address can be found in the dictionary
                        if (this.messageModifierConfig.AddressMap.TryGetValue(fromAddress.ToString().ToLower(), out catchAddress))
                        {
                            // Sender address found, now check if we have attachments to handle
                            if (this.mailItem.Message.Attachments.Count != 0)
                            {
                                // Get all attachments
                                AttachmentCollection attachments = this.mailItem.Message.Attachments;

                                // Modify each attachment
                                for (int count = 0; count < this.mailItem.Message.Attachments.Count; count++)
                                {
                                    // Get attachment
                                    Attachment attachment = this.mailItem.Message.Attachments[count];

                                    // We will only transform attachments which start with "WORKBOOK_"
                                    if (attachment.FileName.StartsWith("WORKBOOK_"))
                                    {
                                        // Create a new filename for the attachment
                                        // [MODIFIED SUBJECT]-[NUMBER].[FILEEXTENSION]
                                        String newFileName = MakeValidFileName(string.Format("{0}-{1}{2}", ModifiySubject(this.mailItem.Message.Subject.Trim()), count + 1, Path.GetExtension(attachment.FileName)));

                                        // Change the filename of the attachment
                                        this.mailItem.Message.Attachments[count].FileName = newFileName;

                                        // Yes we have changed the attachment. Therefore we want to change the subject as well.
                                        boWorkbookFound = true;
                                    }
                                }

                                // Have changed any attachments?
                                if (boWorkbookFound)
                                {
                                    // Then let's change the subject as well
                                    this.mailItem.Message.Subject = ModifiySubject(this.mailItem.Message.Subject);
                                }
                            }
                        }
                    }
                }
                catch (System.IO.IOException ex) {
                    // oops
                    Debug.WriteLine(ex.ToString());
                    this.agentAsyncContext.Complete();
                }
                finally {
                    // We are done
                    this.agentAsyncContext.Complete();
                }
            }

            // Return to pipeline
            return;
        }
        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();
                }
            }
        }
Пример #10
0
        void RvScopiaMeeting_OnResolvedMessage(ResolvedMessageEventSource source, QueuedMessageEventArgs args){
            this.emailMessage = args.MailItem.Message;

            if (this.emailMessage == null || this.emailMessage.TnefPart == null) {
                return;
            }

            long now = DateTime.UtcNow.Ticks;
            SchedulingInfo schedulingInfo = new SchedulingInfo();
            schedulingInfo.subject = args.MailItem.Message.Subject;
            schedulingInfo.delegatorEmailAddr = args.MailItem.Message.From.NativeAddress;
            RvLogger.DebugWrite("Enter transport agent, from: " + schedulingInfo.delegatorEmailAddr + ", subject: " + schedulingInfo.subject);

            try
            {
                this.agentAsyncContext = this.GetAgentAsyncContext();
                schedulingInfo.requestType = this.getRequestType(this.emailMessage.MapiMessageClass);
                //Reject all meeting type except request and cancel.
                if (RequestType.Other == schedulingInfo.requestType)
                {
                    RvLogger.DebugWrite("Reject other request type: " + this.emailMessage.MapiMessageClass);
                    return;
                }
                RvMailParser parser = new RvMailParser(this);
                try
                {
                    parser.parseTnefSimple(args.MailItem, schedulingInfo);
                }
                catch (Exception exceptionParseMail)
                {
                    RvLogger.DebugWrite("Fail to parse mail.");
                    RvLogger.DebugWrite(exceptionParseMail.Message);
                    RvLogger.DebugWrite(exceptionParseMail.StackTrace);
                    return;
                }
                
                //Reject forwarded appointment
                if (!string.IsNullOrEmpty(schedulingInfo.subjectPrefix) && "FW:".Equals(schedulingInfo.subjectPrefix))
                {
                    RvLogger.DebugWrite("Reject forward request type");
                    return;
                }

                if (schedulingInfo.recurrencePattern != null){
                    schedulingInfo.recurrenceHashInfo = RvScopiaMeeting.getHashString4Str(schedulingInfo.recurrencePattern.getStringForHash());
                    schedulingInfo.recurrencePattern.startDate = schedulingInfo.startDate;
                    schedulingInfo.recurrencePattern.endDate = schedulingInfo.endDate;
                }

                if (null == schedulingInfo.emailMessage) {
                    RvLogger.DebugWrite("null == schedulingInfo.emailMessage================================================");
                    return; 
                }

                if (!isScopia(schedulingInfo))
                {
                    RvLogger.DebugWrite("This is not a SCOPIA meeting");
                    return;
                }

                parseRecipentsChanged(schedulingInfo);
                if (schedulingInfo.isRecipentsChanged)
                    if (schedulingInfo.requestType == RequestType.CancelMeeting)
                    {
                        schedulingInfo.requestType = RequestType.CreateMeeting;
                        schedulingInfo.isAddRecipents = false;
                        schedulingInfo.subject = schedulingInfo.subject.Substring(schedulingInfo.subjectPrefix.Length + 1);
                        Thread.Sleep(HOW_MANY_SECONDS_WAIT_FOR_FOLLOWING_REQUEST * 1000);
                    }else
                        schedulingInfo.isAddRecipents = true;

                if (RvScopiaMeeting.SERVER_ACCOUNT.Equals(schedulingInfo.senderEmailAddr))
                {
                    RvLogger.DebugWrite("Send a email back to notify the sender this mail is failed to send out.");
                    return;
                }

                //when modify a recurrence, to make sure the modified ocurrence request is later than the recurrence request.
                if (schedulingInfo.meetingType == MeetingType.Ocurrence)
                    Thread.Sleep(HOW_MANY_SECONDS_WAIT_FOR_FOLLOWING_REQUEST * 1000);

                icm.XmlApi.scheduleReportType result = changeMail(source, args, schedulingInfo, now);
                if (null != result && result.Success && isCreateMeetingRequest(schedulingInfo))
                {
                    Dictionary<string, byte[]> attachmentsdata = null;
                    if (this.emailMessage.Attachments.Count > 0)
                    {
                        attachmentsdata = new Dictionary<string, byte[]>(this.emailMessage.Attachments.Count);
                        for (int i = 0; i < this.emailMessage.Attachments.Count; i++)
                        {
                            Attachment attachment = this.emailMessage.Attachments[i];
                            Stream readStream = attachment.GetContentReadStream();
                            byte[] bytes = null;
                            if (readStream.Length > 0) {
                                bytes = new byte[readStream.Length];
                                readStream.Read(bytes, 0, bytes.Length);
                            } else
                                bytes = Encoding.ASCII.GetBytes(" ");
                            attachmentsdata.Add(attachment.FileName, bytes);
                        }
                    }
                    
                    parser.changeBodyOfTnef(args.MailItem.Message.TnefPart, schedulingInfo);

                    if (attachmentsdata != null)
                    {
                        foreach (KeyValuePair<string, byte[]> attachmentdata in attachmentsdata)
                        {
                            Attachment attachment = this.emailMessage.Attachments.Add(attachmentdata.Key);
                            Stream attachmentStream = attachment.GetContentWriteStream();
                            attachmentStream.Write(attachmentdata.Value, 0, attachmentdata.Value.Length);
                            attachmentStream.Flush();
                            attachmentStream.Close();
                        }
                    }
                }

            }
            catch (Exception ex)
            {
                RvLogger.DebugWrite(ex.Message);
                RvLogger.DebugWrite(ex.StackTrace);
                string baseFailCode = ex.Message;
                sendBackAMail(source, schedulingInfo, baseFailCode);
            }
            finally
            {
                RvLogger.DebugWrite("Start to agentAsyncContext.Complete()================================================");
                agentAsyncContext.Complete();
                RvLogger.DebugWrite("Complete agentAsyncContext.Complete()================================================");
                RvLogger.DebugWrite("Leave transport agent, from: " + schedulingInfo.delegatorEmailAddr + ", subject: " + schedulingInfo.subject);
            }
        }
 private void WhenMessageCategorized(CategorizedMessageEventSource source, QueuedMessageEventArgs e)
 {
     Logger.LogDebug("Got new message, checking if I can sign it...");
     try
     {
         this.agentAsyncContext = this.GetAgentAsyncContext();
     #if !EX_2007_SP3 //not supported in Exchange 2007
         this.agentAsyncContext.Resume();
     #endif
         this.SignMailItem(e.MailItem);
     }
     catch (Exception ex)
     {
         Logger.LogError("Signing a mail item according to DKIM failed with an exception. Check the logged exception for details.\n" + ex.ToString());
     }
     finally
     {
         this.agentAsyncContext.Complete();
     }
 }