Skip to content
Snippets Groups Projects
Select Git revision
  • 820e42ac28755fd85a5b9c940b1e69b611d10eea
  • master default protected
2 results

email.py

Blame
  • Forked from Jean-Marie Place / SCODOC_R6A06
    215 commits behind the upstream repository.
    email.py 3.99 KiB
    # -*- coding: UTF-8 -*
    ##############################################################################
    # ScoDoc
    # Copyright (c) 1999 - 2024 Emmanuel Viennet.  All rights reserved.
    # See LICENSE
    ##############################################################################
    
    import datetime
    from threading import Thread
    
    from flask import current_app, g
    from flask_mail import BadHeaderError, Message
    
    from app import log, mail
    from app.models.departements import Departement
    from app.models.config import ScoDocSiteConfig
    from app.scodoc import sco_preferences
    
    
    def send_async_email(app, msg):
        "Send an email, async"
        with app.app_context():
            try:
                mail.send(msg)
            except BadHeaderError:
                log(
                    f"""send_async_email: BadHeaderError
                    msg={msg}
                    """
                )
                raise
    
    
    def send_email(
        subject: str,
        sender: str,
        recipients: list,
        text_body: str,
        html_body: str | None = None,
        bcc=(),
        attachments=(),
    ):
        """
        Send an email. _All_ ScoDoc mails SHOULD be sent using this function.
    
        If html_body is specified, build a multipart message with HTML content,
        else send a plain text email.
    
        attachements: list of dict { 'filename', 'mimetype', 'data' }
        """
        msg = Message(subject, sender=sender, recipients=recipients, bcc=bcc)
        msg.body = text_body
        msg.html = html_body
        if attachments:
            for attachment in attachments:
                msg.attach(
                    attachment["filename"], attachment["mimetype"], attachment["data"]
                )
        send_message(msg)
    
    
    def send_message(msg: Message):
        """Send a message.
        All ScoDoc emails MUST be sent by this function.
    
        In mail debug mode, addresses are discarded and all mails are sent to the
        specified debugging address.
        """
        email_test_mode_address = False
        if hasattr(g, "scodoc_dept"):
            # on est dans un département, on peut accéder aux préférences
            email_test_mode_address = sco_preferences.get_preference(
                "email_test_mode_address"
            )
            if email_test_mode_address:
                # Mode spécial test: remplace les adresses de destination
                orig_to = msg.recipients
                orig_cc = msg.cc
                orig_bcc = msg.bcc
                msg.recipients = [email_test_mode_address]
                msg.cc = None
                msg.bcc = None
                msg.subject = "[TEST SCODOC] " + msg.subject
                msg.body = (
                    f"""--- Message ScoDoc dérouté pour tests ---
    Adresses d'origine:
     to : {orig_to}
     cc : {orig_cc}
     bcc: {orig_bcc}
    ---
                \n\n"""
                    + msg.body
                )
        now = datetime.datetime.now()
        formatted_time = now.strftime("%Y-%m-%d %H:%M:%S") + ".{:03d}".format(
            now.microsecond // 1000
        )
        current_app.logger.info(
            f"""[{formatted_time}] email sent to{
                ' (mode test)' if email_test_mode_address else ''
            }: {msg.recipients}
            from sender {msg.sender}
            """
        )
        Thread(
            target=send_async_email, args=(current_app._get_current_object(), msg)
        ).start()
    
    
    def get_from_addr(dept_acronym: str = None):
        """L'adresse "from" à utiliser pour envoyer un mail
    
        Si le departement est spécifié, ou si l'attribut `g.scodoc_dept`existe,
        prend le `email_from_addr` des préférences de ce département si ce champ
        est non vide.
        Sinon, utilise le paramètre global `email_from_addr`.
        Sinon, la variable de config `SCODOC_MAIL_FROM`.
        """
        dept_acronym = dept_acronym or getattr(g, "scodoc_dept", None)
        if dept_acronym:
            dept = Departement.query.filter_by(acronym=dept_acronym).first()
            if dept:
                from_addr = (
                    sco_preferences.get_preference("email_from_addr", dept_id=dept.id) or ""
                ).strip()
                if from_addr:
                    return from_addr
        return (
            ScoDocSiteConfig.get("email_from_addr")
            or current_app.config["SCODOC_MAIL_FROM"]
            or "none"
        )