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 ,
} )