Commit 556bd33f authored by Roland Denis's avatar Roland Denis
Browse files

Send mail if job offer form is flooded

Mail is sent only when flood is detected, but not for following
submission failures.
parent 694beb7d
Pipeline #4484 passed with stages
in 55 seconds
......@@ -116,6 +116,12 @@ FLOOD_GLOBAL_LIMIT = 10
FLOOD_LOCAL_TIMEOUT = datetime.timedelta(minutes=5)
FLOOD_LOCAL_LIMIT = 3
# Mail config in case of flood
MAIL_SMTP_SERVER = "172.116.101.1"
MAIL_SENDER = "calcul-owner@math.cnrs.fr"
MAIL_RECEIVERS = ["denis@math.univ-lyon1.fr"]
###############################################################################
class Debug(object):
""" Debugging parameters. """
......@@ -235,12 +241,8 @@ class FloodChecker():
""" Remove previously created submission file """
os.remove(os.path.join(FLOOD_PATH, self.file_name))
def approve_submission(self, client_id):
""" Check if a new submission can be accepted. Return bool and waiting delay. """
# First, create a submission file even if it will be deleted if submission is rejected
# It avoids flooding at the exact same time.
self._create_submission_file(client_id)
def _read_and_calc_delays(self, client_id):
""" Read submission files and return new submission delays for the given client """
self._read_files()
# Calculate submission delays
......@@ -248,25 +250,51 @@ class FloodChecker():
local_delay = self._local_submission_delay(client_id)
delay = max(global_delay, local_delay)
if delay.total_seconds() == 0: # No delay => OK
return True, delay
else: # Otherwise => KO and submission file is removed
flood_details = "[FLOOD] client_id={} client_hash={} global_stats={} global_delay={} local_stats={} local_delay={}".format(
pprint.pformat(client_id),
pprint.pformat(self._client_id_hexdigest(client_id)),
pprint.pformat(self.global_stats),
pprint.pformat(global_delay),
pprint.pformat(self.local_stats),
pprint.pformat(local_delay),
)
print(flood_details, file=sys.stderr)
#TODO: mail
return global_delay, local_delay, delay
def _create_flood_report(self, client_id, global_delay, local_delay):
""" Return message that describe current flooding state for the given client """
return "[FLOOD] client_id={} client_hash={} global_stats={} global_delay={} local_stats={} local_delay={}".format(
pprint.pformat(client_id),
pprint.pformat(self._client_id_hexdigest(client_id)),
pprint.pformat(self.global_stats),
pprint.pformat(global_delay),
pprint.pformat(self.local_stats),
pprint.pformat(local_delay),
)
def approve_submission(self, client_id):
""" Check if a new submission can be accepted. Return bool and waiting delay. """
# First, check current flooding state so that to avoid spamming mail
# if it has already been reported.
global_delay, local_delay, delay = self._read_and_calc_delays(client_id)
# If flooding was already reported, send new report only to webserver log
if delay.total_seconds() > 0:
flood_report = self._create_flood_report(client_id, global_delay, local_delay)
print(flood_report, file=sys.stderr)
return False, delay
# Then, create a submission file and recheck flood state.
# It avoids flooding at the exact same time.
self._create_submission_file(client_id)
global_delay, local_delay, delay = self._read_and_calc_delays(client_id)
# If new flood is detected, send report to webserver log *and* send a mail.
if delay.total_seconds() > 0:
flood_report = self._create_flood_report(client_id, global_delay, local_delay)
print(flood_report, file=sys.stderr)
self._remove_submission_file()
# Send report by mail
import smtplib
with smtplib.SMTP(MAIL_SMTP_SERVER) as smtp:
smtp.sendmail(MAIL_SENDER, MAIL_RECEIVERS, "Subject: Flooding du formulaire d'offre d'emploi\n\n" + flood_report)
return False, delay
# No delay => OK
return True, delay
###############################################################################
class FormData(object):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment