How to write a Windows SMTP Service in C#

The example shows how to write a multi-threaded SMTP server in C#, which runs in a Windows service, listens to incoming connections, accepts incoming mail, and relays mail to external recipients.
 
The code utilizes TCP components from the Clever Internet .NET Suite library
The source code for the example is available on GitHub
Watch more video on YouTube

Creating a service project in Visual Studio and setting up the components:

After creating a Windows Service project (.NET Framework), you need to put the following components on to the Service form: SmtpServer, SmtpFileHandler, SmtpRelay, and Timer. You need to add user accounts to the SmtpServer.UserAccounts collection, specify both the mailbox and the relay folders for the SmtpFileHandler component, add a reference to the SmtpServer instance to the SmtpFileHandler.Server component, and set up the timeout interval for the Timer component.
 
You can start the SMTP server automatically when the Windows service runs:
 
protected override void OnStart(string[] args) 
{
	smtpServer1.Start();
	timer1.Enabled = true;
}

protected override void OnStop() 
{
	smtpServer1.Stop();
}

Delivering outgoing mail to end-recipients:

The server automatically saves all incoming mail for external recipients to the SmtpFileHandler.RelayDir folder. You need to periodically look through this folder, load new messages, and supply them to the SmtpRelay component for delivering directly to recipients' mailboxes.
 
Every time the Timer event occurs, the program starts the Email delivering process:
 
private void timer1_Tick(object sender, EventArgs e) 
{
	timer1.Enabled = false;
	try 
	{
		string path = FileUtils.AddTrailingBackSlash(smtpFileHandler1.RelayDir);
		string[] envelopeList = Directory.GetFiles(path, "*" + 
		SmtpFileHandler.EnvelopeFileExt);
		foreach (string env in envelopeList) 
		{
			string[] envelope = File.ReadAllLines(env);
			if (envelope.Length < 2) continue;

			smtpRelay1.MailFrom = envelope[0];
			smtpRelay1.MailToList = ExtractRelayTo(envelope);

			string msg = Path.ChangeExtension(env, SmtpFileHandler.MessageFileExt);
			using (Stream stream = File.OpenRead(msg)) 
		{
			smtpRelay1.MailData.LoadFromStream(stream, "");
		}

		smtpRelay1.Send();

		File.Delete(msg);
		File.Delete(env);
		}
	}
	finally 
	{
		timer1.Enabled = true;
	}
}
 
private string[] ExtractRelayTo(string[] envelope) 
{
	string[] result = new string[envelope.Length - 1];
	Array.Copy(envelope, 1, result, 0, envelope.Length - 1);
	return result;
}
 
Have questions?
Join us on   Facebook   YouTube   Twitter   Telegram   Newsletter
 
Kind regards
Clever Components team
www.CleverComponents.com

Add Feedback