${COURIER_HOME} is the main installation
  directory, everything lives under here.
  ${COURIER_HOME}/ARCH is a soft link to
  ${ARCH}
  ${COURIER_HOME}/${ARCH}/bin - binary files
  ${COURIER_HOME}/${ARCH}/lib - library files
  ${COURIER_HOME}/bin - mostly soft links to
  arch/bin
  ${COURIER_HOME}/lib - mostly soft links to
  arch/lib
  ${COURIER_HOME}/man - manual pages
  ${COURIER_HOME}/local/config - local
  configuration
  ${COURIER_HOME}/local/msgs - mail queue - messages
  and control files
  ${COURIER_HOME}/local/msgq - mail queue - control
  files, sorted by next scheduled delivery attempt time
  ${COURIER_HOME}/local/tmp - temporary directory
All directories can be softlinks, or mount points, EXCEPT that
  local/msg[sq] and local/tmp must be on
  the same filesystem.
In local/msg[sq] the userid of the control and
  the message file are that of the user who created the
  message.
courierctl scripts - these
  scripts start and stop courierd, and performs other
  administrative functions.
  courierctl.startscripts - these scripts start courierd. They do NOT start any input module daemons, that must be done separately. Note that this command only begins the startup process. courierd may fail to start for some reason, you will need to check your system logs to verify that courierd is properly running.
courierctl.stop- this command stops courierd. courierd is stopped cold, interrupting any pending deliveries.
courierctl.restart- this command restarts courierd by sending it a SIGHUP. courierd will suspend starting any new deliveries, then wait for all current deliveries to finish, then restart itself. This action is necessary after making certain configuration changes.
courierd - the main scheduling daemon.
  The heart of Courier is just a raw scheduler that figures out
  when to attempt to deliver messages that are in the queue. There
  will actually be two courierd processes running, at
  the same time. courierd is started and stopped by
  courierctl.
  courierd scheduling daemon is
  transport neutral, and external modules are used to submit
  messages to courierd, and attempt to deliver messages at regular
  intervals.  The term 'input module' refers to an external
  module that submits messages to courierd, and 'output module'
  refers to an external module that delivers messages. The term
  'transport module', or a plain 'module' refers to both an input
  module and an output module for the same platform, which usually
  come together. For example, Courier typically receives and sends
  mail via ESMTP, however, it is possible to adjust the default
  configuration so that ESMTP is only used to receive mail. For
  sending, mail gets delivered using some other protocol.
  Output module are started by courierd, and
  communicate with courierd via pipes. Output module
  are notified which messages must be delivered, and to which
  addresses. Courier may send multiple messages to the same output
  module, without waiting for an acknowledgement that an attempted
  delivery for previous messages has been made.
E-mail addresses that appear in the message's headers, and which are listed in the message's delivery envelope, are stored in a "canonical" format. E-mail messages that come from an input module have their addresses rewritten from the transport-specific format to the canonical format. E-mail messages which are sent to be delivered to an output module have their addresses rewritten to the canonical format.
The canonical format is the format for E-mail addresses that is used by Courier's system. Therefore, messages that are delivered to local mailboxes do not undergo header or address rewriting.
Messages are submitted to the Courier server by running the ${COURIER_HOME}/bin/submit, which takes care of rewriting addresses from the transport format to canonical format. When an output module receives a message to deliver from Courier's queue, the E-mail addresses in the message will be in the canonical format, and the output module is responsible for rewriting addresses in the headers into the transport-specific format. The output module can take advantage of a set of library functions which automate this process.
On platforms that support dynamically-opened shared libraries, Courier can be compiled to use shared libraries. This allows rewriting functions to be modified, and have the changes take effect without fully shutting down Courier. Otherwise, they can be compiled as regular, statically linked libraries.
submit programsubmit is
  used to submit a message into Courier's scheduling queue.
  submit is not invoked directly. submit
  does not have any global read or execute permissions, only user
  and group permissions, therefore it must be invoked by a process
  that executes at least as group mail. submit
  provides the functionality most transports will need in order to
  submit messages into the queue. Submit accepts several options,
  and one argument: the name of the input module submitting the
  message. submit also reads the environment,
  therefore the environment variables must be scrubbed before
  invoking submit. submit communicates
  via standard input and output with the module to read the
  identify of the sender and the recipients of an E-mail message,
  and the message contents. submit enforces message
  size limits and may reject the sender or any recipient. Options
  are:
  -expn=address- do not accept any message, just attempt to 'expand' this address.
-vrfy=address- do not accept any message, just attempt to 'verify' this address.
-verp- use VERP-encoded envelope sender address.
submit opens the shared libraries,
  reads the E-mail addresses of the sender and the recipient, reads
  the message itself, and rewrites all addresses to the canonical
  format by running the module's address rewriting function in the
  shared library. submit may perform other
  adjustments, such as adding the Date: or the
  Message-ID: header, or adding MIME headers.
  submit also checks if any recipient is a
  system-defined alias, and adds the alias's list of addresses to
  the recipient list. submit will also try to remove
  duplicate E-mail addresses from the recipient list, wherever
  possible.  Wherever possible, submit will
  reject E-mail addresses that it knows are not valid.
  mailq - display current mail queue for the
  running user (or the entire queue, if invoked as root). Since
  individual control files are owned by the originating user. mailq
  simply prints out the contents of every control file it can
  open.
-s - sort messages by starting time. With many messages, this can eat up memory, and CPU cycles. The list is not sorted, by default.
reformime - standalone program that can
  be used by module to implement some header rewriting. I am
  borrowing the reformime tool from the maildrop package, which
  contains complete documentation for reformime.
  That's it. Other program modules come as a part of plug-in transport module. For example, the SMTP transport doesn't have to be installed, resulting in Courier being used to just deliver mail on a single system. Or, only the SMTP output module can be installed, so that the machine will be able to send mail via SMTP, but not receive it. Or, only the SMTP input module can be installed, so that the machine can receive mail via SMTP, but not send it (which also means that bounces can't be delivered, so they double-bounce to postmaster).
submit program also reads the following variables
  from the environment:
  SPAMDATAFILTER=pathname - run this spam filter.
  After receiving this message, run the indicated program. In
  addition to the environment variables inherited by submit, submit
  sets MODULE to the name of the input module, before running the
  spam filter. Please note that the program is run with the
  user/group id of the submit process!
MIME=option - sets options for mime rewriting.
  The options are: none - no mime rewriting whatsoever; 7bit -
  convert 8bit mime sections to quoted-printable; 8bit - convert
  quoted-printable to 8bit.
NOADDMSGID - if set, submit will not add a
  Message-Id: header, if the message does not have
  it.
NOADDDATE - if set, submit will not add a
  Date: header, if the message doesn't have it.
NOADDRREWRITE - if set, submit will not rewrite any
  From:, To:, and Cc: header, or check
  whether the message has a DKIM-Signature: before doing so.
SIZELIMIT - maximum size of a message in bytes.
  Larger messages are rejected. If this environment variable is not
  set, Courier will read the control/sizelimit file.
  If control/sizelimit does not exist, Courier will
  use "0". "0" is used to specify that there is no maximum message
  size limit.