Elyos_FI_Back_Office/E_Sign_Document.py

1138 lines
45 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""
Ce document permet de gerer la signature electronique des documents.
Process (exemple : convention) :
A la creation d'un document, si il est soumis à signature electronique
alors il est stocké dans la collection "e_document_signe" avec les champs :
- related_collection
- related_collection_id
- document_data (le contenu du document)
- statut :
0 - a signer
1 - signé
/!\ IMPORTANT :
- A la creation d'un document, on lui ajoute une cle secrete avec 5 chiffre
- On ajoute une adresse email qui doit signer le mail
Cette clée est utilisé pour :
1 - Recuperer le document
2 - Signer le document.
Dans le lien de signature on doit fournir :
- _id du document
Pour afficher le doc, l'utilisateur doit fournir :
- l'email de la personne
- secret_key : la clé de X caractère
/!\ : Nous effectuons une signature electronique securisée de niveau 2 :
https://www.francenum.gouv.fr/guides-et-conseils/pilotage-de-lentreprise/dematerialisation-des-documents/la-signature#:~:text=L'objectif%20majeur%20de%20la,rapporter%20la%20preuve%20du%20consentement.
En pratique, comment fonctionne la signature électronique avancée (niveau 2) ?
Pour signer numériquement un contrat de location ou même un achat immobilier et que cela ait une valeur légale, il faut passer par un tiers de confiance. Ces entreprises habilitées à effectuer des opérations de sécurité juridique d'authentification, de transmission et de stockage sont nombreuses. Si elles proposent chacune leur solution, plus ou moins élaborées ou faciles dutilisation, leur fonctionnement est relativement similaire : la procédure ressemble un peu à un achat en ligne, avec une authentification par code secret via SMS. Le processus est le suivant.
Vous vous connectez sur le site du tiers de confiance en ligne à laide de vos identifiants, voire de votre clef électronique dans le cas dune authentification qualifiée (niveau 3)
Vous ajoutez les documents (word, PDF, etc…) que vous souhaitez faire signer.
Vous invitez des signataires après avoir renseigné leurs coordonnées (en particulier leur numéro de téléphone portable).
Chaque signataire reçoit par mail une notification pour signer ainsi quun code par SMS permettant de sécuriser la signature.
"""
import base64
import bson
import pymongo
from pymongo import MongoClient
import json
from bson import ObjectId
import re
from datetime import datetime, time
import prj_common as mycommon
import secrets
import inspect
import sys, os
import csv
import pandas as pd
from pymongo import ReturnDocument
import GlobalVariable as MYSY_GV
from math import isnan
import GlobalVariable as MYSY_GV
import ela_index_bdd_classes as eibdd
import email_mgt as email
import jinja2
from flask import send_file
from xhtml2pdf import pisa
from email.message import EmailMessage
from email.mime.text import MIMEText
from email import encoders
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import hashlib
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
import segno
class SignedMessage:
message: bytes = None
digitalsignature: bytes = None
def __init__(self, message: bytes):
self.message = message
def _hash_message(self):
# Generate the hash of this message
return calculateHash(self.message)
def encrypt(self, key):
hash = self._hash_message()
# Instantiating PKCS1_OAEP object with the public key for encryption
cipher = PKCS1_OAEP.new(key=key)
# Encrypting the message with the PKCS1_OAEP object
self.digitalsignature = cipher.encrypt(hash)
"""
Add document du signe
"""
def Create_E_Document(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'file_name', 'related_collection', 'related_collection_id',
'email_destinataire', 'source_document']
incom_keys = diction.keys()
for val in incom_keys:
if val not in field_list and val.startswith('my_') is False:
mycommon.myprint(str(
inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas autorisé")
return False, " Les informations fournies sont incorrectes"
"""
Verification des champs obligatoires
"""
field_list_obligatoire = ['token', 'file_name', 'related_collection', 'related_collection_id',
'email_destinataire', 'source_document']
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
return False, " Les informations fournies sont incorrectes"
"""
Verification de l'identité et autorisation de l'entité qui
appelle cette API
"""
token = ""
if ("token" in diction.keys()):
if diction['token']:
token = diction['token']
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
if (mycommon.isEmailValide(str(diction['email_destinataire'])) is False):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'adresse email " + str(diction['email_destinataire']) + " n'est pas valide")
return False, " L'adresse email " + str(diction['email_destinataire']) + " n'est pas valide "
file_name = diction['file_name']
basename = os.path.basename(file_name)
basename2 = basename.split(".")
if (len(basename2) != 2):
mycommon.myprint(str(inspect.stack()[0][3]) + " - : Le nom du fichier est incorrect")
return False, "Le nom du fichier est incorrect"
if (str(basename2[1]).lower() not in MYSY_GV.ALLOWED_EXTENSIONS):
mycommon.myprint(str(inspect.stack()[0][3]) + " - : le format de fichier '"+str(basename2[1])+"' n'est pas autorisé. Les extentions autorisées sont : "+str(MYSY_GV.ALLOWED_EXTENSIONS))
return False, "le format de fichier '"+str(basename2[1])+"' n'est pas autorisé. Les extentions autorisées sont : "+str(MYSY_GV.ALLOWED_EXTENSIONS)
encoded_pdf_to_string = ""
with open(file_name, "rb") as f:
encoded_pdf_to_string = base64.b64encode(f.read())
secret_key = secrets.token_urlsafe(5)
new_diction = {}
new_diction['document_data'] = encoded_pdf_to_string
new_diction['related_collection'] = "aaaa"
new_diction['related_collection_id'] = 'bbbb'
new_diction['partner_owner_recid'] = my_partner['recid']
new_diction['statut'] = '0'
new_diction['valide'] = '1'
new_diction['locked'] = "0"
new_diction['secret_key_open'] = str(secret_key)
new_diction['email_destinataire'] = str(diction['email_destinataire'])
new_diction['source_document'] = str(diction['source_document'])
new_diction['date_update'] = str(datetime.now())
new_diction['update_by'] = str(my_partner['_id'])
val = MYSY_GV.dbname['e_document_signe'].insert_one(new_diction)
if (val is None):
mycommon.myprint(
" Impossible de créer le E-Document (2) ")
return False, " Impossible de créer le E-Document (2) "
return True, str(val.inserted_id)
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de créer le E-Document "
"""
Recuperation document à signer, sans connexion token
"""
def Get_Given_E_Document_Not_Signed_No_Token(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'e_doc_id', 'secret_key_open', 'user_email' ]
incom_keys = diction.keys()
for val in incom_keys:
if val not in field_list and val.startswith('my_') is False:
mycommon.myprint(str(
inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas autorisé")
return False, " Les informations fournies sont incorrectes"
"""
Verification des champs obligatoires
"""
field_list_obligatoire = ['token', 'e_doc_id', 'secret_key_open', 'user_email' ]
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
return False, " Les informations fournies sont incorrectes"
"""
Verification de l'identité et autorisation de l'entité qui
appelle cette API
"""
token = ""
if ("token" in diction.keys()):
if diction['token']:
token = diction['token']
"""
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
"""
if( mycommon.isEmailValide(str(diction['user_email'])) is False ):
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + str(diction['user_email']) + "' n'est pas un email valide ")
return False, " Les informations fournies sont incorrectes"
RetObject = []
val_tmp = 0
local_partner_owner_recid = ""
qry = { 'valide': '1', 'locked': '0',
'_id': ObjectId(str(diction['e_doc_id'])),
'secret_key_open':str(diction['secret_key_open']),
'statut':'0'}
for New_retVal in MYSY_GV.dbname['e_document_signe'].find(qry).sort([("_id", pymongo.DESCENDING), ]):
if( "email_destinataire" in New_retVal.keys() and New_retVal['email_destinataire']):
list_email = str(New_retVal['email_destinataire']).replace(",",";")
tab_list_email = list_email.split(";")
if( str(diction['user_email']) in tab_list_email ) :
user = New_retVal
user['id'] = str(val_tmp)
if( "signature_digitale" in New_retVal.keys() ):
del New_retVal['signature_digitale']
if ("document_data_signed" in New_retVal.keys()):
del New_retVal['document_data_signed']
val_tmp = val_tmp + 1
decode_data = user['document_data'].decode()
user['document_data'] = decode_data
RetObject.append(mycommon.JSONEncoder().encode(user))
local_partner_owner_recid = str(user['partner_owner_recid'])
if(len(RetObject) <= 0 ):
mycommon.myprint(str(
inspect.stack()[0][3]) + " Aucun E-document trouvé ")
return False, " Aucun E-document trouvé "
"""
Un document a été trouvé, a présent il faut
1 - Créer la clé de signature
2 - Envoyer par email la clé de signature
"""
secret_key_for_sign = secrets.token_urlsafe(5)
update_data = {}
update_data['secret_key_signature'] = secret_key_for_sign
update_data['date_update'] = str(datetime.now())
update_data['update_by'] = str(diction['user_email'])
ret_val2 = MYSY_GV.dbname['e_document_signe'].find_one_and_update(qry,
{"$set": update_data},
return_document=ReturnDocument.AFTER
)
if (ret_val2 is None or "_id" not in ret_val2.keys()):
mycommon.myprint(str(
inspect.stack()[0][3]) + " Impossible d'initialiser le processus de signature ")
return False, " Impossible d'initialiser le processus de signature "
"""
On envoie la clé de validation de la signature par email
"""
"""
Recuperation des parametre SMTP du partner si le client a decidé d'utiliser son propre smpt
"""
partner_own_smtp_value = "0"
partner_own_smtp = MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': local_partner_owner_recid,
'config_name': 'partner_smtp',
'valide': '1',
'locked': '0'})
if (partner_own_smtp and "config_value" in partner_own_smtp.keys()):
partner_own_smtp_value = partner_own_smtp['config_value']
if (str(partner_own_smtp_value) == "1"):
partner_SMTP_COUNT_password = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': local_partner_owner_recid,
'config_name': 'smtp_user_pwd',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_smtpsrv = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': local_partner_owner_recid,
'config_name': 'smtp_server',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_user = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': local_partner_owner_recid,
'config_name': 'smtp_user',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_From_User = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': local_partner_owner_recid,
'config_name': 'smtp_count_from_name',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_port = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': local_partner_owner_recid,
'config_name': 'smtp_count_port',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
if (str(partner_own_smtp_value) == "1"):
smtpserver = smtplib.SMTP(partner_SMTP_COUNT_smtpsrv, partner_SMTP_COUNT_port)
else:
smtpserver = smtplib.SMTP(MYSY_GV.O365_SMTP_COUNT_smtpsrv, MYSY_GV.O365_SMTP_COUNT_port)
# Creation de l'email à enoyer
msg = MIMEMultipart("alternative")
html = """\
<html>
<body>
<br />
<div style="text-align: center;">
<nav style="text-align: center; font-weight: bold;">LOGO</nav>
<br />
<div style="text-align: center;">
<nav style="text-align: center; font-weight: bold;">SIGNATURE ELECTRONIQUE</nav>
<br />
</div>
</div>
<div>
Bonjour
</div>
<div >
Vous venez de lancer une procedure de signature digitale. Voici le code de validation : <br/>
""" + secret_key_for_sign + """<br>
</p>
Cordialement.
</div>
</body>
</html>
"""
# contenu_doc_Template = jinja2.Template(str(courrier_template_data['contenu_doc']))
# sourceHtml = contenu_doc_Template.render(params=body["params"])
html_mime = MIMEText(html, 'html')
if (str(partner_own_smtp_value) == "1"):
msg.attach(html_mime)
msg['From'] = partner_SMTP_COUNT_From_User
msg['Bcc'] = 'contact@mysy-training.com'
msg['Subject'] = " Signature electronique : Clé de signature"
# msg['to'] = "billardman01@hotmail.com"
msg['to'] = str(diction['user_email'])
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(partner_SMTP_COUNT_user, partner_SMTP_COUNT_password)
else:
msg.attach(html_mime)
msg['From'] = MYSY_GV.O365_SMTP_COUNT_From_User
msg['Bcc'] = 'contact@mysy-training.com'
msg['Subject'] = " Signature electronique : Clé de signature"
# msg['to'] = "billardman01@hotmail.com"
msg['to'] = str(diction['user_email'])
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(MYSY_GV.O365_SMTP_COUNT_user, MYSY_GV.O365_SMTP_COUNT_password)
val = smtpserver.send_message(msg)
smtpserver.close()
print(" Email envoyé " + str(val))
return True, RetObject
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de récupérer le document électronique "
def calculateHash(message):
m = hashlib.sha256()
m.update(message)
return m.digest()
def checkIntegrity(calculated_hash, decrypted_hash):
if calculated_hash == decrypted_hash:
return True
else:
return False
"""
Signature du document
"""
def Create_E_Signature_For_E_Document(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'e_doc_id', 'secret_key_signature', 'email_destinataire', 'user_ip' ]
incom_keys = diction.keys()
for val in incom_keys:
if val not in field_list and val.startswith('my_') is False:
mycommon.myprint(str(
inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas autorisé")
return False, " Les informations fournies sont incorrectes"
"""
Verification des champs obligatoires
"""
field_list_obligatoire = ['token', 'e_doc_id', 'secret_key_signature', 'email_destinataire' ]
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
return False, " Les informations fournies sont incorrectes"
"""
Verification de l'identité et autorisation de l'entité qui
appelle cette API
"""
token = ""
if ("token" in diction.keys()):
if diction['token']:
token = diction['token']
"""
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
"""
if (mycommon.isEmailValide(str(diction['email_destinataire'])) is False):
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + str(
diction['user_email']) + "' n'est pas un email valide ")
return False, " Les informations fournies sont incorrectes"
RetObject = []
val_tmp = 0
# Verifier la validité du document
qry = { 'valide': '1', 'locked': '0',
'_id': ObjectId(str(diction['e_doc_id'])),
'secret_key_signature':str(diction['secret_key_signature']),
}
is_valide_e_document = MYSY_GV.dbname['e_document_signe'].count_documents(qry)
if( is_valide_e_document <= 0 ):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'idientifiant du E-Document est invalide ")
return False, " L'idientifiant du E-Document est invalide "
e_document_data = MYSY_GV.dbname['e_document_signe'].find_one(qry)
local_signature_digitale = ""
if ("email_destinataire" in e_document_data.keys() and e_document_data['email_destinataire']):
list_email = str(e_document_data['email_destinataire']).replace(",", ";")
tab_list_email = list_email.split(";")
if (str(diction['email_destinataire']) in tab_list_email):
my_str = str(e_document_data['document_data'])
document_data_as_bytes = str.encode(my_str)
print(type(document_data_as_bytes)) # ensure it is byte representation
message = document_data_as_bytes
msg = SignedMessage(message=message)
# Generating private key (RsaKey object) of key length of 1024 bits
private_key = RSA.generate(1024)
# Generating the public key (RsaKey object) from the private key
public_key = private_key.publickey()
# Calculating the digital signature
msg.encrypt(key=public_key)
print(f"Digital Signature: {msg.digitalsignature}")
# The message is still clear
#print(f"Message: {msg.message}")
# Instantiating PKCS1_OAEP object with the private key for decryption
decrypt = PKCS1_OAEP.new(key=private_key)
# Decrypting the message with the PKCS1_OAEP object
decrypted_message = decrypt.decrypt(msg.digitalsignature)
print(f"decrypted_message: {decrypted_message}")
# We recalculate the hash of the message using the same hash function
calcHash = calculateHash(msg.message)
#print(f"decrypted_message: {msg.message}")
is_signed_valide = checkIntegrity(calcHash, decrypted_message)
if( is_signed_valide is False):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'intégrité du document signé n'est pas valide ")
return False, " Impossible de signer le document(3) "
local_signature_digitale = msg.digitalsignature
"""
Apresent que le message est signé, on va mettre à jour le doc
"""
encoded_signed_pdf_to_string = base64.b64encode(decrypted_message)
new_data = {}
new_data['signature_digitale'] = msg.digitalsignature
new_data['signed_date'] = str(datetime.now())
new_data['signed_email'] = str(diction['email_destinataire'])
new_data['signed_ip_adress'] = str(diction['user_ip'])
new_data['statut'] = "1"
qry_key = {'valide': '1', 'locked': '0',
'_id': ObjectId(str(diction['e_doc_id'])),
'secret_key_signature': str(diction['secret_key_signature']),
'email_destinataire': str(diction['email_destinataire'])}
result = MYSY_GV.dbname['e_document_signe'].find_one_and_update(
qry_key,
{"$set": new_data},
upsert=False,
return_document=ReturnDocument.AFTER
)
if ("_id" not in result.keys()):
mycommon.myprint(
" Impossible de signer le document (2) ")
return False, " Impossible de signer le document (2) "
else:
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'idientifiant du E-Document est invalide ")
return False, " L'idientifiant du E-Document est invalide "
"""
Vu que tout est ok, on va créer le fichier pdf definif.
on va utiliser le contenu du champ "source_document" au quel on a ajouté un tag de la signature
"""
qry_key = {'valide': '1', 'locked': '0',
'_id': ObjectId(str(diction['e_doc_id'])),
'secret_key_signature': str(diction['secret_key_signature']),
'email_destinataire': str(diction['email_destinataire'])}
e_document_date_2 = MYSY_GV.dbname['e_document_signe'].find_one(qry_key)
local_partner_owner_recid = e_document_date_2['partner_owner_recid']
local_signature_digitale = decrypt.decrypt(e_document_date_2['signature_digitale'])
local_url_securite = MYSY_GV.CLIENT_URL_BASE+"E_Document/"+str(e_document_date_2['_id'])+"/"+str(e_document_date_2['partner_owner_recid'])+"/"+str(e_document_date_2['secret_key_signature'])
ts = datetime.now().timestamp()
ts = str(ts).replace(".", "").replace(",", "")[-3:]
qr_code_img_file = str(MYSY_GV.TEMPORARY_DIRECTORY_V2) + "qr_code_" + str(ts) + ".png"
qrcode = segno.make_qr(str(local_url_securite))
qrcode.save(
qr_code_img_file,
scale=5,
dark="darkblue",
)
qr_code_converted_string = ""
with open(qr_code_img_file, "rb") as image2string:
qr_code_converted_string = base64.b64encode(image2string.read()).decode()
print(" ### qr_code_converted_string = ", qr_code_converted_string)
img_qr_code = "data:image/png;base64," + str(qr_code_converted_string)
print(" ### img_qr_code = ", img_qr_code)
body = {
"params": {"mysy_signature_digitale":str(local_signature_digitale),
'mysy_url_securite':local_url_securite,
'mysy_qrcode_securite': "data:image/png;base64," + qr_code_converted_string,
}
}
contenu_doc_Template = jinja2.Template(str(e_document_data['source_document']))
sourceHtml = contenu_doc_Template.render(params=body["params"])
ts = datetime.now().timestamp()
ts = str(ts).replace(".", "").replace(",", "")[-5:]
orig_file_name = "Convention_Signe_" + str(ts) + ".pdf"
outputFilename = str(MYSY_GV.TEMPORARY_DIRECTORY) + "/" + str(orig_file_name)
# open output file for writing (truncated binary)
resultFile = open(outputFilename, "w+b")
# convert HTML to PDF
pisaStatus = pisa.CreatePDF(
src=sourceHtml, # the HTML to convert
dest=resultFile) # file handle to receive result
# close output file
resultFile.close()
final_encoded_pdf_to_string = ""
with open(outputFilename, "rb") as f:
final_encoded_pdf_to_string = base64.b64encode(f.read())
qry_key = {'valide': '1', 'locked': '0',
'_id': ObjectId(str(diction['e_doc_id'])),
'secret_key_signature': str(diction['secret_key_signature']),
'email_destinataire': str(diction['email_destinataire'])}
new_data = {}
new_data['document_data_signed'] = final_encoded_pdf_to_string
result = MYSY_GV.dbname['e_document_signe'].find_one_and_update(
qry_key,
{"$set": new_data},
upsert=False,
return_document=ReturnDocument.AFTER
)
if ("_id" not in result.keys()):
mycommon.myprint(
" Impossible de signer le document (2) ")
return False, " Impossible de signer le document (2) "
"""
On envoie le mail avec le document signé
"""
# Traitement de l'eventuel fichier joint
tab_files_to_attache_to_mail = []
# Attachement du fichier joint
file_to_attache_to_mail = MIMEBase('application', "octet-stream")
file_to_attache_to_mail.set_payload(open(outputFilename, "rb").read())
encoders.encode_base64(file_to_attache_to_mail)
file_to_attache_to_mail.add_header('Content-Disposition',
'attachment; filename="{0}"'.format(os.path.basename(outputFilename)))
new_node = {"attached_file": file_to_attache_to_mail}
tab_files_to_attache_to_mail.append(new_node)
html = """\
<html>
<body>
<br />
<div style="text-align: center;">
<nav style="text-align: center; font-weight: bold;">LOGO</nav>
<br />
<div style="text-align: center;">
<nav style="text-align: center; font-weight: bold;">SIGNATURE ELECTRONIQUE</nav>
<br />
</div>
</div>
<div>
Bonjour
</div>
<div >
Merci de trouver en pièce jointe le document signé electroniquement
<br>
</p>
Cordialement.
</div>
</body>
</html>
"""
# Creation de l'email à enoyer
msg = MIMEMultipart("alternative")
"""
Recuperation des parametre SMTP du partner si le client a decidé d'utiliser son propre smpt
"""
partner_own_smtp_value = "0"
partner_own_smtp = MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': local_partner_owner_recid,
'config_name': 'partner_smtp',
'valide': '1',
'locked': '0'})
if (partner_own_smtp and "config_value" in partner_own_smtp.keys()):
partner_own_smtp_value = partner_own_smtp['config_value']
if (str(partner_own_smtp_value) == "1"):
partner_SMTP_COUNT_password = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': local_partner_owner_recid,
'config_name': 'smtp_user_pwd',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_smtpsrv = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': local_partner_owner_recid,
'config_name': 'smtp_server',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_user = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': local_partner_owner_recid,
'config_name': 'smtp_user',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_From_User = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': local_partner_owner_recid,
'config_name': 'smtp_count_from_name',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_port = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': local_partner_owner_recid,
'config_name': 'smtp_count_port',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
if (str(partner_own_smtp_value) == "1"):
smtpserver = smtplib.SMTP(partner_SMTP_COUNT_smtpsrv, partner_SMTP_COUNT_port)
else:
smtpserver = smtplib.SMTP(MYSY_GV.O365_SMTP_COUNT_smtpsrv, MYSY_GV.O365_SMTP_COUNT_port)
html_mime = MIMEText(html, 'html')
if (str(partner_own_smtp_value) == "1"):
msg.attach(html_mime)
msg['From'] = partner_SMTP_COUNT_From_User
msg['Bcc'] = 'contact@mysy-training.com'
msg['Subject'] = " Votre Document Signé "
# msg['to'] = "billardman01@hotmail.com"
msg['to'] = str(diction['email_destinataire'])
# Attacher l'eventuelle pièces jointes
for myfile in tab_files_to_attache_to_mail:
msg.attach(myfile['attached_file'])
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(partner_SMTP_COUNT_user, partner_SMTP_COUNT_password)
else:
msg.attach(html_mime)
msg['From'] = MYSY_GV.O365_SMTP_COUNT_From_User
msg['Bcc'] = 'contact@mysy-training.com'
msg['Subject'] = " Votre Document Signé "
# msg['to'] = "billardman01@hotmail.com"
msg['to'] = msg['to'] = str(diction['email_destinataire'])
for myfile in tab_files_to_attache_to_mail:
msg.attach(myfile['attached_file'])
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(MYSY_GV.O365_SMTP_COUNT_user, MYSY_GV.O365_SMTP_COUNT_password)
val = smtpserver.send_message(msg)
smtpserver.close()
print(" Email envoyé " + str(val))
return True, " Le document a été correction signé. Vous allez recevoir le document par email"
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de signer le document "
"""
Cette fonction fait une demande de signature d'un document
"""
def Sent_E_Document_Signature_Request(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'e_doc_id', 'user_email', ]
incom_keys = diction.keys()
for val in incom_keys:
if val not in field_list and val.startswith('my_') is False:
mycommon.myprint(str(
inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas autorisé")
return False, " Les informations fournies sont incorrectes"
"""
Verification des champs obligatoires
"""
field_list_obligatoire = ['token', 'e_doc_id', 'user_email', ]
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
return False, " Les informations fournies sont incorrectes"
"""
Verification de l'identité et autorisation de l'entité qui
appelle cette API
"""
token = ""
if ("token" in diction.keys()):
if diction['token']:
token = diction['token']
"""
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
"""
if( mycommon.isEmailValide(str(diction['user_email'])) is False ):
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + str(diction['user_email']) + "' n'est pas un email valide ")
return False, " Les informations fournies sont incorrectes"
RetObject = []
val_tmp = 0
qry = { 'valide': '1', 'locked': '0',
'_id': ObjectId(str(diction['e_doc_id'])),
'statut':'0'}
is_e_document_valide = "0"
e_document_open_code = ""
e_document_data = {}
for New_retVal in MYSY_GV.dbname['e_document_signe'].find(qry).sort([("_id", pymongo.DESCENDING), ]):
if ("email_destinataire" in New_retVal.keys() and New_retVal['email_destinataire']):
list_email = str(New_retVal['email_destinataire']).replace(",", ";")
tab_list_email = list_email.split(";")
if( diction['user_email'] in tab_list_email ):
is_e_document_valide = "1"
e_document_data = New_retVal
e_document_open_code = New_retVal['secret_key_open']
if( is_e_document_valide == "0" ):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'adresse email du destinataire n'est pas autorisée ")
return False, " L'adresse email du destinataire n'est pas autorisée "
"""
Si le document est valide, alors on envoie la demande de signture
"""
url_signature = MYSY_GV.CLIENT_URL_BASE+"E_Signature/"+str(e_document_data['_id'])
"""
Recuperation des parametre SMTP du partner si le client a decidé d'utiliser son propre smpt
"""
partner_own_smtp_value = "0"
partner_own_smtp = MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(e_document_data['partner_owner_recid']),
'config_name': 'partner_smtp',
'valide': '1',
'locked': '0'})
if (partner_own_smtp and "config_value" in partner_own_smtp.keys()):
partner_own_smtp_value = partner_own_smtp['config_value']
if (str(partner_own_smtp_value) == "1"):
partner_SMTP_COUNT_password = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(e_document_data['partner_owner_recid']),
'config_name': 'smtp_user_pwd',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_smtpsrv = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(e_document_data['partner_owner_recid']),
'config_name': 'smtp_server',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_user = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(e_document_data['partner_owner_recid']),
'config_name': 'smtp_user',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_From_User = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(e_document_data['partner_owner_recid']),
'config_name': 'smtp_count_from_name',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_port = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(e_document_data['partner_owner_recid']),
'config_name': 'smtp_count_port',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
if (str(partner_own_smtp_value) == "1"):
smtpserver = smtplib.SMTP(partner_SMTP_COUNT_smtpsrv, partner_SMTP_COUNT_port)
else:
smtpserver = smtplib.SMTP(MYSY_GV.O365_SMTP_COUNT_smtpsrv, MYSY_GV.O365_SMTP_COUNT_port)
# Creation de l'email à enoyer
msg = MIMEMultipart("alternative")
html = """\
<html>
<body>
<br />
<div style="text-align: center;">
<nav style="text-align: center; font-weight: bold;">LOGO</nav>
<br />
<div style="text-align: center;">
<nav style="text-align: center; font-weight: bold;">SIGNATURE ELECTRONIQUE</nav>
<br />
</div>
</div>
<div>
Bonjour
</div>
<div >
Cliquez sur le lien ci-dessous pour signer electroniquement le document : <br/>
""" + url_signature + """<br>
</p>
<p>
Le code d'ouverture du document est : """+ str(e_document_open_code) +"""
</p>
Cordialement.
</div>
</body>
</html>
"""
#contenu_doc_Template = jinja2.Template(str(courrier_template_data['contenu_doc']))
#sourceHtml = contenu_doc_Template.render(params=body["params"])
html_mime = MIMEText(html, 'html')
if (str(partner_own_smtp_value) == "1"):
msg.attach(html_mime)
msg['From'] = partner_SMTP_COUNT_From_User
msg['Bcc'] = 'contact@mysy-training.com'
msg['Subject'] = " Signature electronique document"
# msg['to'] = "billardman01@hotmail.com"
msg['to'] = str(diction['user_email'])
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(partner_SMTP_COUNT_user, partner_SMTP_COUNT_password)
else:
msg.attach(html_mime)
msg['From'] = MYSY_GV.O365_SMTP_COUNT_From_User
msg['Bcc'] = 'contact@mysy-training.com'
msg['Subject'] = " Signature electronique document"
# msg['to'] = "billardman01@hotmail.com"
msg['to'] = str(diction['user_email'])
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(MYSY_GV.O365_SMTP_COUNT_user, MYSY_GV.O365_SMTP_COUNT_password)
val = smtpserver.send_message(msg)
smtpserver.close()
print(" Email envoyé " + str(val))
return True, RetObject
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de récupérer le document électronique "
"""
Cette fonction permet d'afficher une document pdf signé et validé
ex : quand on scan le qr code sur le document pdf
"""
"""
Recuperation document à signer, sans connexion token
"""
def Get_Given_E_Document_Signed_No_Token(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'e_doc_id', 'secret_key_signature', 'partner_owner_recid']
incom_keys = diction.keys()
for val in incom_keys:
if val not in field_list and val.startswith('my_') is False:
mycommon.myprint(str(
inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas autorisé")
return False, " Les informations fournies sont incorrectes"
"""
Verification des champs obligatoires
"""
field_list_obligatoire = ['token', 'e_doc_id', 'secret_key_signature', 'partner_owner_recid']
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
return False, " Les informations fournies sont incorrectes"
"""
Verification de l'identité et autorisation de l'entité qui
appelle cette API
"""
token = ""
if ("token" in diction.keys()):
if diction['token']:
token = diction['token']
"""
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
"""
RetObject = []
val_tmp = 0
local_partner_owner_recid = ""
qry = {'valide': '1', 'locked': '0',
'_id': ObjectId(str(diction['e_doc_id'])),
'secret_key_signature': str(diction['secret_key_signature']),
'statut': '1',
'partner_owner_recid':str(diction['partner_owner_recid']),}
for New_retVal in MYSY_GV.dbname['e_document_signe'].find(qry, {'_id':1, 'document_data_signed':1}).sort([("_id", pymongo.DESCENDING), ]):
user = New_retVal
user['id'] = str(val_tmp)
if ("signature_digitale" in New_retVal.keys()):
del New_retVal['signature_digitale']
if ("signature_digitale" in New_retVal.keys()):
del New_retVal['signature_digitale']
val_tmp = val_tmp + 1
decode_data = user['document_data_signed'].decode()
user['document_data_signed'] = decode_data
RetObject.append(mycommon.JSONEncoder().encode(user))
if (len(RetObject) <= 0):
mycommon.myprint(str(
inspect.stack()[0][3]) + " Aucun E-document trouvé ")
return False, " Aucun E-document trouvé "
return True, RetObject
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de récupérer le document électronique "