forked from GithubBackups/healthchecks
Implement email body decoding in the "Ping Details" dialog
This commit is contained in:
parent
18b39a5a79
commit
1bc89f0d5d
@ -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)
|
||||||
|
@ -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="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", 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="alice@example.org", 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="alice@example.org", 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="alice@example.org", 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, "<b>hello</b>")
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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>
|
<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>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user