A Python Mail Server

Overview

Build Status Coverage Status Documentation Status

Salmon - A Python Mail Server

Salmon is a pure Python mail server designed to create robust and complex mail applications in the style of modern web frameworks. Salmon is designed to sit behind a traditional mail server in the same way a web application sits behind Apache or Nginx. It has all the features of a web application stack (templates, routing, handlers, state machine) and plays well with other libraries, such as Django and SQLAlchemy.

Salmon has been released uner the GNU GPLv3, as published by the FSF.

Features

Salmon supports running in many contexts for processing mail using the best technology currently available. Since Salmon is aiming to be a modern mail server and Mail processing framework, it has some features you don't find in any other Mail server.

  • Written in portable Python that should run on almost any Unix server.
  • Handles mail in almost any encoding and format, including attachments, and canonicalizes them for easier processing.
  • Sends nearly pristine clean mail that is easier to process by other receiving servers.
  • Properly decodes internationalized mail into Python unicode, and translates Python unicode back into nice clean ascii and/or UTF-8 mail.
  • Supports working with Maildir queues to defer work and distribute it to multiple machines.
  • Can run as an non-root user on privileged ports to reduce the risk of intrusion.
  • Salmon can also run in a completely separate virtualenv for easy deployment.
  • A flexible and easy to use routing system lets you write stateful or stateless handlers of your email.
  • Ability to use Jinja2 or Mako templates to craft emails including the headers.
  • Easily configurable to use alternative sending and receiving systems, database libraries, or any other systems you need to talk to.
  • Yet, you don't have to configure everything to get stated. A simple salmon gen command lets you get an application up and running quick.
  • Finally, many helpful commands for general mail server debugging and cleaning.

Installing

pip install salmon-mail

Project Information

Project documentation can be found here

Fork

Salmon is a fork of Lamson. In the summer of 2012 (2012-07-13 to be exact), Lamson was relicensed under a BSD variant that was revokable. The two clauses that were of most concern:

4. Contributors agree that any contributions are owned by the copyright holder
and that contributors have absolutely no rights to their contributions.

5. The copyright holder reserves the right to revoke this license on anyone who
uses this copyrighted work at any time for any reason.

I read that to mean that I could make a contribution but then have said work denied to me because the original author didn't like the colour of my socks. So I went and found the latest version that was available under the GNU GPL version 3.

Salmon is an anagram of Lamson, if you hadn't worked it out already.

Source

You can find the source on GitHub:

https://github.com/moggers87/salmon

Status

Salmon has just had some major changes to modernise the code-base. The main APIs should be compatible with releases prior to 3.0.0, but there's no guarantee that older applications won't need changes.

Python versions supported are: 3.5, 3.6, 3.7 and 3.8.

See the CHANGELOG for more details on what's changed since Salmon version 2.

License

Salmon is released under the GNU GPLv3 license, which can be found here

Contributing

Pull requests and issues are most welcome. Please read our code of conduct before contributing!

I will not accept code that has been submitted for inclusion in the original project due to the terms of its new licence.

Code Of Conduct

The Salmon project has adopted the Contributor Covenant Code version 1.4. By contributing to this project, you agree to abide by its terms.

The full text of the code of conduct can be found here

Testing

The Salmon project needs unit tests, code reviews, coverage information, source analysis, and security reviews to maintain quality. If you find a bug, please take the time to write a test case that fails or provide a piece of mail that causes the failure.

If you contribute new code then your code should have as much coverage as possible, with a minimal amount of mocking.

Tests can be run via:

$ python setup.py test

Alternatively, if you have multiple versions of Python installed locally:

$ pip install tox
$ tox -e py36,py37

Refer to the tox documentation for more information.

Development

Salmon is written entirely in Python and runs on Python 3. It should hopefully run on any platform that supports Python and has Unix semantics.

If you find yourself lost in source code, just yell.

PEP-8 should be followed where possible, but feel free to ignore the 80 character limit it imposes (120 is a good marker IMO).

Funding

If you have found Salmon to be useful and would like to see its continued development, please consider buying me a coffee.

Comments
  • Question: How to ignore mail with unknown

    Question: How to ignore mail with unknown "To" host?

    Not sure if this is a proper place to ask for questions/help (see #45).

    I'm now wondering how I can just ignore emails which are sent to some other host than what I've specified.

    My undeliverable queue fills up with some spam that my server receives. That spam is designated to some weird email addresses with weird hosts. I'd like just ignore the mail if the "To" host isn't one of my accepted host names (I have a few of them). Is there a place to list these valid hostnames or are they automatically parsed from the used handlers? And how then ignore mail that doesn't match these host names?

    Anyway, thanks a ton for working on this Lamson fork, this is great.

    opened by jluttine 12
  • You have to use the new license.

    You have to use the new license.

    Sorry but you can't just fork a project at some random point and declare it licensed contrary to what I want. I own copyright and that means if I want my BSD license then that's what you use.

    Basically you ripped out my license modifications which then means you took away the rights I have to give you rights.

    I'd appreciate it if you'd put the license back the way it is supposed to be. It's that way for a reason.

    opened by zedshaw 12
  • Fix regression in 4855991

    Fix regression in 4855991

    This commit fixes a regression in 4855991 which is raising an AttributeError on both 2.7.5 and 3.6.5.

    $ pyenv shell 3.6.5; python -c "import email; assert email.header.Header"
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    AttributeError: module 'email' has no attribute 'header'
    
    opened by cburmeister 9
  • Integrate into Django project?

    Integrate into Django project?

    I try to use salmon in my django project (1.7>=), and when I try to access django ORM in salmon router code, it raises AppRegistryNotReady: Models aren't loaded yet.. Any suggestion how to use django & salmon? Popular answers from google is os.environ.setdefault("DJANGO_SETTINGS_MODULE", "http_handler.settings") and django.setup() but it does not work for salmon projects.

    question 
    opened by soyapark 8
  • How to set up as a simple mail server?

    How to set up as a simple mail server?

    I'm trying to set up a very simple mail server: listen to emails for a particular domain, determine whom it should be sent to based on the address and send the email using ISP mail server as a relay. A very simple mailing list server.

    This was very easy with Lamson. With Salmon, there was a bug(?) in SMTPReceiver that only one recipient was handled. With LMTPReceiver (which is now the default), this is fixed but now there is suddenly the nightmare of setting up a mail server gateway in front of Salmon. The main reason to use Lamson/Salmon - at least for me - was to avoid setting up and maintaining these huge massive complex mail servers and just have a very simple process running and doing the simple thing. Or perhaps I'm missing something and it should be as easy with Salmon too somehow? I'm a bit confused on how Salmon is supposed to be used.. The only instructions I found were: "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."

    For these reasons, I would really appreciate some help on how to set up Salmon so that it works as a mail server. If that really requires some mail server gateway in front, then it'd be great to have some instructions or at least pointers on how to achieve this in a very lightweight way. I don't need mailboxes, I don't need mail sending server (I use my ISP mail server as a relay). If you have any ideas how to proceed, I'd be really happy to hear. If I get it working, I could perhaps write some instructions in case that's useful for other users. Anyway, thanks for this great package and your efforts!

    opened by jluttine 6
  • QueueReceiver performance is quite bad

    QueueReceiver performance is quite bad

    QueueReceiver is quite bad at handling a large influx of messages in a reasonable amount of time.

    Implementation-wise QueueReceiver is the only receiver class that doesn't use threading. Though it's quite a simple class, I think it's also what makes it slow: we're waiting for each message to be processed before fetching another.

    Investigate how threading could improve performance and how badly it would complicate code.

    enhancement 
    opened by moggers87 6
  • Release 3.0.0

    Release 3.0.0

    Thanks for this great project! I noticed there hasn't been a release in a while, last one is version 2, from 20 Jun 2014. Almost three years old.. Would you like to make a new release? Or is the state after every commit equally stable and ready for production? If you'll make releases, may I suggest using semantic versioning so it's easy to notice, for instance, if the API changes in possibly backwards incompatible ways.

    opened by jluttine 6
  • Mail delivered to only one address

    Mail delivered to only one address

    It seems that if the list of recipients contains several email addresses that Salmon needs to handle, it only handles one and delivers the mail there. At least I've been trying to send one email to several recipients and only one of them receives it each time.

    bug 
    opened by jluttine 6
  • Python 3 support

    Python 3 support

    Fixes #7

    • Try to avoid easy_install
    • Remove win32 "support" - it was untested and couldn't be used in production anyway.
    • Mock chardet rather than the string object
    • Don't use reserved words
    • Do binary file reading properly
    • SMTPD messages are slightly different between Python 2 and 3
    • Put test states.db in a folder that gets cleaned between test runs
    • Depending on what version of Python we're using, reload could in one of three places.
    • Use more modern try: except: syntax
    • Print is a function in Python 3
    opened by moggers87 5
  • Port Old Lamson Docs to Salmon

    Port Old Lamson Docs to Salmon

    I'm in the process of converting the old Lamson docs (from the old gpl3 version that salmon was forked from ) into rst in the form of a sphinx project so it can be deployed as a rtd project or through github sites.

    I still need to do some tweaking and cleanup to match changes in salmon since the fork but before I put too much more work into tweaking stuff, I wanted to see if there's an interest in such a PR

    opened by tflink 5
  • Question related to deployment in production

    Question related to deployment in production

    Hi ✋ !

    I am planning to develop an app which needs to act on emails receiving and have some questions about production deployment with Salmon.

    1. Do you have some guidelines or documentation about configuring Salmon behind Postfix or Sendmail as advised ?
    2. Is it possible to have a Django app running behind Nginx on a server and a Salmon process running behing Postfix or Sendmail on the same server with Salmon and Django interacting with each other ? (I have seen a quick demo code in Salmon documentation about this)

    Thank you in advance,

    opened by girardinsamuel 4
  • docs: Fix a few typos

    docs: Fix a few typos

    There are small typos in:

    • README.rst
    • docs/conf.py
    • salmon/commands.py
    • salmon/routing.py
    • tests/test_integration.py
    • tests/test_server.py

    Fixes:

    • Should read under rather than uner.
    • Should read that rather than shat.
    • Should read only rather than onlly.
    • Should read module rather than modiule.
    • Should read destroyed rather than destoryed.
    • Should read configuration rather than configureation.
    • Should read affected rather than afffected.

    Semi-automated pull request generated by https://github.com/timgates42/meticulous/blob/master/docs/NOTE.md

    opened by timgates42 2
  • Adding DKIM signatures

    Adding DKIM signatures

    Hi,

    Would you be interested in a PR that adds DKIM signatures to salmon? This is somewhat related to #72 but its use case is different (it allows mails originating from salmon to contain correct signatures for their domain).

    enhancement PR-welcome 
    opened by DrDub 1
  • QueueReceiver unreliable test

    QueueReceiver unreliable test

      ======================================================================
      FAIL: test_queue_receiver_sleep (tests.test_server.ServerTestCase)
      ----------------------------------------------------------------------
      Traceback (most recent call last):
        File "/Users/runner/hostedtoolcache/Python/3.6.15/x64/lib/python3.6/unittest/mock.py", line 1183, in patched
          return func(*args, **keywargs)
        File "/Users/runner/work/salmon/salmon/tests/test_server.py", line 303, in test_queue_receiver_sleep
          self.assertEqual(sleep_mock.call_count, 2)
      AssertionError: 3 != 2
    

    I feel like I've seen this fail before. Maybe just checking the call count is greater than 0 would be enough to ensure correctness?

    bug tests 
    opened by moggers87 0
  • Stop locking on every handler call

    Stop locking on every handler call

    Salmon should have been thread-safe and performant from the start. This PR makes that true.

    • [x] Write tests for locking handler call
    • [x] Write tests for locking and nolocking decorators
    • [x] Make sure state storages are thread-safe (I think they are already, but it's worth checking)
    • [x] Update docs
    opened by moggers87 1
  • Allow Salmon to do something other than raise an exception when encountering certain decoding errors

    Allow Salmon to do something other than raise an exception when encountering certain decoding errors

    It would be great if Salmon could be told to treat errors in byte decoding with something other than "strict". For example, it might be desirable to use "replace" instead if half an email was better than no email.

    guess_encoding_and_decode has an optional argument errors which is set to DEFAULT_ERROR_HANDLING by default. Because this is set in the function signature it's impossible to monkey-patch the default to some other value without monkey-patching the entire function.

    I imagine this was the original intention behind errors/DEFAULT_ERROR_HANDLING as other variables can be monkey-patched at runtime in lieu of a proper settings sytems.

    1. Change the default value of errors to None and then set errors to DEFAULT_ERROR_HANDLING if errors is still None when the function is called.
    2. Go up the function chain, all the way up to calls from MailRequest and give each one an errors argument. Also give MailRequest some property which can be set after object initialisation that controls the value of errors.

    1 is required to be done to close this issue, 2 would be nice if there aren't too many functions between MailRequest and guess_encoding_and_decode

    enhancement 
    opened by moggers87 0
Releases(3.2.0)
  • 3.2.0(Dec 31, 2019)

    • Switch from argparse to click (#80)
      • Commandline interface is now documented
      • Salmon now exits with non-zero return codes (#112)
    • Fix error in the way default values were handled on start and log commands (#126)
    • Minor fixups of commandline help
    • salmon.server.QueueReceiver now uses threads (#67)
      • For those using @nolocking, this will mean massive improvements in performance
    • salmon.queue.Queue now implements __len__
    • Remove nosetests and just use Python's builtin unit test modules (#96)
    • Directories required for Salmon startup will now be created if they don't exist (#111)
    • Fix routes, blast, and cleanse commands (#102, #103)
    • Python 3.8 is now supported
    • Import settings file on routes command (#128)
    Source code(tar.gz)
    Source code(zip)
    salmon-mail-3.2.0.tar.gz(451.72 KB)
  • 3.2.0rc2(Dec 20, 2019)

  • 3.2.0rc1(Dec 6, 2019)

    Version 3.2.0rc1

    • Switch from argparse to click (#80)
      • Commandline interface is now documented
      • Salmon now exits with non-zero return codes (#112)
    • salmon.server.QueueReceiver now uses threads (#67)
      • For those using @nolocking, this will mean massive improvements in performance
    • salmon.queue.Queue now implements __len__
    • Remove nosetests and just use Python's builtin unit test modules (#96)
    • Directories required for Salmon startup will now be created if they don't exist (#111)
    • Fix routes, blast, and cleanse commands (#102, #103)
    • Python 3.8 is now supported
    Source code(tar.gz)
    Source code(zip)
    salmon-mail-3.2.0rc1.tar.gz(451.30 KB)
Owner
Matt Molyneaux
Pronouns: they/them \\ https://ko-fi.com/moggers87
Matt Molyneaux
Send e-mails to teachers with specified school-website using Aula, anonymously

Information : This only works in Denmark! Send e-mails to teachers with specified school-website using Aula, anonymously. Find your school via the att

Binary.club 1 Jan 24, 2022
Django module to easily send templated emails using django templates, or using a transactional mail provider (mailchimp, silverpop, etc.)

Django-Templated-Email Info: A Django oriented templated email sending class Author: Bradley Whittington (http://github.com/bradwhittington, http://tw

Vinta Software 659 Dec 27, 2022
This is the mail server that handles responses from the Contact Form

mailserver About This is the mail server that handles responses from the Contact Form Contributors ✨ Thanks goes to these wonderful people (emoji key)

IoLang 3 Jan 03, 2022
EmailAll - a powerful Email Collect tool

EmailAll A powerful Email Collect tool 0x1 介绍 😲 EmailAll is a powerful Email Co

473 Dec 22, 2022
Generate Email, Register for anything, Get the OTP/Link

OTE : One Time Email Introduction ote is a command line utility that generates temporary email address and automatically extracts OTPs or confirmation

Somdev Sangwan 457 Jan 03, 2023
Python Email Sender (PES) is a program made with Python using smtplib, socket and tkinter.

Python Email Sender (PES) is a program made with Python using smtplib, socket and tkinter. This program was made for sender email to be a gmail account because that's what I used when testing it out,

Zacky2613 1 Aug 26, 2022
Simple Email Sender using Python 3.

Email Sender 使用 Python 3 实现的简单邮件发送工具。 Version: 0.1.2 (Beta) 主要功能 使用 SMTP 协议发送邮件 支持 SSL/TLS 、 STARTTLS 加密(为保证安全,强制加密发送) 支持邮件模板与邮件生成 支持向多人群发邮件 日志记录 脚本执行

SUMSC 1 Feb 13, 2022
Secret Service Email Encryption/Steganography

SecretService Decoy Encrypted Emailer

Unit 221B 6 Aug 05, 2022
send email & telegram message whenever an analog in is recieved

send email & telegram message whenever an analog in is recieved (so when attached to an alarm siren out it will alert via mail)

Naor Livne 2 Feb 11, 2022
Django module to easily send emails/sms/tts/push using django templates stored on database and managed through the Django Admin

Django-Db-Mailer Documentation available at Read the Docs. What's that Django module to easily send emails/push/sms/tts using django templates stored

LPgenerator 250 Dec 21, 2022
This library is helpful when creating accounts, it has everything you need for this

AccountGeneratorHelper Library to facilitate accounts generation. Unofficial API for temp email services. Receive SMS from free services. Parsing and

Denis 52 Jan 07, 2023
A news curator and newsletter subscription package for Django

django-newsfeed What is django-newsfeed? django-newsfeed is a news curator and newsletter subscription package for django. It can be used to create a

Maksudul Haque 179 Nov 14, 2022
A research into mail services used by different business sectors.

A research into mail services used by different business sectors. Data, scripts and results available.

Focus Chen 1 Dec 24, 2021
:incoming_envelope: IMAP/SMTP sync system with modern APIs

Nylas Sync Engine The Nylas Sync Engine provides a RESTful API on top of a powerful email sync platform, making it easy to build apps on top of email.

Nylas 3.5k Dec 23, 2022
利用阿里的云函数发送电子邮件

alifc_email 主要特性 利用阿里的云函数发送电子邮件 使用场景 hw中的钓鱼邮件发送,一些邮服会解析出邮件的来源ip(此来源ip并不是邮服的ip,而是从客户端发送邮件时,邮服自动带上的客户端ip),对于这些来源ip可能会做一些风控。 本项目利用云函数出口ip较多来绕过这些风控 使用方法 首

19 Dec 01, 2022
📧 CLI to deduplicate mails from mail boxes.

Mail Deduplicate Command-line tool to deduplicate mails from a set of boxes. Stable release: Development: Features Duplicate detection based on cherry

Kevin Deldycke 134 Dec 14, 2022
This Tool Is For Sending Emails From A Terminal(Termux/Kali) etc.

This is a Basic python script to send emails from a Terminal(Termux/Kali) are the only tested currently.

AnonyVox 2 Apr 04, 2022
This Python program generates a random email address and password from a 2 big lists and checks the generated email.

This Python program generates a random email address and password from a 2 big lists and checks the generated email.

Killin 13 Dec 04, 2022
GMailBomber is a form of Internet abuse which is perpetrated through the sending of massive volumes of email to a specific email address with the goal of overflowing the mailbox and overwhelming the mail server hosting the address, making it into some form of denial of service attack.

GMailBomber is a form of Internet abuse which is perpetrated through the sending of massive volumes of email to a specific email address with the goal of overflowing the mailbox and overwhelming the

Muneeb 5 Nov 13, 2022
A Python Mail Server

Salmon - A Python Mail Server Download: https://pypi.org/project/salmon-mail/ Source: https://github.com/moggers87/salmon Docs: https://salmon-mail.re

Matt Molyneaux 582 Dec 30, 2022