def _handle(self, socket, address): log.accept(self.server.socket, socket, address) try: self.handle(socket, address) except Exception: logging.log_exception(__name__) raise
def load(self): for id in self.ops.get_ids(): try: meta = self.ops.read_meta(id) yield (meta['timestamp'], id) except OSError: logging.log_exception(__name__, queue_id=id)
def get(self, ip, timeout=None, strict=False): """Checks this DNSBL for the given IP address. This method does not check the answer, only that the response was not ``NXDOMAIN``. :param ip: The IP address string to check. :param timeout: A timeout in seconds before ``False`` is returned. :param strict: If ``True``, DNS exceptions that are not ``NXDOMAIN`` (including timeouts) will also result in a ``True`` return value. :returns: ``True`` if the DNSBL had an entry for the given IP address, ``False`` otherwise. """ with gevent.Timeout(timeout, None): query = self._build_query(ip) try: answers = dns_resolver.query(query, 'A') except NXDOMAIN: return False except DNSException: logging.log_exception(__name__, query=query) return not strict else: return True return strict
def get(self, ip, timeout=None, strict=False): """Checks this DNSBL for the given IP address. This method does not check the answer, only that the response was not ``NXDOMAIN``. :param ip: The IP address string to check. :param timeout: A timeout in seconds before ``False`` is returned. :param strict: If ``True``, DNS exceptions that are not ``NXDOMAIN`` (including timeouts) will also result in a ``True`` return value. :returns: ``True`` if the DNSBL had an entry for the given IP address, ``False`` otherwise. """ with gevent.Timeout(timeout, None): query = self._build_query(ip) try: DNSResolver.query(query, 'A').get() except DNSError as exc: if exc.errno == ARES_ENOTFOUND: return False logging.log_exception(__name__, query=query) return not strict else: return True return strict
def _wait_channel(cls): poll = select.poll() fds_map = OrderedDict() try: while True: fds_map = cls._register_fds(poll, fds_map) if not fds_map: break timeout = cls._channel.timeout() if not timeout: cls._channel.process_fd(pycares.ARES_SOCKET_BAD, pycares.ARES_SOCKET_BAD) continue for fd, event in poll.poll(timeout): if event & (select.POLLIN | select.POLLPRI): cls._channel.process_fd(fd, pycares.ARES_SOCKET_BAD) if event & select.POLLOUT: cls._channel.process_fd(pycares.ARES_SOCKET_BAD, fd) except Exception: logging.log_exception(__name__) cls._channel.cancel() cls._channel = None raise finally: cls._thread = None
def _run(self): try: hostname, _, _ = socket.gethostbyaddr(self.ip) except (socket.herror, socket.gaierror, gevent.GreenletExit): pass except Exception: logging.log_exception(__name__, query=self.ip) else: return hostname
def write(self, envelope, timestamp): storage_id = self.obj_store.write_message(envelope, timestamp) if self.msg_queue: try: self.msg_queue.queue_message(storage_id, timestamp) except Exception: logging.log_exception(__name__) log.write(storage_id, envelope) return storage_id
def attempt_delivery(self, envelope, attempts): try: self.relay.attempt(envelope, attempts) except TransientRelayError as exc: self._handle_transient_failure(envelope, attempts, exc.reply) except PermanentRelayError as exc: self.enqueue_bounce(envelope, exc.reply) except Exception as exc: log_exception(__name__) reply = Reply('450', '4.0.0 Unhandled delivery error: ' + str(exc)) self._handle_transient_failure(envelope, attempts, reply) raise
def attempt_delivery(self, envelope, attempts): try: self.relay.attempt(envelope, attempts) except TransientRelayError as exc: self._handle_transient_failure(envelope, attempts, exc.reply) except PermanentRelayError as exc: self.enqueue_bounce(envelope, exc.reply) except Exception as exc: log_exception(__name__) reply = Reply('450', '4.0.0 Unhandled delivery error: '+str(exc)) self._handle_transient_failure(envelope, attempts, reply) raise
def _attempt(self, id, envelope, attempts): try: self.relay._attempt(envelope, attempts) except TransientRelayError as e: self._pool_spawn('store', self._retry_later, id, envelope, e.reply) except PermanentRelayError as e: self._perm_fail(id, envelope, e.reply) except Exception as e: log_exception(__name__) reply = Reply('450', '4.0.0 Unhandled delivery error: '+str(e)) self._pool_spawn('store', self._retry_later, id, envelope, reply) raise else: self._pool_spawn('store', self.store.remove, id)
def _ptr_lookup(self): try: ptraddr = reversename.from_address(self.address[0]) try: answers = resolver.query(ptraddr, 'PTR') except resolver.NXDOMAIN: answers = [] try: self.reverse_address = str(answers[0]) except IndexError: pass except Exception: logging.log_exception(__name__, query=self.address[0]) raise
def _ptr_lookup(self, environ): ip = environ.get('REMOTE_ADDR', '0.0.0.0') try: ptraddr = reversename.from_address(ip) try: answers = dns_resolver.query(ptraddr, 'PTR') except NXDOMAIN: answers = [] try: environ['slimta.reverse_address'] = str(answers[0]) except IndexError: pass except Exception: log_exception(__name__, query=ip)
def _run(self): # StreamServer can return an ipv4 address with an ipv6 prefix "::ffff:" # which is not handled correctly by gethostbyaddr and throws an error ip = str(self.ip) if ip.find("::ffff:") == 0: ip = ip.replace("::ffff:", "") try: hostname, _, _ = socket.gethostbyaddr(ip) except (socket.herror, socket.gaierror, gevent.GreenletExit): pass except Exception: logging.log_exception(__name__, query=ip) else: return hostname
def _attempt(self, id, envelope, attempts): try: self.relay._attempt(envelope, attempts) except TransientRelayError as e: self._pool_spawn('store', self._retry_later, id, envelope, e.reply) except PermanentRelayError as e: self._perm_fail(id, envelope, e.reply) except Exception as e: log_exception(__name__) reply = Reply('450', '4.0.0 Unhandled delivery error: ' + str(e)) self._pool_spawn('store', self._retry_later, id, envelope, reply) raise else: self._pool_spawn('store', self.store.remove, id)
def _run(self): try: ptraddr = reversename.from_address(self.ip) try: answers = dns_resolver.query(ptraddr, 'PTR') except NXDOMAIN: answers = [] try: return str(answers[0]) except IndexError: pass except (DnsSyntaxError, gevent.GreenletExit): pass except Exception: logging.log_exception(__name__, query=self.ip)
def _attempt(self, id, envelope, attempts): try: results = self.relay._attempt(envelope, attempts) except TransientRelayError as e: self._pool_spawn('store', self._retry_later, id, envelope, e.reply) except PermanentRelayError as e: self._perm_fail(id, envelope, e.reply) except Exception as e: log_exception(__name__) reply = Reply('450', '4.0.0 Unhandled delivery error: '+str(e)) self._pool_spawn('store', self._retry_later, id, envelope, reply) raise else: if isinstance(results, collections.Sequence): self._handle_partial_relay(id, envelope, attempts, results) else: self._remove(id)
def _attempt(self, id, envelope, attempts): try: results = self.relay._attempt(envelope, attempts) except TransientRelayError as e: self._pool_spawn('store', self._retry_later, id, envelope, e.reply) except PermanentRelayError as e: self._perm_fail(id, envelope, e.reply) except Exception as e: log_exception(__name__) reply = Reply('450', '4.0.0 Unhandled delivery error: ' + str(e)) self._pool_spawn('store', self._retry_later, id, envelope, reply) raise else: if isinstance(results, collections.Sequence): self._handle_partial_relay(id, envelope, attempts, results) else: self._remove(id)
def test_log_exception(self, l): log_exception('test', extra='not logged') try: raise ValueError('testing stuff') except Exception: log_exception('test', extra='more stuff') self.assertEqual(1, len(l.records)) rec = l.records[0] self.assertEqual('test', rec.name) self.assertEqual('ERROR', rec.levelname) type, id, op, data = parseline(rec.msg) self.assertEqual('exception', type) self.assertEqual('ValueError', id) self.assertEqual('unhandled', op) self.assertEqual('more stuff', data['extra']) self.assertEqual(('testing stuff', ), data['args']) self.assertEqual('testing stuff', data['message']) self.assertTrue(data['traceback'])
def __call__(self, environ, start_response): self._trigger_ptr_lookup(environ) try: self._validate_request(environ) env = self._get_envelope(environ) self._add_envelope_extras(environ, env) self._enqueue_envelope(env) except WsgiResponse as res: start_response(res.status, res.headers) return res.data except Exception as exc: log_exception(__name__) msg = "{0!s}\n".format(exc) headers = [("Content-Length", len(msg)), ("Content-Type", "text/plain")] start_response("500 Internal Server Error", headers) return [msg] finally: environ["slimta.ptr_lookup_thread"].kill(block=False)
def __call__(self, environ, start_response): self._trigger_ptr_lookup(environ) try: self._validate_request(environ) env = self._get_envelope(environ) self._add_envelope_extras(environ, env) self._enqueue_envelope(env) except WsgiResponse as res: start_response(res.status, res.headers) return res.data except Exception as exc: log_exception(__name__) msg = '{0!s}\n'.format(exc) headers = [('Content-Length', len(msg)), ('Content-Type', 'text/plain')] start_response('500 Internal Server Error', headers) return [msg] finally: environ['slimta.ptr_lookup_thread'].kill(block=False)
def __call__(self, environ, start_response): self._trigger_ptr_lookup(environ) try: self._validate_request(environ) env = self._get_envelope(environ) self._add_envelope_extras(environ, env) self._enqueue_envelope(env) except WsgiResponse as res: start_response(res.status, res.headers) return res.data except Exception as exc: log_exception(__name__) msg = '{0!s}\n'.format(exc) content_length = str(len(msg)) headers = [('Content-Length', content_length), ('Content-Type', 'text/plain')] start_response('500 Internal Server Error', headers) return [msg] finally: environ['slimta.ptr_lookup_thread'].kill(block=False)
def __call__(self, environ, start_response): ptr_lookup = PtrLookup(environ.get('REMOTE_ADDR', '0.0.0.0')) ptr_lookup.start() try: self._validate_request(environ) env = self._get_envelope(environ) self._add_envelope_extras(environ, env, ptr_lookup) self._enqueue_envelope(env) except WsgiResponse as res: start_response(res.status, res.headers) return res.data except Exception as exc: logging.log_exception(__name__) msg = '{0!s}\n'.format(exc) content_length = str(len(msg)) headers = [('Content-Length', content_length), ('Content-Type', 'text/plain')] start_response('500 Internal Server Error', headers) return [msg] finally: ptr_lookup.kill(block=False)
def handoff(self, envelope): """This method may be called manually or by whatever mechanism a sub-class uses to receive new |Envelope| messages from a client. Because a |QueuePolicy| may generate new |Envelope| objects, this method returns a list of tuples, ``(envelope, result)`` where ``result`` is either an ID string or a :class:`~slimta.queue.QueueError`. The edge service can then use this information to report back success or failure to the client. :param envelope: |Envelope| containing the received message. :returns: List of tuples containing each |Envelope| and its corresponding ID string or :class:`~slimta.queue.QueueError`. """ envelope.receiver = self.hostname envelope.timestamp = time.time() try: return self.queue.enqueue(envelope) except Exception: logging.log_exception(__name__) raise
def _wait_channel(cls): try: while True: read_fds, write_fds = cls._channel.getsock() if not read_fds and not write_fds: break timeout = cls._channel.timeout() if not timeout: cls._channel.process_fd(pycares.ARES_SOCKET_BAD, pycares.ARES_SOCKET_BAD) continue rlist, wlist, xlist = select.select( read_fds, write_fds, [], timeout) for fd in rlist: cls._channel.process_fd(fd, pycares.ARES_SOCKET_BAD) for fd in wlist: cls._channel.process_fd(pycares.ARES_SOCKET_BAD, fd) except Exception: logging.log_exception(__name__) cls._channel.cancel() cls._channel = None raise finally: cls._thread = None
def attempt(self, envelope, attempts): domain = self._get_rcpt_domain(envelope) if domain in self._force_mx: dest, port = self._force_mx[domain] else: record = self._mx_records.setdefault(domain, MxRecord(domain)) try: dest = self.choose_mx(record.get(), attempts) except ValueError as exc: msg = str(exc) reply = Reply('550', '5.1.2 '+msg) raise PermanentRelayError(msg, reply) except DNSError: log_exception(__name__) msg = 'DNS lookup failed' reply = Reply('451', '4.4.3 '+msg) raise TransientRelayError(msg, reply) port = 25 try: relayer = self._relayers[(dest, port)] except KeyError: relayer = self.new_static_relay(dest, port) self._relayers[(dest, port)] = relayer return relayer.attempt(envelope, attempts)
def attempt(self, envelope, attempts): domain = self._get_rcpt_domain(envelope) if domain in self._force_mx: dest, port = self._force_mx[domain] else: record = self._mx_records.setdefault(domain, MxRecord(domain)) try: dest = self.choose_mx(record.get(), attempts) except ValueError as exc: msg = str(exc) reply = Reply('550', '5.1.2 ' + msg) raise PermanentRelayError(msg, reply) except DNSException: log_exception(__name__) msg = 'DNS lookup failed' reply = Reply('451', '4.4.3 ' + msg) raise TransientRelayError(msg, reply) port = 25 try: relayer = self._relayers[(dest, port)] except KeyError: relayer = self.new_static_relay(dest, port) self._relayers[(dest, port)] = relayer return relayer.attempt(envelope, attempts)
def _wait_channel(cls): try: while True: read_fds, write_fds = cls._channel.getsock() if not read_fds and not write_fds: break timeout = cls._channel.timeout() if not timeout: cls._channel.process_fd(pycares.ARES_SOCKET_BAD, pycares.ARES_SOCKET_BAD) continue rlist, wlist, xlist = select.select(read_fds, write_fds, [], timeout) for fd in rlist: cls._channel.process_fd(fd, pycares.ARES_SOCKET_BAD) for fd in wlist: cls._channel.process_fd(pycares.ARES_SOCKET_BAD, fd) except Exception: logging.log_exception(__name__) cls._channel.cancel() cls._channel = None raise finally: cls._thread = None