mirror of
https://github.com/hrfee/jellyfin-accounts.git
synced 2024-12-22 09:00:14 +00:00
Load templates directly, Account for daylight savings time
password reset files use UTC always, which I did not realize when writing the password reset handler as the UK uses UTC and we weren't in daylight savings time. The expiry time is now correctly handled as UTC. An environment is no longer initialised for every email construction, instead the templates are loaded directly.
This commit is contained in:
parent
658f660e19
commit
95989840f1
@ -8,7 +8,7 @@ from email.mime.text import MIMEText
|
|||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from dateutil import parser as date_parser
|
from dateutil import parser as date_parser
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Template
|
||||||
from jellyfin_accounts import config
|
from jellyfin_accounts import config
|
||||||
from jellyfin_accounts import email_log as log
|
from jellyfin_accounts import email_log as log
|
||||||
|
|
||||||
@ -35,8 +35,15 @@ class Email:
|
|||||||
+ f"({self.from_name})"
|
+ f"({self.from_name})"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
# sp = Path(config["invite_emails"]["email_
|
||||||
|
# template_loader = FileSystemLoader(searchpath=sp)
|
||||||
|
# template_loader = PackageLoader("jellyfin_accounts", "data")
|
||||||
|
# self.template_env = Environment(loader=template_loader)
|
||||||
|
|
||||||
def pretty_time(self, expiry):
|
def pretty_time(self, expiry, tzaware=False):
|
||||||
|
if tzaware:
|
||||||
|
current_time = datetime.datetime.utcnow().replace(tzinfo=pytz.utc)
|
||||||
|
else:
|
||||||
current_time = datetime.datetime.now()
|
current_time = datetime.datetime.now()
|
||||||
date = expiry.strftime(config["email"]["date_format"])
|
date = expiry.strftime(config["email"]["date_format"])
|
||||||
if config.getboolean("email", "use_24h"):
|
if config.getboolean("email", "use_24h"):
|
||||||
@ -68,12 +75,9 @@ class Email:
|
|||||||
invite_link = config["invite_emails"]["url_base"]
|
invite_link = config["invite_emails"]["url_base"]
|
||||||
invite_link += "/" + invite["code"]
|
invite_link += "/" + invite["code"]
|
||||||
for key in ["text", "html"]:
|
for key in ["text", "html"]:
|
||||||
sp = Path(config["invite_emails"]["email_" + key]) / ".."
|
fpath = Path(config["invite_emails"]["email_" + key])
|
||||||
sp = str(sp.resolve()) + "/"
|
with open(fpath, 'r') as f:
|
||||||
template_loader = FileSystemLoader(searchpath=sp)
|
template = Template(f.read())
|
||||||
template_env = Environment(loader=template_loader)
|
|
||||||
fname = Path(config["invite_emails"]["email_" + key]).name
|
|
||||||
template = template_env.get_template(fname)
|
|
||||||
c = template.render(
|
c = template.render(
|
||||||
expiry_date=pretty["date"],
|
expiry_date=pretty["date"],
|
||||||
expiry_time=pretty["time"],
|
expiry_time=pretty["time"],
|
||||||
@ -89,12 +93,9 @@ class Email:
|
|||||||
log.debug(f'Constructing expiry notification for {invite["code"]}')
|
log.debug(f'Constructing expiry notification for {invite["code"]}')
|
||||||
expiry = format_datetime(invite["expiry"])
|
expiry = format_datetime(invite["expiry"])
|
||||||
for key in ["text", "html"]:
|
for key in ["text", "html"]:
|
||||||
sp = Path(config["notifications"]["expiry_" + key]) / ".."
|
fpath = Path(config["notifications"]["expiry_" + key])
|
||||||
sp = str(sp.resolve()) + "/"
|
with open(fpath, 'r') as f:
|
||||||
template_loader = FileSystemLoader(searchpath=sp)
|
template = Template(f.read())
|
||||||
template_env = Environment(loader=template_loader)
|
|
||||||
fname = Path(config["notifications"]["expiry_" + key]).name
|
|
||||||
template = template_env.get_template(fname)
|
|
||||||
c = template.render(code=invite["code"], expiry=expiry)
|
c = template.render(code=invite["code"], expiry=expiry)
|
||||||
self.content[key] = c
|
self.content[key] = c
|
||||||
log.info(f"{self.address}: {key} constructed")
|
log.info(f"{self.address}: {key} constructed")
|
||||||
@ -102,19 +103,16 @@ class Email:
|
|||||||
|
|
||||||
def construct_created(self, invite):
|
def construct_created(self, invite):
|
||||||
self.subject = "Notice: User created"
|
self.subject = "Notice: User created"
|
||||||
log.debug(f'Constructing expiry notification for {invite["code"]}')
|
log.debug(f'Constructing user creation notification for {invite["code"]}')
|
||||||
created = format_datetime(invite["created"])
|
created = format_datetime(invite["created"])
|
||||||
if config.getboolean("email", "no_username"):
|
if config.getboolean("email", "no_username"):
|
||||||
email = "n/a"
|
email = "n/a"
|
||||||
else:
|
else:
|
||||||
email = invite["address"]
|
email = invite["address"]
|
||||||
for key in ["text", "html"]:
|
for key in ["text", "html"]:
|
||||||
sp = Path(config["notifications"]["created_" + key]) / ".."
|
fpath = Path(config["notifications"]["created_" + key])
|
||||||
sp = str(sp.resolve()) + "/"
|
with open(fpath, 'r') as f:
|
||||||
template_loader = FileSystemLoader(searchpath=sp)
|
template = Template(f.read())
|
||||||
template_env = Environment(loader=template_loader)
|
|
||||||
fname = Path(config["notifications"]["created_" + key]).name
|
|
||||||
template = template_env.get_template(fname)
|
|
||||||
c = template.render(
|
c = template.render(
|
||||||
code=invite["code"],
|
code=invite["code"],
|
||||||
username=invite["username"],
|
username=invite["username"],
|
||||||
@ -131,22 +129,18 @@ class Email:
|
|||||||
log.debug(f"{self.address}: Constructing email content")
|
log.debug(f"{self.address}: Constructing email content")
|
||||||
try:
|
try:
|
||||||
expiry = date_parser.parse(reset["ExpirationDate"])
|
expiry = date_parser.parse(reset["ExpirationDate"])
|
||||||
expiry = expiry.replace(tzinfo=None)
|
|
||||||
except:
|
except:
|
||||||
log.error(f"{self.address}: Couldn't parse expiry time")
|
log.error(f"{self.address}: Couldn't parse expiry time")
|
||||||
return False
|
return False
|
||||||
current_time = datetime.datetime.now()
|
current_time = datetime.datetime.utcnow().replace(tzinfo=pytz.utc)
|
||||||
if expiry >= current_time:
|
if expiry >= current_time:
|
||||||
log.debug(f"{self.address}: Invite valid")
|
log.debug(f"{self.address}: Invite valid")
|
||||||
pretty = self.pretty_time(expiry)
|
pretty = self.pretty_time(expiry, tzaware=True)
|
||||||
email_message = config["email"]["message"]
|
email_message = config["email"]["message"]
|
||||||
for key in ["text", "html"]:
|
for key in ["text", "html"]:
|
||||||
sp = Path(config["password_resets"]["email_" + key]) / ".."
|
fpath = Path(config["password_resets"]["email_" + key])
|
||||||
sp = str(sp.resolve()) + "/"
|
with open(fpath, 'r') as f:
|
||||||
template_loader = FileSystemLoader(searchpath=sp)
|
template = Template(f.read())
|
||||||
template_env = Environment(loader=template_loader)
|
|
||||||
fname = Path(config["password_resets"]["email_" + key]).name
|
|
||||||
template = template_env.get_template(fname)
|
|
||||||
c = template.render(
|
c = template.render(
|
||||||
username=reset["UserName"],
|
username=reset["UserName"],
|
||||||
expiry_date=pretty["date"],
|
expiry_date=pretty["date"],
|
||||||
@ -169,6 +163,11 @@ class Email:
|
|||||||
|
|
||||||
|
|
||||||
class Mailgun(Email):
|
class Mailgun(Email):
|
||||||
|
errors = {
|
||||||
|
400: "Mailgun failed with 400: Bad request",
|
||||||
|
401: "Mailgun failed with 401: Invalid API key",
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, address):
|
def __init__(self, address):
|
||||||
super().__init__(address)
|
super().__init__(address)
|
||||||
self.api_url = config["mailgun"]["api_url"]
|
self.api_url = config["mailgun"]["api_url"]
|
||||||
@ -190,7 +189,12 @@ class Mailgun(Email):
|
|||||||
if response.ok:
|
if response.ok:
|
||||||
log.info(f"{self.address}: Sent via mailgun.")
|
log.info(f"{self.address}: Sent via mailgun.")
|
||||||
return True
|
return True
|
||||||
log.debug(f"{self.address}: Mailgun: {response.status_code}")
|
elif response.status_code in Mailgun.errors:
|
||||||
|
log.error(f"{self.address}: {Mailgun.errors[response.status_code]}")
|
||||||
|
else:
|
||||||
|
log.error(
|
||||||
|
f"{self.address}: Mailgun failed with error {response.status_code}"
|
||||||
|
)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@ -238,9 +242,9 @@ class Smtp(Email):
|
|||||||
log.info(f"{self.address}: Sent via smtp (starttls)")
|
log.info(f"{self.address}: Sent via smtp (starttls)")
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
err = f"{self.address}: Failed to send via smtp: "
|
log.error(
|
||||||
err += type(e).__name__
|
f"{self.address}: Failed to send via smtp ({type(e).__name__}: {e.args})"
|
||||||
log.error(err)
|
)
|
||||||
try:
|
try:
|
||||||
log.error(e.smtp_error)
|
log.error(e.smtp_error)
|
||||||
except:
|
except:
|
||||||
|
Loading…
Reference in New Issue
Block a user