Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/mailing list #47

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
86 changes: 86 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@
from secrets import token_bytes
from address import get_addresses
from slugify import slugify
from requests.exceptions import HTTPError

import json
import logging
import os
import sys
import requests
import hashlib

app = Flask(__name__)
app.logger.addHandler(logging.StreamHandler(sys.stdout))
Expand All @@ -43,6 +46,28 @@
app.secret_key = skey


""" For developers running on a newer version of openssl:
A recent update to openssl was pushed to fix something
called a logjam attack. The ciphers that are being used
in some of the libs mustn't be up to date yet which
may cause errors when running the server in a dev env.
This try/catch bypasses the requirement of a longer key.
"""
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += "HIGH:!DH:!aNULL"
try:
requests.packages.urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST += (
"HIGH:!DH:!aNULL"
davidswarbrick marked this conversation as resolved.
Show resolved Hide resolved
)
except AttributeError:
# no pyopenssl support used / needed / available
pass


url = "https://us10.api.mailchimp.com/3.0/lists/{}/members/".format(
os.environ["MCLIST_ID"]
)


@app.before_request
def force_https():
criteria = [
Expand Down Expand Up @@ -129,3 +154,64 @@ def display_template(template_slug):
matching_templates, name, postcode, address
)
return render_template("single_email.html", email=email_template[0])


@app.route("/newsletter/subscribe", methods=["POST"])
def subscribe_to_newsletter():

post_params = {"email_address": request.form["email"], "status": "subscribed"}
r = requests.post(
url, auth=("foo", os.environ["MAILCHIMP_SECRET_KEY"]), json=post_params
davidswarbrick marked this conversation as resolved.
Show resolved Hide resolved
)
try:
r.raise_for_status()
except HTTPError:
return jsonify(status="failed")

return jsonify(status="success")


@app.route("/newsletter/check", methods=["POST"])
def check_user_newsletter():

print(request.form)
email = request.form["email"].encode("utf-8")
user_hash = hashlib.md5(email).hexdigest()
req_url = "{}{}".format(url, user_hash)
print(req_url)
r = requests.get(req_url, auth=("foo", os.environ["MAILCHIMP_SECRET_KEY"]))
try:
r.raise_for_status()
except HTTPError:
return jsonify(status="failed")

return jsonify(status="success", action=request.form["action"], user=user_hash)


@app.route("/newsletter/unsubscribe", methods=["POST"])
def unsubscribe_user_newsletter():
print(request.form)
req_url = "{}{}".format(url, request.form["user"])
print(req_url)
r = requests.delete(req_url, auth=("foo", os.environ["MAILCHIMP_SECRET_KEY"]))
try:
r.raise_for_status()
except HTTPError:
return jsonify(status="failed")

return jsonify(status="success")


@app.route("/newsletter/permanently_delete", methods=["POST"])
def permanently_delete_user_newsletter():

print(request.form)
req_url = "{}{}/actions/delete-permanent".format(url, request.form["user"])
print(req_url)
r = requests.post(req_url, auth=("foo", os.environ["MAILCHIMP_SECRET_KEY"]))
try:
r.raise_for_status()
except HTTPError:
return jsonify(status="failed")

return jsonify(status="success")
235 changes: 235 additions & 0 deletions templates/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,243 @@
<a href="{{ url_for('aboutus')}}">About us.</a>
<br>
<a href="mailto:[email protected]?subject=Website%20Issue%3A&body=Issue%20Description%3A">Found an issue with the website? Report it here.</a>
<br>
<a data-toggle="modal" href="" data-target="#unsubChoiceModal">Unsubscribe from our mailing list</a>
</footer>
</body>



<div class="modal fade" id="unsubChoiceModal" tabindex="-1" role="dialog" aria-labelledby="unsubChoiceModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="unsubChoiceModalLabel">Unsubscribe</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div>
Consider subscribing to our newsletter to receive updates about new templates and upcoming features
</div>
<div>
<label class="control-label">E-Mail Address</label>
<div>
<input type="email" class="form-control" required name="email" id="email-input" data-placement='bottom' title='Please enter a valid email address' placeholder="[email protected]">
</div>
</div>
</div>

<div class="modal-footer">
<button class="btn btn-warning mb-1" id="unsub-button" >Unsubscribe</button>
<button class="btn btn-danger mb-1" id="perm-delete-button">Permanently delete</button>
</div>

</div>
</div>
</div>


<div class="modal fade" id="unsubConfirmModal" tabindex="-1" role="dialog" aria-labelledby="unsubConfirmModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="unsubConfirmModalLabel">Unsubscribe</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form id="unsub-confirm-form" style="display: none">
<input type="text" id="user-hash">
</form>
<div id="unsub-confirm-warning">

</div>
</div>

