Developer Guide

From NMail

Jump to: navigation, search

Contents

Introduction

NMail is a complete mail system; it is not a separate mail transport agent (MTA) and mail retrieval system (via IMAP or POP3), instead it is both. NMail is very modular; it tries to use well defined interfaces and any component can easily be replaced by and alternate implementation. This document is indented to help new NMail developers get up to speed on how the system is designed and how each module interacts with the system. The other good place to look for documentation is the API documentation. NMail is written entirely using the .net framework version 2.0. To date all of the components have been written using C#, however, this does not prevent plugin and components developers from using alternative languages such as Visual Basic .net and Iron Python.

Overview

Security

NMail should be implemented and deployed with Microsoft’s “SD3+C” principle in mind [1]. It stands for: secure by design, secure by default and secure in deployment and communications.

Logging

All logging should be done using the log4net library [2]. Generally each class should use its own private log for logging. However for plugins it may make sense to use a shared log per plugin.

Configuration

The majority of NMail’s configuration is done using the ‘System.Configuration’ API. There is a global configuration class that is created on first reference using a static constructor. Each component is then free to load its own configuration is a similar way. The local store delivery actions can use the local store API to load and save some user specific configuration data.

Parsing Text

Many of the services in NMail are required to parse lines of text to communicate with other clients and servers. The cleanest way to parse this data seems to be using a good hierarchy of classes for each part of the data. For example often a line will begin with a specific command, e.g.:

C: HELO host.domain

In this case the client has sent the “HELO” command. The session class can just check the first token of the message. At this point it knows the client has sent a “HELO” command and can pass the remainder of the data to the HELO command class to parse. The HELO command class can in turn check if it has only received one token and then pass that to the Host class to parse.

State Machines

Many services in NMail also have a set of states that the client can reach. A nice way of implementing this is using the State pattern. Firstly an abstract base state is created which returns an error message for each possible command, e.g.:

public virtual void MailFrom(string command) {
	throw new ApplicationException("Invalid state.");
}

Then in the appropriate subclass an overridden method is provided:

public virtual void MailFrom(string command) {
	// Parse mail from, extracting sender and parameters
	SenderCommand senderCommand = new SenderCommand(command);
	...
}

This approach allows for good code reuse and helps to implement consistent error checking code.

SMTP Overview

Sending and receiving mail via SMTP is done using several components, see Figure 1. The SMTP service is the component that accepts all incoming mail from local clients and remote servers. The SMTP client provides a means to send messages to remote SMTP servers. The message router has two roles. Firstly it provides the SMTP service with access to the message spool. Secondly, it determines if a message should be delivered locally into the local store or be sent to a remote server via the SMTP client. Each of these components along with the spool and local store systems are discussed further below.

Figure 1: Overview of the major SMTP components.
Figure 1: Overview of the major SMTP components.

SMTP Service

The SMTP service is the component that accepts incoming messages from SMTP clients sending mail and SMTP servers delivering mail [3],[4]. This service is implementing using the State pattern discussed above.

State Machine

The service provides a concrete class for the states shown in Figure 2. After entering the negotiated state each state can return to the negotiated state by receiving a reset command (“RSET”). At each state the client can also disconnect or send the quit command (“QUIT”), ending the session.

Figure 2: SMTP service state machine.
Figure 2: SMTP service state machine.

SMTP Client

The SMTP client is the component that sends outgoing mail to remote SMTP servers. It provides a simple high level interface for sending mail and could be used with out an NMail server instance, i.e. in a separate program.

Message Router

The message router is the component connects the SMTP service, SMTP client, spool service and local store. As mentioned above it is responsible for determining which messages should go to the local store and which should be delivered remotely. The message router does this by querying the local store to see if it will accept mail for the current email address’s hostname.

Spool Overview

Spooling mail involves the components shown in Figure 3 and the state diagram for spooled messages is shown in Figure 4. Each component is discussed further below.

Figure 3: An overview of spool components.
Figure 3: An overview of spool components.
Figure 4: State diagram for spooled messages.
Figure 4: State diagram for spooled messages.

Spool Service

The spool service is the component that spools messages tentatively accepted for delivery but not yet delivered. Each message received from the SMTP service is spool before it is either forwarded or delivered locally. Initially the spool service will just place the spooled message into the spool data repository. It then waits for the spool filter service to filter the message. Finally messages a batched up based on delivery address and one or more delivery attempts is made.

Spool Filter Service

The spool filter service is the component that filters messages in the spool and can modify, pass or fail messages. Each message placed into the spool data repository will reside there until the spool filter service examines the message and flags that it is ready to delivery.

Spool Filter Plugins

TODO :(

Spool Data

The spool data interface simply provides a repository independent API for the spool components to use. One current implementation uses a database to store the messages.

Local Access Overview

Figure 5: Overview of the major local store components.
Figure 5: Overview of the major local store components.

Local Store

The local store is the message repository used for local users to store their email. It is typically accessed via the IMAP service.

IMAP Service

The IMAP service provides clients with an IMAP server to access the local store with.

State Machine

Command Resolution

Remote Access

NMail provides a TCP based remoting interface for querying and administering the running server. An overview of the major interactions with this interface is shown in Figure 6.

Figure 6: Remote Access overview.
Figure 6: Remote Access overview.

TCP Interface

Security

The TCP remoting interface is protected using the built in remoting authorization support. The NMail configuration contains a list of allowed users and client addresses which are used to validate and incoming connections.

Web Services Interface

NMail provides a web service interface for accessing functions of the local store. It is intended to provide a richer interface to the server than would otherwise be available via protocols such as IMAP.

Getting Started

Here are the steps needed to start developing with NMail:

  1. Download a copy of the NMail source code.
  2. Download the .NET 2.0 SDK.
  3. Download MySql server and .NET connector.
  4. Run the two MySql setup scripts.
  5. Create a MySql user called “NMail” with password “moo” with access to the two new databases.
  6. Edit the server configuration.
  7. Compile with NAnt or Visual Studio (NAnt current requires one of the 0.85 nightly builds to work properly).
  8. Start the console server.

After these steps the NMail server should be running. You can access the server with the username “Administrator” and password “changeme”.

Personal tools