]> Frank Brehm's Git Trees - pixelpark/pp-admin-tools.git/commitdiff
Adding lib/pp_admintools/mail_app.py for class BaseMailApplication
authorFrank Brehm <frank@brehm-online.com>
Sun, 27 Mar 2022 13:26:53 +0000 (15:26 +0200)
committerFrank Brehm <frank@brehm-online.com>
Sun, 27 Mar 2022 13:26:53 +0000 (15:26 +0200)
lib/pp_admintools/mail_app.py [new file with mode: 0644]

diff --git a/lib/pp_admintools/mail_app.py b/lib/pp_admintools/mail_app.py
new file mode 100644 (file)
index 0000000..d618437
--- /dev/null
@@ -0,0 +1,261 @@
+# -*- coding: utf-8 -*-
+"""
+@author: Frank Brehm
+@contact: frank.brehm@pixelpark.com
+@copyright: © 2022 by Frank Brehm, Berlin
+@summary: A base module for application classes with mail sending support
+"""
+from __future__ import absolute_import
+
+# Standard modules
+import logging
+import copy
+
+from email.mime.text import MIMEText
+from email import charset
+
+import smtplib
+
+# Own modules
+from . import __version__ as GLOBAL_VERSION
+
+from fb_tools.common import pp
+
+from fb_tools.cfg_app import FbConfigApplication
+
+from fb_tools.errors import FbAppError
+
+from fb_tools.xlate import format_list
+
+from .xlate import XLATOR
+
+from .mail_config import MailConfigError, MailConfiguration
+from .mail_config import VALID_MAIL_METHODS, MAX_PORT_NUMBER
+
+__version__ = '0.1.1'
+LOG = logging.getLogger(__name__)
+
+_ = XLATOR.gettext
+ngettext = XLATOR.ngettext
+
+
+# =============================================================================
+class MailAppError(FbAppError):
+    """ Base exception class for all exceptions in all mail sending application classes."""
+    pass
+
+# =============================================================================
+class BaseMailApplication(FbConfigApplication):
+    """
+    Base class for all mail sending application classes.
+    """
+
+    charset.add_charset('utf-8', charset.SHORTEST, charset.QP)
+
+    # -------------------------------------------------------------------------
+    def __init__(
+        self, appname=None, verbose=0, version=GLOBAL_VERSION, base_dir=None,
+            cfg_class=MailConfiguration, initialized=False, usage=None, description=None,
+            argparse_epilog=None, argparse_prefix_chars='-', env_prefix=None):
+
+        super(BaseMailApplication, self).__init__(
+            appname=appname, verbose=verbose, version=version, base_dir=base_dir,
+            description=description, cfg_class=cfg_class, initialized=False,
+        )
+
+    # -------------------------------------------------------------------------
+    def post_init(self):
+        """
+        Method to execute before calling run(). Here could be done some
+        finishing actions after reading in commandline parameters,
+        configuration a.s.o.
+
+        This method could be overwritten by descendant classes, these
+        methhods should allways include a call to post_init() of the
+        parent class.
+
+        """
+
+        self.initialized = False
+
+        super(BaseMailApplication, self).post_init()
+
+        v = getattr(self.args, 'mail_method', None)
+        if v:
+            self.cfg.mail_method = v
+
+        v = getattr(self.args, 'mail_server', None)
+        if v:
+            self.cfg.mail_server = v
+
+        v = getattr(self.args, 'smtp_port', None)
+        if v is not None:
+            if v <= 0 or v > MAX_PORT_NUMBER:
+                msg = _("Got invalid SMTP port number {!r}.").format(v)
+                LOG.error(msg)
+            else:
+                self.cfg.smtp_port = v
+
+        self._perform_cmdline_mail_from()
+        self._perform_cmdline_mail_rcpt()
+        self._perform_cmdline_mail_cc()
+        self._perform_cmdline_reply_to()
+
+    # -------------------------------------------------------------------------
+    def _perform_cmdline_mail_from(self):
+
+        v = getattr(self.args, 'mail_from', None)
+        if not v:
+            return
+
+        if not MailAddress.valid_address(v):
+            msg = _("Got invalid mail from address {!r}.").format(v)
+            LOG.error(msg)
+            self.exit(1)
+
+        self.cfg.mail_from = v
+
+    # -------------------------------------------------------------------------
+    def _perform_cmdline_mail_rcpt(self):
+
+        v = getattr(self.args, 'mail_recipients', None)
+        if v not None:
+            return
+
+        recipients = []
+        bad_rcpts = []
+
+        for addr in v:
+            if MailAddress.valid_address(addr):
+                recipients.append(addr)
+            else:
+                bad_rcpts.append(addr)
+
+        if bad_rcpts:
+            msg = _("Got invalid recipient mail addresses:")
+            msg += " " + format_list(bad_rcpts, , do_repr=True)
+            LOG.error(msg)
+            self.exit(1)
+
+        self.cfg.mail_recipients = copy.copy(recipients)
+
+        if not self.cfg.mail_recipients:
+            msg = ("Did not found any valid recipient mail addresses.")
+            LOG.error(msg)
+
+    # -------------------------------------------------------------------------
+    def _perform_cmdline_mail_cc(self):
+
+        v = getattr(self.args, 'mail_cc', None)
+        if v is None:
+            return
+
+        cc = []
+        bad_cc = []
+
+        for addr in v:
+            if MailAddress.valid_address(addr):
+                cc.append(addr)
+            else:
+                bad_cc.append(addr)
+
+        if bad_cc:
+            msg = _("Got invalid cc mail addresses:")
+            msg += " " + format_list(bad_cc, , do_repr=True)
+            LOG.error(msg)
+            self.exit(1)
+
+        self.cfg.mail_cc = copy.copy(cc)
+
+    # -------------------------------------------------------------------------
+    def _perform_cmdline_reply_to(self):
+
+        v = getattr(self.args, 'mail_reply_to', None)
+        if not v:
+            return
+
+        if not MailAddress.valid_address(v):
+            msg = _("Got invalid reply mail address {!r}.").format(v)
+            LOG.error(msg)
+            self.exit(1)
+
+        self.cfg.reply_to = v
+
+    # -------------------------------------------------------------------------
+    def init_arg_parser(self):
+        """
+        Public available method to initiate the argument parser.
+        """
+
+        super(BaseMailApplication, self).init_arg_parser()
+
+        mail_group = self.arg_parser.add_argument_group(_('Mailing options'))
+
+        mail_group.add_argument(
+            '--from', '--mail-from',
+             metavar=_("ADDRESS"), dest="mail_from",
+            help=_(
+                "Sender mail address for mails generated by this script. "
+                "Default: {!r}").format(self.cfg.mail_from),
+        )
+
+        mail_group.add_argument(
+            '--recipients', '--mail-recipients',
+            metavar=_("ADDRESS"), nargs='+', dest="mail_recipients",
+            help=_("Mail addresses of all recipients for mails generated by this script.")
+        )
+
+        mail_group.add_argument(
+            '--cc', '--mail-cc',
+            metavar=_("ADDRESS"), nargs='*', dest="mail_cc",
+            help=_("Mail addresses of all CC recipients for mails generated by this script.")
+        )
+
+        mail_group.add_argument(
+            '--reply-to', '--mail-reply-to',
+            metavar=_("ADDRESS"), dest="mail_reply_to",
+            help=_("Reply mail address for mails generated by this script.")
+        )
+
+        method_list = format_list(VALID_MAIL_METHODS, do_repr=True)
+        mail_group.add_argument(
+            '--mail-method',
+            metavar=_("METHOD"), choices=VALID_MAIL_METHODS, dest="mail_method",
+            help=_(
+                "Method for sending the mails generated by this script. "
+                "Valid values: {v}, default: {d!r}.").format(
+                    v=method_list, d=self.cfg.mail_method)
+        )
+
+        mail_group.add_argument(
+            '--mail-server',
+            metavar=_("SERVER"), dest="mail_server",
+            help=_(
+                "Mail server for submitting generated by this script if "
+                "the mail method of this script is 'smtp'. Default: {!r}.").format(
+                self.cfg.mail_server)
+        )
+
+        mail_group.add_argument(
+            '--smtp-port',
+            metavar=_("PORT"), type=int, dest='smtp_port',
+            help=_(
+                "The port to use for submitting generated by this script if "
+                "the mail method of this script is 'smtp'. Default: {}.").format(self.cfg.smtp_port)
+        )
+
+    # -------------------------------------------------------------------------
+    def perform_arg_parser(self):
+
+        if self.verbose > 2:
+            LOG.debug(_("Got command line arguments:") + '\n' + pp(self.args))
+
+
+# =============================================================================
+if __name__ == "__main__":
+
+    pass
+
+# =============================================================================
+
+# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list