Skip to content
Snippets Groups Projects
Commit 12259818 authored by Robin Sonnabend's avatar Robin Sonnabend
Browse files

Sending mail with attached protocol

parent 4f136efa
No related branches found
No related tags found
No related merge requests found
......@@ -2,6 +2,7 @@ from flask import render_template, send_file, url_for, redirect, flash, request
from datetime import datetime, time, date, timedelta
import math
from io import StringIO, BytesIO
from shared import db
from utils import random_string, url_manager, get_etherpad_url
......@@ -104,8 +105,6 @@ class ProtocolType(db.Model):
if protocoltype.has_private_view_right(user)
]
class Protocol(db.Model):
__tablename__ = "protocols"
id = db.Column(db.Integer, primary_key=True)
......@@ -283,6 +282,10 @@ class Document(db.Model):
def get_filename(self):
return os.path.join(config.DOCUMENTS_PATH, self.filename)
def as_file_like(self):
with open(self.get_filename(), "rb") as file:
return BytesIO(file.read())
@event.listens_for(Document, "before_delete")
def on_document_delete(mapper, connection, document):
if document.filename is not None:
......
......@@ -565,6 +565,19 @@ def update_protocol(protocol_id):
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
return render_template("protocol-update.html", upload_form=upload_form, edit_form=edit_form, protocol=protocol)
@app.route("/prococol/send/<int:protocol_id>")
@login_required
def send_protocol(protocol_id):
user = current_user()
protocol = Protocol.query.filter_by(id=protocol_id).first()
if protocol is None or not protocol.protocoltype.has_modify_right(user):
flash("Invalides Protokoll oder keine Berechtigung.", "alert-error")
return redirect(request.args.get("next") or url_for("index"))
tasks.send_protocol(protocol)
flash("Das Protokoll wurde versandt.", "alert-success")
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
@app.route("/protocol/tops/new/<int:protocol_id>", methods=["GET", "POST"])
@login_required
def new_top(protocol_id):
......@@ -738,9 +751,7 @@ def download_document(document_id):
and not document.protocol.protocoltype.has_public_view_right(user))):
flash("Keine Berechtigung.", "alert-error")
return redirect(request.args.get("next") or url_for("index"))
with open(document.get_filename(), "rb") as file:
file_like = BytesIO(file.read())
return send_file(file_like, cache_timeout=1, as_attachment=True, attachment_filename=document.name)
return send_file(document.as_file_like(), cache_timeout=1, as_attachment=True, attachment_filename=document.name)
@app.route("/document/upload/<int:protocol_id>", methods=["POST"])
@login_required
......
......@@ -199,7 +199,6 @@ def parse_protocol_async(protocol_id, encoded_kwargs):
content_private = render_template("protocol.txt", render_type=RenderType.plaintext, show_private=True, **render_kwargs)
content_public = render_template("protocol.txt", render_type=RenderType.plaintext, show_private=False, **render_kwargs)
if content_private != content_public:
print("different")
privacy_states.append(True)
protocol.content_private = content_private
protocol.content_public = content_public
......@@ -316,23 +315,40 @@ def send_reminder_async(reminder_id, protocol_id):
with app.app_context():
reminder = MeetingReminder.query.filter_by(id=reminder_id).first()
protocol = Protocol.query.filter_by(id=protocol_id).first()
reminder_text = render_template("reminder.txt", reminder=reminder, protocol=protocol)
reminder_text = render_template("reminder-mail.txt", reminder=reminder, protocol=protocol)
if reminder.send_public:
send_mail(protocol, protocol.protocoltype.public_mail, "Tagesordnung der {}".format(protocol.protocoltype.name), reminder_text)
if reminder.send_private:
send_mail(protocol, protocol.protocoltype.private_mail, "Tagesordnung der {}".format(protocol.protocoltype.name), reminder_text)
def send_mail(protocol, to_addr, subject, content):
def send_protocol(protocol):
send_protocol_async.delay(protocol.id, show_private=True)
send_protocol_async.delay(protocol.id, show_private=False)
@celery.task
def send_protocol_async(protocol_id, show_private):
with app.app_context():
protocol = Protocol.query.filter_by(id=protocol_id).first()
to_addr = protocol.protocoltype.private_mail if show_private else protocol.protocoltype.public_mail
subject = "{}{}-Protokoll vom {}".format("Internes " if show_private else "", protocol.protocoltype.short_name, date_filter(protocol.date))
mail_content = render_template("protocol-mail.txt", protocol=protocol)
appendix = [(document.name, document.as_file_like())
for document in protocol.documents
if show_private or not document.is_private
]
send_mail(protocol, to_addr, subject, mail_content, appendix)
def send_mail(protocol, to_addr, subject, content, appendix=None):
if to_addr is not None and len(to_addr.strip()) > 0:
send_mail_async.delay(protocol.id, to_addr, subject, content)
send_mail_async.delay(protocol.id, to_addr, subject, content, appendix)
@celery.task
def send_mail_async(protocol_id, to_addr, subject, content):
def send_mail_async(protocol_id, to_addr, subject, content, appendix):
with app.app_context():
protocol = Protocol.query.filter_by(id=protocol_id).first()
try:
print("sending {} to {}".format(subject, to_addr))
mail_manager.send(to_addr, subject, content)
mail_manager.send(to_addr, subject, content, appendix)
except Exception as exc:
error = protocol.create_error("Sending Mail", "Sending mail failed", str(exc))
db.session.add(error)
......
Protocol der {{protocol.name}} vom {{protocol.date|datify}}
Datum: {{protocol.date|datify_long}}
Zeit: von {{protocol.start_time|timify}} bis {{protocol.end_time|timify}}
Protokollant: {{protocol.author}}
Anwesende: {{protocol.participants}}
Die Tagesordnung ist:
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if not default_top.is_at_end() %}
* {{default_top.name}}
{% endif %}
{% endfor %}
{% endif %}
{% for top in protocol.tops %}
* {{top.name }}
{% endfor %}
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if default_top.is_at_end() %}
* {{default_top.name}}
{% endif %}
{% endfor %}
{% endif %}
Beschlüsse:
{% if protocol.decisions|length > 0 %}
{% for decision in protocol.decisions %}
* {{decision.content}}
{% endfor %}
{% else %}
* Keine Beschlüsse
{% endif %}
......@@ -20,6 +20,8 @@
{% if not protocol.is_done() %}
<a class="btn btn-default" href="{{url_for("get_protocol_template", protocol_id=protocol.id)}}">Vorlage</a>
<a class="btn btn-primary" href="{{url_for("etherpush_protocol", protocol_id=protocol.id)}}">In Etherpad</a>
{% else %}
<a class="btn btn-default" href="{{url_for("send_protocol", protocol_id=protocol.id)}}">Per Mail versenden</a>
{% endif %}
<a class="btn btn-default" href="{{protocol.get_etherpad_link()}}" target="_blank">Etherpad</a>
<a class="btn btn-default" href="{{url_for("show_type", type_id=protocol.protocoltype.id)}}">Typ</a>
......
File moved
......@@ -6,6 +6,7 @@ import regex
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from datetime import datetime, date, timedelta
import requests
from io import BytesIO
......@@ -68,18 +69,23 @@ class MailManager:
self.username = getattr(config, "MAIL_USER", "")
self.password = getattr(config, "MAIL_PASSWORD", "")
def send(self, to_addr, subject, content):
def send(self, to_addr, subject, content, appendix=None):
if (not self.active
or not self.hostname
or not self.username
or not self.password
or not self.from_addr):
return
msg = MIMEMultipart("alternative")
msg = MIMEMultipart("mixed") # todo: test if clients accept attachment-free mails set to multipart/mixed
msg["From"] = self.from_addr
msg["To"] = to_addr
msg["Subject"] = subject
msg.attach(MIMEText(content, _charset="utf-8"))
if appendix is not None:
for name, file_like in appendix:
part = MIMEApplication(file_like.read(), "octet-stream")
part["Content-Disposition"] = 'attachment; filename="{}"'.format(name)
msg.attach(part)
server = smtplib.SMTP_SSL(self.hostname)
server.login(self.username, self.password)
server.sendmail(self.from_addr, to_addr, msg.as_string())
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment