Fix msg body display, download link for email bounces

This commit is contained in:
Lance Edgar 2023-09-08 10:56:25 -05:00
parent 6e50288bd4
commit 7221400b88
3 changed files with 18 additions and 35 deletions

View file

@ -48,9 +48,7 @@
<%def name="render_this_page()"> <%def name="render_this_page()">
${parent.render_this_page()} ${parent.render_this_page()}
<pre class="email-message-body"> <pre class="email-message-body">${message}</pre>
${message}
</pre>
</%def> </%def>

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2022 Lance Edgar # Copyright © 2010-2023 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -24,18 +24,12 @@
Views for Email Bounces Views for Email Bounces
""" """
from __future__ import unicode_literals, absolute_import
import os import os
import datetime import datetime
import six
from rattail.db import model from rattail.db import model
from rattail.bouncer import get_handler
from rattail.bouncer.config import get_profile_keys from rattail.bouncer.config import get_profile_keys
from pyramid.response import FileResponse
from webhelpers2.html import HTML, tags from webhelpers2.html import HTML, tags
from tailbone.views import MasterView from tailbone.views import MasterView
@ -50,6 +44,7 @@ class EmailBounceView(MasterView):
url_prefix = '/email-bounces' url_prefix = '/email-bounces'
creatable = False creatable = False
editable = False editable = False
downloadable = True
labels = { labels = {
'config_key': "Source", 'config_key': "Source",
@ -70,7 +65,8 @@ class EmailBounceView(MasterView):
self.handler_options = sorted(get_profile_keys(self.rattail_config)) self.handler_options = sorted(get_profile_keys(self.rattail_config))
def get_handler(self, bounce): def get_handler(self, bounce):
return get_handler(self.rattail_config, bounce.config_key) app = self.get_rattail_app()
return app.get_bounce_handler(bounce.config_key)
def configure_grid(self, g): def configure_grid(self, g):
super(EmailBounceView, self).configure_grid(g) super(EmailBounceView, self).configure_grid(g)
@ -142,11 +138,16 @@ class EmailBounceView(MasterView):
path = handler.msgpath(bounce) path = handler.msgpath(bounce)
if os.path.exists(path): if os.path.exists(path):
with open(path, 'rb') as f: with open(path, 'rb') as f:
kwargs['message'] = f.read() # TODO: how to determine encoding? (is utf_8 guaranteed?)
kwargs['message'] = f.read().decode('utf_8')
else: else:
kwargs['message'] = "(file not found)" kwargs['message'] = "(file not found)"
return kwargs return kwargs
def download_path(self, bounce, filename):
handler = self.get_handler(bounce)
return handler.msgpath(bounce)
# TODO: should require POST here # TODO: should require POST here
def process(self): def process(self):
""" """
@ -169,20 +170,13 @@ class EmailBounceView(MasterView):
self.request.session.flash("Email bounce has been marked UN-processed.") self.request.session.flash("Email bounce has been marked UN-processed.")
return self.redirect(self.get_action_url('view', bounce)) return self.redirect(self.get_action_url('view', bounce))
def download(self):
"""
View for downloading the message file associated with a bounce.
"""
bounce = self.get_instance()
handler = self.get_handler(bounce)
path = handler.msgpath(bounce)
response = FileResponse(path, request=self.request)
response.headers[b'Content-Length'] = six.binary_type(os.path.getsize(path))
response.headers[b'Content-Disposition'] = b'attachment; filename="bounce.eml"'
return response
@classmethod @classmethod
def defaults(cls, config): def defaults(cls, config):
cls._bounce_defaults(config)
cls._defaults(config)
@classmethod
def _bounce_defaults(cls, config):
config.add_tailbone_permission_group('emailbounces', "Email Bounces", overwrite=False) config.add_tailbone_permission_group('emailbounces', "Email Bounces", overwrite=False)
@ -200,15 +194,6 @@ class EmailBounceView(MasterView):
config.add_tailbone_permission('emailbounces', 'emailbounces.unprocess', config.add_tailbone_permission('emailbounces', 'emailbounces.unprocess',
"Mark Email Bounce as UN-processed") "Mark Email Bounce as UN-processed")
# download raw email
config.add_route('emailbounces.download', '/email-bounces/{uuid}/download')
config.add_view(cls, attr='download', route_name='emailbounces.download',
permission='emailbounces.download')
config.add_tailbone_permission('emailbounces', 'emailbounces.download',
"Download raw message of Email Bounce")
cls._defaults(config)
def defaults(config, **kwargs): def defaults(config, **kwargs):
base = globals() base = globals()

View file

@ -1593,9 +1593,9 @@ class MasterView(View):
""" """
obj = self.get_instance() obj = self.get_instance()
filename = self.request.GET.get('filename', None) filename = self.request.GET.get('filename', None)
if not filename:
raise self.notfound()
path = self.download_path(obj, filename) path = self.download_path(obj, filename)
if not path or not os.path.exists(path):
raise self.notfound()
response = FileResponse(path, request=self.request) response = FileResponse(path, request=self.request)
response.content_length = os.path.getsize(path) response.content_length = os.path.getsize(path)
content_type = self.download_content_type(path, filename) content_type = self.download_content_type(path, filename)