Browse Source

Send emails using djrill (Mandrill)

pull/7/head
Pēteris Caune 9 years ago
parent
commit
c54cb6469d
12 changed files with 129 additions and 46 deletions
  1. +15
    -10
      hc/accounts/views.py
  2. +9
    -0
      hc/api/admin.py
  3. +3
    -4
      hc/api/management/commands/sendalerts.py
  4. +26
    -0
      hc/api/models.py
  5. +1
    -14
      hc/front/forms.py
  6. +13
    -11
      hc/lib/emails.py
  7. +2
    -7
      hc/settings.py
  8. +1
    -0
      requirements.txt
  9. +51
    -0
      templates/emails/alert/body.html
  10. +2
    -0
      templates/emails/alert/subject.txt
  11. +5
    -0
      templates/emails/login/body.html
  12. +1
    -0
      templates/emails/login/subject.txt

+ 15
- 10
hc/accounts/views.py View File

@ -8,9 +8,11 @@ from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.http import HttpResponseBadRequest
from django.shortcuts import redirect, render
from django.template import loader
from hc.accounts.forms import EmailForm
from hc.api.models import Check
from hc.lib.emails import send
def _make_user(email):
@ -28,6 +30,18 @@ def _associate_demo_check(request, user):
check.save()
def _send_login_link(user):
token = str(uuid.uuid4())
user.set_password(token)
user.save()
login_link = reverse("hc-check-token", args=[user.username, token])
login_link = settings.SITE_ROOT + login_link
ctx = {"login_link": login_link}
send(user.email, "emails/login", ctx)
def login(request):
if request.method == 'POST':
form = EmailForm(request.POST)
@ -43,16 +57,7 @@ def login(request):
if user.is_staff:
return HttpResponseBadRequest()
token = str(uuid.uuid4())
user.set_password(token)
user.save()
login_link = reverse("hc-check-token", args=[user.username, token])
login_link = settings.SITE_ROOT + login_link
body = "login link: %s" % login_link
send_mail('Log In', body, settings.DEFAULT_FROM_EMAIL, [email],
fail_silently=False)
_send_login_link(user)
return redirect("hc-login-link-sent")


+ 9
- 0
hc/api/admin.py View File

@ -6,3 +6,12 @@ from hc.api.models import Check
@admin.register(Check)
class ChecksAdmin(admin.ModelAdmin):
list_display = ("id", "code", "user", "last_ping")
actions = ["send_alert"]
def send_alert(self, request, qs):
for check in qs:
check.send_alert()
self.message_user(request, "%d alert(s) sent" % qs.count())
send_alert.short_description = "Send Alert"

+ 3
- 4
hc/api/management/commands/sendalerts.py View File

@ -5,7 +5,6 @@ from django.core.management.base import BaseCommand
from django.utils import timezone
from hc.api.models import Check
from hc.lib.emails import send_status_notification
def _log(message):
@ -14,7 +13,7 @@ def _log(message):
class Command(BaseCommand):
help = 'Ensures triggers exist in database'
help = 'Sends UP/DOWN email alerts'
def handle(self, *args, **options):
@ -29,7 +28,7 @@ class Command(BaseCommand):
check.status = "down"
_log("\nSending email about going down for %s\n" % check.code)
send_status_notification(check)
check.send_alert()
ticks = 0
# Save status after the notification is sent
@ -44,7 +43,7 @@ class Command(BaseCommand):
check.status = "up"
_log("\nSending email about going up for %s\n" % check.code)
send_status_notification(check)
check.send_alert()
ticks = 0
# Save status after the notification is sent


+ 26
- 0
hc/api/models.py View File

@ -5,8 +5,22 @@ from django.conf import settings
from django.contrib.auth.models import User
from django.db import models
from hc.lib.emails import send
STATUSES = (("up", "Up"), ("down", "Down"), ("new", "New"))
DEFAULT_TIMEOUT = td(days=1)
TIMEOUT_CHOICES = (
("15 minutes", td(minutes=15)),
("30 minutes", td(minutes=30)),
("1 hour", td(hours=1)),
("3 hours", td(hours=3)),
("6 hours", td(hours=6)),
("12 hours", td(hours=12)),
("1 day", td(days=1)),
("2 days", td(days=2)),
("3 days", td(days=3)),
("1 week", td(weeks=1))
)
class Check(models.Model):
@ -21,3 +35,15 @@ class Check(models.Model):
def url(self):
return settings.PING_ENDPOINT + str(self.code)
def send_alert(self):
ctx = {
"timeout_choices": TIMEOUT_CHOICES,
"check": self,
"checks": self.user.check_set.order_by("created")
}
if self.status in ("up", "down"):
send(self.user.email, "emails/alert", ctx)
else:
raise NotImplemented("Unexpected status: %s" % self.status)

