From f393f1b522de7f7da2cac02b64fbaee81fb8394f Mon Sep 17 00:00:00 2001 From: Benjamin Renard Date: Tue, 14 Mar 2023 16:04:53 +0100 Subject: [PATCH] Email: add possibility to specify more than one recipient --- mylib/email.py | 38 ++++++++++++++++--------- mylib/scripts/email_test.py | 7 +++-- mylib/scripts/email_test_with_config.py | 7 +++-- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/mylib/email.py b/mylib/email.py index 9370de2..71a78e6 100644 --- a/mylib/email.py +++ b/mylib/email.py @@ -177,7 +177,7 @@ class EmailClient( def forge_message( self, - rcpt_to, + recipients, subject=None, html_body=None, text_body=None, # pylint: disable=too-many-arguments,too-many-locals @@ -192,8 +192,8 @@ class EmailClient( """ Forge a message - :param rcpt_to: The recipient of the email. Could be a tuple(name, email) or - just the email of the recipient. + :param recipients: The recipient(s) of the email. List of tuple(name, email) or + just the email of the recipients. :param subject: The subject of the email. :param html_body: The HTML body of the email :param text_body: The plain text body of the email @@ -206,8 +206,14 @@ class EmailClient( All other parameters will be consider as template variables. """ + recipients = [recipients] if not isinstance(recipients, list) else recipients msg = MIMEMultipart("alternative") - msg["To"] = email.utils.formataddr(rcpt_to) if isinstance(rcpt_to, tuple) else rcpt_to + msg["To"] = ", ".join( + [ + email.utils.formataddr(recipient) if isinstance(recipient, tuple) else recipient + for recipient in recipients + ] + ) msg["From"] = email.utils.formataddr( ( sender_name or self._get_option("sender_name"), @@ -280,12 +286,12 @@ class EmailClient( msg.attach(part) return msg - def send(self, rcpt_to, msg=None, subject=None, just_try=False, **forge_args): + def send(self, recipients, msg=None, subject=None, just_try=False, **forge_args): """ Send an email - :param rcpt_to: The recipient of the email. Could be a tuple(name, email) - or just the email of the recipient. + :param recipients: The recipient(s) of the email. List of tuple(name, email) or + just the email of the recipients. :param msg: The message of this email (as MIMEBase or derivated classes) :param subject: The subject of the email (only if the message is not provided using msg parameter) @@ -295,20 +301,21 @@ class EmailClient( All other parameters will be consider as parameters to forge the message (only if the message is not provided using msg parameter). """ - msg = msg if msg else self.forge_message(rcpt_to, subject, **forge_args) + recipients = [recipients] if not isinstance(recipients, list) else recipients + msg = msg if msg else self.forge_message(recipients, subject, **forge_args) if just_try or self._get_option("just_try"): log.debug( 'Just-try mode: do not really send this email to %s (subject="%s")', - rcpt_to, + ", ".join(recipients), subject or msg.get("subject", "No subject"), ) return True catch_addr = self._get_option("catch_all_addr") if catch_addr: - log.debug("Catch email originaly send to %s to %s", rcpt_to, catch_addr) - rcpt_to = catch_addr + log.debug("Catch email originaly send to %s to %s", ", ".join(recipients), catch_addr) + recipients = catch_addr if isinstance(catch_addr, list) else list(catch_addr) smtp_host = self._get_option("smtp_host") smtp_port = self._get_option("smtp_port") @@ -347,15 +354,18 @@ class EmailClient( error = False try: - log.info("Sending email to %s", rcpt_to) + log.info("Sending email to %s", ", ".join(recipients)) server.sendmail( self._get_option("sender_email"), - [rcpt_to[1] if isinstance(rcpt_to, tuple) else rcpt_to], + [ + recipient[1] if isinstance(recipient, tuple) else recipient + for recipient in recipients + ], msg.as_string(), ) except smtplib.SMTPException: error = True - log.error("Error sending email to %s", rcpt_to, exc_info=True) + log.error("Error sending email to %s", ", ".join(recipients), exc_info=True) finally: server.quit() diff --git a/mylib/scripts/email_test.py b/mylib/scripts/email_test.py index 542170a..e619f2e 100644 --- a/mylib/scripts/email_test.py +++ b/mylib/scripts/email_test.py @@ -30,7 +30,8 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements action="store", type=str, dest="test_to", - help="Test email recipient", + help="Test email recipient(s)", + nargs="+", ) test_opts.add_argument( @@ -53,7 +54,7 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements options = parser.parse_args() if not options.test_to: - parser.error("You must specify test email recipient using -t/--to parameter") + parser.error("You must specify at least one test email recipient using -t/--to parameter") sys.exit(1) # Initialize logs @@ -64,7 +65,7 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements email_client = init_email_client(options) - log.info("Send a test email to %s", options.test_to) + log.info("Send a test email to %s", ", ".join(options.test_to)) if email_client.send(options.test_to, template="test", sent_date=datetime.datetime.now()): log.info("Test email sent") sys.exit(0) diff --git a/mylib/scripts/email_test_with_config.py b/mylib/scripts/email_test_with_config.py index 2533eac..e137575 100644 --- a/mylib/scripts/email_test_with_config.py +++ b/mylib/scripts/email_test_with_config.py @@ -35,7 +35,8 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements action="store", type=str, dest="test_to", - help="Test email recipient", + help="Test email recipient(s)", + nargs="+", ) test_opts.add_argument( @@ -58,10 +59,10 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements options = config.parse_arguments_options() if not options.test_to: - parser.error("You must specify test email recipient using -t/--to parameter") + parser.error("You must specify at least one test email recipient using -t/--to parameter") sys.exit(1) - logging.info("Send a test email to %s", options.test_to) + logging.info("Send a test email to %s", ", ".join(options.test_to)) if email_client.send(options.test_to, template="test", sent_date=datetime.datetime.now()): logging.info("Test email sent") sys.exit(0)