Home All Groups Group Topic Archive Search About

Creating a multi-threaded C# OnArrival SMTP Sink

Author
27 Nov 2004 5:03 PM
David Kornitz

Goal: Write C# managed sink against the SMTP OnSubmission event. Compare
recipient list against known "good" list and remove invalid recipients.

Make it multi-threaded so multiple messages can be processes simultaneously.

Problem: I don't know how to convert my working sample code from
Non-threaded to multi-threaded.  Below is the applicable code:

using System;
using System.Threading;
using System.Data.SqlClient;
using System.Runtime.InteropServices;
using Microsoft.Exchange.Transport.EventInterop;

namespace SmtpRecipientFilter
{
[Guid("2BE22109-14D6-4d13-A8FE-795E2233DABD")]
public class InboundSink : IMailTransportSubmission, IEventIsCacheable
{
MailMsg emailMessage;

public InboundSink()
{
// Constructor
}

void IEventIsCacheable.IsCacheable()
{
// T8his will return S_OK by default.
}

void IMailTransportSubmission.OnMessageSubmission
(MailMsg message, IMailTransportNotify ntf, IntPtr ptr)
{
emailMessage = message;

processMessage();
}

/// Compare the recipient list against a known good list of email
/// addresses and process accordingly.
private void processMessage()
{
MessageProcessor mp = new MessageProcessor();

mp.EmailMessage = emailMessage;
mp.ValidateRecipientList();
mp = null;

}
}
}

The MessageProcessor class looks like this:

using System;
using System.Collections.Specialized;
using Microsoft.Exchange.Transport.EventInterop;
using Microsoft.Exchange.Transport.EventWrappers;

namespace SmtpRecipientFilter
{
public class MessageProcessor
{
private MailMsg emailMessage;

public MessageProcessor()
{
// Constructor
}

/// Compare the recipient list of the EmailMessage to the known good
/// list of email addresses. Remove invalid recipients from the email ///
message and log to a file for later analysis.

public void ValidateRecipientList()
{

// Get the list of valid email addresses that the recipient list will be
// compared against.

StringDictionary sdEmailList = DataLayer.GetValidEmailAddresses();

Message msg = new Message(emailMessage);

int numRecips = (int) msg.Recips.Count;

RecipsAdd newRecips = msg.AllocNewList();
string recipEmailAddress;
for (uint i = 0; i < numRecips; i++)
{
recipEmailAddress = msg.Recips[i].SMTPAddress;
if (sdEmailList.ContainsKey(recipEmailAddress))
{
newRecips.AddSMTPRecipient(recipEmailAddress);
}
}
msg.WriteList(newRecips);

msg = null;
}

public MailMsg EmailMessage
{
get
{
return emailMessage;
}
set
{
emailMessage = value;
}
}
}
}


The code works correctly in a non-threaded mode, when I add the lines below,
in an attempt to convert to a threaded applicaiton, the "mp.EmailMessage =
emailMessage;" [emailMessage] does not contain any information (or is null)
and therefore it throws a "System.NullReferenceException".  I'm using the
same message when testing the code. 

Thread synchThread = new Thread(new ThreadStart(processMessage));
synchThread.Priority = ThreadPriority.Lowest;
synchThread.Start();

The "System.NullReferenceException" occurs at the following line.

recipEmailAddress = msg.Recips[i].SMTPAddress;

Any help would be greatly appreciated.

Thanks in advance.

Author
29 Nov 2004 10:42 AM
TSw
> Thread synchThread = new Thread(new ThreadStart(processMessage));
> synchThread.Priority = ThreadPriority.Lowest;
> synchThread.Start();
>

You have to start a new thread passing an object Message to it - the
code has to look like this:

ClassThread newThread = new ClassThread(Message Msg);
Thread synchThread = new Thread(new
ThreadStart(newThread.processMessage));

But even if you do it like this, it looks completly useless for me.
There is no need for starting new threads from event sinks. Check
http://www.geocities.com/smtptracker - this might be useful for you -
I can send some examples, how to write this sort of thing...

TSw
smtptrac***@yahoo.com

Bookmark and Share