"""
Signal handlers and custom exceptions
-------------------------------------
In order to shut down gracefully, we want to provide a signal handler when a
service (handler) loop starts. Also, CHAPPS raises a few different custom
exceptions, which are defined here.
"""
import signal
import logging
logger = logging.getLogger(__name__)
[docs]class SignalHandlerFactory: # pragma: no cover
"""A class for containing classmethods to create signal handlers"""
# could be organized differently; instantiating the class would return
# an instance with __call__ defined, so that it is callable, and then
# would in turn call the closure function;
[docs] @classmethod
def signal_handler(cls, loop=None) -> callable:
"""Returns a signal-checking, exiting closure
:param loop: *Deprecated*
:returns: a closure that looks for :const:`~signal.SIGTERM` or
:const:`~signal.SIGINT` and raises :exc:`SystemExit` if it finds
either one.
.. todo::
Since the returned closure is actually completely static, this could
be simplified greatly. However, it works and doesn't cost much, so
it low on the list.
"""
def signal_handler_closure(sig, frame=None):
if sig in {signal.SIGTERM, sig.SIGINT}:
logger.info(
f"CHAPPS exiting on {signal.Signals(sig)} ({sig})."
)
raise SystemExit
return signal_handler_closure
[docs]class CHAPPSException(Exception):
"""Parent class for CHAPPS exceptions"""
[docs]class CallableExhausted(CHAPPSException):
"""A special exception for use during testing"""
[docs]class NotAnEmailAddressException(CHAPPSException):
"""An email address contained no at-signs"""
[docs]class TooManyAtsException(CHAPPSException):
"""An email address had too many at-signs in it"""
[docs]class ConfigurationError(CHAPPSException):
"""There was an error in the setting of configuration elements"""
[docs]class OutboundPolicyException(CHAPPSException):
"""Parent of exceptions which occur during outbound mail processing"""
[docs]class NullSenderException(OutboundPolicyException):
"""No sender address exists in the current policy request"""
[docs]class AuthenticationFailureException(OutboundPolicyException):
"""Lack of user-identifier being treated as authentication failure"""
[docs]class InboundPolicyException(CHAPPSException):
"""Parent of exceptions arising during inbound email processing"""
[docs]class NoRecipientsException(InboundPolicyException):
"""This is raised if the recipient field is somehow empty"""
[docs]class NoSuchDomainException(CHAPPSException):
"""A domain operation was attempted against a nonexistent Domain"""
[docs]class HELOWLException(CHAPPSException):
"""HELO Whitelisting exceptions"""
[docs]class AddressDoesNotMatchDNS(HELOWLException):
"""A supplied IP address in the HELO Whitelist doesn't match the A record"""
[docs]class NameDoesNotMatchPTR(HELOWLException):
"""The IP address obtained for the HELO name has a PTR record which does
not match the name supplied"""