Getting Started =============== Setup ----- Install Salmon from PyPI: .. code-block:: bash $ pip install [--user] salmon-mail Now run the ``gen`` command to create the basic layout of your first project: .. code-block:: bash $ salmon gen myproject Then change directory to ``myproject`` .. warning:: Users of older versions of Salmon should note that the project template now uses LMPTReceiver as its default Handlers -------- Handlers are how your application will process incoming mail. Open ``app/handlers/sample.py`` and you'll see the following: .. literalinclude:: ../salmon/data/prototype/app/handlers/sample.py :language: python Each handler returns the next handler for that sender. ``START`` is the default handler for senders that Salmon doesn't know about. This `state` is stored in memory by default. Let's start up a server and see how it all works: .. code-block:: bash $ salmon start $ salmon status Salmon running with PID 4557 If you look at ``logs/salmon.log``, you'll see various start-up messages from Salmon. Now send an email to our server: .. code-block:: bash $ telnet localhost 8823 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. 220 localhost Salmon Mail router LMTPD, version 3 MAIL FROM: sender@example.com 250 Ok RCPT TO: rcpt@example.com 250 Ok DATA 354 End data with . Hello . 250 Ok QUIT 221 Bye Connection closed by foreign host. Check ``logs/salmon.log`` and you'll see the following lines: .. code-block:: none 2016-01-11 00:49:49,947 - root - DEBUG - Message received from Peer: ('127.0.0.1', 38150), From: 'sender@example.com', to To ['rcpt@example.com']. 2016-01-11 01:00:49,949 - routing - DEBUG - Matched 'rcpt@example.com' against START. 2016-01-11 01:00:49,949 - sample_app - INFO - START: rcpt@example.com 2016-01-11 01:00:49,950 - routing - DEBUG - Message to rcpt@example.com was handled by app.handlers.sample.START If you send the message again you'll see this: .. code-block:: none 2016-01-11 01:01:36,486 - root - DEBUG - Message received from Peer: ('127.0.0.1', 54628), From: 'sender@example.com', to To ['rcpt@example.com']. 2016-01-11 01:01:36,487 - routing - DEBUG - Matched 'rcpt@example.com' against NEW_USER. 2016-01-11 01:01:36,488 - routing - DEBUG - Message to rcpt@example.com was handled by app.handlers.sample.NEW_USER As the ``NEW_USER`` handler returns itself, every message from "sender@example" will now be processed by ``NEW_USER`` Once you're done, stop the server: .. code-block:: bash $ salmon stop Stopping processes with the following PID files: ['./run/stmp.pid'] Attempting to stop salmon at pid 4557 Configuration ------------- By default, all configuration happens in ``config/`` ``boot.py`` ^^^^^^^^^^^ This file is used by Salmon during start-up to configure the daemon with various things, such as starting the ``LMTPReceiver``. It's a bit like the ``wsgi.py`` file that Python web apps have. If you want to use a different boot module, you can specify it with the ``--boot`` argument. E.g. to use ``myapp/othermodule.py``, do: .. code-block:: bash $ salmon start --boot myapp.othermodule ``testing.py`` ^^^^^^^^^^^^^^ Just like ``boot.py``, except for testing. You can specify ``--boot config.testing`` when starting Salmon to try it out. ``logging.conf`` and ``test_logging.conf`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Standard Python logging configuration files. See Python's documentation for more details. ``settings.py`` ^^^^^^^^^^^^^^^ This file contains generic settings used by the rest of your application, e.g. which port the receiver should listen to. The default settings module is ``config.settings`` You can specify a different settings module via the environment variable ``SALMON_SETTINGS_MODULE``: .. code-block:: bash $ SALMON_SETTINGS_MODULE="myapp.othersettings" salmon start Deploying --------- Salmon is best deployed behind another mailserver such as Postfix or Sendmail - much in the same way as you host a WSGI application behind Apache or Nginx. As seen above, a new Salmon project will start a LMTP server that listens on ``localhost:8823``. You can go into ``config/settings.py`` and change the host and port Salmon uses. You can also switch out ``LMTPReceiver`` for ``SMTPReceiver`` if you require Salmon to use SMTP instead. .. warning:: Due to the way Salmon has been implemented it is better suited as a LMTP server than a SMTP server. ``SMTPReceiver`` is unable to handle multiple recipients in one transaction as it doesn't implement the nessessary features to properly implement this part of the SMTP protocol. This is a compromise ``SMTPReceiver`` makes in order to allow users more freedom in what they do in their handlers. ``LMTPReceiver`` is unaffected by this issue and implements the LMTP protocol fully.