added automatic waitlist email sending
This commit is contained in:
@@ -2,6 +2,7 @@ from flask import Flask
|
|||||||
from app.config import Config
|
from app.config import Config
|
||||||
from app.extensions import db, mail, limiter
|
from app.extensions import db, mail, limiter
|
||||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||||
|
import logging
|
||||||
|
|
||||||
def create_app(config_class=Config):
|
def create_app(config_class=Config):
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
@@ -9,6 +10,10 @@ def create_app(config_class=Config):
|
|||||||
|
|
||||||
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)
|
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)
|
||||||
|
|
||||||
|
gunicorn_logger = logging.getLogger("gunicorn.error")
|
||||||
|
app.logger.handlers = gunicorn_logger.handlers
|
||||||
|
app.logger.setLevel(gunicorn_logger.level)
|
||||||
|
|
||||||
# Initialize extensions
|
# Initialize extensions
|
||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
mail.init_app(app)
|
mail.init_app(app)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ def send_verification_email(user, is_new=True):
|
|||||||
msg = Message('Verify your CTF Registration', recipients=[user.email])
|
msg = Message('Verify your CTF Registration', recipients=[user.email])
|
||||||
msg.html = render_template("email.html", user_name=user.name, register_link=register_link, remove_link=remove_link, logo_url=logo)
|
msg.html = render_template("email.html", user_name=user.name, register_link=register_link, remove_link=remove_link, logo_url=logo)
|
||||||
mail.send(msg)
|
mail.send(msg)
|
||||||
|
current_app.logger.info(f"Sent verification email to {user.email}")
|
||||||
user.num_emails_sent += 1
|
user.num_emails_sent += 1
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
if is_new:
|
if is_new:
|
||||||
@@ -43,8 +44,24 @@ def send_waitlist_email(user):
|
|||||||
msg = Message('h4tum CTF 2026 Registration', recipients=[user.email])
|
msg = Message('h4tum CTF 2026 Registration', recipients=[user.email])
|
||||||
logo = url_for('static', filename='h4tum_white.png', _external=True)
|
logo = url_for('static', filename='h4tum_white.png', _external=True)
|
||||||
msg.html = render_template("waitlist_email.html", logo_url=logo, user_name=user.name)
|
msg.html = render_template("waitlist_email.html", logo_url=logo, user_name=user.name)
|
||||||
|
current_app.logger.info(msg)
|
||||||
mail.send(msg)
|
mail.send(msg)
|
||||||
|
|
||||||
|
def send_waitlist_newsletter():
|
||||||
|
results = db.session.query(Participant.email).filter(Participant.on_waitlist == True).all()
|
||||||
|
waitlist_emails = [r[0] for r in results]
|
||||||
|
logo = url_for('static', filename='h4tum_white.png', _external=True)
|
||||||
|
s = URLSafeTimedSerializer(current_app.config['SECRET_KEY'])
|
||||||
|
for email in waitlist_emails:
|
||||||
|
register_token = s.dumps(email, salt='email-confirm-h4tum-ctf-2025')
|
||||||
|
register_link = url_for('main.verify_email', token=register_token, _external=True)
|
||||||
|
remove_token = s.dumps(email, salt='email-remove-h4tum-ctf-2026')
|
||||||
|
remove_link = url_for('main.remove_registration', token=remove_token, _external=True)
|
||||||
|
msg = Message('h4tum CTF 2026 Free Spot available', recipients=[email])
|
||||||
|
msg.html = render_template("waitlist_maillist_email.html", logo_url=logo, register_link=register_link, remove_link=remove_link)
|
||||||
|
mail.send(msg)
|
||||||
|
current_app.logger.info(f"Sent waitlist newsletter email to {email}")
|
||||||
|
|
||||||
@bp.route('/', methods=['GET', 'POST'])
|
@bp.route('/', methods=['GET', 'POST'])
|
||||||
@limiter.limit("5 per hour", methods=["POST"])
|
@limiter.limit("5 per hour", methods=["POST"])
|
||||||
def index():
|
def index():
|
||||||
@@ -109,9 +126,11 @@ def verify_email(token):
|
|||||||
if user.confirmed:
|
if user.confirmed:
|
||||||
return render_template('success.html', message="You are confirmed", discord_link=current_app.config['DISCORD_LINK'], discord_token=user.discord_token)
|
return render_template('success.html', message="You are confirmed", discord_link=current_app.config['DISCORD_LINK'], discord_token=user.discord_token)
|
||||||
else:
|
else:
|
||||||
return render_template("error.html", error_message="Sorry! The event filled up while you were verifying.")
|
return render_template("error.html", error_message="Sorry! The event filled up while you were claiming the last spot.")
|
||||||
else:
|
else:
|
||||||
user.confirmed = True
|
user.confirmed = True
|
||||||
|
if user.on_waitlist:
|
||||||
|
user.on_waitlist = False
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
discord_link = current_app.config['DISCORD_LINK']
|
discord_link = current_app.config['DISCORD_LINK']
|
||||||
@@ -137,16 +156,14 @@ def remove_registration(token):
|
|||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
return render_template("error.html", error_message="No user found.")
|
return render_template("error.html", error_message="No user found.")
|
||||||
|
db.session.delete(user)
|
||||||
try:
|
db.session.commit()
|
||||||
db.session.delete(user)
|
|
||||||
db.session.commit()
|
if get_confirmed_count() == current_app.config['MAX_SPOTS'] - 1:
|
||||||
return render_template("deregistered.html", message="Sad to see you go. Comeback next time :D")
|
send_waitlist_newsletter()
|
||||||
except:
|
|
||||||
db.session.rollback()
|
return render_template("deregistered.html", message="Sad to see you go. Comeback next time :D")
|
||||||
return render_template("error.html", error_message="Removing user did not work")
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/dsgvo')
|
@bp.route('/dsgvo')
|
||||||
@limiter.exempt
|
@limiter.exempt
|
||||||
def dsgvo():
|
def dsgvo():
|
||||||
|
|||||||
69
app/templates/waitlist_maillist_email.html
Normal file
69
app/templates/waitlist_maillist_email.html
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<html>
|
||||||
|
<body style="margin: 0; padding: 0; background-color: #1a1a1a; font-family: 'Courier New', Courier, monospace; color: #ffffff;">
|
||||||
|
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="background-color: #1a1a1a; padding: 20px;">
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="max-width: 600px; background-color: #222222; border: 1px solid #00ff00; padding: 30px;">
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding-bottom: 20px;">
|
||||||
|
<img src="{{ logo_url }}" alt="Club Logo" width="150" style="display: block; border: 0;">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding-bottom: 20px;">
|
||||||
|
<h1 style="color: #00ff00; font-size: 24px; margin: 0; text-transform: uppercase; text-align: center;">Registration Received</h1>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding-bottom: 30px; font-size: 16px; line-height: 1.5; text-align: center;">
|
||||||
|
A spot has just become available for h4tum CTF 2026! Be fast and claim it!
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding-bottom: 30px;">
|
||||||
|
<table border="0" cellspacing="0" cellpadding="0" align="center">
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#00ff00" style="padding: 15px 25px;">
|
||||||
|
<a href="{{ register_link }}" target="_blank" style="font-size: 18px; font-weight: bold; color: #000000; text-decoration: none; display: inline-block;">
|
||||||
|
CLAIM THE SPOT
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding-bottom: 30px; font-size: 16px; line-height: 1.5; text-align: center;">
|
||||||
|
If you can not attend anymore / don't want to receive any further emails:
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding-bottom: 30px;">
|
||||||
|
<table border="0" cellspacing="0" cellpadding="0" align="center">
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#D32F2F" style="padding: 15px 25px;">
|
||||||
|
<a href="{{ remove_link }}" target="_blank" style="font-size: 18px; font-weight: bold; color: #000000; text-decoration: none; display: inline-block;">
|
||||||
|
DEREGISTER
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding-top: 20px; border-top: 1px solid #333333; font-size: 12px; color: #888888; text-align: center;">
|
||||||
|
This email is sent automatically every time a place becomes available. You can unsubscribe by pressing the big red button.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user