// ***************************************************************
//
// 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;
}
}
}