mail.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. """Cement core mail module."""
  2. from ..core import interface, handler
  3. from ..utils.misc import minimal_logger
  4. LOG = minimal_logger(__name__)
  5. def mail_validator(klass, obj):
  6. """Validates a handler implementation against the IMail interface."""
  7. members = [
  8. '_setup',
  9. 'send',
  10. ]
  11. # FIX ME: Validate Meta/Configuration Defaults Here
  12. interface.validate(IMail, obj, members)
  13. class IMail(interface.Interface):
  14. """
  15. This class defines the Mail Handler Interface. Classes that
  16. implement this handler must provide the methods and attributes defined
  17. below.
  18. Implementations do *not* subclass from interfaces.
  19. **Configuration**
  20. Implementations much support the following configuration settings:
  21. * **to** - Default ``to`` addresses (list, or comma separated depending
  22. on the ConfigHandler in use)
  23. * **from_addr** - Default ``from_addr`` address
  24. * **cc** - Default ``cc`` addresses (list, or comma separated depending
  25. on the ConfigHandler in use)
  26. * **bcc** - Default ``bcc`` addresses (list, or comma separated depending
  27. on the ConfigHandler in use)
  28. * **subject** - Default ``subject``
  29. * **subject_prefix** - Additional string to prepend to the ``subject``
  30. **Usage**
  31. .. code-block:: python
  32. from cement.core import mail
  33. class MyMailHandler(object):
  34. class Meta:
  35. interface = mail.IMail
  36. label = 'my_mail_handler'
  37. ...
  38. """
  39. # pylint: disable=W0232, C0111, R0903
  40. class IMeta:
  41. """Interface meta-data."""
  42. label = 'mail'
  43. """The label (or type identifier) of the interface."""
  44. validator = mail_validator
  45. """Interface validator function."""
  46. # Must be provided by the implementation
  47. Meta = interface.Attribute('Handler meta-data')
  48. def _setup(app_obj):
  49. """
  50. The _setup function is called during application initialization and
  51. must 'setup' the handler object making it ready for the framework
  52. or the application to make further calls to it.
  53. :param app_obj: The application object.
  54. :returns: None
  55. """
  56. def send(body, **kwargs):
  57. """
  58. Send a mail message. Keyword arguments override configuration
  59. defaults (cc, bcc, etc).
  60. :param body: The message body to send
  61. :type body: ``multiline string``
  62. :keyword to: List of recipients (generally email addresses)
  63. :type to: ``list``
  64. :keyword from_addr: Address (generally email) of the sender
  65. :type from_addr: ``str``
  66. :keyword cc: List of CC Recipients
  67. :type cc: ``list``
  68. :keyword bcc: List of BCC Recipients
  69. :type bcc: ``list``
  70. :keyword subject: Message subject line
  71. :type subject: ``str``
  72. :returns: Boolean (``True`` if message is sent successfully, ``False``
  73. otherwise)
  74. **Usage**
  75. .. code-block:: python
  76. # Using all configuration defaults
  77. app.send('This is my message body')
  78. # Overriding configuration defaults
  79. app.send('My message body'
  80. to=['john@example.com'],
  81. from_addr='me@example.com',
  82. cc=['jane@example.com', 'rita@example.com'],
  83. subject='This is my subject',
  84. )
  85. """
  86. class CementMailHandler(handler.CementBaseHandler):
  87. """
  88. Base class that all Mail Handlers should sub-class from.
  89. **Configuration Options**
  90. This handler supports the following configuration options under a
  91. """
  92. class Meta:
  93. """
  94. Handler meta-data (can be passed as keyword arguments to the parent
  95. class).
  96. """
  97. #: String identifier of this handler implementation.
  98. label = None
  99. #: The interface that this handler class implements.
  100. interface = IMail
  101. #: Configuration default values
  102. config_defaults = {
  103. 'to': [],
  104. 'from_addr': 'noreply@example.com',
  105. 'cc': [],
  106. 'bcc': [],
  107. 'subject': 'Default Subject Line',
  108. 'subject_prefix': '',
  109. }
  110. def __init__(self, *args, **kw):
  111. super(CementMailHandler, self).__init__(*args, **kw)
  112. def _setup(self, app_obj):
  113. super(CementMailHandler, self)._setup(app_obj)
  114. self._validate_config()
  115. def send(self, body, **kw):
  116. raise NotImplementedError # pragma: nocover
  117. def _validate_config(self):
  118. # convert comma separated strings to lists (ConfigParser)
  119. for item in ['to', 'cc', 'bcc']:
  120. if item in self.app.config.keys(self._meta.config_section):
  121. value = self.app.config.get(self._meta.config_section, item)
  122. # convert a comma-separated string to a list
  123. if type(value) is str:
  124. value_list = value.split(',')
  125. # clean up extra space if they had it inbetween commas
  126. value_list = [x.strip() for x in value_list]
  127. # set the new extensions value in the config
  128. self.app.config.set(self._meta.config_section, item,
  129. value_list)