def _start_outbound_edge(args, queue): from slimta.edge.smtp import SmtpEdge, SmtpValidators from slimta.util.dnsbl import check_dnsbl from site_data import credentials, outbound_banner class EdgeValidators(SmtpValidators): @check_dnsbl('zen.spamhaus.org') def handle_banner(self, reply, address): reply.message = outbound_banner def handle_auth(self, reply, creds): try: password = credentials[creds.authcid] assert creds.check_secret(password) except (KeyError, AssertionError): reply.code = '535' reply.message = '5.7.8 Authentication credentials invalid' def handle_mail(self, reply, sender, params): if not self.session.auth: reply.code = '550' reply.message = '5.7.1 Sender <{0}> Not allowed'.format(sender) context = _get_ssl_context_server(args) edge = SmtpEdge(('', args.outbound_port), queue, context=context, validator_class=EdgeValidators, auth=[b'PLAIN', b'LOGIN'], command_timeout=20.0, data_timeout=30.0) edge.start() return edge
def _start_inbound_edge(args, queue): from slimta.edge.smtp import SmtpEdge, SmtpValidators from slimta.util.dnsbl import check_dnsbl from site_data import inbound_banner, deliverable_addresses class EdgeValidators(SmtpValidators): @check_dnsbl('zen.spamhaus.org', match_code='520') def handle_banner(self, reply, address): reply.message = inbound_banner def handle_rcpt(self, reply, recipient): if recipient not in deliverable_addresses: reply.code = '550' reply.message = '5.7.1 Recipient <{0}> Not allowed'.format(recipient) return tls = _get_tls_args(args) edge = SmtpEdge(('', args.inbound_port), queue, max_size=10240, validator_class=EdgeValidators, tls=tls, command_timeout=20.0, data_timeout=30.0) edge.start() return edge
def _start_inbound_edge(args, queue): from slimta.edge.smtp import SmtpEdge, SmtpValidators from slimta.util.dnsbl import check_dnsbl from site_data import inbound_banner, deliverable_addresses class EdgeValidators(SmtpValidators): @check_dnsbl('zen.spamhaus.org', match_code='520') def handle_banner(self, reply, address): reply.message = inbound_banner def handle_rcpt(self, reply, recipient, params): if recipient not in deliverable_addresses: reply.code = '550' reply.message = \ '5.7.1 Recipient <{0}> Not allowed'.format(recipient) tls = _get_tls_args(args) edge = SmtpEdge(('', args.inbound_port), queue, max_size=10240, validator_class=EdgeValidators, tls=tls, command_timeout=20.0, data_timeout=30.0) edge.start() return edge
def _start_outbound_edge(args, queue): from slimta.edge.smtp import SmtpEdge, SmtpValidators from slimta.util.dnsbl import check_dnsbl from site_data import credentials, outbound_banner class EdgeValidators(SmtpValidators): @check_dnsbl('zen.spamhaus.org') def handle_banner(self, reply, address): reply.message = outbound_banner def handle_auth(self, reply, creds): try: password = credentials[creds.authcid] assert creds.check_secret(password) except (KeyError, AssertionError): reply.code = '535' reply.message = '5.7.8 Authentication credentials invalid' def handle_mail(self, reply, sender, params): if not self.session.auth: reply.code = '550' reply.message = '5.7.1 Sender <{0}> Not allowed'.format(sender) tls = _get_tls_args(args) edge = SmtpEdge(('', args.outbound_port), queue, tls=tls, validator_class=EdgeValidators, auth=[b'PLAIN', b'LOGIN'], command_timeout=20.0, data_timeout=30.0) edge.start() return edge
def _start_edge(self, name, options=None): if name in self.edges: return self.edges[name] if not options: options = getattr(self.cfg.edge, name) new_edge = None if options.type == 'smtp': from slimta.edge.smtp import SmtpEdge from .helpers import build_smtpedge_validators, build_smtpedge_auth from .helpers import fill_hostname_template ip = options.listener.get('interface', '127.0.0.1') port = int(options.listener.get('port', 25)) queue_name = options.queue queue = self._start_queue(queue_name) kwargs = {} if options.get('tls'): kwargs['tls'] = dict(options.tls) kwargs['tls_immediately'] = options.get('tls_immediately', False) kwargs['validator_class'] = build_smtpedge_validators(options) kwargs['auth_class'] = build_smtpedge_auth(options) kwargs['command_timeout'] = 20.0 kwargs['data_timeout'] = 30.0 kwargs['max_size'] = options.get('max_size', 10485760) kwargs['hostname'] = fill_hostname_template(options.get('hostname')) new_edge = SmtpEdge((ip, port), queue, **kwargs) new_edge.start() else: raise ConfigError('edge type does not exist: '+options.type) self.edges[name] = new_edge return new_edge
def test_smtp_edge(self): queue = self.mox.CreateMockAnything() queue.enqueue(IsA(Envelope)).AndReturn([(Envelope(), 'testid')]) self.mox.ReplayAll() server = SmtpEdge(('127.0.0.1', 0), queue) server.start() gevent.sleep(0) client_sock = create_connection(server.server.address) client = Client(client_sock) client.get_banner() client.ehlo('there') client.mailfrom('*****@*****.**') client.rcptto('*****@*****.**') client.data() client.send_empty_data() client.quit() client_sock.close()
class MDA(MTA): def __init__(self, msa, mail_list_url, mda_domain, list_subject_prefix=None): self.msa = msa # Relay: relay = DovecotLdaRelay(config['LDA']['dovecot_path'], timeout=10.0) # Queue: #env_db = shelve.open('envelope') #meta_db = shelve.open('meta') #storage = DictStorage(env_db, meta_db) # !!! replace with DiskStorage! (installed via pip install python-slimta-diskstorage) storage = DiskStorage(config['MDA']['ds_env'], config['MDA']['ds_meta']) self.queue = Queue( storage, relay) # no backoff - just fail local delivery immediately self.queue.start() # Headers: self.queue.add_policy(AddDateHeader()) self.queue.add_policy(AddMessageIdHeader()) self.queue.add_policy(AddReceivedHeader()) # Mailing List: self.queue.add_policy( MailingListDistribution(self.msa, mail_list_url, mda_domain, list_subject_prefix)) # SpamAssassin: #self.queue.add_policy(SpamAssassin()) # Edge: #tls_args = {'keyfile': '/home/jmcaine/dev/temp/slimta/tls/key.pem', 'certfile': '/home/jmcaine/dev/temp/slimta/tls/certificate.pem'} -- gone, see https://docs.slimta.org/en/latest/blog/2016-11-14.html ssl = SSLContext(PROTOCOL_SSLv23) ssl.load_cert_chain(config['SSL']['certificate_path'], config['SSL']['key_path']) self.edge = SmtpEdge(('0.0.0.0', 25), self.queue, validator_class=MDA_Validators, hostname=mda_domain, context=ssl) self.edge.start()
def _start_edge(self, name, options=None): if name in self.edges: return self.edges[name] if not options: options = getattr(self.cfg.edge, name) new_edge = None queue_name = options.queue queue = self._start_queue(queue_name) ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) if options.type == 'smtp': from slimta.edge.smtp import SmtpEdge from .helpers import build_smtpedge_validators from .helpers import fill_hostname_template hostname = fill_hostname_template(options.get('hostname')) listener_defaults = {'interface': '127.0.0.1', 'port': 25} listener = self._get_listener(options.listener, listener_defaults) kwargs = {} kwargs['context'] = self._get_ssl_context(ctx, options.get('tls')) kwargs['tls_immediately'] = options.get('tls_immediately', False) kwargs['validator_class'] = build_smtpedge_validators(options) kwargs['auth'] = ['PLAIN', 'LOGIN'] kwargs['command_timeout'] = 20.0 kwargs['data_timeout'] = 30.0 kwargs['max_size'] = int(options.get('max_size', 10485760)) kwargs['hostname'] = hostname new_edge = SmtpEdge(listener, queue, **kwargs) new_edge.start() elif options.type == 'http': from slimta.edge.wsgi import WsgiEdge from .helpers import build_wsgiedge_validators from .helpers import fill_hostname_template hostname = fill_hostname_template(options.get('hostname')) uri_pattern = options.get('uri') validator_class = build_wsgiedge_validators(options) new_edge = WsgiEdge(queue, hostname, validator_class, uri_pattern) listener_defaults = {'interface': '127.0.0.1', 'port': 8025} listener = self._get_listener(options.listener, listener_defaults) server = new_edge.build_server(listener, tls=options.get('tls')) server.start() elif options.type == 'custom': new_edge = self._load_from_custom(options, queue) else: msg = 'edge type does not exist: '+options.type raise ConfigValidationError(msg) self.edges[name] = new_edge return new_edge
def _start_outbound_edge(args, queue): from slimta.edge.smtp import SmtpEdge, SmtpValidators from slimta.util.dnsbl import check_dnsbl from slimta.smtp.auth import Auth, CredentialsInvalidError from site_data import credentials, outbound_banner class EdgeAuth(Auth): def verify_secret(self, username, password, identity=None): try: assert credentials[username] == password except (KeyError, AssertionError): raise CredentialsInvalidError() return username def get_secret(self, username, identity=None): try: return credentials[username], username except KeyError: raise CredentialsInvalidError() class EdgeValidators(SmtpValidators): @check_dnsbl('zen.spamhaus.org') def handle_banner(self, reply, address): reply.message = outbound_banner def handle_mail(self, reply, sender): print self.session.auth_result if not self.session.auth_result: reply.code = '550' reply.message = '5.7.1 Sender <{0}> Not allowed'.format(sender) tls = _get_tls_args(args) edge = SmtpEdge(('', args.outbound_port), queue, tls=tls, validator_class=EdgeValidators, auth_class=EdgeAuth, command_timeout=20.0, data_timeout=30.0) edge.start() ssl_edge = SmtpEdge(('', args.outbound_ssl_port), queue, validator_class=EdgeValidators, auth_class=EdgeAuth, tls=tls, tls_immediately=True, command_timeout=20.0, data_timeout=30.0) ssl_edge.start() return edge, ssl_edge
class MSA(MTA): 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_inbound_edge(args, queue): from slimta.edge.smtp import SmtpEdge, SmtpValidators from slimta.util.dnsbl import check_dnsbl from site_data import inbound_banner, deliverable_addresses class EdgeValidators(SmtpValidators): @check_dnsbl('zen.spamhaus.org', match_code='520') def handle_banner(self, reply, address): reply.message = inbound_banner def handle_rcpt(self, reply, recipient, params): if recipient not in deliverable_addresses: reply.code = '550' reply.message = \ '5.7.1 Recipient <{0}> Not allowed'.format(recipient) context = _get_ssl_context_server(args) edge = SmtpEdge(('', args.inbound_port), queue, max_size=10240, validator_class=EdgeValidators, context=context, command_timeout=20.0, data_timeout=30.0) edge.start() ssl_edge = SmtpEdge(('', args.inbound_ssl_port), queue, validator_class=EdgeValidators, auth=[b'PLAIN', b'LOGIN'], context=context, tls_immediately=True, command_timeout=20.0, data_timeout=30.0) ssl_edge.start() return edge, ssl_edge
def _start_edge(self, name, options=None): if not options: options = getattr(self.cfg.edge, name) new_edges = [] queue_name = options.queue queue = self._start_queue(queue_name) if options.type == 'smtp': from slimta.edge.smtp import SmtpEdge from .helpers import build_smtpedge_validators from .helpers import fill_hostname_template kwargs = {} kwargs['context'] = self._get_server_ssl_context(options.tls) kwargs['tls_immediately'] = options.tls_immediately kwargs['validator_class'] = build_smtpedge_validators(options) kwargs['auth'] = [b'PLAIN', b'LOGIN'] kwargs['command_timeout'] = 20.0 kwargs['data_timeout'] = 30.0 kwargs['max_size'] = int(options.get('max_size', 10485760)) kwargs['hostname'] = fill_hostname_template(options.hostname) for listener in Listeners(options, 25): new_edge = SmtpEdge(listener, queue, **kwargs) if options.proxyprotocol: ProxyProtocol.mixin(new_edge) new_edge.start() self.edges.append(new_edge) elif options.type == 'http': from slimta.edge.wsgi import WsgiEdge from .helpers import build_wsgiedge_validators from .helpers import fill_hostname_template kwargs = {} kwargs['hostname'] = fill_hostname_template(options.hostname) kwargs['validator_class'] = build_wsgiedge_validators(options) kwargs['uri_pattern'] = options.uri kwargs['context'] = self._get_server_ssl_context(options.tls) listener = self._get_listener(options, 8025) for listener in Listeners(options, 8025): new_edge = WsgiEdge(queue, listener=listener, **kwargs) if options.proxyprotocol: ProxyProtocol.mixin(new_edge) new_edge.start() self.edges.append(new_edge) elif options.type == 'custom': new_edge = custom_factory(options, queue) self.edges.append(new_edge) else: msg = 'edge type does not exist: '+options.type raise ConfigValidationError(msg)
from slimta.queue.dict import DictStorage from slimta.relay import RelayError from slimta.relay.smtp.static import StaticSmtpRelay def backoff(envelope, attempts): if attempts <= 5: return 5.0 * attempts relay = StaticSmtpRelay('mail.example.com', 25, pool_size=2) env_db = shelve.open('envelope.db') meta_db = shelve.open('meta.db') queue_storage = DictStorage(env_db, meta_db) queue = Queue(queue_storage, relay, backoff) edge = SmtpEdge(('127.0.0.1', 1337), queue) edge.start() queue.start() try: edge.get() except KeyboardInterrupt: print finally: for key in env_db.keys(): print 'env', key for key in meta_db.keys(): print 'meta', key env_db.close() meta_db.close() # vim:et:fdm=marker:sts=4:sw=4:ts=4