Skip to content

Commit

Permalink
Merge pull request #74 from moggers87/73-mailrequest-str-defined-twice
Browse files Browse the repository at this point in the history
PEP8 fixes
  • Loading branch information
moggers87 committed May 25, 2018
2 parents d6a5bec + 9bea825 commit 902959b
Show file tree
Hide file tree
Showing 27 changed files with 172 additions and 136 deletions.
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ matrix:
env: TOX_ENV=docs
install: pip install tox
script: tox -e $TOX_ENV
- python: "2.7"
env: TOX_ENV=lint
install: pip install tox
script: tox -e $TOX_ENV

install:
- travis_retry pip install -e .
Expand Down
2 changes: 1 addition & 1 deletion salmon/bounce.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
u'77': u'Message integrity failure',
}


def match_bounce_headers(msg):
"""
Goes through the headers in a potential bounce message recursively
Expand Down Expand Up @@ -236,7 +237,6 @@ def __init__(self, headers, score):

self.notification = self.content_parts.get('notification', None)


def is_hard(self):
"""
Tells you if this was a hard bounce, which is determined by the message
Expand Down
57 changes: 36 additions & 21 deletions salmon/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ def log_command(parser):
each message it receives and also stores it to the run/queue
so that you can make sure it was received in testing.
"""
def command(port, host, pid, chdir, chroot=None, uid=False, gid=False, umask=False, force=False, debug=False, daemon=True):
loader = lambda: utils.make_fake_settings(host, port)
utils.start_server(pid, force, chroot, chdir, uid, gid, umask, loader, debug, daemon)
def command(port, host, pid, chdir, chroot=None, uid=False, gid=False, umask=False,
force=False, debug=False, daemon=True):
utils.start_server(pid, force, chroot, chdir, uid, gid, umask,
lambda: utils.make_fake_settings(host, port), debug, daemon)

parser.set_defaults(func=command)

Expand All @@ -92,21 +93,25 @@ def command(port, host, pid, chdir, chroot=None, uid=False, gid=False, umask=Fal
uid_group.add_argument("--gid", type=int, default=argparse.SUPPRESS, help="run with this group id")

daemon_group = parser.add_mutually_exclusive_group()
daemon_group.add_argument("--no-daemon", default=argparse.SUPPRESS, dest="daemon", action="store_false", help="start server in foreground")
daemon_group.add_argument("--daemon", default=argparse.SUPPRESS, dest="daemon", action="store_true", help="start server as daemon (default)")
daemon_group.add_argument("--no-daemon", default=argparse.SUPPRESS, dest="daemon", action="store_false",
help="start server in foreground")
daemon_group.add_argument("--daemon", default=argparse.SUPPRESS, dest="daemon", action="store_true",
help="start server as daemon (default)")


def send_command(parser):
"""
Sends an email to someone as a test message.
See the sendmail command for a sendmail replacement.
"""
def command(port, host, username=None, password=None, ssl=None, starttls=None, lmtp=None, sender=None, to=None, subject=None, body=None, attach=None):
def command(port, host, username=None, password=None, ssl=None, starttls=None, lmtp=None,
sender=None, to=None, subject=None, body=None, attach=None):
message = mail.MailResponse(From=sender, To=to, Subject=subject, Body=body)
if attach:
message.attach(attach)

relay = server.Relay(host, port=port, username=username, password=password, ssl=ssl, starttls=starttls, lmtp=lmtp, debug=False)
relay = server.Relay(host, port=port, username=username, password=password, ssl=ssl,
starttls=starttls, lmtp=lmtp, debug=False)
relay.deliver(message)

parser.set_defaults(func=command)
Expand Down Expand Up @@ -153,8 +158,8 @@ def start_command(parser):
Runs a salmon server out of the current directory
"""
def command(pid, force, chdir, boot, chroot=False, uid=False, gid=False, umask=False, debug=False, daemon=True):
loader = lambda: utils.import_settings(True, boot_module=boot)
utils.start_server(pid, force, chroot, chdir, uid, gid, umask, loader, debug, daemon)
utils.start_server(pid, force, chroot, chdir, uid, gid, umask,
lambda: utils.import_settings(True, boot_module=boot), debug, daemon)