<div class="modal-footer">
<button class="btn btn-danger mb-1" form="unsub-confirm-form" id="unsub-confirm-button"></button>
<button class="btn btn-success mb-1" data-dismiss="modal">Cancel</button>
</div>

</div>
</div>
</div>

<div class="modal fade" id="unknownUserModal" tabindex="-1" role="dialog" aria-labelledby="unknownUserModal" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="unknownUserModal">Unsubscribe</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div>
The email you have entered is not in our database, make sure you have entered it correctly.
</div>
</div>

<div class="modal-footer">
<button class="btn btn-primary mb-1" data-dismiss="modal">Ok</button>
</div>

</div>
</div>
</div>

<div class="modal fade" id="successfulUnsubModal" tabindex="-1" role="dialog" aria-labelledby="successfulUnsubModal" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="successfulUnsubModal">Unsubscribe</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div id="successful-unsub-info">

</div>
</div>

<div class="modal-footer">
<button class="btn btn-primary mb-1" data-dismiss="modal">Ok</button>
</div>

</div>
</div>
</div>

<!--
Have a modal which asks between unsub and perm del. Have a listener on each button which runs a js func which depending on the button which called it will fill a
modal with an email form which will check for the existence of the email in the db. If email is in the db then another modal pops up telling that their mail is
in the db and will ask to confirm action.
-->

<script type="text/javascript">

function checkEmail()
{
var email = document.getElementById('email-input');
if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email.value))
{
return (true)
}
$('#email-input').tooltip('show');
return (false)
}

function mailCheckSubmit(event)
{
if ( checkEmail() == true)
{
var target_id = event.target.id;
var request = new XMLHttpRequest();
request.addEventListener('load', mailCheckShow);
request.open('POST', {{ url_for('check_user_newsletter') | tojson}});
var form = new FormData();
form.append('email', document.getElementById('email-input').value)
form.append('action', target_id);
request.send(form);
}
}

function mailCheckShow()
{
var response = JSON.parse(this.responseText);
$('#unsubChoiceModal').modal('hide');
if (response.status == 'success')
{
document.getElementById('user-hash').value = response.user;
if (response.action == 'unsub-button')
{
$('#unsub-confirm-warning').text('Are you sure you want to unsubscribe from our newsletter? This action is reversible.');
$('#unsub-confirm-button').text('Unsubscribe');

document.getElementById('unsub-confirm-form').addEventListener('submit', unsubscribe);
}

if (response.action == 'perm-delete-button')
{
$('#unsub-confirm-warning').text('Are you sure you want to unsubscribe from our newsletter? This action is irreversible.');
$('#unsub-confirm-button').text('Permanently delete');

document.getElementById('unsub-confirm-form').addEventListener('submit', permanently_delete);
}
$('#unsubConfirmModal').modal('show');
}
else if (response.status == 'failed')
{
$('#unknownUserModal').modal('show');
}
}

function unsubscribe(ev)
{
document.getElementById('unsub-confirm-form').removeEventListener('submit', unsubscribe);
ev.preventDefault();
var request = new XMLHttpRequest();
request.addEventListener('load', unsub_outcome);
request.open('POST', {{url_for('unsubscribe_user_newsletter') | tojson}});
var form = new FormData();
form.append('user', document.getElementById('user-hash').value );
request.send(form);
}

function permanently_delete(ev)
{
document.getElementById('unsub-confirm-form').removeEventListener('submit', permanently_delete);
ev.preventDefault();
var request = new XMLHttpRequest();
request.addEventListener('load', perm_delete_outcome);
request.open('POST', {{url_for('permanently_delete_user_newsletter') | tojson}});
var form = new FormData();
form.append('user', document.getElementById('user-hash').value );
request.send(form);
}

function unsub_outcome()
{
$("#unsubConfirmModal").modal('hide');
var response = JSON.parse(this.responseText);
if (response.status == 'success')
{
$("#successful-unsub-info").text('You are no longer subscribed to our newsletter');
}
else if (response.status == 'failed')
{
$("#successful-unsub-info").text('There was a problem with removing your subscription, please try again later');
}
$('#successfulUnsubModal').modal('show');
}

function perm_delete_outcome()
{
$("#unsubConfirmModal").modal('hide');
var response = JSON.parse(this.responseText);
if (response.status == 'success')
{
$("#successful-unsub-info").text('We have successfully deleted your profile from our database');
}
else if (response.status == 'failed')
{
$("#successful-unsub-info").text('There was a problem with removing you from our database, please try again later');
}
$('#successfulUnsubModal').modal('show');

}


var unsub = document.getElementById('unsub-button');
unsub.addEventListener('click', mailCheckSubmit);

var perm_delete = document.getElementById('perm-delete-button');
perm_delete.addEventListener('click', mailCheckSubmit);

</script>

</html>
Loading