+ 1
- 14
hc/front/forms.py View File

@ -1,19 +1,6 @@
from datetime import timedelta as td
from django import forms
TIMEOUT_CHOICES = (
("15 minutes", td(minutes=15)),
("30 minutes", td(minutes=30)),
("1 hour", td(hours=1)),
("3 hours", td(hours=3)),
("6 hours", td(hours=6)),
("12 hours", td(hours=12)),
("1 day", td(days=1)),
("2 days", td(days=2)),
("3 days", td(days=3)),
("1 week", td(weeks=1))
)
from hc.api.models import TIMEOUT_CHOICES
class TimeoutForm(forms.Form):


+ 13
- 11
hc/lib/emails.py View File

@ -1,16 +1,18 @@
from django.conf import settings
from django.core.mail import send_mail
from django.template.loader import render_to_string
def send_status_notification(check):
if check.status == "down":
subject = "Alert DOWN"
body = "Hi, the check %s has gone down" % check.code
elif check.status == "up":
subject = "Alert UP"
body = "Hi, the check %s has gone up" % check.code
else:
raise NotImplemented("Unexpected status: %s" % check.status)
def send(to, template_directory, ctx):
""" Send HTML email using Mandrill.
send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, [check.user.email],
fail_silently=False)
Expect template_directory to be a path containing
- subject.txt
- body.html
"""
from_email = settings.DEFAULT_FROM_EMAIL
subject = render_to_string("%s/subject.txt" % template_directory, ctx)
body = render_to_string("%s/body.html" % template_directory, ctx)
send_mail(subject, "", from_email, [to], html_message=body)

+ 2
- 7
hc/settings.py View File

@ -30,6 +30,7 @@ INSTALLED_APPS = (
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'djrill',
'hc.accounts',
'hc.api',
@ -92,13 +93,7 @@ STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]
STATIC_ROOT = os.path.join(BASE_DIR, 'static-collected')
# AWS
EMAIL_BACKEND = 'django_ses_backend.SESBackend'
AWS_SES_ACCESS_KEY_ID = "---"
AWS_SES_SECRET_ACCESS_KEY = "---"
AWS_SES_REGION_NAME = 'us-east-1'
AWS_SES_REGION_ENDPOINT = 'email.us-east-1.amazonaws.com'
EMAIL_BACKEND = "djrill.mail.backends.djrill.DjrillBackend"
try:
from local_settings import *


+ 1
- 0
requirements.txt View File

@ -2,4 +2,5 @@ Django==1.8.2
django-ses
psycopg2==2.6
django-ses-backend
djrill
pygments

+ 51
- 0
templates/emails/alert/body.html View File

@ -0,0 +1,51 @@
{% load humanize %}
<p>Hello,</p>
<p>This is a notification sent by healthchecks.io</p>
<p>The check "{{ check.name }}" has gone {{ check.status }}.</p>
<p>Here is a summary of all your checks:</p>
<table>
<tr>
<th></th>
<th>Name</th>
<th>URL</th>
<th>Frequency</th>
<th>Last Ping</th>
</tr>
{% for check in checks %}
<tr>
<td>
{% if check.status == "new" %}
<span class="glyphicon glyphicon-question-sign new"></span>
{% elif now < check.alert_after %}
<span class="glyphicon glyphicon-ok-sign up"></span>
{% else %}
<span class="glyphicon glyphicon-exclamation-sign down"></span>
{% endif %}
</td>
<td>
{{ check.name }}
</td>
<td class="url-cell">
<code>{{ check.url }}</code>
</td>
<td>
{% for label, value in timeout_choices %}
{% if check.timeout == value %}
{{ label }}
{% endif %}
{% endfor %}
</td>
<td>
{% if check.last_ping %}
{{ check.last_ping|naturaltime }}
{% else %}
Never
{% endif %}
</td>
</tr>
{% endfor %}
</table>

+ 2
- 0
templates/emails/alert/subject.txt View File

@ -0,0 +1,2 @@
{{ check.name }} is {{ check.status }}

+ 5
- 0
templates/emails/login/body.html View File

@ -0,0 +1,5 @@
<p>Hello from healthchecks.io!</p>
<p>Here's a link to log yourself in:</p>
<p><a href="{{ login_link }}">{{ login_link }}</a></p>

+ 1
- 0
templates/emails/login/subject.txt View File

@ -0,0 +1 @@
Log in to healthchecks.io

Loading…
Cancel
Save