parser.set_defaults(func=command)

Expand All @@ -171,8 +176,10 @@ def command(pid, force, chdir, boot, chroot=False, uid=False, gid=False, umask=F
uid_group.add_argument("--gid", type=int, default=argparse.SUPPRESS, help="run with this group id")

daemon_group = parser.add_mutually_exclusive_group()
daemon_group.add_argument("--no-daemon", default=argparse.SUPPRESS, dest="daemon", action="store_false", help="start server in foreground")
daemon_group.add_argument("--daemon", default=argparse.SUPPRESS, dest="daemon", action="store_true", help="start server as daemon (default)")
daemon_group.add_argument("--no-daemon", default=argparse.SUPPRESS, dest="daemon", action="store_false",
help="start server in foreground")
daemon_group.add_argument("--daemon", default=argparse.SUPPRESS, dest="daemon", action="store_true",
help="start server as daemon (default)")


def stop_command(parser):
Expand Down Expand Up @@ -212,8 +219,10 @@ def command(pid, kill=False, all=False):
parser.set_defaults(func=command)

parser.add_argument("--pid", default=DEFAULT_PID_FILE, help="path to pid file")
parser.add_argument("-f", "--force", dest="kill", default=DEFAULT_PID_FILE, action="store_true", help="force stop server")
parser.add_argument("--all", default=argparse.SUPPRESS, help="stops all servers with .pid files in the specified directory")
parser.add_argument("-f", "--force", dest="kill", default=DEFAULT_PID_FILE, action="store_true",
help="force stop server")
parser.add_argument("--all", default=argparse.SUPPRESS,
help="stops all servers with .pid files in the specified directory")


def status_command(parser):
Expand Down Expand Up @@ -261,10 +270,13 @@ def command(name, pop=False, get=False, keys=False, remove=False, count=False, c
parser.set_defaults(func=command)

command_group = parser.add_mutually_exclusive_group(required=True)
command_group.add_argument("--pop", action="store_true", default=argparse.SUPPRESS, help="pop a message from queue")
command_group.add_argument("--pop", action="store_true", default=argparse.SUPPRESS,
help="pop a message from queue")
command_group.add_argument("--get", metavar="KEY", default=argparse.SUPPRESS, help="get key from queue")
command_group.add_argument("--remove", metavar="KEY", default=argparse.SUPPRESS, help="remove chosen key from queue")
command_group.add_argument("--count", action="store_true", default=argparse.SUPPRESS, help="count messages in queue")
command_group.add_argument("--remove", metavar="KEY", default=argparse.SUPPRESS,
help="remove chosen key from queue")
command_group.add_argument("--count", action="store_true", default=argparse.SUPPRESS,
help="count messages in queue")
command_group.add_argument("--clear", action="store_true", default=argparse.SUPPRESS, help="clear queue")
command_group.add_argument("--keys", action="store_true", default=argparse.SUPPRESS, help="print queue keys")

Expand Down Expand Up @@ -309,7 +321,8 @@ def command(modules, path=os.getcwd(), test=""):
parser.set_defaults(func=command)

parser.add_argument("--path", default=argparse.SUPPRESS, help="search path for modules")
parser.add_argument("modules", metavar="module", nargs="*", default=["config.testing"], help="config modules to process")
parser.add_argument("modules", metavar="module", nargs="*", default=["config.testing"],
help="config modules to process")
parser.add_argument("--test", metavar="EMAIL", default=argparse.SUPPRESS, help="test address")


Expand All @@ -332,7 +345,8 @@ def command(project, force=False):
parser.set_defaults(func=command)

parser.add_argument("project", help="project name")
parser.add_argument("-f", "--force", action="store_true", default=argparse.SUPPRESS, help="overwrite existing directories")
parser.add_argument("-f", "--force", action="store_true", default=argparse.SUPPRESS,
help="overwrite existing directories")


def cleanse_command(parser):
Expand Down Expand Up @@ -400,14 +414,15 @@ def command(input, host, port, lmtp=None, debug=False):

# Bring it all together

_parser = argparse.ArgumentParser(description="Python mail server", epilog=copyright_notice, formatter_class=argparse.RawDescriptionHelpFormatter)
_parser = argparse.ArgumentParser(description="Python mail server", epilog=copyright_notice,
formatter_class=argparse.RawDescriptionHelpFormatter)

_parser.add_argument("-v", "--version", action="version", version=version_info)
_subparsers = _parser.add_subparsers(metavar="<command>")
_subparsers.required = True

for cmd, help_txt in COMMANDS:
function = globals()["{0}_command".format(cmd)]
cmd_parser = _subparsers.add_parser(cmd, description=function.__doc__,
help=help_txt, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
cmd_parser = _subparsers.add_parser(cmd, description=function.__doc__, help=help_txt,
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
function(cmd_parser)
6 changes: 4 additions & 2 deletions salmon/confirm.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
"""
from __future__ import print_function, unicode_literals

from email.utils import parseaddr
import uuid

from salmon import queue, view
from email.utils import parseaddr


class ConfirmationStorage(object):
"""
Expand Down Expand Up @@ -81,6 +83,7 @@ def store(self, target, from_address, expected_secret, pending_message_id):
self.confirmations[self.key(target, from_address)] = (expected_secret,
pending_message_id)


class ConfirmationEngine(object):
"""
The confirmation engine is what does the work of sending a confirmation,
Expand Down Expand Up @@ -120,7 +123,6 @@ def delete_pending(self, pending_id):
"""
self.pending.remove(pending_id)


def cancel(self, target, from_address, expect_secret):
"""
Used to cancel a pending confirmation.
Expand Down
12 changes: 6 additions & 6 deletions salmon/data/prototype/tests/handlers/open_relay_tests.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from nose.tools import *
from salmon.testing import *
import os
from salmon import server
from nose.tools import * # noqa
from salmon.testing import relay, RouterConversation, queue


relay = relay(port=8823)
client = RouterConversation("somedude@localhost", "requests_tests")
Expand All @@ -25,5 +24,6 @@ def test_drops_open_relay_messages():
"""
client.begin()
client.say("tester@badplace.notinterwebs", "Relay should not happen")
assert queue().count() == 0, "You are configured currently to accept everything. You should change config/settings.py router_defaults so host is your actual host name that will receive mail."

assert queue().count() == 0, "You are configured currently to accept everything. " \
"You should change config/settings.py router_defaults " \
"so host is your actual host name that will receive mail."
27 changes: 15 additions & 12 deletions salmon/encoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,10 @@
from email import encoders
from email.charset import Charset
from email.message import Message
from email.mime.base import MIMEBase
from email.utils import parseaddr
import email
import re
import string
import sys
import warnings

import chardet
Expand All @@ -94,10 +92,13 @@
ENCODING_END_REGEX = re.compile(r"\?=", REGEX_OPTS)
INDENT_REGEX = re.compile(r"\n\s+")

VALUE_IS_EMAIL_ADDRESS = lambda v: '@' in v
ADDRESS_HEADERS_WHITELIST = ['From', 'To', 'Delivered-To', 'Cc', 'Bcc']


def VALUE_IS_EMAIL_ADDRESS(v):
return "@" in v


class EncodingError(Exception):
"""Thrown when there is an encoding error."""
pass
Expand Down Expand Up @@ -206,7 +207,7 @@ def __delitem__(self, key):
del self.mime_part[key]

def __nonzero__(self):
return self.body != None or len(self.mime_part) > 0 or len(self.parts) > 0
return self.body is not None or len(self.mime_part) > 0 or len(self.parts) > 0

def items(self):
return [(normalize_header(key), header_from_mime_encoding(header)) for key, header in self.mime_part.items()]
Expand Down Expand Up @@ -246,7 +247,6 @@ def body(self, value):
ctype, params = self.content_encoding['Content-Type']
self.mime_part.set_payload(value, params.get("charset", None))


def attach_file(self, filename, data, ctype, disposition):
"""
A file attachment is a raw attachment with a disposition that
Expand All @@ -262,7 +262,6 @@ def attach_file(self, filename, data, ctype, disposition):
{'filename': filename})
self.parts.append(part)


def attach_text(self, data, ctype):
"""
This attaches a simpler text encoded part, which doesn't have a
Expand Down Expand Up @@ -302,7 +301,7 @@ def add_text(self, content, charset=None):
# this is text, so encode it in canonical form
if charset is not None:
warnings.warn("You are adding text that is neither ASCII nor UTF-8. Please reconsider your choice.",
UnicodeWarning)
UnicodeWarning)

charset = charset or 'ascii'
try:
Expand Down Expand Up @@ -337,8 +336,9 @@ def extract_payload(self, mail):

def __repr__(self):
return "<MIMEPart '%s': %r, %r, multipart=%r>" % (self.mimetype, self['Content-Type'],
self['Content-Disposition'],
self.is_multipart())
self['Content-Disposition'],
self.is_multipart())


def from_message(message, parent=None):
"""
Expand Down Expand Up @@ -372,7 +372,8 @@ def to_message(mail):
ctype = 'text/plain'
else:
if mail.parts:
assert ctype.startswith("multipart") or ctype.startswith("message"), "Content type should be multipart or message, not %r" % ctype
assert ctype.startswith("multipart") or ctype.startswith("message"), \
"Content type should be multipart or message, not %r" % ctype

# adjust the content type according to what it should be now
mail.content_encoding['Content-Type'] = (ctype, params)
Expand Down Expand Up @@ -456,7 +457,8 @@ def parse_parameter_header(message, header):
params_dict = dict(params)

for key in CONTENT_ENCODING_REMOVED_PARAMS:
if key in params_dict: del params_dict[key]
if key in params_dict:
del params_dict[key]

return value, params_dict
else:
Expand Down Expand Up @@ -495,7 +497,8 @@ def properly_encode_header(value, encoder, not_email):


def header_to_mime_encoding(value, not_email=False):
if not value: return ""
if not value:
return ""

encoder = Charset(DEFAULT_ENCODING)
if isinstance(value, list):
Expand Down
5 changes: 3 additions & 2 deletions salmon/handlers/forward.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
of allowed hosts your machine answers to and only forwards those.
"""

import logging

from salmon.routing import route, stateless
from salmon.utils import settings
import logging


@route("(to)@(host)", to=".+", host=".+")
@stateless
def START(message, to=None, host=None):
"""Forwards every mail it gets to the relay. BE CAREFUL WITH THIS."""
logging.debug("MESSAGE to %s@%s forwarded to the relay host.", to, host)
settings.relay.deliver(message)

6 changes: 3 additions & 3 deletions salmon/handlers/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
receives and dumps it to the logging.debug stream.
"""

from salmon.routing import route, stateless
import logging

from salmon.routing import route, stateless


@route("(to)@(host)", to=".+", host=".+")
@stateless
def START(message, to=None, host=None):
"""This is stateless and handles every email no matter what, logging what it receives."""
logging.debug("MESSAGE to %s@%s:\n%s", to, host, str(message))


6 changes: 4 additions & 2 deletions salmon/handlers/queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
the salmon queue command.
"""

import logging

from salmon.routing import route_like, stateless, nolocking
from salmon import queue, handlers
import logging


@route_like(handlers.log.START)
@stateless
Expand All @@ -17,6 +19,6 @@ def START(message, to=None, host=None):
@stateless and routes however handlers.log.START routes (everything).
Has @nolocking, but that's alright since it's just writing to a Maildir.
"""
logging.debug("MESSAGE to %s@%s added to queue.", to, host)
q = queue.Queue('run/queue')
q.push(message)

Loading

0 comments on commit 902959b

Please sign in to comment.