diff --git a/maildump/smtp.py b/maildump/smtp.py index 6f0043f..ed3586b 100644 --- a/maildump/smtp.py +++ b/maildump/smtp.py @@ -17,11 +17,11 @@ def __init__(self, server, conn, addr, smtp_auth): self._authorized = False def is_valid_user(self, auth_data): - auth_data_splitted = auth_data.split('\x00') + auth_data_splitted = auth_data.split(b'\x00') if len(auth_data_splitted) != 3: return False - if not auth_data.startswith('\x00') and auth_data_splitted[0] != auth_data_splitted[1]: + if not auth_data.startswith(b'\x00') and auth_data_splitted[0] != auth_data_splitted[1]: return False return self._smtp_auth.check_password(auth_data_splitted[1], auth_data_splitted[2]) @@ -30,17 +30,28 @@ def smtp_EHLO(self, arg): if not arg: self.push('501 Syntax: EHLO hostname') return - if self.__greeting: + # See issue #21783 for a discussion of this behavior. + if self.seen_greeting: self.push('503 Duplicate HELO/EHLO') return - self.__greeting = arg - self.push('250-%s' % self.__fqdn) + self._set_rset_state() + self.seen_greeting = arg + self.extended_smtp = True + self.push('250-%s' % self.fqdn) if self._smtp_auth: self.push('250-AUTH PLAIN') + if self.data_size_limit: + self.push('250-SIZE %s' % self.data_size_limit) + self.command_size_limits['MAIL'] += 26 + if not self._decode_data: + self.push('250-8BITMIME') + if self.enable_SMTPUTF8: + self.push('250-SMTPUTF8') + self.command_size_limits['MAIL'] += 10 self.push('250 HELP') def smtp_AUTH(self, arg): - print >> smtpd.DEBUGSTREAM, '===> AUTH', arg + print('auth:', arg, file=smtpd.DEBUGSTREAM) if not self._smtp_auth: self.push('501 Syntax: AUTH not enabled') return @@ -97,7 +108,7 @@ def handle_accept(self): pair = self.accept() if pair is not None: conn, addr = pair - print >> smtpd.DEBUGSTREAM, 'Incoming connection from %s' % repr(addr) + print('Incoming connection from %s' % repr(addr), file=smtpd.DEBUGSTREAM) channel = SMTPChannel(self, conn, addr, self._smtp_auth) def process_message(self, peer, mailfrom, rcpttos, data, **kwargs): diff --git a/maildump_runner/main.py b/maildump_runner/main.py index 6082396..178b3c9 100644 --- a/maildump_runner/main.py +++ b/maildump_runner/main.py @@ -91,11 +91,19 @@ def main(): args.htpasswd = os.path.abspath(args.htpasswd) print('Htpasswd path is relative, using {0}'.format(args.htpasswd)) + if args.smtp_auth and not os.path.isabs(args.smtp_auth): + args.smtp_auth = os.path.abspath(args.smtp_auth) + print('SMTP Htpasswd path is relative, using {0}'.format(args.smtp_auth)) + # Check if the password file is valid if args.htpasswd and not os.path.isfile(args.htpasswd): print('Htpasswd file does not exist') sys.exit(1) + if args.smtp_auth and not os.path.isfile(args.smtp_auth): + print('SMTP Htpasswd file does not exist') + sys.exit(1) + daemon_kw = { 'monkey_greenlet_report': False, 'signal_map': {signal.SIGTERM: terminate_server, signal.SIGINT: terminate_server}, @@ -137,7 +145,7 @@ def main(): app.debug = args.debug app.config['MAILDUMP_HTPASSWD'] = None - if args.htpasswd: + if args.htpasswd or args.smtp_auth: # passlib is broken on py39, hence the local import # https://foss.heptapod.net/python-libs/passlib/-/issues/115 try: @@ -145,6 +153,8 @@ def main(): except OSError: print('Are you using Python 3.9? If yes, authentication is currently not available due to a bug.\n\n') raise + + if args.htpasswd: app.config['MAILDUMP_HTPASSWD'] = HtpasswdFile(args.htpasswd) app.config['MAILDUMP_NO_QUIT'] = args.no_quit smtp_auth = HtpasswdFile(args.smtp_auth) if args.smtp_auth else None