# Own modules
+from . import __version__ as GLOBAL_VERSION
from .errors import PuppetToolsError
-
from .xlate import XLATOR
CONFIG_DIR = 'pixelpark'
-__version__ = '0.1.0'
+__version__ = '0.2.0'
LOG = logging.getLogger(__name__)
VALID_MAIL_METHODS = ('smtp', 'sendmail')
DEFAULT_DOMAIN = 'pixelpark.com'
# =============================================================================
class DpxPuppetConfig(BaseMultiConfig):
- """Base class for reading and providing configuration."""
+ """Class for reading and providing configuration for all
+ application classes in this package."""
default_mail_recipients = [
'solution@pixelpark.com'
valid_mail_methods = VALID_MAIL_METHODS
default_mail_method = 'smtp'
+ re_whitespace = re.compile(r'(?:[,;]+|\s*[,;]*\s+)+')
+
# -------------------------------------------------------------------------
def __init__(
self, appname=None, verbose=0, version=__version__, base_dir=None,
self.mail_server = self.default_mail_server
self.smtp_port = self.default_smtp_port
+ add_stems = []
+ if additional_stems:
+ if is_sequence(additional_stems):
+ for stem in additional_stems:
+ add_stems.append(stem)
+ else:
+ add_stems.append(additional_stems)
+
+ for stem in ('mail', 'hooks'):
+ if stem not in add_stems:
+ add_stems.append(stem)
+
+ self._mail_cc_configured = False
+
super(DpxPuppetConfig, self).__init__(
appname=appname, verbose=verbose, version=version, base_dir=base_dir,
append_appname_to_stems=append_appname_to_stems, config_dir=config_dir,
- additional_stems=additional_stems, additional_cfgdirs=additional_cfgdirs,
+ additional_stems=add_stems, additional_cfgdirs=additional_cfgdirs,
encoding=encoding, additional_config_file=additional_config_file,
ensure_privacy=ensure_privacy, use_chardet=use_chardet,
raise_on_error=raise_on_error, initialized=False)
+ self.xmailer = "{a} (Admin Tools version {v})".format(
+ a=self.appname, v=GLOBAL_VERSION)
+
if initialized:
self.initialized = True
+ # -----------------------------------------------------------
+ @property
+ def mail_cc_configured(self):
+ """Is the mail-CC array already configured?"""
+ return self._mail_cc_configured
+
+ @mail_cc_configured.setter
+ def mail_cc_configured(self, value):
+ self._mail_cc_configured = to_bool(value)
+
# -------------------------------------------------------------------------
def as_dict(self, short=True):
"""
res = super(DpxPuppetConfig, self).as_dict(short=short)
- res['default_mail_recipients'] = self.default_mail_recipients
- res['default_mail_cc'] = self.default_mail_cc
- res['default_reply_to'] = self.default_reply_to
- res['default_mail_server'] = self.default_mail_server
- res['default_smtp_port'] = self.default_smtp_port
- res['current_user_name'] = self.current_user_name
res['current_user_gecos'] = self.current_user_gecos
- res['default_mail_from'] = self.default_mail_from
+ res['current_user_name'] = self.current_user_name
res['default_domain'] = self.default_domain
- res['default_mail_from_complete'] = self.default_mail_from_complete
+ res['default_mail_cc'] = self.default_mail_cc
res['default_mail_method'] = self.default_mail_method
+ res['default_mail_recipients'] = self.default_mail_recipients
+ res['default_mail_from'] = self.default_mail_from
+ res['default_mail_from_complete'] = self.default_mail_from_complete
+ res['default_mail_server'] = self.default_mail_server
+ res['default_reply_to'] = self.default_reply_to
+ res['default_smtp_port'] = self.default_smtp_port
+ res['mail_cc_configured'] = self.mail_cc_configured
res['valid_mail_methods'] = self.valid_mail_methods
return res
+ # -------------------------------------------------------------------------
+ def eval(self):
+
+ self.mail_recipients = []
+ self.mail_cc = []
+
+ super(DpxPuppetConfig, self).eval()
+
+ if not self.mail_recipients:
+ self.mail_recipients = copy.copy(self.default_mail_recipients)
+
+ if not self.mail_cc and not self.mail_cc_configured:
+ self.mail_cc = copy.copy(self.default_mail_cc)
+
+ # -------------------------------------------------------------------------
+ def eval_section(self, section_name):
+
+ super(DpxPuppetConfig, self).eval_section(section_name)
+ sn = section_name.lower()
+
+ if sn == 'mail':
+ section = self.cfg[section_name]
+ return self._eval_mail(section_name, section)
+
+ # -------------------------------------------------------------------------
+ def _eval_mail(self, section_name, section):
+
+ if self.verbose > 2:
+ msg = _("Evaluating config section {!r}:").format(section_name)
+ LOG.debug(msg + '\n' + pp(section))
+
+ self._eval_mail_from(section_name, section)
+ self._eval_mail_rcpt(section_name, section)
+ self._eval_mail_cc(section_name, section)
+ self._eval_mail_reply_to(section_name, section)
+ self._eval_mail_method(section_name, section)
+ self._eval_mail_server(section_name, section)
+ self._eval_smtp_port(section_name, section)
+
+ # -------------------------------------------------------------------------
+ def _split_mailaddress_tokens(self, value, what=None):
+
+ result = []
+
+ tokens = self.whitespace_re.split(value)
+ for token in tokens:
+ if MailAddress.valid_address(token):
+ result.append(token)
+ else:
+ msg = _("Found invalid {what} {addr!r} in configuration.")
+ LOG.error(msg.format(what=what, addr=token))
+
+ return result
+
+ # -------------------------------------------------------------------------
+ def _eval_mail_from(self, section_name, section):
+
+ re_from = re.compile(r'^\s*(mail[_-]?)?from\s*$', re.IGNORECASE)
+
+ for key in section.keys():
+ if not re_from.search(key):
+ continue
+
+ val = section[key]
+
+ if is_sequence(val):
+ if not len(val):
+ continue
+ val = val[0]
+
+ if MailAddress.valid_address(val):
+ self.mail_from = val
+ else:
+ msg = _("Found invalid {what} {addr!r} in configuration.")
+ LOG.error(msg.format(what=_("from address"), addr=val))
+
+ # -------------------------------------------------------------------------
+ def _eval_mail_rcpt(self, section_name, section):
+
+ re_rcpt = re.compile(r'^\s*(mail[_-]?)?(recipients?|rcpt)\s*$', re.IGNORECASE)
+
+ for key in section.keys():
+ if not re_rcpt.search(key):
+ continue
+
+ val = section[key]
+ if not val:
+ continue
+ if is_sequence(val):
+ for v in val:
+ result = self._split_mailaddress_tokens(v, _("recipient mail address"))
+ if result:
+ self.mail_recipients.expand(result)
+ else:
+ result = self._split_mailaddress_tokens(val, _("recipient mail address"))
+ if result:
+ self.mail_recipients.expand(result)
+
+ # -------------------------------------------------------------------------
+ def _eval_mail_cc(self, section_name, section):
+
+ re_cc = re.compile(r'^\s*(mail[_-]?)?cc\s*$', re.IGNORECASE)
+
+ for key in section.keys():
+
+ self.mail_cc_configured = True
+ if not re_cc.search(key):
+ continue
+
+ val = section[key]
+ if not val:
+ continue
+ if is_sequence(val):
+ for v in val:
+ result = self._split_mailaddress_tokens(v, _("cc mail address"))
+ if result:
+ self.mail_cc.expand(result)
+ else:
+ result = self._split_mailaddress_tokens(val, _("cc mail address"))
+ if result:
+ self.mail_cc.expand(result)
+
+ # -------------------------------------------------------------------------
+ def _eval_mail_reply_to(self, section_name, section):
+
+ re_reply = re.compile(r'^\s*(mail[_-]?)?reply([-_]?to)?\s*$', re.IGNORECASE)
+
+ for key in section.keys():
+ if not re_reply.search(key):
+ continue
+
+ val = section[key]
+
+ if is_sequence(val):
+ if not len(val):
+ continue
+ val = val[0]
+
+ if MailAddress.valid_address(val):
+ self.reply_to = val
+ else:
+ msg = _("Found invalid {what} {addr!r} in configuration.")
+ LOG.error(msg.format(what=_("reply to address"), addr=val))
+
+ # -------------------------------------------------------------------------
+ def _eval_mail_method(self, section_name, section):
+
+ re_method = re.compile(r'^\s*(mail[_-]?)?method\s*$', re.IGNORECASE)
+
+ for key in section.keys():
+ if not re_method.search(key):
+ continue
+
+ val = section[key].strip().lower()
+ if not val:
+ continue
+
+ if val not in self.valid_mail_methods:
+ msg = _("Found invalid mail method {!r} in configuration.")
+ LOG.error(msg.format(section[key]))
+ continue
+
+ self.mail_method = val
+
+ # -------------------------------------------------------------------------
+ def _eval_mail_server(self, section_name, section):
+
+ re_server = re.compile(r'^\s*(mail[_-]?)?server\s*$', re.IGNORECASE)
+
+ for key in section.keys():
+ if not re_server.search(key):
+ continue
+
+ val = section[key].strip().lower()
+ if not val:
+ continue
+
+ self.mail_server = val
+
+ # -------------------------------------------------------------------------
+ def _eval_smtp_port(self, section_name, section):
+
+ re_server = re.compile(r'^\s*(smtp[_-]?)?port\s*$', re.IGNORECASE)
+
+ for key in section.keys():
+ if not re_server.search(key):
+ continue
+
+ val = section[key]
+ try:
+ port = int(val)
+ except (ValueError, TypeError) as e:
+ msg = _("Value {!r} for SMTP port is invalid:").format(val)
+ msg += ' ' + str(e)
+ LOG.error(msg)
+ continue
+ if port <= 0 or port > MAX_PORT_NUMBER:
+ msg = _("Found invalid SMTP port number {} in configuration.").format(port)
+ LOG.error(msg)
+ continue
+
+ self.smtp_port = port
+
# =============================================================================