Giter VIP home page Giter VIP logo

secure-smtpd's Introduction

Secure SMTPD

Secure-SMTPD extends on Petri Lehtinen's SMTPD library adding support for AUTH and SSL.

Usage

from secure_smtpd import SMTPServer, FakeCredentialValidator
SMTPServer(
    self,
    ('0.0.0.0', 465),
    None,
    require_authentication=True,
    ssl=True,
    certfile='examples/server.crt',
    keyfile='examples/server.key',
    credential_validator=FakeCredentialValidator(),
)
asyncore.loop()

secure-smtpd's People

Contributors

aldur avatar bcoe avatar cltrudeau avatar duongkai avatar grantedwards avatar pauloppenheim-liveloop avatar pneuman avatar pysquared avatar svisser avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

secure-smtpd's Issues

ssl.SSLWantReadError not being handled

Any time I receive messages with a body longer than a few dozen bytes, I get a failure that looks like this (I've add a bit of extra info to the normal log messages in smtp_server.py):

2018-01-17 21:38:59,100 smtpfwd[2144]:    INFO: _accept_subprocess(): smtp connection accepted within subprocess: (<socket._socketobject object at 0x7f5acd080d00>, ('nnn.nnn.nnn.nnn', 33114)).
2018-01-17 21:38:59,138 smtpfwd[2144]:    INFO: _accept_subprocess(): starting asyncore within subprocess. map={10: <secure_smtpd.smtp_channel.SMTPChannel connected nnn.nnn.nnn.nnn:33114 at 0x7f5acd04f710>}
2018-01-17 21:38:59,342 smtpfwd[2144]:    INFO: login by [elided] OK
2018-01-17 21:38:59,458 smtpfwd[2144]:   ERROR: _accept_subprocess(): asyncore loop exited.

AFAICT, in this failure case my message handler is never being called at all.

How do I find out what the problem is?

Shorter messages seem to work fine and the log looks like this:

2018-01-17 21:23:10,748 smtpfwd[1804]:    INFO: _accept_subprocess(): starting asyncore within subprocess. map={9: <secure_smtpd.smtp_channel.SMTPChannel connected 209.85.223.176nnn.nnn.nnn.nnn:44329 at 0x7f2c4e795b90>}
2018-01-17 21:23:10,938 smtpfwd[1804]:    INFO: login by [elided] OK
[... status messages from my message handler ...]
2018-01-17 21:23:12,301 smtpfwd[1804]:    INFO: _accept_subprocess(): smtp channel terminated asyncore.

How to debug?

I've been running a simple mail forwarder using secure_smtpd for a couple years. It has recently stopped working and I'm trying to figure out why.

How do I log the SMTP commands and responses?

Update Logging Approach

The logging approach used in secure-smtpd should be updated so that it's easier to filter on specific log levels.

Error When AUTH

My code:
`
import logging
from secure_smtpd import SMTPServer, FakeCredentialValidator, LOG_NAME

class SSLSMTPServer(SMTPServer):
def process_message(self, peer, mailfrom, rcpttos, message_data):
print(message_data)

logger = logging.getLogger( LOG_NAME )
logger.setLevel(logging.INFO)

server = SSLSMTPServer(
('0.0.0.0', 4896),
None,
require_authentication=True,
ssl=False,
credential_validator=FakeCredentialValidator(),
maximum_execution_time = 1.0
)

server.run()
`

ERROR:
error: uncaptured python exception, closing channel <__main__.SSLSMTPServer listening 0.0.0.0:4896 at 0x2e3e108> (<class 'pickle.PicklingError'>:Can't pickle <built-in method recvfrom_into of _socket.socket object at 0x0000000002E3E130>: it's not found as __main__.recvfrom_into [C:\Python27\lib\asyncore.py|read|83] [C:\Python27\lib\asyncore.py|handle_read_event|443] [C:\Python27\lib\site-packages\secure_smtpd-3.0.0-py2.7.egg\secure_smtpd\smtp_server.py|handle_accept|31] [C:\Python27\lib\site-packages\secure_smtpd-3.0.0-py2.7.egg\secure_smtpd\process_pool.py|__init__|10] [C:\Python27\lib\site-packages\secure_smtpd-3.0.0-py2.7.egg\secure_smtpd\process_pool.py|_create_processes|16] [C:\Python27\lib\multiprocessing\process.py|start|130] [C:\Python27\lib\multiprocessing\forking.py|__init__|277] [C:\Python27\lib\multiprocessing\forking.py|dump|199] [C:\Python27\lib\pickle.py|dump|224] [C:\Python27\lib\pickle.py|save|331] [C:\Python27\lib\pickle.py|save_reduce|425] [C:\Python27\lib\pickle.py|save|286] [C:\Python27\lib\pickle.py|save_dict|655] [C:\Python27\lib\pickle.py|_batch_setitems|687] [C:\Python27\lib\pickle.py|save|286] [C:\Python27\lib\multiprocessing\forking.py|dispatcher|67] [C:\Python27\lib\pickle.py|save_reduce|401] [C:\Python27\lib\pickle.py|save|286] [C:\Python27\lib\pickle.py|save_tuple|554] [C:\Python27\lib\pickle.py|save|286] [C:\Python27\lib\pickle.py|save_inst|731] [C:\Python27\lib\pickle.py|save|286] [C:\Python27\lib\pickle.py|save_dict|655] [C:\Python27\lib\pickle.py|_batch_setitems|687] [C:\Python27\lib\pickle.py|save|331] [C:\Python27\lib\pickle.py|save_reduce|425] [C:\Python27\lib\pickle.py|save|286] [C:\Python27\lib\pickle.py|save_tuple|554] [C:\Python27\lib\pickle.py|save|286] [C:\Python27\lib\pickle.py|save_dict|655] [C:\Python27\lib\pickle.py|_batch_setitems|687] [C:\Python27\lib\pickle.py|save|286] [C:\Python27\lib\pickle.py|save_global|754])

AUTH LOGIN broken

The strings to be encoded are:

  • 'Username:'
  • 'Password:'

Mind the ":" at the end!

Error while launching example code

Traceback (most recent call last):
  File "C:\WorkFolder\secure-mail-server\server\server.py", line 1, in <module>
    from secure_smtpd import SMTPServer, FakeCredentialValidator
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\secure_smtpd\__init__.py", line 3, in <module>
    from .smtp_server import SMTPServer
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\secure_smtpd\smtp_server.py", line 4, in <module>
    from .smtp_channel import SMTPChannel
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\secure_smtpd\smtp_channel.py", line 5, in <module>
    from smtpd import NEWLINE, EMPTYSTRING
ImportError: cannot import name 'EMPTYSTRING' from 'smtpd' (C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\smtpd.py)

while launching

from secure_smtpd import SMTPServer, FakeCredentialValidator
SMTPServer(
    self,
    ('0.0.0.0', 465),
    None,
    require_authentication=True,
    ssl=True,
    certfile='cert.crt',
    keyfile='key.key',
    credential_validator=FakeCredentialValidator(),
)
asyncore.loop()

Unable to run secure-smtpd on Python 3.5

(env3) secure-smtpd [master] % python examples/ssl_server.py
Traceback (most recent call last):
  File "examples/ssl_server.py", line 2, in <module>
    from secure_smtpd import SMTPServer, FakeCredentialValidator, LOG_NAME
  File "/Users/sli/secure-smtpd/secure_smtpd/__init__.py", line 3, in <module>
    from .smtp_server import SMTPServer
  File "/Users/sli/secure-smtpd/secure_smtpd/smtp_server.py", line 4, in <module>
    from .smtp_channel import SMTPChannel
  File "/Users/sli/secure-smtpd/secure_smtpd/smtp_channel.py", line 9, in <module>
    from smtpd import NEWLINE, EMPTYSTRING
ImportError: cannot import name 'EMPTYSTRING'

EMPTYSTRING was removed 21 month ago in Python 3.5.1.

AUTH LOGIN returns unicode 334 answer

With Python 2.7.3, I am getting the strange effect, that the answer to AUTH LOGIN apparently is transmitted as a unicode string which clients do not understand.

This is a tcpflow snippet demonstrating this:

046.163.077.142.01025-176.083.128.183.54917: 250-AUTH LOGIN PLAIN
250 EHLO
176.083.128.183.54917-046.163.077.142.01025: AUTH LOGIN
....163.077.142.01025-176.083.128.183.54917: 3...3...4... ...V...X...N...l...c...m...5...h...b...W...U...=...

Dots are zeros in tcpflow-speak.

If I change encode_b64 as follows (i.e., remove the final 'decode' statement), it works like a charm:

def encode_b64(data):
    '''Wrapper for b64encode, without having to struggle with bytestrings.'''
    byte_string = data.encode('utf-8')
    encoded = base64.b64encode(byte_string)
    return encoded

Switch to Using Process Pool

The main overhead in the server is currently that of spawning off new processes for inbound requests.

I should switch to using a pool of processes.

Thunderbird: send helo first?

Hello,

I am trying to run a secure_smtp server and connect with thunderbird.
Everytime I try to sent a email, I get this error:

"error: send helo first"

I have no clue where this is comming from or how to fix this.

Here is my Code:

`
class CredentialValidator(object):
def validate(self, username, password):
if username == 'foo' and password == 'bar':
return True
return False

class SSLSMTPServer(SMTPServer):
def process_message(self, peer, mailfrom, rcpttos, message_data):
print(message_data)

server = SSLSMTPServer(
('0.0.0.0', 61455),
None,
require_authentication=True,
ssl=True,
#ssl_version=ssl.PROTOCOL_TLSv1_2,
certfile='/home/fullchain.pem',
keyfile='/home/privkey.pem',
credential_validator=CredentialValidator(),
#maximum_execution_time = 1.0
)

server.run()
`

Any ideas?

SMTPChannel Login

Older mail clients (outlook 2007) seems to balk when connecting.

Fix is to encode Username: not Username and Password: not Password.

Other than that great little extension looking to add TLS support will issue pull request if we get it working.

MANIFEST.in with trailing forward slash

Hey bcoe,

Just came across an issue when installing secure-smtpd, my python version is 2.7.2 in Windows, and my Lib\distutil\util.py was complaining about 'path examples/ cannot end with /', the path came from MANIFEST.in, then the install failed.

Same applies to examples/benchmarking/

Cheers,
hjbolide

support for Python3

Please add support for Python 3.2+

$ sudo easy_install3 -U secure-smtpd
[sudo] password for ddarko:
Searching for secure-smtpd
Reading http://pypi.python.org/simple/secure-smtpd/
Reading https://github.com/bcoe/secure-smtpd
Best match: secure-smtpd 1.1.9
Downloading http://pypi.python.org/packages/source/s/secure-smtpd/secure-smtpd-1.1.9.tar.gz#md5=8b8aa9bb0d24098edf8ba0e97bacf870
Processing secure-smtpd-1.1.9.tar.gz
Running secure-smtpd-1.1.9/setup.py -q bdist_egg --dist-dir /tmp/easy_install-pftrn2/secure-smtpd-1.1.9/egg-dist-tmp-s3ag7j
File "build/bdist.linux-i686/egg/secure_smtpd/smtp_server.py", line 69
except Exception, e:
^
SyntaxError: invalid syntax

File "build/bdist.linux-i686/egg/secure_smtpd/proxy_server.py", line 81
except smtplib.SMTPRecipientsRefused, e:
^
SyntaxError: invalid syntax

"except Exception, e:"
to:
"except Exception as e:"

How do you kill a server?

Killing the initial/parent process doesn't seem to do anything: that process goes away, but there are still worker processes hanging around accepting connections. How is
something like a Unix "init" script supposed to shut down a daemon running secure-smtpd server?

TypeError: __init__() got an unexpected keyword argument 'debug'

Documentation on pypi and github says it should be instantiated like this:

SMTPServer(
    self,
    ('0.0.0.0', 465),
    None,
    require_authentication=True,
    ssl=True,
    certfile='examples/server.crt',
    keyfile='examples/server.key',
    credential_validator=FakeCredentialValidator(),
    debug=True
)

However it is not correct as constructor in recent release does not have debug parameter and it results in:

TypeError: __init__() got an unexpected keyword argument 'debug'

Please fix documentation or implement debugging and debug argument.

example from README does not work as-is - syntax error

(fosdem-volunteers)emanuil@midori:~/software/secure-smtpd$ python --version
Python 2.7.6

(fosdem-volunteers)emanuil@midori:~/software/secure-smtpd$ pip freeze | grep smtpd
secure-smtpd==3.0.0

(fosdem-volunteers)emanuil@midori:~/software/secure-smtpd$ cat run.py 
from secure_smtpd import SMTPServer, FakeCredentialValidator
SMTPServer(
self,
('0.0.0.0', 465),
None,
require_authentication=True,
ssl=True,
certfile='examples/server.crt',
keyfile='examples/server.key',
credential_validator=FakeCredentialValidator(),
)
asyncore.loop()

(fosdem-volunteers)emanuil@midori:~/software/secure-smtpd$ python run.py                                                                                                                
Traceback (most recent call last):                                                                                                                                                      
  File "run.py", line 3, in <module>                                                                                                                                                    
    self,                                                                                                                                                                               
NameError: name 'self' is not defined

Python 3 - 503 Error: send HELO first

On Python 3 I've got the following error while trying to send any mail: 503 Error: send HELO first.

I managed to investigate the source and it appears to be as follows.

You subclass smtpd.SMTPChannel and override the method smtp_EHLO.
In the CPython implementation of this method the instance variable self.seen_greeting is set and then, in the smtp_RCPT method, there is a check on that same variable (relevant code here).
This check fails and trigger the error.

As far as I can see, there is no need to override the smtp_EHLO method.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.