# -*- 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 Message from app import 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(): mail.send(msg) def send_email( subject: str, sender: str, recipients: list, text_body: str, html_body="", 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" )