Skip to content

Commit

Permalink
feat: Implement a PeriodicTask to check the remaining SIB email quota
Browse files Browse the repository at this point in the history
  • Loading branch information
sveneberth committed Aug 10, 2023
1 parent 9e6d95e commit aac640a
Showing 1 changed file with 53 additions and 6 deletions.
59 changes: 53 additions & 6 deletions src/viur/core/email.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import logging, os
import json, base64
from urllib import request
import base64
import json
import logging
import os
from abc import ABC, abstractmethod
from typing import Any, Callable, Union, List, Dict
from typing import Any, Callable, Dict, List, Union
from urllib import request

import requests

from viur.core import db, utils
from viur.core.config import conf
from viur.core import utils, db
from viur.core.tasks import CallDeferred, QueryIter, PeriodicTask, DeleteEntitiesIter
from viur.core.tasks import CallDeferred, DeleteEntitiesIter, PeriodicTask

"""
This module implements an email delivery system for ViUR. Emails will be queued so that we don't overwhelm
Expand Down Expand Up @@ -375,3 +380,45 @@ def validateQueueEntity(entity: db.Entity):
ext = attachment["filename"].split(".")[-1].lower()
if ext not in EmailTransportSendInBlue.allowedExtensions:
raise ValueError("The file-extension %s cannot be send using Send in Blue" % ext)

@PeriodicTask(60 * 60)
@staticmethod
def check_sib_quota() -> None:
"""Periodically checks the remaining SendInBlue email quota.
This task does not have to be enabled.
It automatically checks if the apiKey is configured.
There are three thresholds: 1000, 500, 100
An email will be sent for the lowest threshold that has been undercut.
"""
if conf.get("viur.email.sendInBlue.apiKey") is None:
return # no SIB key, we cannot check

req = requests.get(
"https://api.sendinblue.com/v3/account",
headers={"api-key": conf["viur.email.sendInBlue.apiKey"]},
)
if not req.ok:
logging.error("Failed to fetch SIB account information")
return
data = req.json()
logging.debug(f"SIB account data: {data}")
for plan in data["plan"]:
if plan["type"] == "payAsYouGo":
credits = plan["credits"]
break
else:
credits = -1

logging.info(f"SIB E-Mail credits: {credits}")

for idx, limit in list(enumerate((1000, 500, 100), 1))[::-1]:
if credits < limit:
sendEMailToAdmins(
f"SendInBlue email budget for {conf['viur.instance.project_id']}: "
f"{credits} ({idx}. warning)",
f"The SendInBlue email budget reached {credits} credits "
f"for {data['email']}. Please increase soon.",
)
break

0 comments on commit aac640a

Please sign in to comment.