fonctions d'envoi de mails

This commit is contained in:
Emmanuel Viennet 2021-08-26 23:43:54 +02:00
parent 5902fe81e2
commit 72c63812fa
14 changed files with 91 additions and 253 deletions

View File

@ -10,10 +10,21 @@ def send_async_email(app, msg):
mail.send(msg)
def send_email(subject, sender, recipients, text_body, html_body):
def send_email(
subject: str, sender: str, recipients: list, text_body: str, html_body=""
):
"""
Send an email
If html_body is specified, build a multipart message with HTML content,
else send a plain text email.
"""
msg = Message(subject, sender=sender, recipients=recipients)
msg.body = text_body
msg.html = html_body
send_message(msg)
def send_message(msg):
Thread(
target=send_async_email, args=(current_app._get_current_object(), msg)
).start()

View File

@ -4,12 +4,11 @@
import os
import time
import traceback
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
from flask import g, current_app
from app import email
"""Simple & stupid file logguer, used only to debug
(logging to SQL is done in scolog)
"""
@ -19,7 +18,7 @@ DEFAULT_LOG_DIR = (
"/opt/scodoc-data/log" # clients should call set_log_directory to change this
)
ALARM_DESTINATION = "emmanuel.viennet@gmail.com" # XXX a mettre en preference
ALARM_DESTINATION = "emmanuel@scodoc.org"
class _logguer(object):
@ -66,20 +65,11 @@ log = _logguer()
# Alarms by email:
def sendAlarm(subj, txt):
from . import sco_utils
from . import sco_emails
from . import sco_preferences
def sendAlarm(subject, txt):
from app.scodoc import sco_preferences
msg = MIMEMultipart()
subj = Header(subj, sco_utils.SCO_ENCODING)
msg["Subject"] = subj
msg["From"] = sco_preferences.get_preference("email_from_addr")
msg["To"] = ALARM_DESTINATION
msg.epilogue = ""
txt = MIMEText(txt, "plain", sco_utils.SCO_ENCODING)
msg.attach(txt)
sco_emails.sendEmail(msg)
sender = sco_preferences.get_preference("email_from_addr")
email.send_email(subject, sender, [ALARM_DESTINATION], txt)
# Debug: log call stack

View File

@ -33,13 +33,9 @@ Il suffit d'appeler abs_notify() après chaque ajout d'absence.
"""
import datetime
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
from flask import g, url_for
from flask_mail import Message
from app.scodoc import sco_emails
import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu
from app.scodoc.notes_log import log
@ -48,6 +44,7 @@ from app.scodoc import sco_etud
from app.scodoc import sco_formsemestre
from app.scodoc import sco_preferences
from app.scodoc import sco_users
from app import email
def abs_notify(etudid, date):
@ -108,12 +105,11 @@ def abs_notify_send(destinations, etudid, msg, nbabs, nbabsjust, formsemestre_id
cnx = ndb.GetDBConnexion()
log("abs_notify: sending notification to %s" % destinations)
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
for email in destinations:
del msg["To"]
msg["To"] = email
sco_emails.sendEmail(msg)
for dest_addr in destinations:
msg.recipients = [dest_addr]
email.send_message(msg)
ndb.SimpleQuery(
"""insert into absences_notifications
"""INSERT into absences_notifications
(etudid, email, nbabs, nbabsjust, formsemestre_id)
VALUES (%(etudid)s, %(email)s, %(nbabs)s, %(nbabsjust)s, %(formsemestre_id)s)
""",
@ -229,7 +225,8 @@ def user_nbdays_since_last_notif(email_addr, etudid):
def abs_notification_message(sem, prefs, etudid, nbabs, nbabsjust):
"""Mime notification message based on template.
returns None if sending should be canceled (emplty template).
returns a Message instance
or None if sending should be canceled (empty template).
"""
from app.scodoc import sco_bulletins
@ -252,14 +249,9 @@ def abs_notification_message(sem, prefs, etudid, nbabs, nbabsjust):
log("abs_notification_message: empty template, not sending message")
return None
subject = """Trop d'absences pour %(nomprenom)s""" % etud
#
msg = MIMEMultipart()
subj = Header("[ScoDoc] " + subject, scu.SCO_ENCODING)
msg["Subject"] = subj
msg["From"] = prefs["email_from_addr"]
txt = MIMEText(txt, "plain", scu.SCO_ENCODING)
msg.attach(txt)
subject = """[ScoDoc] Trop d'absences pour %(nomprenom)s""" % etud
msg = Message(subject, sender=prefs["email_from_addr"])
msg.body = txt
return msg

