|
The Submit Task is a NAFlet which accepts incoming messages, and stores them in the MTA for onward delivery.
It is probably the single most important Mailismus component.
The Submit task is composed of one or more NAF Listeners, which hand off incoming connections to the SMTP-servers components.
Although we speak here of Task, Listeners and Servers, the whole assemblage can loosely be referred to as the application's server component.
The Submit task typically only has one Listener (listening on the standard SMTP port 25),
but if for some reason you do have more than one (eg. alternative ports or multiple interfaces with different config),
we would recommend running each one in a separate thread (but within the same JVM process), to minimise its connection-management overhead.
This means you would have multiple Submit tasks (or multiple instances of the Submit task, if you would rather think of it that way).
You would implement this by creating an extra Dispatcher entry (see NAF Guide) in
naf.xml,
which would have to point at a different
submit
block in
mailismus.xml.
The key to this is that the Submit block does not actually have to be called
submit,
but merely has to match the XPath notation of the
configfile
element's
root
attribute in the naf.xml config file.
So the alternative block could be called (say)
submit2
to make it distinct.
<submit> <maxconnections initcap="10">1000</maxconnections> <listeners> <listener name="SMTP"> <server> ... </server> </listener> </listeners> </submit> |
maxconnections
This specifies the max number of simultaneous connections that will be allowed.
If the incoming load exceeds this, then the excess clients will promptly be disconnected.
This setting defaults to 1000, and a value of zero means there is no upper limit.
The
initcap
attribute specifies the initial number of SMTP-Server objects that will be allocated, and defaults to 10.
Mailismus will allocate more as needed, up to the configured maximum.
The Listener is a generic NAF component that is documented in the NAF Guide, but we just need to note the following aspects of this listener:
• It's
port
attribute need not specified, since in this context, it defaults to the standard SMTP port of 25
• Likewise the server's
class
attribute is omitted, as it defaults to the Mailismus SMTP-Server class.
The server's config block is listed below, with largely default values.
There is one config setting which is of major relevance to the server but is specified outside this block, and that is the
served_domains
block. See §4.2.
<server> <transcript>DIRLOG%/transcripts/smtpserver.log</transcript> <stats_interval>1h</stats_interval> <relay_clients>SYSNAME%/24 | localhost</relay_clients> <announcehost>hostname</announcehost> <smtpgreet>greeting message</smtpgreet> <validate_helo syntaxonly="Y" fqdn="N" direction="forward" dotted="true">Y</validate_helo> <validate_sender syntaxonly="Y" fqdn="N">Y</validate_sender> <validate_recip syntaxonly="Y" fqdn="N">Y</validate_recip> <sender_deny>domain1 | domain2 | domain3</sender_deny> <maxpeerconnections>0</maxpeerconnections> <maxmsgsize>0</maxmsgsize> <maxrecips>0</maxrecips> <maxmessages>0</maxmessages> <maxbadreqs>2</maxbadreqs> <timeout>2m</timeout> <delay_greet>0</delay_greet> <delay_badrecip>10s</delay_badrecip> <delay_badreq>20s</delay_badreq> <recvbufsize>2048</recvbufsize> <xmitbufsize>96</xmitbufsize> <omitreceivedheader>N</omitreceivedheader> <extPIPELINING>Y</extPIPELINING> <extSIZE>Y</extSIZE> <ext8BITMIME>N</ext8BITMIME> <blacklist> ... </blacklist> <greylist> ... </greylist> <remotenets> <remotenet ip="%SYSNAME%/24"> <sender_deny>.</sender_deny> <sender_permit>domain1 | domain2 | domain3</sender_permit> ... </remotenet> </remotenets> </server> |
transcript
This config item supports the same attributes as the GreyLog loggers (rotation, bufffering, etc - see
GreyLog Guide).
This config item has no default and transcripts will be turned off if it is omitted.
See §4.4.7 for a description of the transcript contents.
stats_interval
The Server prints various stats to the logfile at a recurring interval, which is 1 hour by default.
Set to zero to disable stats.
Here is a sample of the output:
14:00:00.197 INFO Stats since 13:00:00 - Conns=1385 (peak=61, ill=442), Msgs=289, Recips=437 (ok=431) 15:00:00.199 INFO Stats since 14:00:00 - Conns=1262 (peak=42, ill=501), Msgs=182, Recips=401 (ok=380) 16:00:00.197 INFO Stats since 15:00:00 - Conns=1207 (peak=47, ill=412), Msgs=173, Recips=313 (ok=209) |
The first line tells us that 1385 connections were received in that period, with simultaneous connections peaking at 61.
The remote clients tried sending a total of 289 messages to 437 recipients (as many messages contain multiple recipients), which resulted in 431 message-recipient pairs being successfully accepted.
442 of the connections were aborted at various stages due to ill-formed/ill-intention/illegal (or just plain ill) commands.
relay_clients
This specifies the set of clients who are allowed to relay messages through this server.
Relaying is defined as submitting a message to a recipient address which is not served by this server,
ie. not listed in the
served_domains
block (see §4.2).
Clients can be specified as an individual hostname or IP, or as a subnet block in CIDR notation, and multiple specs are allowed separated by a vertical bar.
You may specify a hostname in place of the CIDR IP part, and it will be mapped to its IP to derive the corresponding CIDR block.
There is no default, meaning that if omitted, nobody is allowed to relay messages through this server.
The example setting shown above is the suggested setting in the initial
mailismus.xml
file which ships with Mailismus, and means that other machines on a typical local Class C subnet are permitted, as are applications on this machine itself.
announcehost
This controls how the Server will announce itself in its greeting message.
If absent it defaults to the setting in the
system
block - see §4.1
smtpgreet
This lets you set the SMTP greeting message issued by the server.
This setting defaults to:
%H% %MTATYPE% ESMTP Ready
where
%H%
is replaced by the announce-hostname as configured above, and
%MTATYPE%
is replaced by the MTA type specified in the
system
block - see §4.1
The standard SMTP reply code of 220 is prepended, so if you don't alter any of the defaults, the final greeting would come out as:
220 this_hostname Mailismus ESMTP Ready |
validate_helo
This controls how the hostname supplied in the client's
HELO
(or
EHLO)
greeting is validated, and the default settings are illustrated in the above config block.
The inner value is a simple boolean, and defaults to Yes.
If set to Yes, the full set of attributes are:
validate_sender
This controls how the domain part (only) of the sender email address (SMTP:
MAIL FROM)
is validated, and the default setting is illustrated in the above config block.
The inner value is a simple boolean, and defaults to Yes.
If set to Yes, it differs from HELO validation, as we're dealing with email domains rather than hostnames, and the full set of attributes are:
validate_recip
This controls how the domain part (only) of the recipient email addresses
(SMTP:
RCPT TO)
are validated, and the default setting is illustrated in the above config block.
This setting has identical attributes and defaults to
validate_sender.
sender_deny
This specifies a list of email domains separated by vertical bars, and if the sender address matches any of them, the connection will be rejected on the grounds that it's probably forged.
There is no Deny list by default, so any sender address would be allowed.
This is based on the observation that spammers often spoof the target domain as the sender address too, so the typical usage for this setting would be to list all your local domains (probably the same set of domains as specified in
served_domains
- see §4.2), and then specify a null list in the
remotenet
block for local clients (as illustrated above - a dot indicates a null list).
This would have the effect that only local clients are allowed to specify one of your domains as the sender address.
sender_permit
This is the inverse of
sender_deny
and the connection will be rejected if the sender address does NOT match any of the specified domains.
This is probably less broadly useful than the Deny list, and you would typically specify it on your local
remotenet
blocks, to prevent your own users sending forged emails.
Once again, a dot indicates a null list (ie. anything allowed), and can be used to override an enclosing sender_permit definition.
maxpeerconnections
This specifies the max simultaneous connections allowed from any one client IP.
The default of zero means no limit.
The special value of -1 means no connections allowed, and would only make sense within a specific
remotenet
blocks.
maxmsgsize
This specifies the max message size that will be accepted, either as plain bytes or in units of KiloBytes or MegaBytes using notation like
2000K
or
2M
The default of zero means no limit.
maxrecips
This specifies the max number of recipients that will be accepted per message.
The default of zero means no limit.
If you're using
FilesysQueue
(see §4.3.2) however, this setting defaults to 100.
maxmessages
This specifies the max number of messages that will be accepted per SMTP connections.
The default of zero means no limit.
maxbadreqs
This specifies the max number of consecutive invalid commands that can be sent, before we terminate the connection.
The default is 2, and zero means we won't tolerate a single invalid command.
There is of course no reason for a valid SMTP client to ever send an invalid command, and it is likely to be a human user mistyping when manually probing an SMTP Server via Telnet.
If an automated client issues an invalid command, it invariably means an irrecoverable breakdown in the SMTP dialogue to a protocol error in either party.
See
delay_badreq
timeout
This specifies the max idle period,
after which the server will disconnect the remote client.
The default is 2 minutes, and zero would mean no timeout, which is highly inadvisable.
delay_greet
This is an anti-spam measure, which specifies a delay before the Server will issue its greeting, after a connection is accepted.
Clients are not supposed to send any commands until they receive the initial greeting, so if they do we will immediately disconnect them.
The default of zero means no greet-delay, but if you do wish to enable it, we would recommend 1.5 to 2 seconds (1.5 can be specified as 1500).
The downside is obviously that legitimate senders also get delayed a bit.
The potential effectiveness of this measure is based on the observation that a lot of spamming mass mailers violate the SMTP protocol by not waiting for the initial greeting, or indeed any other response.
They simply fire out their prepared commands as quickly as possible and move on to their next victim.
delay_badrecip
This specifies a delay that will be applied when rejecting any recipients, ie. we will pause this long before replying with any status other than 250 (OK), in response to an SMTP
RCPT TO
command.
The default is 10 seconds, and zero means no delay.
This is an anti-spam measure, as it effectively "tarpits" a client which is sending an excessive number of bad recipients, and of course one of the signatures of a spammer is that they specify long speculative lists of largely invalid recipients.
delay_badreq
This specifies a delay that will be applied when sending the error response to any invalid commands we receive.
The default is 20 seconds, and zero means no delay.
This is another anti-spam tarpit measure, but it's of lesser value as invalid commands are a rarity, and we will disconnect before receiving too many.
See
maxbadreqs
recvbufsize
This specifies the size of the I/O buffer in which the server holds the incoming SMTP commands and data.
The default is 2K, and there is little reason to change that.
A larger value may fractionally reduce connection times if every single message was enormous, but this comes at a high cost in memory footprint.
xmitbufsize
This specifies the size of the I/O buffer in which the server dynamically constructs outgoing SMTP responses.
The default is 96 bytes, and there is even less reason to play with this than with
recvbufsize.
omitreceivedheader
SMTP servers are required to add a
Received
header to the message body as it passes through them, and Mailismus duly does so.
This setting allows it to relay the messages more stealthily, should you wish to do so for whatever reason.
extPIPELINING
This option makes Mailismus advertise support for the EMSTP command-pipelining extension.
On by default.
extSIZE
This option makes Mailismus advertise support for the EMSTP SIZE extension.
On by default.
ext8BITMIME
This option makes Mailismus advertise support for the EMSTP 8BITMIME extension, and is off by default.
Mailismus itself is 8-bit clean, and does transparently relay 8-bit content.
The difficulty is that upstream MTAs may not be, and if we advertise 8-bit support, we could find ourselves with messages on our hands that cannot be successfully relayed onwards ... unless we do content conversion, and Mailismus doesn't support that.
You would enable this extension if you are operating in a closed environment where you know that the upstream MTAs also support 8BITMIME, or you're willing to take the chance that other MTAs will cleanly receive 8-bit message content even if they don't advertise this extension.
blacklist
greylist
See sections §4.4.5 and §4.4.6 below.
remotenets
This is an optional block containing one or more nested
remotenet
blocks. Each
remotenet
block has an
ip
attribute which specifies an IP address block in CIDR notation,
but you may specify a hostname in place of the IP part (as illustrated above).
The purpose of this is that each
remotenet
block identifies a family of clients (ie. those whose IP matches the CIDR block) to which you want to apply alternative config settings.
There are no new settings defined for the
remotenet
block, but it may override most of the settings defined in the common server config.
The full list of settings that may be overridden within a
remotenet
block is:
• announcehost
• smtpgreet
• validate_helo
• validate_sender
• validate_recip
• sender_deny
• sender_permit
• maxpeerconnections
• maxmsgsize
• maxrecips
• maxmessages
• maxbadreqs
• timeout
• delay_greet
• delay_badrecip
• delay_badreq
• omitreceivedheader
• extPIPELINING
• extSIZE
• ext8BITMIME
Blacklisting is a facility whereby all emails from specified IPs can be rejected, based on a config file which lists the barred IPs.
The precise behaviour is controlled by the config block below, which illustrates the default values.
<blacklist> <sourcefile>%DIRVAR%/blacklist.txt<sourcefile> <netprefix>28<netprefix> <hostnames>Y<hostnames> <interval>6h<interval> <mem_threshold>0<mem_threshold> <smtpreply>Service refused - your IP is on a blacklist<smtpreply> </blacklist> |
sourcefile
The central blacklisting parameter, and the only one which is mandatory and has no default, this specifies the full pathname of the file from which Mailismus will read the list of barred IPs.
The IPs are listed one per line.
netprefix
This specifies a CIDR-style net prefix which will be applied to all entries in the IPs file.
By default, each entry is aggregated with a prefix of 28, meaning that whatever IPs you specify, the ban applies to all other IPs in the same /28 subnet.
A value of 32 means each entry represents only that single IP, but we don't recommend making netprefix any larger than 28 as that represents the smallest subnet that is expected to be under a single ownership (apart from static single IPs assigned by domestic ISPs, but any mailservers running on such an account are not likely to rank high in the trust ratings).
Similiarly, we don't recommend making it any smaller than 24, as hosts in distinct /24 subnets are virtually guaranteed to be under separate administrations.
If the source file contains multiple entries that fall within the same subnet, then the redundant ones will be ignored.
hostnames
If true (which is the default), the IP entries in the source file can actually be expressed as hostnames, rather than dotted decimal IPs.
This does not preclude a mixture of hostnames and literal dotted IPs.
The netprefix setting still applies, so if (say) you had netprefix=28, then an entry such as smtp.marketeers.com represents that host and any others in the same /28 subnet.
interval
A blacklist is likely to be regularly updated by whatever data provider you use, meaning that the configured source file is effectively a feed.
It will therefore need to be reloaded at regular intervals, and this setting lets you specify that.
The default is 6 hours.
mem_threshold
Memory Threshold - the default is zero, meaning that the blacklist will be held in memory, no matter how large.
If non-zero, then the blacklist will be stored in a database instead, if its size exceeds that threshold.
Rather than unconditionally decreeing whether the blacklist should be held in memory or database, this setting allows you to gracefully handle the situation where future automated reloads may result in a blacklist that is much bigger (or smaller) than you had initially bargained for.
See the
application/database
config block in §4.1,
for database-related config.
smtpreply
By default, emails from blacklisted IPs will be rejected with this SMTP response message:
550 Service refused - your IP is on a blacklist |
This setting lets you override the free-text portion of that message (but not the numeric SMTP reply code of 550).
Greylisting is a simple but powerful technique which may block 95% of all spam, at a minimal cost in processing resources.
It is based on the observation that most spammers don't send their emails out via regular MTAs which queue the outgoing messages and retry any that fail.
Indeed, their account might not even stay up long enough to wait for reasonable retry intervals.
Rather they blast out as many emails as they can, as quickly as they can, using customised email clients that discard any emails which fail -- or in many cases, aren't even aware of any failures as they just pump out a scripted pipeline of SMTP commands without waiting for a response (see the
delay_greet
setting in §4.4.4 for another application of this rationale).
The idea behind Greylisting is to initially reject messages from unknown senders and only accept them on a subsequent retry, which ensures that the remote peer is at least a compliant MTA, and hence probably not a spammer.
The mechanism is that the upstream IP address, sender email address and recipient email address of each message are extracted as a 3-tuple (or triplet) and recorded in a local database.
If the 3-tuple isn't already registered, then the message will be rejected with a temporary error code (which should trigger a retry), else the message is accepted and a timestamp recording when we last saw this 3-tuple is updated.
When the initial message is rejected, the associated 3-tuple enters what's known as a quarantine period, and further retries will not be accepted until this quarantine period is over.
If the sender was a spammer, the probability is that no retries will ever be attempted.
Once a retry is accepted, the 3-tuple is marked as approved, and any subsequent messages that match it will be accepted without delay.
Give or take some implemention-related fine tuning and housekeeping, that's basically it.
As can be seen, Greylisting is an automated mechanism that requires no manual intervention once turned on.
It works purely by inspecting the SMTP header, so it doesn't have to open the actual message body, or invoke any expensive tools to scan it.
Furthermore, it saves on bandwidth by rejecting the incoming message before the (potentially large) body is transmitted.
Disadvantages:
With all these benefits, there must be a catch, and the disadvantage of greylisting is the loss of immediacy when messages are received from rare corresponds, as they will be delayed for at least the quarantine period (exactly how long they're delayed depends on the upstream MTA's retry schedule).
Note that regular correspondents will not be delayed because their 3-tuple will already be registered.
MX Considerations:
Beware that the presence of alternate MX relays for your domains is a complicating factor for greylisting, if they don't share the same greylisting registry - and a shared database server would be a lot less performant than an embedded database (which cannot be shared).
Greylisting is obviously pointless if all the related MX relays don't implement it, as once it's accepted by any one of them it will eventually get successfully sent.
For the same reason, the MX servers for a domain are also obliged not to apply greylisting to each other, since that will only serve to pointlessly delay a transaction that is bound to ultimately succeed (since they are all properly functioning MTAs with retry capability).
Therefore, in the event that they each have their own greylisting registry, and each retry attempt by the upstream sender targets a different MX, then if there are N MX relays, it follows that the first N send attempts will all end in failure.
If N is only 2 or 3 this increases the delay for first-time correspondents, but does not constitute a problem as legitimate MTAs are well equipped to handle that amount of retries, but if N is very large and the upstream MTA has significant retry delays, the message may expire on its queue before it can be accepted.
Greylisting therefore works best if there's only a small number of MX relays for a domain, and/or the ultimate destination has the lowest MX preference, which means that all retry attempts ought to be made against it (but all MX secondaries still need to apply greylisting as well, else a spammer could target the weak links).
Configuration:
The greylisting config block is as follows, with the default values illustrated:
<greylist> <whitelist> ... </whitelist> <quarantine_interval>30m</quarantine_interval> <quarantine_grace>6h</quarantine_grace> <expiry_interval>7d</expiry_interval> <purge_interval>3h</purge_interval> <updates_freeze>1h</updates_freeze> <smtpreply>Please try again later<smtpreply> </greylist> |
whitelist
This specifies a set of hosts to which greylisting should not be applied. (ie. accept their emails without delay).
At a mimimum, it should comprise local clients (ie. machines for which we are the outgoing SMTP server) and all the other MX hosts for any domains we serve.
This whitelist block has the same configuration syntax as the blacklist block we saw above in §4.4.5, and the only practical difference is that whereas a blacklist is probably going to be an automatically updated feed, this whitelist will typically be a static config file, which you update manually when changes occur.
quarantine_interval
This specifies the duration of the quarantine period when a new correspondent sends a message, ie. it is the length of time for which a new 3-tuple will be greylisted.
Defaults to 30 minutes.
As explained above, any further retries (or indeed any other messages matching the correspondence specified by this 3-tuple) during this quarantine period will also be rejected.
quarantine_grace
This specifies how long we will wait for a greylisted message to be resent, once the quarantine period is over.
If it is not resent during this period, then the 3-tuple is considered to be stale and will be removed from the registry during the next purge.
Any subsequent messages for this correspondence will have to go through the greylisting process from the beginning.
Defaults to 6 hours.
In other words, the default settings are that a new correspondent should not retry for 30 minutes (it's not actually wrong to do so, but the messages will be rejected), and should retry during the following 6 hour period.
If no follow-up has been recieved after 6.5 hours, then this 3-tuple will be purged from the registry.
expiry_interval
This specifies how long a correspondence remains valid, since the last time a message matching its 3-tuple was received.
If no messages matching a 3-tuple are received during this interval, then it is considered to be stale and will be removed from the registry during the next purge.
Any subsequent messages for this correspondence will have to go through the greylisting process all over again.
Defaults to 1 week.
purge_interval
This is the interval at which the greylisting registry is purged.
As referred to in some of the above settings, stale quarantined and approved entries are periodically deleted (to prevent the registry growing indefinitely), and this is known as purging the registry.
Defaults to 3 hours.
updates_freeze
This is an optimisation which avoids updating the last-received timestamp of an approved 3-tuple every single time a matching message is received, as that could result in heavy database traffic for a particularly active correspondence.
Instead, we put a freeze on any further updates for this interval, and the next matching message to arrive after that will update the timestamp.
Defaults to 1 hour.
smtpreply
By default, greylisted emails will be rejected with this SMTP response message:
450 Please try again later |
This setting lets you override the free-text portion of that message (but not the numeric SMTP reply code of 450).
Requirements:
This feature requires database functionality to be enabled.
See the
application/database
config block in §4.8,
for database-related config.
NAFMAN Commands:
You can issue the following NAFMAN commands to display the live greylist status:
A sample transcript fragment is shown below, which includes two successful message submissions plus some invalid HELO commands
E1 ===== 2010-10-27 09:23:30.955 << Connection from 91.189.234.122:62663 to 192.168.101.13:25 E3 ===== 2010-10-27 09:23:31.236 << Connection from 82.218.125.213:62665 to 192.168.101.13:25 E1 09:23:32.955 >> 220 Grey Server (Mailismus) ESMTP Ready E3 09:23:33.236 >> 220 Grey Server (Mailismus) ESMTP Ready E1 09:23:33.585 << EHLO [91.189.234.122] E1 09:23:33.585 >> 250-Grey Server Hello 250 PIPELINING E3 09:23:33.869 << EHLO h082218125213.host.wavenet.com E3 09:23:33.869 >> 250-Grey Server Hello 250 PIPELINING E1 09:23:34.215 << MAIL FROM:<sender@source1.ie> E1 09:23:34.215 >> 250 OK E3 09:23:34.498 << MAIL FROM:<sender@source2.com> E3 09:23:34.498 >> 250 OK E1 09:23:34.850 << RCPT TO:<info@domain1.org.uk> E1 09:23:34.850 >> 250 OK E3 09:23:35.126 << RCPT TO:<info@domain2.org.uk> E3 09:23:35.126 >> 250 OK E1 09:23:35.479 << DATA E1 09:23:35.479 >> 354 Start mail input; end with <CRLF>.<CRLF> E3 09:23:35.776 << DATA E3 09:23:35.776 >> 354 Start mail input; end with <CRLF>.<CRLF> E1 09:23:36.129 Event: Received MailBody octets=3238 E1 09:23:36.129 >> 250 Message accepted as CF83C625 E3 09:23:36.413 Event: Received MailBody octets=3191 E3 09:23:36.413 >> 250 Message accepted as CF83C626 E1 09:23:36.771 << QUIT E1 09:23:36.771 >> 221 Closing connection E1 09:23:36.771 Event: Disconnect E3 09:23:37.039 << QUIT E3 09:23:37.039 >> 221 Closing connection E3 09:23:37.039 Event: Disconnect E3 ===== 2010-10-27 09:25:56.925 << Connection from 190.146.10.71:62595 to 192.168.101.13:25 E3 09:25:58.924 >> 220 Grey Server (Mailismus) ESMTP Ready E3 09:25:59.116 << EHLO CENTRAL E4 ===== 2010-10-27 09:26:09.304 << Connection from 190.146.10.71:62633 to 192.168.101.13:25 E4 09:26:11.304 >> 220 Grey Server (Mailismus) ESMTP Ready E4 09:26:11.516 << EHLO CENTRAL E3 09:26:19.114 >> 501 Please say Hello properly E3 09:26:19.114 Event: Disconnect |
The first thing you will notice is that each line begins with an entity number.
This identifies a particular SMTP Server entity or object, and its only significance is that it allows you to trace the activity on a particular connection, when it is interleaved with other connections.
Between the connect and disconnect events, all the lines tagged with the same entity ID refer to the same connection.
References to the same entity will recur continuously throughout a transcript, but following a Disconnect event, you know that they refer to unrelated connections, so there is no significance in it being the same entity.
You can see that happening above, when following the end of one SMTP connection, Server object E3 is immediately reused for another connection.
It is easiest to trace a particular connection when using an editor that supports regular expressions and lets you specify a start-of-line pattern like say
^E3,
to trace the connection that is being handled by server instance E3.
Some editors (such as the
Vi
GUI,
gvim)
can highlight all matching text sequences, making the connection stand out particularly effectively if it's interleaved with lots of others.
The second thing to note is the use of directional chevrons to indicate if traffic is incoming or outgoing.
Since this is a server transcript, all the incoming lines are SMTP client requests, and the outgoing lines are the server's responses.
Also noteworthy, is that the transcript records events (eg. connect and disconnect) as well as the SMTP dialogue.
If the reason for a disconnect is not obvious from the dialogue, the disconnect event will be annotated to explain why.
Finally, you'll note that the potentially hundreds or thousands of data chunks required to convey the message body are not individually logged.
Instead, they are collapsed into a single event line at the end, which reports the size of the received message.
You'll see that Mailismus advertises the pipelining extension, but it appears that the clients sent their commands one at a time anyway.
That's not necessarily what actually happened though.
It's just that Mailismus only transcripts the commands as it processes them, so you will only ever see client commands timestamped and logged individually.
While the Transcript logging tries to be as efficient as possible, it should be obvious that it imposes some processing burden, and on extremely busy servers, it will be a significant burden.
Transcripts should only really be turned on when you want to investigate something, or capture some sample traffic.