diff --git a/app/email.py b/app/email.py
index f2d8164d8c..226429df24 100644
--- a/app/email.py
+++ b/app/email.py
@@ -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()
diff --git a/app/scodoc/notes_log.py b/app/scodoc/notes_log.py
index 0781373405..6f91ec1220 100644
--- a/app/scodoc/notes_log.py
+++ b/app/scodoc/notes_log.py
@@ -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
diff --git a/app/scodoc/sco_abs_notification.py b/app/scodoc/sco_abs_notification.py
index c397c73f0a..5ac4315ef8 100644
--- a/app/scodoc/sco_abs_notification.py
+++ b/app/scodoc/sco_abs_notification.py
@@ -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
diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py
index 9cbff15581..c1ce03ef62 100644
--- a/app/scodoc/sco_bulletins.py
+++ b/app/scodoc/sco_bulletins.py
@@ -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(
diff --git a/app/scodoc/sco_emails.py b/app/scodoc/sco_emails.py
deleted file mode 100644
index a50db77f9d..0000000000
--- a/app/scodoc/sco_emails.py
+++ /dev/null
@@ -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", "
")
- return txt
\ No newline at end of file
diff --git a/app/scodoc/sco_etud.py b/app/scodoc/sco_etud.py
index 0d8682a5e3..7915b0af6d 100644
--- a/app/scodoc/sco_etud.py
+++ b/app/scodoc/sco_etud.py
@@ -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
diff --git a/app/scodoc/sco_import_users.py b/app/scodoc/sco_import_users.py
index 81ba3a4eac..3a46257c3f 100644
--- a/app/scodoc/sco_import_users.py
+++ b/app/scodoc/sco_import_users.py
@@ -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)
diff --git a/app/scodoc/sco_news.py b/app/scodoc/sco_news.py
index a564bfd8c8..22d50fae3d 100644
--- a/app/scodoc/sco_news.py
+++ b/app/scodoc/sco_news.py
@@ -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.
"""
- % SCO_ANNONCES_WEBSITE
+ % scu.SCO_ANNONCES_WEBSITE
)
H.append("")
@@ -270,15 +266,7 @@ def _send_news_by_mail(n):
# (si on veut des messages non html)
txt = re.sub(r'(.*?)', 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)
diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py
index 72aba2be28..1a54104488 100644
--- a/app/scodoc/sco_utils.py
+++ b/app/scodoc/sco_utils.py
@@ -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):
diff --git a/app/static/icons/scologo_img.png b/app/static/icons/scologo_img.png
index 2c55de0f05..830e126684 100644
Binary files a/app/static/icons/scologo_img.png and b/app/static/icons/scologo_img.png differ
diff --git a/sco_version.py b/sco_version.py
index b07e5945ac..c696a09d48 100644
--- a/sco_version.py
+++ b/sco_version.py
@@ -1,7 +1,7 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
-SCOVERSION = "9.0.2"
+SCOVERSION = "9.0.3"
SCONAME = "ScoDoc"
diff --git a/tools/build_release.sh b/tools/build_release.sh
index 13b0564a3a..35c2e3793e 100644
--- a/tools/build_release.sh
+++ b/tools/build_release.sh
@@ -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"
+
diff --git a/tools/configure-scodoc9.sh b/tools/configure-scodoc9.sh
index 0f2f694f4b..2c60d1563f 100755
--- a/tools/configure-scodoc9.sh
+++ b/tools/configure-scodoc9.sh
@@ -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' ]
diff --git a/tools/get_scodoc_version.sh b/tools/get_scodoc_version.sh
index 767eec454c..9c06bfcad9 100755
--- a/tools/get_scodoc_version.sh
+++ b/tools/get_scodoc_version.sh
@@ -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 ]