Browse Source

Implement email body decoding in the "Ping Details" dialog

pull/485/head
Pēteris Caune 4 years ago
parent
commit
1bc89f0d5d
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
4 changed files with 119 additions and 1 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +69
    -0
      hc/front/tests/test_ping_details.py
  3. +13
    -1
      hc/front/views.py
  4. +36
    -0
      templates/front/ping_details.html

+ 1
- 0
CHANGELOG.md View File

@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file.
## Improvements ## Improvements
- Rename VictorOps -> Splunk On-Call - Rename VictorOps -> Splunk On-Call
- Implement email body decoding in the "Ping Details" dialog
## Bug Fixes ## Bug Fixes
- Fix downtime summary to handle months when the check didn't exist yet (#472) - Fix downtime summary to handle months when the check didn't exist yet (#472)


+ 69
- 0
hc/front/tests/test_ping_details.py View File

@ -1,6 +1,39 @@
from hc.api.models import Check, Ping from hc.api.models import Check, Ping
from hc.test import BaseTestCase from hc.test import BaseTestCase
PLAINTEXT_EMAIL = """Content-Type: multipart/alternative; boundary=bbb
--bbb
Content-Type: text/plain;charset=utf-8
Content-Transfer-Encoding: base64
aGVsbG8gd29ybGQ=
--bbb
"""
BAD_BASE64_EMAIL = """Content-Type: multipart/alternative; boundary=bbb
--bbb
Content-Type: text/plain;charset=utf-8
Content-Transfer-Encoding: base64
!!!
--bbb
"""
HTML_EMAIL = """Content-Type: multipart/alternative; boundary=bbb
--bbb
Content-Type: text/html;charset=utf-8
Content-Transfer-Encoding: base64
PGI+aGVsbG88L2I+
--bbb
"""
class PingDetailsTestCase(BaseTestCase): class PingDetailsTestCase(BaseTestCase):
def setUp(self): def setUp(self):
@ -73,3 +106,39 @@ class PingDetailsTestCase(BaseTestCase):
self.client.login(username="[email protected]", password="password") self.client.login(username="[email protected]", password="password")
r = self.client.get(self.url) r = self.client.get(self.url)
self.assertContains(r, "(exit status 0)", status_code=200) self.assertContains(r, "(exit status 0)", status_code=200)
def test_it_decodes_plaintext_email_body(self):
Ping.objects.create(owner=self.check, scheme="email", body=PLAINTEXT_EMAIL)
self.client.login(username="[email protected]", password="password")
r = self.client.get(self.url)
self.assertContains(r, "email-body-plain", status_code=200)
self.assertNotContains(r, "email-body-html")
# aGVsbG8gd29ybGQ= is base64("hello world")
self.assertContains(r, "aGVsbG8gd29ybGQ=")
self.assertContains(r, "hello world")
def test_it_handles_bad_base64_in_email_body(self):
Ping.objects.create(owner=self.check, scheme="email", body=BAD_BASE64_EMAIL)
self.client.login(username="[email protected]", password="password")
r = self.client.get(self.url)
self.assertContains(r, "!!!", status_code=200)
self.assertNotContains(r, "email-body-plain")
self.assertNotContains(r, "email-body-html")
def test_it_decodes_html_email_body(self):
Ping.objects.create(owner=self.check, scheme="email", body=HTML_EMAIL)
self.client.login(username="[email protected]", password="password")
r = self.client.get(self.url)
self.assertNotContains(r, "email-body-plain", status_code=200)
self.assertContains(r, "email-body-html")
# PGI+aGVsbG88L2I+ is base64("<b>hello</b>")
self.assertContains(r, "PGI+aGVsbG88L2I+")
self.assertContains(r, "&lt;b&gt;hello&lt;/b&gt;")

+ 13
- 1
hc/front/views.py View File

@ -1,4 +1,5 @@
from datetime import datetime, timedelta as td from datetime import datetime, timedelta as td
import email
import json import json
import os import os
import re import re
@ -507,7 +508,18 @@ def ping_details(request, code, n=None):
except Ping.DoesNotExist: except Ping.DoesNotExist:
return render(request, "front/ping_details_not_found.html") return render(request, "front/ping_details_not_found.html")
ctx = {"check": check, "ping": ping}
ctx = {"check": check, "ping": ping, "plain": None, "html": None}
if ping.scheme == "email":
parsed = email.message_from_string(ping.body, policy=email.policy.SMTP)
plain_mime_part = parsed.get_body(("plain",))
if plain_mime_part:
ctx["plain"] = plain_mime_part.get_content()
html_mime_part = parsed.get_body(("html",))
if html_mime_part:
ctx["html"] = html_mime_part.get_content()
return render(request, "front/ping_details.html", ctx) return render(request, "front/ping_details.html", ctx)


+ 36
- 0
templates/front/ping_details.html View File

@ -66,6 +66,42 @@
{% if ping.body %} {% if ping.body %}
<h4>Request Body</h4> <h4>Request Body</h4>
{% if plain or html %}
<ul class="nav nav-pills">
<li class="active">
<a href="#email-body-raw" data-toggle="tab">Raw Message</a>
</li>
{% if plain %}
<li>
<a href="#email-body-plain" data-toggle="tab">Text</a>
</li>
{% endif %}
{% if html %}
<li>
<a href="#email-body-html" data-toggle="tab">HTML</a>
</li>
{% endif %}
</ul>
<div class="tab-content">
<div id="email-body-raw" class="tab-pane active">
<pre>{{ ping.body }}</pre>
</div>
{% if plain %}
<div id="email-body-plain" class="tab-pane">
<pre>{{ plain }}</pre>
</div>
{% endif %}
{% if html %}
<div id="email-body-html" class="tab-pane">
<pre>{{ html }}</pre>
</div>
{% endif %}
</div>
{% else %}
<pre>{{ ping.body }}</pre> <pre>{{ ping.body }}</pre>
{% endif %}
{% endif %} {% endif %}
</div> </div>

Loading…
Cancel
Save