def test_choose_mx(self): records = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)] mx = MxSmtpRelay() self.assertEqual(1, mx.choose_mx(records, 0)) self.assertEqual(5, mx.choose_mx(records, 4)) self.assertEqual(1, mx.choose_mx(records, 5)) self.assertEqual(3, mx.choose_mx(records, 7)) self.assertEqual(2, mx.choose_mx(records, 1821))
def test_attempt_no_answer(self): env = Envelope('*****@*****.**', ['*****@*****.**']) mx = MxSmtpRelay() self.mox.StubOutWithMock(mx, 'new_static_relay') self.mox.StubOutWithMock(dns_resolver, 'query') dns_resolver.query('example.com', 'MX').AndRaise(DNSTimeout) self.mox.ReplayAll() with assert_raises(TransientRelayError): mx.attempt(env, 0)
def test_attempt_no_answer(self): env = Envelope('*****@*****.**', ['*****@*****.**']) mx = MxSmtpRelay() self.mox.StubOutWithMock(mx, 'new_static_relay') self.mox.StubOutWithMock(dns_resolver, 'query') dns_resolver.query('example.com', 'MX').AndRaise(DNSTimeout) self.mox.ReplayAll() with self.assertRaises(TransientRelayError): mx.attempt(env, 0)
def test_attempt_no_answer(self): env = Envelope("*****@*****.**", ["*****@*****.**"]) mx = MxSmtpRelay() self.mox.StubOutWithMock(mx, "new_static_relay") self.mox.StubOutWithMock(dns_resolver, "query") dns_resolver.query("example.com", "MX").AndRaise(DNSTimeout) self.mox.ReplayAll() with assert_raises(TransientRelayError): mx.attempt(env, 0)
def test_attempt_no_records(self): env = Envelope('*****@*****.**', ['*****@*****.**']) mx = MxSmtpRelay() self.mox.StubOutWithMock(mx, 'new_static_relay') self.mox.StubOutWithMock(DNSResolver, 'query') DNSResolver.query('example.com', 'MX').AndRaise(DNSError(ARES_ENOTFOUND)) DNSResolver.query('example.com', 'A').AndRaise(DNSError(ARES_ENOTFOUND)) self.mox.ReplayAll() with self.assertRaises(PermanentRelayError): mx.attempt(env, 0)
def test_attempt_no_answer(self): env = Envelope('*****@*****.**', ['*****@*****.**']) mx = MxSmtpRelay() self.mox.StubOutWithMock(mx, 'new_static_relay') self.mox.StubOutWithMock(DNSResolver, 'query') DNSResolver.query('example.com', 'MX').AndRaise(DNSError(ARES_ENODATA)) DNSResolver.query('example.com', 'A').AndRaise(DNSError(ARES_ENODATA)) self.mox.ReplayAll() with self.assertRaises(PermanentRelayError): mx.attempt(env, 0)
def test_attempt_no_records(self): env = Envelope('*****@*****.**', ['*****@*****.**']) mx = MxSmtpRelay() static = self.mox.CreateMock(StaticSmtpRelay) self.mox.StubOutWithMock(mx, 'new_static_relay') self.mox.StubOutWithMock(dns.resolver, 'query') dns.resolver.query('example.com', 'MX').AndRaise(dns.resolver.NXDOMAIN) dns.resolver.query('example.com', 'A').AndRaise(dns.resolver.NXDOMAIN) self.mox.ReplayAll() with self.assertRaises(PermanentRelayError): mx.attempt(env, 0)
def test_attempt_no_records(self): env = Envelope('*****@*****.**', ['*****@*****.**']) mx = MxSmtpRelay() static = self.mox.CreateMock(StaticSmtpRelay) self.mox.StubOutWithMock(mx, 'new_static_relay') self.mox.StubOutWithMock(dns_resolver, 'query') dns_resolver.query('example.com', 'MX').AndRaise(dns.resolver.NXDOMAIN) dns_resolver.query('example.com', 'A').AndRaise(dns.resolver.NXDOMAIN) self.mox.ReplayAll() with assert_raises(PermanentRelayError): mx.attempt(env, 0)
def test_attempt_no_records(self): env = Envelope("*****@*****.**", ["*****@*****.**"]) mx = MxSmtpRelay() static = self.mox.CreateMock(StaticSmtpRelay) self.mox.StubOutWithMock(mx, "new_static_relay") self.mox.StubOutWithMock(dns_resolver, "query") dns_resolver.query("example.com", "MX").AndRaise(dns.resolver.NXDOMAIN) dns_resolver.query("example.com", "A").AndRaise(dns.resolver.NXDOMAIN) self.mox.ReplayAll() with assert_raises(PermanentRelayError): mx.attempt(env, 0)
def test_attempt_no_mx(self): env = Envelope('*****@*****.**', ['*****@*****.**']) a_ret = FakeAAnswer(False, [('1.2.3.4', )]) mx = MxSmtpRelay() static = self.mox.CreateMock(StaticSmtpRelay) self.mox.StubOutWithMock(mx, 'new_static_relay') self.mox.StubOutWithMock(DNSResolver, 'query') DNSResolver.query('example.com', 'MX').AndRaise(DNSError(ARES_ENOTFOUND)) DNSResolver.query('example.com', 'A').AndReturn(FakeAsyncResult(a_ret)) mx.new_static_relay('example.com', 25).AndReturn(static) static.attempt(env, 0) self.mox.ReplayAll() mx.attempt(env, 0)
def test_attempt_no_mx(self): env = Envelope("*****@*****.**", ["*****@*****.**"]) a_ret = FakeAAnswer(False, [("1.2.3.4",)]) mx = MxSmtpRelay() static = self.mox.CreateMock(StaticSmtpRelay) self.mox.StubOutWithMock(mx, "new_static_relay") self.mox.StubOutWithMock(dns_resolver, "query") dns_resolver.query("example.com", "MX").AndRaise(dns.resolver.NXDOMAIN) dns_resolver.query("example.com", "A").AndReturn(a_ret) mx.new_static_relay("1.2.3.4", 25).AndReturn(static) static.attempt(env, 0) self.mox.ReplayAll() mx.attempt(env, 0)
def test_attempt_no_mx(self): env = Envelope('*****@*****.**', ['*****@*****.**']) a_ret = FakeAAnswer(False, [('1.2.3.4', )]) mx = MxSmtpRelay() static = self.mox.CreateMock(StaticSmtpRelay) self.mox.StubOutWithMock(mx, 'new_static_relay') self.mox.StubOutWithMock(dns.resolver, 'query') dns.resolver.query('example.com', 'MX').AndRaise(dns.resolver.NXDOMAIN) dns.resolver.query('example.com', 'A').AndReturn(a_ret) mx.new_static_relay('1.2.3.4', 25).AndReturn(static) static.attempt(env, 0) self.mox.ReplayAll() mx.attempt(env, 0)
def test_attempt_force_mx(self): env = Envelope('*****@*****.**', ['*****@*****.**']) mx = MxSmtpRelay() static = self.mox.CreateMock(StaticSmtpRelay) self.mox.StubOutWithMock(mx, 'new_static_relay') mx.new_static_relay('mail.example.com', 25).AndReturn(static) static.attempt(env, 0) static.attempt(env, 1) self.mox.ReplayAll() mx.force_mx('example.com', 'mail.example.com') mx.attempt(env, 0) mx.attempt(env, 1)
def _start_outbound_relay(args): from slimta.relay.smtp.mx import MxSmtpRelay tls = _get_tls_args(args) relay = MxSmtpRelay(tls=tls, connect_timeout=20.0, command_timeout=10.0, data_timeout=20.0, idle_timeout=10.0) return relay
def _start_outbound_relay(args): from slimta.relay.smtp.mx import MxSmtpRelay context = _get_ssl_context_client(args) relay = MxSmtpRelay(connect_timeout=20.0, command_timeout=10.0, data_timeout=20.0, idle_timeout=10.0, context=context) return relay
def test_attempt_force_mx(self): env = Envelope("*****@*****.**", ["*****@*****.**"]) mx = MxSmtpRelay() static = self.mox.CreateMock(StaticSmtpRelay) self.mox.StubOutWithMock(mx, "new_static_relay") mx.new_static_relay("mail.example.com", 25).AndReturn(static) static.attempt(env, 0) static.attempt(env, 1) self.mox.ReplayAll() mx.force_mx("example.com", "mail.example.com") mx.attempt(env, 0) mx.attempt(env, 1)
def test_attempt(self): env = Envelope('*****@*****.**', ['*****@*****.**']) mx_ret = FakeMxAnswer(False, [(5, 'mx1.example.com'), (10, 'mx2.example.com')]) mx = MxSmtpRelay() static = self.mox.CreateMock(StaticSmtpRelay) self.mox.StubOutWithMock(mx, 'new_static_relay') self.mox.StubOutWithMock(DNSResolver, 'query') DNSResolver.query('example.com', 'MX').AndReturn(FakeAsyncResult(mx_ret)) mx.new_static_relay('mx1.example.com', 25).AndReturn(static) static.attempt(env, 0) mx.new_static_relay('mx2.example.com', 25).AndReturn(static) static.attempt(env, 1) self.mox.ReplayAll() mx.attempt(env, 0) mx.attempt(env, 1)
def test_attempt(self): env = Envelope("*****@*****.**", ["*****@*****.**"]) mx_ret = FakeMxAnswer(False, [(5, "mx1.example.com"), (10, "mx2.example.com")]) mx = MxSmtpRelay() static = self.mox.CreateMock(StaticSmtpRelay) self.mox.StubOutWithMock(mx, "new_static_relay") self.mox.StubOutWithMock(dns_resolver, "query") dns_resolver.query("example.com", "MX").AndReturn(mx_ret) mx.new_static_relay("mx1.example.com", 25).AndReturn(static) static.attempt(env, 0) mx.new_static_relay("mx2.example.com", 25).AndReturn(static) static.attempt(env, 1) self.mox.ReplayAll() mx.attempt(env, 0) mx.attempt(env, 1)
def test_attempt(self): env = Envelope('*****@*****.**', ['*****@*****.**']) mx_ret = FakeMxAnswer(False, [(5, 'mx1.example.com'), (10, 'mx2.example.com')]) mx = MxSmtpRelay() static = self.mox.CreateMock(StaticSmtpRelay) self.mox.StubOutWithMock(mx, 'new_static_relay') self.mox.StubOutWithMock(dns.resolver, 'query') dns.resolver.query('example.com', 'MX').AndReturn(mx_ret) mx.new_static_relay('mx1.example.com', 25).AndReturn(static) static.attempt(env, 0) mx.new_static_relay('mx2.example.com', 25).AndReturn(static) static.attempt(env, 1) self.mox.ReplayAll() mx.attempt(env, 0) mx.attempt(env, 1)
def test_attempt_no_mx(self): env = Envelope('*****@*****.**', ['*****@*****.**']) a_ret = FakeAAnswer(False, [('1.2.3.4', )]) mx = MxSmtpRelay() static = self.mox.CreateMock(StaticSmtpRelay) self.mox.StubOutWithMock(mx, 'new_static_relay') self.mox.StubOutWithMock(dns_resolver, 'query') dns_resolver.query('example.com', 'MX').AndRaise(dns.resolver.NXDOMAIN) dns_resolver.query('example.com', 'A').AndReturn(a_ret) mx.new_static_relay('1.2.3.4', 25).AndReturn(static) static.attempt(env, 0) self.mox.ReplayAll() mx.attempt(env, 0)
def test_attempt_no_mx(self): env = Envelope('*****@*****.**', ['*****@*****.**']) a_ret = FakeAAnswer(False, [('1.2.3.4', )]) mx = MxSmtpRelay() static = self.mox.CreateMock(StaticSmtpRelay) self.mox.StubOutWithMock(mx, 'new_static_relay') self.mox.StubOutWithMock(DNSResolver, 'query') DNSResolver.query('example.com', 'MX').AndRaise(DNSError(ARES_ENOTFOUND)) DNSResolver.query('example.com', 'A').AndReturn(FakeAsyncResult(a_ret)) mx.new_static_relay('1.2.3.4', 25).AndReturn(static) static.attempt(env, 0) self.mox.ReplayAll() mx.attempt(env, 0)
def __init__(self): # Relay: ssl = SSLContext(PROTOCOL_SSLv23) ssl.load_cert_chain(config['SSL']['certificate_path'], config['SSL']['key_path']) self.relay = MxSmtpRelay(context=ssl, connect_timeout=20, command_timeout=10, data_timeout=20, idle_timeout=30) # Queue: #env_db = shelve.open('msa_envelope') #meta_db = shelve.open('msa_meta') #storage = DictStorage(env_db, meta_db) # !!! replace with DiskStorage! (installed via pip install python-slimta-diskstorage) storage = DiskStorage(config['MSA']['ds_env'], config['MSA']['ds_meta']) def retry_backoff(envelope, attempts): if attempts < 10: return 60 * attempts * attempts # try again at increasingly long intervals; give up after 10 tries (100 minutes) return None self.queue = Queue(storage, self.relay, backoff=retry_backoff) self.queue.start() # Headers: self.queue.add_policy(AddDateHeader()) self.queue.add_policy(AddMessageIdHeader()) self.queue.add_policy(AddReceivedHeader()) self.queue.add_policy(RecipientDomainSplit()) # !!! Add Forward policy here, to manage general forwarding (but not list distribution - do that in mda!) # Edge: self.edge = SmtpEdge( ('localhost', 587), self.queue, auth=False ) #, auth=True, validator_class=MSA_Validators) # ?!!! context=ssl, tls_immediately=True, self.edge.start()
def _start_relay(self, name, options=None): if name in self.relays: return self.relays[name] if not options: options = getattr(self.cfg.relay, name) new_relay = None if options.type == 'mx': from slimta.relay.smtp.mx import MxSmtpRelay from .helpers import fill_hostname_template kwargs = {} kwargs['connect_timeout'] = options.get('connect_timeout', 30) kwargs['command_timeout'] = options.get('command_timeout', 30) kwargs['data_timeout'] = options.get('data_timeout', 60) kwargs['idle_timeout'] = options.get('idle_timeout', 10) kwargs['pool_size'] = options.get('concurrent_connections', 5) kwargs['ehlo_as'] = fill_hostname_template(options.ehlo_as) kwargs['context'] = self._get_client_ssl_context(options.tls) if options.ipv4_only: kwargs['socket_creator'] = build_ipv4_socket_creator([25]) new_relay = MxSmtpRelay(**kwargs) if 'force_mx' in options: for domain, dest in options.force_mx: new_relay.force_mx(domain, dest) elif options.type == 'static': from slimta.relay.smtp.static import StaticSmtpRelay from .helpers import fill_hostname_template, get_relay_credentials kwargs = {} kwargs['host'] = options.host kwargs['port'] = options.get('port', 25) kwargs['connect_timeout'] = options.get('connect_timeout', 30) kwargs['command_timeout'] = options.get('command_timeout', 30) kwargs['data_timeout'] = options.get('data_timeout', 60) kwargs['idle_timeout'] = options.get('idle_timeout', 10) kwargs['pool_size'] = options.get('concurrent_connections', 5) kwargs['ehlo_as'] = fill_hostname_template(options.ehlo_as) kwargs['context'] = self._get_client_ssl_context(options.tls) if 'credentials' in options: credentials = get_relay_credentials(options.credentials) kwargs['credentials'] = credentials if options.ipv4_only: kwargs['socket_creator'] = \ build_ipv4_socket_creator([kwargs['port']]) new_relay = StaticSmtpRelay(**kwargs) elif options.type == 'lmtp': from slimta.relay.smtp.static import StaticLmtpRelay from .helpers import fill_hostname_template, get_relay_credentials kwargs = {} kwargs['host'] = options.get('host', 'localhost') kwargs['port'] = options.get('port', 24) kwargs['connect_timeout'] = options.get('connect_timeout', 30) kwargs['command_timeout'] = options.get('command_timeout', 30) kwargs['data_timeout'] = options.get('data_timeout', 60) kwargs['idle_timeout'] = options.get('idle_timeout', 10) kwargs['pool_size'] = options.get('concurrent_connections', 5) kwargs['ehlo_as'] = fill_hostname_template(options.ehlo_as) kwargs['context'] = self._get_client_ssl_context(options.tls) if 'credentials' in options: credentials = get_relay_credentials(options.credentials) kwargs['credentials'] = credentials if options.ipv4_only: kwargs['socket_creator'] = \ build_ipv4_socket_creator([kwargs['port']]) new_relay = StaticLmtpRelay(**kwargs) elif options.type == 'http': from slimta.relay.http import HttpRelay from .helpers import fill_hostname_template kwargs = {} kwargs['ehlo_as'] = fill_hostname_template(options.ehlo_as) kwargs['timeout'] = options.get('timeout', 60) kwargs['idle_timeout'] = options.get('idle_timeout', 10) kwargs['context'] = self._get_client_ssl_context(options.tls) new_relay = HttpRelay(options.url, **kwargs) elif options.type == 'blackhole': from slimta.relay.blackhole import BlackholeRelay new_relay = BlackholeRelay() elif options.type == 'pipe': from slimta.relay.pipe import PipeRelay new_relay = PipeRelay(options.args) elif options.type == 'maildrop': from slimta.relay.pipe import MaildropRelay path = options.path new_relay = MaildropRelay(path) elif options.type == 'dovecot': from slimta.relay.pipe import DovecotLdaRelay path = options.path new_relay = DovecotLdaRelay(path) elif options.type == 'custom': new_relay = custom_factory(options) else: msg = 'relay type does not exist: '+options.type raise ConfigValidationError(msg) self.relays[name] = new_relay return new_relay
def test_get_rcpt_domain(self): env = Envelope("*****@*****.**", ["*****@*****.**"]) mx = MxSmtpRelay() assert_equal("example.com", mx._get_rcpt_domain(env))
def test_get_rcpt_domain(self): env = Envelope('*****@*****.**', ['*****@*****.**']) mx = MxSmtpRelay() self.assertEqual('example.com', mx._get_rcpt_domain(env))
def test_get_rcpt_domain_error(self): env = Envelope('*****@*****.**', ['badrcpt']) mx = MxSmtpRelay() self.assertRaises(NoDomainError, mx._get_rcpt_domain, env)