Compare commits
No commits in common. "e71fb2829546eb53c96b87abec0580e87aae7ff7" and "5aa6a0cea4300195afe97b6dc2f997b64883d920" have entirely different histories.
e71fb28295
...
5aa6a0cea4
8 changed files with 47 additions and 122 deletions
|
@ -116,10 +116,6 @@ class BaseOption: # pylint: disable=too-many-instance-attributes
|
||||||
|
|
||||||
self._set = True
|
self._set = True
|
||||||
|
|
||||||
def set_default(self, default_value):
|
|
||||||
"""Set option default value"""
|
|
||||||
self.default = default_value
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parser_action(self):
|
def parser_action(self):
|
||||||
"""Get action as accept by argparse.ArgumentParser"""
|
"""Get action as accept by argparse.ArgumentParser"""
|
||||||
|
@ -515,16 +511,6 @@ class ConfigSection:
|
||||||
assert self.defined(option), f"Option {option} unknown"
|
assert self.defined(option), f"Option {option} unknown"
|
||||||
return self.options[option].set(value)
|
return self.options[option].set(value)
|
||||||
|
|
||||||
def set_default(self, option, default_value):
|
|
||||||
"""Set default option value"""
|
|
||||||
assert self.defined(option), f"Option {option} unknown"
|
|
||||||
return self.options[option].set_default(default_value)
|
|
||||||
|
|
||||||
def set_defaults(self, **default_values):
|
|
||||||
"""Set default options value"""
|
|
||||||
for option, default_value in default_values.items():
|
|
||||||
self.set_default(option, default_value)
|
|
||||||
|
|
||||||
def add_options_to_parser(self, parser):
|
def add_options_to_parser(self, parser):
|
||||||
"""Add section to argparse.ArgumentParser"""
|
"""Add section to argparse.ArgumentParser"""
|
||||||
assert isinstance(parser, argparse.ArgumentParser)
|
assert isinstance(parser, argparse.ArgumentParser)
|
||||||
|
@ -674,18 +660,6 @@ class Config: # pylint: disable=too-many-instance-attributes
|
||||||
self._init_config_parser()
|
self._init_config_parser()
|
||||||
self.sections[section].set(option, value)
|
self.sections[section].set(option, value)
|
||||||
|
|
||||||
def set_default(self, section, option, default_value):
|
|
||||||
"""Set default option value"""
|
|
||||||
assert self.defined(section, option), f"Unknown option {section}.{option}"
|
|
||||||
self._init_config_parser()
|
|
||||||
self.sections[section].set_default(option, default_value)
|
|
||||||
|
|
||||||
def set_defaults(self, section, **default_values):
|
|
||||||
"""Set default options value"""
|
|
||||||
assert section in self.sections, f"Unknown section {section}"
|
|
||||||
self._init_config_parser()
|
|
||||||
self.sections[section].set_defaults(**default_values)
|
|
||||||
|
|
||||||
def _init_config_parser(self, force=False):
|
def _init_config_parser(self, force=False):
|
||||||
"""Initialize ConfigParser object"""
|
"""Initialize ConfigParser object"""
|
||||||
if not self.config_parser or force:
|
if not self.config_parser or force:
|
||||||
|
|
|
@ -46,18 +46,15 @@ class EmailClient(
|
||||||
"encoding": "utf-8",
|
"encoding": "utf-8",
|
||||||
"catch_all_addr": None,
|
"catch_all_addr": None,
|
||||||
"just_try": False,
|
"just_try": False,
|
||||||
"templates_path": None,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
templates = {}
|
templates = {}
|
||||||
|
|
||||||
def __init__(self, templates=None, initialize=False, **kwargs):
|
def __init__(self, templates=None, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
assert templates is None or isinstance(templates, dict)
|
assert templates is None or isinstance(templates, dict)
|
||||||
self.templates = templates if templates else {}
|
self.templates = templates if templates else {}
|
||||||
if initialize:
|
|
||||||
self.initialize()
|
|
||||||
|
|
||||||
# pylint: disable=arguments-differ,arguments-renamed
|
# pylint: disable=arguments-differ,arguments-renamed
|
||||||
def configure(self, use_smtp=True, just_try=True, **kwargs):
|
def configure(self, use_smtp=True, just_try=True, **kwargs):
|
||||||
|
@ -140,40 +137,8 @@ class EmailClient(
|
||||||
comment="Just-try mode: do not really send emails",
|
comment="Just-try mode: do not really send emails",
|
||||||
)
|
)
|
||||||
|
|
||||||
section.add_option(
|
|
||||||
StringOption,
|
|
||||||
"templates_path",
|
|
||||||
comment="Path to templates directory",
|
|
||||||
)
|
|
||||||
|
|
||||||
return section
|
return section
|
||||||
|
|
||||||
def initialize(self, *args, **kwargs): # pylint: disable=arguments-differ
|
|
||||||
"""Configuration initialized hook"""
|
|
||||||
super().initialize(*args, **kwargs)
|
|
||||||
self.load_templates_directory()
|
|
||||||
|
|
||||||
def load_templates_directory(self, templates_path=None):
|
|
||||||
"""Load templates from specified directory"""
|
|
||||||
if templates_path is None:
|
|
||||||
templates_path = self._get_option("templates_path")
|
|
||||||
if not templates_path:
|
|
||||||
return
|
|
||||||
log.debug("Load email templates from %s directory", templates_path)
|
|
||||||
for filename in os.listdir(templates_path):
|
|
||||||
filepath = os.path.join(templates_path, filename)
|
|
||||||
if not os.path.isfile(filepath):
|
|
||||||
continue
|
|
||||||
template_name, template_type = os.path.splitext(filename)
|
|
||||||
if template_type not in [".html", ".txt", ".subject"]:
|
|
||||||
continue
|
|
||||||
template_type = "text" if template_type == ".txt" else template_type[1:]
|
|
||||||
if template_name not in self.templates:
|
|
||||||
self.templates[template_name] = {}
|
|
||||||
log.debug("Load email template %s %s from %s", template_name, template_type, filepath)
|
|
||||||
with open(filepath, encoding="utf8") as file_desc:
|
|
||||||
self.templates[template_name][template_type] = MakoTemplate(file_desc.read())
|
|
||||||
|
|
||||||
def forge_message(
|
def forge_message(
|
||||||
self,
|
self,
|
||||||
rcpt_to,
|
rcpt_to,
|
||||||
|
@ -214,11 +179,7 @@ class EmailClient(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if subject:
|
if subject:
|
||||||
msg["Subject"] = (
|
msg["Subject"] = subject.format(**template_vars)
|
||||||
subject.render(**template_vars)
|
|
||||||
if isinstance(subject, MakoTemplate)
|
|
||||||
else subject.format(**template_vars)
|
|
||||||
)
|
|
||||||
msg["Date"] = email.utils.formatdate(None, True)
|
msg["Date"] = email.utils.formatdate(None, True)
|
||||||
encoding = encoding if encoding else self._get_option("encoding")
|
encoding = encoding if encoding else self._get_option("encoding")
|
||||||
if template:
|
if template:
|
||||||
|
@ -228,11 +189,7 @@ class EmailClient(
|
||||||
assert self.templates[template].get(
|
assert self.templates[template].get(
|
||||||
"subject"
|
"subject"
|
||||||
), f"No subject defined in template {template}"
|
), f"No subject defined in template {template}"
|
||||||
msg["Subject"] = (
|
msg["Subject"] = self.templates[template]["subject"].format(**template_vars)
|
||||||
self.templates[template]["subject"].render(**template_vars)
|
|
||||||
if isinstance(self.templates[template]["subject"], MakoTemplate)
|
|
||||||
else self.templates[template]["subject"].format(**template_vars)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Put HTML part in last one to prefered it
|
# Put HTML part in last one to prefered it
|
||||||
parts = []
|
parts = []
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
<strong>Just a test email.</strong> <small>(sent at ${sent_date})</small>
|
|
|
@ -1 +0,0 @@
|
||||||
Test email
|
|
|
@ -1 +0,0 @@
|
||||||
Just a test email sent at ${sent_date}.
|
|
|
@ -2,9 +2,10 @@
|
||||||
import datetime
|
import datetime
|
||||||
import getpass
|
import getpass
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from mako.template import Template as MakoTemplate
|
||||||
|
|
||||||
from mylib.scripts.helpers import add_email_opts, get_opts_parser, init_email_client, init_logging
|
from mylib.scripts.helpers import add_email_opts, get_opts_parser, init_email_client, init_logging
|
||||||
|
|
||||||
log = logging.getLogger("mylib.scripts.email_test")
|
log = logging.getLogger("mylib.scripts.email_test")
|
||||||
|
@ -17,10 +18,7 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements
|
||||||
|
|
||||||
# Options parser
|
# Options parser
|
||||||
parser = get_opts_parser(just_try=True)
|
parser = get_opts_parser(just_try=True)
|
||||||
add_email_opts(
|
add_email_opts(parser)
|
||||||
parser,
|
|
||||||
templates_path=os.path.join(os.path.dirname(os.path.realpath(__file__)), "email_templates"),
|
|
||||||
)
|
|
||||||
|
|
||||||
test_opts = parser.add_argument_group("Test email options")
|
test_opts = parser.add_argument_group("Test email options")
|
||||||
|
|
||||||
|
@ -33,15 +31,6 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements
|
||||||
help="Test email recipient",
|
help="Test email recipient",
|
||||||
)
|
)
|
||||||
|
|
||||||
test_opts.add_argument(
|
|
||||||
"-T",
|
|
||||||
"--template",
|
|
||||||
action="store_true",
|
|
||||||
dest="template",
|
|
||||||
help="Template name to send (default: test)",
|
|
||||||
default="test",
|
|
||||||
)
|
|
||||||
|
|
||||||
test_opts.add_argument(
|
test_opts.add_argument(
|
||||||
"-m",
|
"-m",
|
||||||
"--mako",
|
"--mako",
|
||||||
|
@ -62,7 +51,26 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements
|
||||||
if options.email_smtp_user and not options.email_smtp_password:
|
if options.email_smtp_user and not options.email_smtp_password:
|
||||||
options.email_smtp_password = getpass.getpass("Please enter SMTP password: ")
|
options.email_smtp_password = getpass.getpass("Please enter SMTP password: ")
|
||||||
|
|
||||||
email_client = init_email_client(options)
|
email_client = init_email_client(
|
||||||
|
options,
|
||||||
|
templates=dict(
|
||||||
|
test=dict(
|
||||||
|
subject="Test email",
|
||||||
|
text=(
|
||||||
|
"Just a test email sent at {sent_date}."
|
||||||
|
if not options.test_mako
|
||||||
|
else MakoTemplate("Just a test email sent at ${sent_date}.")
|
||||||
|
),
|
||||||
|
html=(
|
||||||
|
"<strong>Just a test email.</strong> <small>(sent at {sent_date})</small>"
|
||||||
|
if not options.test_mako
|
||||||
|
else MakoTemplate(
|
||||||
|
"<strong>Just a test email.</strong> <small>(sent at ${sent_date})</small>"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
log.info("Send a test email to %s", options.test_to)
|
log.info("Send a test email to %s", options.test_to)
|
||||||
if email_client.send(options.test_to, template="test", sent_date=datetime.datetime.now()):
|
if email_client.send(options.test_to, template="test", sent_date=datetime.datetime.now()):
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
""" Test Email client using mylib.config.Config for configuration """
|
""" Test Email client using mylib.config.Config for configuration """
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from mako.template import Template as MakoTemplate
|
||||||
|
|
||||||
from mylib.config import Config
|
from mylib.config import Config
|
||||||
from mylib.email import EmailClient
|
from mylib.email import EmailClient
|
||||||
|
|
||||||
|
@ -19,11 +20,6 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements
|
||||||
|
|
||||||
email_client = EmailClient(config=config)
|
email_client = EmailClient(config=config)
|
||||||
email_client.configure()
|
email_client.configure()
|
||||||
config.set_default(
|
|
||||||
"email",
|
|
||||||
"templates_path",
|
|
||||||
os.path.join(os.path.dirname(os.path.realpath(__file__)), "email_templates"),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Options parser
|
# Options parser
|
||||||
parser = config.get_arguments_parser(description=__doc__)
|
parser = config.get_arguments_parser(description=__doc__)
|
||||||
|
@ -39,15 +35,6 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements
|
||||||
help="Test email recipient",
|
help="Test email recipient",
|
||||||
)
|
)
|
||||||
|
|
||||||
test_opts.add_argument(
|
|
||||||
"-T",
|
|
||||||
"--template",
|
|
||||||
action="store_true",
|
|
||||||
dest="template",
|
|
||||||
help="Template name to send (default: test)",
|
|
||||||
default="test",
|
|
||||||
)
|
|
||||||
|
|
||||||
test_opts.add_argument(
|
test_opts.add_argument(
|
||||||
"-m",
|
"-m",
|
||||||
"--mako",
|
"--mako",
|
||||||
|
@ -62,6 +49,24 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements
|
||||||
parser.error("You must specify test email recipient using -t/--to parameter")
|
parser.error("You must specify test email recipient using -t/--to parameter")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
email_client.templates = dict(
|
||||||
|
test=dict(
|
||||||
|
subject="Test email",
|
||||||
|
text=(
|
||||||
|
"Just a test email sent at {sent_date}."
|
||||||
|
if not options.test_mako
|
||||||
|
else MakoTemplate("Just a test email sent at ${sent_date}.")
|
||||||
|
),
|
||||||
|
html=(
|
||||||
|
"<strong>Just a test email.</strong> <small>(sent at {sent_date})</small>"
|
||||||
|
if not options.test_mako
|
||||||
|
else MakoTemplate(
|
||||||
|
"<strong>Just a test email.</strong> <small>(sent at ${sent_date})</small>"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
logging.info("Send a test email to %s", options.test_to)
|
logging.info("Send a test email to %s", options.test_to)
|
||||||
if email_client.send(options.test_to, template="test", sent_date=datetime.datetime.now()):
|
if email_client.send(options.test_to, template="test", sent_date=datetime.datetime.now()):
|
||||||
logging.info("Test email sent")
|
logging.info("Test email sent")
|
||||||
|
|
|
@ -87,7 +87,7 @@ def get_opts_parser(desc=None, just_try=False, just_one=False, progress=False, c
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
def add_email_opts(parser, config=None, **defaults):
|
def add_email_opts(parser, config=None):
|
||||||
"""Add email options"""
|
"""Add email options"""
|
||||||
email_opts = parser.add_argument_group("Email options")
|
email_opts = parser.add_argument_group("Email options")
|
||||||
|
|
||||||
|
@ -103,9 +103,7 @@ def add_email_opts(parser, config=None, **defaults):
|
||||||
sender_name=getpass.getuser(),
|
sender_name=getpass.getuser(),
|
||||||
sender_email=f"{getpass.getuser()}@{socket.gethostname()}",
|
sender_email=f"{getpass.getuser()}@{socket.gethostname()}",
|
||||||
catch_all=False,
|
catch_all=False,
|
||||||
templates_path=None,
|
|
||||||
)
|
)
|
||||||
default_config.update(defaults)
|
|
||||||
|
|
||||||
email_opts.add_argument(
|
email_opts.add_argument(
|
||||||
"--smtp-host",
|
"--smtp-host",
|
||||||
|
@ -222,18 +220,6 @@ def add_email_opts(parser, config=None, **defaults):
|
||||||
default=get_default_opt_value(config, default_config, "catch_all"),
|
default=get_default_opt_value(config, default_config, "catch_all"),
|
||||||
)
|
)
|
||||||
|
|
||||||
email_opts.add_argument(
|
|
||||||
"--templates-path",
|
|
||||||
action="store",
|
|
||||||
type=str,
|
|
||||||
dest="email_templates_path",
|
|
||||||
help=(
|
|
||||||
"Load templates from specify directory "
|
|
||||||
f'(default: {get_default_opt_value(config, default_config, "templates_path")})'
|
|
||||||
),
|
|
||||||
default=get_default_opt_value(config, default_config, "templates_path"),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def init_email_client(options, **kwargs):
|
def init_email_client(options, **kwargs):
|
||||||
"""Initialize email client from calling script options"""
|
"""Initialize email client from calling script options"""
|
||||||
|
@ -253,8 +239,6 @@ def init_email_client(options, **kwargs):
|
||||||
catch_all_addr=options.email_catch_all,
|
catch_all_addr=options.email_catch_all,
|
||||||
just_try=options.just_try if hasattr(options, "just_try") else False,
|
just_try=options.just_try if hasattr(options, "just_try") else False,
|
||||||
encoding=options.email_encoding,
|
encoding=options.email_encoding,
|
||||||
templates_path=options.email_templates_path,
|
|
||||||
initialize=True,
|
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue