Send report with emailcheck

This commit is contained in:
Stefan Bethke 2024-05-25 13:35:09 +02:00
parent 5fc42907e3
commit 89b0659cba
2 changed files with 30 additions and 21 deletions

View file

@ -75,7 +75,7 @@ Command is one of:
|------------|------------------------------------------------------------------------------------------------------------| |------------|------------------------------------------------------------------------------------------------------------|
| check | Print a list of revisions and notes that would be expired, based on the given parameters for `-n` and `-r` | | check | Print a list of revisions and notes that would be expired, based on the given parameters for `-n` and `-r` |
| cron | Run `expire` at 2 am local time each day. Will run until killed. | | cron | Run `expire` at 2 am local time each day. Will run until killed. |
| emailcheck | Send a test email from the configured sender to themselves. | | emailcheck | Send an email from the configured sender to themselves with the the check report. |
| expire | Expire old revisions and notes. | | expire | Expire old revisions and notes. |
### Environment variables ### Environment variables

View file

@ -69,7 +69,7 @@ class EmailSender:
except Exception as e: except Exception as e:
print(f'Unable to send mail through {self}: {e}') print(f'Unable to send mail through {self}: {e}')
raise e raise e
print(f'Test email to {self.mail_from} sent successfully.') print(f'Report email to {self.mail_from} sent successfully.')
def __str__(self): def __str__(self):
return f'EmailSender<{self.hostname},{self.port},{self.username},{self.mail_from}>' return f'EmailSender<{self.hostname},{self.port},{self.username},{self.mail_from}>'
@ -168,26 +168,29 @@ class HedgedocExpire:
}) })
return revisions return revisions
def check_notes_to_be_expired(self, db) -> None: def check_notes_to_be_expired(self, db) -> str:
""" """
Print a list of notes that will be expired. Return a list of notes that will be expired.
:param db: the database connection :param db: the database connection
:return: :return: a multi-line text suitable for humans to read
""" """
r = ''
cutoff = datetime.now(timezone.utc) - self.config.note_age cutoff = datetime.now(timezone.utc) - self.config.note_age
print(f'Notes to be deleted not changed since {cutoff} ({humanize.naturaldelta(self.config.note_age)}):') r += f'Notes to be deleted not changed since {cutoff} ({humanize.naturaldelta(self.config.note_age)}):\n'
for note in self.notes_to_be_expired(db): for note in self.notes_to_be_expired(db):
age = datetime.now(timezone.utc) - datetime.fromisoformat(note['updatedAt']) age = datetime.now(timezone.utc) - datetime.fromisoformat(note['updatedAt'])
url = self.config.url + '/' + (note["alias"] if note["alias"] is not None else note["shortid"]) url = self.config.url + '/' + (note["alias"] if note["alias"] is not None else note["shortid"])
print(f' {self.email_from_email_or_profile(note)} ({humanize.naturaldelta(age)}) {url}: {note["title"]}') r += f' {self.email_from_email_or_profile(note)} ({humanize.naturaldelta(age)}) {url}: {note["title"]}\n'
return r
def check_revisions_to_be_expired(self, db) -> None: def check_revisions_to_be_expired(self, db) -> str:
""" """
Print a list of revisions that will be expired. Return a list of revisions that will be expired.
:return: :return: a multi-line text suitable for humans to read
""" """
r = ''
cutoff = datetime.now(timezone.utc) - self.config.revision_age cutoff = datetime.now(timezone.utc) - self.config.revision_age
print(f'Revisions to be deleted created before {cutoff} ({humanize.naturaldelta(self.config.revision_age)}):') r += f'Revisions to be deleted created before {cutoff} ({humanize.naturaldelta(self.config.revision_age)}):\n'
notes = {} notes = {}
for row in self.revisions_to_be_expired(db): for row in self.revisions_to_be_expired(db):
row['age'] = datetime.now(timezone.utc) - datetime.fromisoformat(row['createdAt']) row['age'] = datetime.now(timezone.utc) - datetime.fromisoformat(row['createdAt'])
@ -198,9 +201,10 @@ class HedgedocExpire:
addr = self.email_from_email_or_profile(revisions[0]) addr = self.email_from_email_or_profile(revisions[0])
url = self.config.url + '/' + ( url = self.config.url + '/' + (
revisions[0]["alias"] if revisions[0]["alias"] is not None else revisions[0]["shortid"]) revisions[0]["alias"] if revisions[0]["alias"] is not None else revisions[0]["shortid"])
print(f' {addr} {url}: {revisions[0]["title"]}') r += f' {addr} {url}: {revisions[0]["title"]}\n'
for rev in revisions: for rev in revisions:
print(f' {humanize.naturaldelta(rev["age"])}: {rev["revisionId"]}') r += f' {humanize.naturaldelta(rev["age"])}: {rev["revisionId"]}\n'
return r
def expire_old_notes(self, db) -> None: def expire_old_notes(self, db) -> None:
""" """
@ -256,16 +260,21 @@ class HedgedocExpire:
def cmd_check(self) -> None: def cmd_check(self) -> None:
with pgsql.Connection((self.config.postgres_hostname, self.config.postgres_port), with pgsql.Connection((self.config.postgres_hostname, self.config.postgres_port),
self.config.postgres_username, self.config.postgres_password) as db: self.config.postgres_username, self.config.postgres_password) as db:
self.check_revisions_to_be_expired(db) print(self.check_revisions_to_be_expired(db) +
self.check_notes_to_be_expired(db) self.check_notes_to_be_expired(db))
def cmd_emailcheck(self) -> None: def cmd_emailcheck(self) -> None:
with pgsql.Connection((self.config.postgres_hostname, self.config.postgres_port),
self.config.postgres_username, self.config.postgres_password) as db:
report = self.check_revisions_to_be_expired(db) + self.check_notes_to_be_expired(db)
msg = MIMEMultipart() msg = MIMEMultipart()
msg['From'] = self.email_sender.mail_from msg['From'] = self.email_sender.mail_from
msg['To'] = self.email_sender.mail_from msg['To'] = self.email_sender.mail_from
msg['Subject'] = f'Hedgedoc Expire: Test Mail' msg['Subject'] = f'Hedgedoc Expire: Report'
msg.attach(MIMEText(dedent(f'''\ msg.attach(MIMEText(dedent(f'''\
This is a test email to confirm proper configuration of the SMTP client. This report shows which notes and revisions would be deleted if expire would be run now.
''') + report + dedent(f'''\
The admin team for {self.config.url} The admin team for {self.config.url}
'''))) ''')))
@ -292,7 +301,7 @@ def main():
command is one of: command is one of:
- check: print a list of revisions and notes to be expired - check: print a list of revisions and notes to be expired
- cron: run expire every 24 hours - cron: run expire every 24 hours
- emailcheck: send a test email from the configured sender to themselves - emailcheck: send am email from the configured sender to themselves with the the check report
- expire: expire old revisions and untouched notes - expire: expire old revisions and untouched notes
See https://git.hamburg.ccc.de/CCCHH/hedgedoc-expire See https://git.hamburg.ccc.de/CCCHH/hedgedoc-expire