ScoDoc-Lille/app/auth/email.py
2021-10-19 17:20:58 +02:00

83 lines
3.9 KiB
Python

# -*- coding: UTF-8 -*
import re
from flask import render_template, current_app
from app import ScoValueError
from app.email import send_email
# Fonctions de manipulation des adresses mail
# Objectif: traiter puis élminier les adresses mail doublonnées
# pour pouvoir , à terme, les utilisaer commen identifiant pour inclusion d'un LDAP comme outil d'identification
# principe: les adresses mails doublonnées superflues(note) sont transformées/numérotées sous une forme non autorisée
# * les comptes ainsi modifiés seront désactivés et déclencheront une demande d'action auprès de l'utilisateur et/ou
# administrateur
# * une notice est ajouté à la page des utlisateurs pour indiquer à l administrateur l'existence (et
# la liste) de doublons. Un bouton qui traite ces doublons est ajouté à cette liste.
# note: une des adresses doublonnée sera conservée sous sa forme initiale (heuristique: on prend l'adresse du compte
# actif utilisé le plus récement)
# transformation proposée: * un marqueur ( '.' initial normalement interdit dans les adresses mail est ajouté un
# numéro d'ordre (+xxx) est ajouté à la partie locale de l'adresse
# ainsi les trois adresses identiques u@domaine.org seront renommés en:
# u@domaine.org, .u+2@domaine.org et .u@domaine+3.org (la numérotation commence à 2)
# cette transformation peut être redéfinie en remplaçant les fonctions check_email, transform_email et initial_email
initial_re = re.compile(r"([^@]*)@(.*)")
processes_re = re.compile(r"\.(.*)\+([0-9]*)@(.*)")
def is_disabled_email_addr(email: str) -> bool:
""" Indique si un email a été transformé
:param email: l'adresse mail testée
:return: True si l'adresse a été transformée
"""
return email[0] == '.'
def disable_email_addr(email: str, rang: int) -> str:
"""transformation de l adresse. ajoute un '.' initial et ajoute le rang
l'email ne doit pas avoir été déjà transformée.
hypothèse: l'adresse mail ne comporte qu'un seul @ (en vrai un @ peut être utilisé autrement que comme séparateur
si quoté comme dans '"abc@def"@dom.org').
:param email: l'adresse mail à modifier
:param rang: le rang à ajouter
:return: l'adresse mail transformée.
"""
if is_disabled_email_addr(email):
raise ScoValueError("Tentative de traitement d'une adresse déjà traitée")
decomposition = initial_re.match(email)
if decomposition is None: # adresse mail non conforme
raise ScoValueError("tentative de traitement de l\'adresse email non reconnue '%s' % email")
return ".%s+%s@%s" % (decomposition.group(1), rang, decomposition.group(2))
def initial_email_address(email) -> (str, int):
"""récupération de la valeur initiale de l'adresse (transformation reciproque de transform_email_adr.
enlève le '.' initial et supprime la terminaison '+xxx' de la partie locale.
Attention: il peut y avoir un autre + dans l'adresse.
:param email: l'adresse après transformation
:return: l'adresse email initiale et le rang
"""
if not is_disabled_email_addr(email):
return email, 1 # l'adresse n'a pas été transformée. on la retourne à l'identique (avec l'indice 1)
decomposition = processes_re.match(email)
if decomposition is None: # l'adresse a été transformée mais n'est pas reconnue
raise ScoValueError("Adresse mail transformée non reconnue'%s'" % email)
rang = int(decomposition.group(2))
return "%s@%s" % (decomposition.group(1), decomposition.group(3)), rang
def send_password_reset_email(user):
token = user.get_reset_password_token()
send_email(
"[ScoDoc] Réinitialisation de votre mot de passe",
sender=current_app.config["ADMINS"][0],
recipients=[user.email],
text_body=render_template("email/reset_password.txt", user=user, token=token),
html_body=render_template("email/reset_password.html", user=user, token=token),
)