// *************************************************************** // // Copyright (C) Microsoft Corporation. All rights reserved. // // // A simple agent that logs messages on an Edge Transport server. // // *************************************************************** namespace Microsoft.Exchange.Samples.Agents.EdgeTransportLogging { using System; using System.IO; using System.Diagnostics; using System.Reflection; using System.Text; using Microsoft.Exchange.Data.Transport; using Microsoft.Exchange.Data.Transport.Smtp; using System.Globalization; public class MessageLoggerFactory : SmtpReceiveAgentFactory { public override SmtpReceiveAgent CreateAgent(SmtpServer server) { return new MessageLogger(); } } public class MessageLogger : SmtpReceiveAgent { // The agent uses the fileLock object to synchronize access to the log file private object fileLock = new object(); // 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. private AgentAsyncContext agentAsyncContext; public MessageLogger() { //Register an OnEndOfData event handler this.OnEndOfData += new EndOfDataEventHandler(this.OnEndOfDataHandler); } // The OnEndOfDataHandler method is invoked when the entire message has been received public void OnEndOfDataHandler(ReceiveEventSource source, EndOfDataEventArgs eodArgs) { // Begin a background thread that will save the message to disk System.Threading.ThreadPool.QueueUserWorkItem(this.LogMessage, eodArgs.MailItem); // GetAgentAsyncContext causes the server to wait for this agent // to invoke the returned callback before continuing to // process the current message. this.agentAsyncContext = this.GetAgentAsyncContext(); return; } // Append the given stream to the message log public void LogMessage(object state) { MailItem mailItem = state as MailItem; using (Stream messageStream = mailItem.GetMimeReadStream()) { lock (fileLock) { try { string filename = mailItem.Message.MessageId; foreach (char pathChar in Path.GetInvalidFileNameChars()) filename = filename.Replace(pathChar, '-'); filename = String.Concat(DateTime.Now.ToString("yyyy-MM-dd_HHmmss", CultureInfo.InvariantCulture), "_", filename, ".log"); string logDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\Log"; string logFile = Path.Combine(logDir, filename); if (!Directory.Exists(logDir)) { Directory.CreateDirectory(logDir); } if (!File.Exists(logFile)) { File.CreateText(logFile).Close(); } using (FileStream fileStream = new FileStream(logFile, FileMode.Create, FileAccess.Write, FileShare.Read)) using (BinaryWriter writer = new BinaryWriter(fileStream)) { const int bufferSize = 4096; byte[] buffer = new byte[bufferSize]; messageStream.Seek(0, SeekOrigin.Begin); int dataSize = 0; while ((dataSize = messageStream.Read(buffer, 0, bufferSize)) > 0) fileStream.Write(buffer, 0, dataSize); } } catch (System.IO.IOException ex) { Debug.WriteLine(ex.ToString()); } } } this.agentAsyncContext.Complete(); this.agentAsyncContext = null; } } }