View File

@ -42,8 +42,8 @@ import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
from flask import g
from flask import url_for
from flask_login import current_user
from flask_mail import Message
from app.scodoc import sco_emails
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
from app.scodoc.notes_log import log
@ -68,7 +68,7 @@ from app.scodoc import sco_photos
from app.scodoc import sco_preferences
from app.scodoc import sco_pvjury
from app.scodoc import sco_users
from app import email
# ----- CLASSES DE BULLETINS DE NOTES
from app.scodoc import sco_bulletins_standard
@ -983,28 +983,21 @@ def mail_bulletin(formsemestre_id, I, pdfdata, filename, recipient_addr):
etud["etudid"], with_evals=False, format="text"
)
msg = MIMEMultipart()
subj = Header("Relevé de notes de %s" % etud["nomprenom"], scu.SCO_ENCODING)
subject = "Relevé de notes de %s" % etud["nomprenom"]
recipients = [recipient_addr]
msg["Subject"] = subj
msg["From"] = sco_preferences.get_preference("email_from_addr", formsemestre_id)
msg["To"] = " ,".join(recipients)
sender = sco_preferences.get_preference("email_from_addr", formsemestre_id)
if copy_addr:
msg["Bcc"] = copy_addr.strip()
# Guarantees the message ends in a newline
msg.epilogue = ""
# Text
txt = MIMEText(hea, "plain", scu.SCO_ENCODING)
# log('hea:\n' + hea)
msg.attach(txt)
bcc = copy_addr.strip()
else:
bcc = ""
msg = Message(subject, sender=sender, recipients=recipients, bcc=bcc)
msg.body = hea
# Attach pdf
att = MIMEBase("application", "pdf")
att.add_header("Content-Disposition", "attachment", filename=filename)
att.set_payload(pdfdata)
email.encoders.encode_base64(att)
msg.attach(att)
log("mail bulletin a %s" % msg["To"])
sco_emails.sendEmail(msg)
msg.attach(filename, scu.PDF_MIMETYPE, pdfdata)
log("mail bulletin a %s" % recipient_addr)
email.send_message(msg)
def _formsemestre_bulletinetud_header_html(

View File

@ -1,146 +0,0 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Gestion scolarite IUT
#
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Emmanuel Viennet emmanuel.viennet@viennet.net
#
##############################################################################
"""Gestion des emails
"""
from flask import request
# XXX WIP: à ré-écrire pour ScoDoc 8 (étaient des méthodes de ZScoDoc)
import os
import time
# from email.MIMEMultipart import ( # pylint: disable=no-name-in-module,import-error
# MIMEMultipart,
# )
# from email.MIMEText import MIMEText # pylint: disable=no-name-in-module,import-error
# from email.MIMEBase import MIMEBase # pylint: disable=no-name-in-module,import-error
# from email.Header import Header # pylint: disable=no-name-in-module,import-error
# from email import Encoders # pylint: disable=no-name-in-module,import-error
import app.scodoc.sco_utils as scu
from app.scodoc.notes_log import log
import sco_version
def sendEmail(msg): # TODO A REECRIRE ScoDoc8
"""Send an email to the address using the mailhost, if there is one."""
raise NotImplementedError()
try:
mail_host = xxx.MailHost
except:
log("warning: sendEmail: no MailHost found !")
return
# a failed notification shouldn't cause a Zope error on a site.
try:
mail_host.send(msg.as_string())
log("sendEmail: ok")
except Exception as e:
log("sendEmail: exception while sending message")
log(e)
pass
def sendEmailFromException(msg):
# Send email by hand, as it seems to be not possible to use Zope Mail Host
# from an exception handler (see https://bugs.launchpad.net/zope2/+bug/246748)
log("sendEmailFromException")
try:
p = os.popen("sendmail -t", "w") # old brute force method
p.write(msg.as_string())
exitcode = p.close()
if exitcode:
log("sendmail exit code: %s" % exitcode)
except:
log("an exception occurred sending mail")
def send_debug_alert(txt, REQUEST=None):
"""Send an alert email (bug report) to ScoDoc developpers"""
if not scu.SCO_EXC_MAIL:
log("send_debug_alert: email disabled")
return
if REQUEST:
txt = _report_request(REQUEST) + txt
URL = REQUEST.URL
else:
URL = "send_debug_alert"
msg = MIMEMultipart()
subj = Header("[scodoc] exc %s" % URL, scu.SCO_ENCODING)
msg["Subject"] = subj
recipients = [scu.SCO_EXC_MAIL]
msg["To"] = " ,".join(recipients)
msg["From"] = "scodoc-alert"
msg.epilogue = ""
msg.attach(MIMEText(txt, "plain", scu.SCO_ENCODING))
sendEmailFromException(msg)
log("Sent mail alert:\n" + txt)
def _report_request(REQUEST, fmt="txt"):
"""string describing current request for bug reports"""
QUERY_STRING = REQUEST.QUERY_STRING
if QUERY_STRING:
QUERY_STRING = "?" + QUERY_STRING
if fmt == "txt":
REFERER = request.referrer
HTTP_USER_AGENT = request.user_agent
else:
REFERER = "na"
HTTP_USER_AGENT = "na"
params = dict(
AUTHENTICATED_USER=REQUEST.AUTHENTICATED_USER,
dt=time.asctime(),
URL=REQUEST.URL,
QUERY_STRING=QUERY_STRING,
METHOD=request.method,
REFERER=REFERER,
HTTP_USER_AGENT=HTTP_USER_AGENT,
form=REQUEST.form,
HTTP_X_FORWARDED_FOR="?",
SCOVERSION=sco_version.SCOVERSION,
)
txt = (
"""
Version: %(SCOVERSION)s
User: %(AUTHENTICATED_USER)s
Date: %(dt)s
URL: %(URL)s%(QUERY_STRING)s
Method: %(METHOD)s
REFERER: %(REFERER)s
Form: %(form)s
Origin: %(HTTP_X_FORWARDED_FOR)s
Agent: %(HTTP_USER_AGENT)s
"""
% params
)
if fmt == "html":
txt = txt.replace("\n", "<br/>")
return txt

View File

@ -40,7 +40,6 @@ from email.header import Header
from email.mime.base import MIMEBase
from operator import itemgetter
from app.scodoc import sco_emails
import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import SCO_ENCODING
import app.scodoc.notesdb as ndb
@ -51,6 +50,8 @@ from app.scodoc.TrivialFormulator import TrivialFormulator
from app.scodoc import safehtml
from app.scodoc import sco_preferences
from app.scodoc.scolog import logdb
from flask_mail import Message
from app import mail
MONTH_NAMES_ABBREV = [
"Jan ",
@ -454,14 +455,9 @@ def notify_etud_change(email_addr, etud, before, after, subject):
log("notify_etud_change: sending notification to %s" % email_addr)
log("notify_etud_change: subject: %s" % subject)
log(txt)
msg = MIMEMultipart()
subj = Header("[ScoDoc] " + subject, SCO_ENCODING)
msg["Subject"] = subj
msg["From"] = sco_preferences.get_preference("email_from_addr")
msg["To"] = email_addr
mime_txt = MIMEText(txt, "plain", SCO_ENCODING)
msg.attach(mime_txt)
sco_emails.sendEmail(msg)
mail.send_email(
subject, sco_preferences.get_preference("email_from_addr"), [email_addr], txt
)
return txt

View File

@ -35,7 +35,6 @@ from email.mime.text import MIMEText
from email.header import Header
from app import db, Departement
from app.scodoc import sco_emails
import app.scodoc.sco_utils as scu
from app.scodoc.notes_log import log
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError, ScoException
@ -47,6 +46,9 @@ from flask import g
from flask_login import current_user
from app.auth.models import User, UserRole
from app import email
TITLES = ("user_name", "nom", "prenom", "email", "roles", "dept")
COMMENTS = (
"""user_name:
@ -335,12 +337,8 @@ Pour plus d'informations sur ce logiciel, voir %s
)
msg = MIMEMultipart()
if reset:
msg["Subject"] = Header("Mot de passe ScoDoc", scu.SCO_ENCODING)
subject = "Mot de passe ScoDoc"
else:
msg["Subject"] = Header("Votre accès ScoDoc", scu.SCO_ENCODING)
msg["From"] = sco_preferences.get_preference("email_from_addr")
msg["To"] = u["email"]
msg.epilogue = ""
txt = MIMEText(txt, "plain", scu.SCO_ENCODING)
msg.attach(txt)
# sco_emails.sendEmail(msg) # TODO ScoDoc9 pending function
subject = "Votre accès ScoDoc"
sender = sco_preferences.get_preference("email_from_addr")
email.send_email(subject, sender, [u["email"]], txt)

View File

@ -27,13 +27,10 @@
"""Gestion des "nouvelles"
"""
import datetime
import re
import time
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
from operator import itemgetter
from flask import g
@ -42,13 +39,12 @@ from flask_login import current_user
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
from app.scodoc.notes_log import log
from app.scodoc import safehtml
from app.scodoc import sco_emails
from app.scodoc.sco_utils import SCO_ENCODING, SCO_ANNONCES_WEBSITE
from app.scodoc import sco_formsemestre
from app.scodoc import sco_moduleimpl
from app.scodoc import sco_preferences
from app.scodoc import sco_users
from app import email
_scolar_news_editor = ndb.EditableTable(
"scolar_news",
@ -225,7 +221,7 @@ def scolar_news_summary_html(n=5):
abonner à la liste de diffusion</a>.
</div>
"""
% SCO_ANNONCES_WEBSITE
% scu.SCO_ANNONCES_WEBSITE
)
H.append("</div>")
@ -270,15 +266,7 @@ def _send_news_by_mail(n):
# (si on veut des messages non html)
txt = re.sub(r'<a.*?href\s*=\s*"(.*?)".*?>(.*?)</a>', r"\2: \1", txt)
msg = MIMEMultipart()
msg["Subject"] = Header("[ScoDoc] " + NEWS_MAP.get(n["type"], "?"), SCO_ENCODING)
msg["From"] = prefs["email_from_addr"]
txt = MIMEText(txt, "plain", SCO_ENCODING)
msg.attach(txt)
subject = "[ScoDoc] " + NEWS_MAP.get(n["type"], "?")
sender = prefs["email_from_addr"]
for email_addr in destinations:
if email_addr:
del msg["To"]
msg["To"] = email_addr
# log('xxx mail: %s' % msg)
sco_emails.sendEmail(msg)
email.send_email(subject, sender, destinations, txt)

View File

@ -561,7 +561,7 @@ def sendResult(REQUEST, data, name=None, format=None, force_outer_xml_tag=True):
def get_scodoc_version():
"return a string identifying ScoDoc version"
return os.popen("cd %s; ./get_scodoc_version.sh -s" % SCO_TOOLS_DIR).read().strip()
return sco_version.SCOVERSION
def check_scodoc7_password(scodoc7_hash, password):

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,7 +1,7 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
SCOVERSION = "9.0.2"
SCOVERSION = "9.0.3"
SCONAME = "ScoDoc"

View File

@ -2,6 +2,8 @@
# Préparation d'une release ScoDoc:
# Utilise jq sur Debian 11 VM
apt-get install jq
# Le répertoire de ce script: .../scodoc/tools
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
@ -15,7 +17,7 @@ SCODOC_RELEASE=$(grep SCOVERSION "$SCRIPT_DIR/../sco_version.py" | awk '{ print
# Dernière release
GITEA_RELEASE_URL="https://scodoc.org/git/api/v1/repos/viennet/ScoDoc/releases?pre-release=true"
LAST_RELEASE_TAG=$(curl "$GITEA_RELEASE_URL" | jq ".[].tag_name" | sort | tail -1 | awk '{ print substr($1, 1, length($1)) }')
LAST_RELEASE_TAG=$(curl "$GITEA_RELEASE_URL" | jq ".[].tag_name" | sort | tail -1 | awk '{ print substr($1, 2, length($1)-2) }')
echo
echo "Version détectée dans le source: $SCODOC_RELEASE"
@ -75,7 +77,7 @@ SCODOC_DIR="$optdir"/scodoc
[ -d "$SCODOC_DIR" ] || die "die Erreur: $SCODOC_DIR inexistant"
# Inject version (eg 9.0.2) in debian:control
sed -i.bak "s/Version: x.y.z/Version: $PACKAGE_VERSION/g" /tmp/control
sed -i.bak "s/Version: x.y.z/Version: $PACKAGE_VERSION/g" "$SCODOC_DIR/tools/debian/control"
# and double check
v=$(grep Version "$SCODOC_DIR/tools/debian/control" | awk '{ print $2 }')
if [ "$v" != "$PACKAGE_VERSION" ]
@ -106,7 +108,20 @@ chmod 755 "$slash"/DEBIAN/*inst || die "can't chmod debian scripts"
# -------- THE END
echo "Terminé."
echo "Après vérification, construire le paquet .deb avec:"
echo " dpkg-deb --build --root-owner-group $DEST_DIR"
echo -n "Voulez-vous poursuivre et construire le .deb ? (y/n) [y] "
read -r ans
if [ "$(norm_ans "$ans")" != 'N' ]
then
echo "ok"
else
echo "arrêt."
exit 0
fi
dpkg-deb --build --root-owner-group $DEST_DIR
DEB_FILE="$DEST_DIR".deb
echo "paquet construit: $DEB_FILE"

View File

@ -111,8 +111,8 @@ change_scodoc_file_ownership
# ------------ CREATION BASE DE DONNEES
echo
echo "Voulez-vous créer la base SQL SCODOC ?"
echo "répondre O sauf si vous avez déjà une base existante"
echo "que vous souhaitez conserver."
echo "répondre oui sauf si vous avez déjà une base existante"
echo "que vous souhaitez conserver (mais pour les migrations, répondre oui)."
echo -n 'Créer la base de données SCODOC ? (y/n) [y] '
read -r ans
if [ "$(norm_ans "$ans")" != 'N' ]

View File

@ -1,5 +1,7 @@
#!/bin/bash
# Script non utilisé
# Get version information
# Use VERSION.py, VERSION, last commit, diff, and last upstream commit date
@ -10,11 +12,10 @@ source "$SCRIPT_DIR/config.sh"
source "$SCRIPT_DIR/utils.sh"
# Source code version:
x=$(grep SCOVERSION "$SCODOC_DIR/app/scodoc/VERSION.py") || terminate "can't access VERSION.py" 1
x=${x#*\"}
src_version=${x%\"*}
src_version=$(grep SCOVERSION "$SCRIPT_DIR/../sco_version.py" | awk '{ print substr($3, 2, length($3)-2) }')
release_version=$(cat "$SCODOC_DIR/VERSION")
release_version=""
git status >& /dev/null
if [ $? = 0 ]