You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
5.8 KiB

from django.shortcuts import render, HttpResponse
from django.http import FileResponse
from django.core.mail import EmailMultiAlternatives
from django.conf import settings
from .models import Address, PDF, EmailSent, DownloadAttempt, CCEmail, BCCEmail
from .forms import CodeForm
from core.models import QuoteUser
from django.template.loader import render_to_string
from django.conf import settings
import ipinfo
import json
from datetime import date
import datetime
import hashlib
import os
IPINFO_HANDLER = ipinfo.getHandler()
def get_cc_emails():
return [x.email for x in CCEmail.objects.filter(active=True)]
def get_bcc_emails():
return [x.email for x in BCCEmail.objects.filter(active=True)]
# https://stackoverflow.com/a/4581997
def get_client_ip(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
return ip
def get_client_ip_info(request):
realip = get_client_ip(request)
handler = ipinfo.getHandler()
details = handler.getDetails(realip)
# needed for testing
if settings.DEBUG and (details.ip == '127.0.0.1' or details.ip == '::1'):
details.city = 'Local'
details.region = 'Local'
details.country = 'Local'
return details
# Create your views here.
def starter(request):
return render(request, 'download/download-page.html', {
'things': list(Address.objects.all())
})
def search(request, addr):
if len(addr) <= 3:
return HttpResponse(json.dumps([]))
return HttpResponse(json.dumps(
[x.toDict() for x in Address.objects.filter(address__icontains=addr)[:10]]
))
def send_email(to, addr, pdf, dt_date):
# send email
email = EmailMultiAlternatives()
# TODO: redefining template
email.subject = "Your quote for " + addr.address + " is attached"
email.to = [to]
context = {
'address': addr.address,
'subject': settings.QUOTE_SUBJECT
}
# Remove CC/BCC to stop spam catchers.
#email.bcc = get_bcc_emails()
#email.cc = get_cc_emails()
email.body = render_to_string('download/email/quote.txt', context)
email.attach_alternative(render_to_string('download/email/quote.html', context), 'text/html')
with open(str(pdf.upload_file), 'rb') as f:
content = f.read()
email.attach(pdf.address.address + '.pdf', content, 'application/octate-stream')
email.send()
def save_email(user, addr, pdf, dt):
EmailSent.objects.create(
user=user,
pdf=pdf,
ref_code=hashlib.sha256(dt.strftime("%Y%m%d%H%M%S").encode()).hexdigest()
)
def download(request):
if request.method == 'POST':
form = CodeForm(request.POST)
if form.is_valid():
# get addr by id
addr = Address.objects.filter(address=form.cleaned_data['address'])
if len(addr) == 0:
return HttpResponse('{ "status": "ERR", "message": "Address not found."}', content_type='application/json')
# only get first addr
addr = addr[0]
user, created = QuoteUser.objects.get_or_create(username=form.cleaned_data['email'], email=form.cleaned_data['email'])
# disallow login for new users
if created:
user.set_unusable_password()
user.save()
# TODO: fail gracefully
ip = get_client_ip_info(request)
# create download attempt
dla = DownloadAttempt.objects.create(
user=user,
pdf=PDF.objects.filter(address=addr).order_by('-upload_date')[0],
ip=ip.ip,
geolocation="{0}, {1}, {2}".format(
ip.city,
ip.region,
ip.country
)
)
pdf_quotes = PDF.objects.filter(address=addr, code=form.cleaned_data['code']).order_by('upload_date').reverse()
if len(pdf_quotes) == 0:
return HttpResponse('{ "status": "ERR", "message": "Incorrect code"}', content_type='application/json')
pdf_quote = pdf_quotes[0]
dla.code_correct = True
dla.save()
# stop spam; only allow 3 sends in one day
today = date.today()
today_good_attempts = DownloadAttempt.objects.filter(timestamp__day=today.day, timestamp__month=today.month, timestamp__year=today.year, email_sent=True, pdf__address=addr)
if len(today_good_attempts) >= settings.MAX_EMAILS_PER_DAY:
return HttpResponse('{ "status": "ERR", "message": "An email has been sent out for this address ' + str(settings.MAX_EMAILS_PER_DAY) + ' times today. Try again tomorrow." }', content_type='application/json');
# create timestamps
dt_date = datetime.datetime.now()
try:
send_email(form.cleaned_data['email'], addr, pdf_quote, dt_date)
except Exception as e:
print(e)
return HttpResponse('{ "status": "ERR", "message": "Email failed to send."}', content_type='application/json')
# only saves email if it sent
save_email(user, addr, pdf_quote, dt_date)
# only makes successful if email is sent
dla.email_sent = True
dla.save()
return HttpResponse('{ "status": "OK" }', content_type="application/json")
else:
form = CodeForm()
return render(request, 'download/code-form.html', {
'form': form
})
def download_preload(request, addid):
if request.method == 'POST':
code = request.POST.get('code')
email = request.POST.get('email')
form = CodeForm(initial={'code': code, 'email': email})
return render(request, 'download/code-form.html', {
'form': form,
'id': addrid,
})