portal-oddajanje-solar/portal/base.py

251 lines
7.8 KiB
Python
Raw Normal View History

import re
import hashlib
import time
import ssl
from pathlib import Path
import imaplib
from smtplib import SMTP_SSL
import email
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
import pdfkit
from jinja2 import Environment, FileSystemLoader
ENABLED_FILETYPES = ['txt', 'csv', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'xml', 'mxliff', 'tmx']
REGEX_EMAIL = re.compile('^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,3}$')
class ContractCreator:
def __init__(self):
template_loader = FileSystemLoader(searchpath="./")
template_env = Environment(loader=template_loader)
self.template = template_env.get_template('contract/template.html')
self.pdfkit_options = {
'page-size': 'A4',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
'custom-header' : [
('Accept-Encoding', 'gzip')
]
}
def fill_template(self, **kwargs):
return self.template.render(**kwargs)
def create_pdf(self, out_f, fields_dict):
html_str = self.fill_template(**fields_dict)
pdfkit.from_string(html_str, out_f, options=self.pdfkit_options)
contract_creator = ContractCreator()
def get_upload_metadata(corpus_name, request):
upload_metadata = dict()
file_hashes = create_file_hashes(request.files)
file_names = file_hashes.keys()
form_data = request.form.copy()
upload_timestamp = int(time.time())
upload_id = create_upload_id(corpus_name, form_data, upload_timestamp, file_hashes)
upload_metadata['corpus_name'] = corpus_name
upload_metadata['form_data'] = form_data
upload_metadata['upload_id'] = upload_id
upload_metadata['timestamp'] = upload_timestamp
upload_metadata['file_hashes'] = file_hashes
upload_metadata['file_names'] = file_names
return upload_metadata
def check_suffixes(files):
for key, f in files.items():
if key.startswith('file'):
suffix = f.filename.split('.')[-1]
if suffix not in ENABLED_FILETYPES:
return 'Datoteka "{}" ni pravilnega formata.'.format(f.filename)
return None
def get_subdir(uploads_path, dir_name):
subdir = uploads_path / dir_name
if not subdir.exists():
subdir.mkdir(parents=True)
return subdir
def create_upload_id(corpus_name, form_data, upload_timestamp, file_hashes):
ime = form_data.get('ime')
podjetje = form_data.get('podjetje')
naslov = form_data.get('naslov')
posta = form_data.get('posta')
email = form_data.get('email')
telefon = form_data.get('telefon')
# This hash serves as an unique identifier for the whole upload.
metahash = hashlib.md5((corpus_name+ime+podjetje+naslov+posta+email+telefon).encode())
# Include file hashes to avoid metafile name collisions if they have the same form values,
# but different data files. Sort hashes first so upload order doesn't matter.
sorted_f_hashes = list(file_hashes.values())
sorted_f_hashes.sort()
metahash.update(''.join(sorted_f_hashes).encode())
metahash = metahash.hexdigest()
return metahash
def check_form(form):
ime = form.get('ime')
podjetje = form.get('podjetje')
naslov = form.get('naslov')
posta = form.get('posta')
email = form.get('email')
telefon = form.get('telefon')
if len(ime) > 100:
return 'Predolgo ime.'
if len(podjetje) > 100:
return 'Predolgo ime institucije.'
if len(email) > 100:
return 'Predolgi email naslov'
elif not re.search(REGEX_EMAIL, email):
return 'Email napačnega formata.'
if len(telefon) > 100:
return 'Predolga telefonska št.'
if len(naslov) > 100:
return 'Predolg naslov.'
if len(posta) > 100:
return 'Predolga pošta'
return None
def create_file_hashes(files):
res = dict()
for key, f in files.items():
if key.startswith('file'):
h = hashlib.md5(f.filename.encode())
h.update(f.stream.read())
res[f.filename] = h.hexdigest()
f.seek(0)
return res
def store_metadata(uploads_path, upload_metadata):
base = get_subdir(uploads_path, 'meta')
timestamp = upload_metadata['timestamp']
upload_id = upload_metadata['upload_id']
form_data = upload_metadata['form_data']
email = form_data['email']
file_hashes = upload_metadata['file_hashes']
contract = upload_metadata['contract']
filename = str(timestamp) + '-' + email + '-' + upload_id + '.meta'
sorted_f_hashes = list(file_hashes.values())
sorted_f_hashes.sort()
path = base / filename
with path.open('w') as f:
f.write('korpus=' + upload_metadata['corpus_name'])
f.write('\nime=' + form_data['ime'])
f.write('\npodjetje=' + form_data['podjetje'])
f.write('\nnaslov=' + form_data['naslov'])
f.write('\nposta=' + form_data['posta'])
f.write('\nemail=' + form_data['email'])
f.write('\ndatoteke=' + str(sorted_f_hashes))
f.write('\npogodba=' + contract)
def store_datafiles(uploads_path, files, upload_metadata):
base = get_subdir(uploads_path, 'files')
file_hashes = upload_metadata['file_hashes']
for key, f in files.items():
if key.startswith('file'):
path = base / file_hashes[f.filename]
if not path.exists():
path.mkdir()
f.save(path / f.filename)
def generate_contract_pdf(uploads_path, upload_metadata, contract_client_contact):
base = get_subdir(uploads_path, 'contracts')
contract_file_name = upload_metadata['upload_id'] + '.pdf'
form_data = upload_metadata['form_data']
files_table_str = []
for file_name in upload_metadata['file_names']:
files_table_str.append('<tr><td style="text-align: center;">')
files_table_str.append(file_name)
files_table_str.append('</td></tr>')
files_table_str = ''.join(files_table_str)
data = {
'ime_priimek': form_data['ime'],
'naslov': form_data['naslov'],
'posta': form_data['posta'],
'kontakt_narocnik': contract_client_contact,
'kontakt_imetnikpravic': form_data['ime'],
'files_table_str': files_table_str
}
contract_creator.create_pdf(base / contract_file_name, data)
return contract_file_name
def send_confirm_mail(subject, body, uploads_path, upload_metadata, mail_host, mail_login, mail_pass, imap_port=993, smtp_port=465):
upload_id = upload_metadata['upload_id']
message = MIMEMultipart()
message['From'] = mail_login
message['To'] = upload_metadata['form_data']['email']
message['Subject'] = subject.format(upload_id=upload_id)
body = body.format(upload_id=upload_id)
message.attach(MIMEText(body, "plain"))
contracts_dir = get_subdir(uploads_path, 'contracts')
base_name = upload_metadata['contract']
contract_file = contracts_dir / base_name
with open(contract_file, "rb") as f:
part = MIMEApplication(
f.read(),
Name = base_name
)
part['Content-Disposition'] = 'attachment; filename="%s"' % base_name
message.attach(part)
text = message.as_string()
# Create a secure SSL context
context = ssl.create_default_context()
with SMTP_SSL(mail_host, smtp_port, context=context) as server:
server.login(mail_login, mail_pass)
server.sendmail(message['From'], message['To'], text)
# Save copy of sent mail in Sent mailbox
imap = imaplib.IMAP4_SSL(mail_host, imap_port)
imap.login(mail_login, mail_pass)
imap.append('Sent', '\\Seen', imaplib.Time2Internaldate(time.time()), text.encode('utf8'))
imap.logout()