diff --git a/bin/fail2ban_digest b/bin/fail2ban_digest
index 4bfcd99..dcf67b7 100755
--- a/bin/fail2ban_digest
+++ b/bin/fail2ban_digest
@@ -45,6 +45,63 @@ Regards,
Fail2ban Digest
''')
+default_html_template = Template('''
+
+
+
+
+
+ Hi,
+ This is a digest email of banned IPs since ${creation_date} and ${date_now}:
+
+
+ # |
+ IPs |
+ When |
+
+${digest}
+
+ Regards,
+ Fail2Ban Digest
+
+
+''')
+html_tr_template = Template('''
+ ${count} |
+ ${ip} |
+ ${events} |
+
+''')
+html_error_template = Template('''
+ ${error_msg} |
+
''')
class Ban:
def __init__(self, ip, events):
self.ip = ip
@@ -127,7 +184,7 @@ def add(db, ip):
close_db(db)
return
-def digest(db, delete):
+def digest(db, delete, sort):
db_file = db_location + '/' + db + '.dbm'
new_db_file = db_location + '/.' + db + '.dbm'
try:
@@ -158,22 +215,31 @@ def digest(db, delete):
msg = ''
msg_html = ''
for ban in events_list:
+ msg_html += html_tr_template.substitute(count = len(ban.events), ip = ban.ip, events = '
'.join(ban.events))
msg += '%3d event(s) for IP %-42s: %s\n' %(len(ban.events), ban.ip, ', '.join(ban.events))
+ return (db_creation_date, msg, msg_html)
-def mail_digest(db, mail_to, mail_from, delete, quiet):
+def mail_digest(db, mail_to, mail_from, delete, html, quiet, sort):
msg = EmailMessage()
date_now = datetime.now().strftime(db_date_format)
- creation_date, dgst = digest(db, delete)
+ creation_date, dgst, dgst_html = digest(db, delete, sort)
if dgst == '':
if quiet:
return
else:
dgst = ' No ban event recorded for the named time frame.'
+ dgst_html = html_error_template.substitute(error_msg = dgst)
msg.set_content(default_mail_template.substitute(
creation_date = creation_date,
date_now = date_now,
digest = dgst
))
+ if html:
+ msg.add_alternative(default_html_template.substitute(
+ creation_date = creation_date,
+ date_now = date_now,
+ digest = dgst_html
+ ), subtype = 'html')
msg['To'] = mail_to
msg['From'] = mail_from
msg['Subject'] = '[Fail2Ban] %s: digest for %s %s' % (db, socket.gethostname(), date_now)
@@ -186,9 +252,9 @@ def main(args):
if args.cmd == 'add':
add(args.database, args.ip)
elif args.cmd == 'digest':
- print(digest(args.database, args.delete)[1])
+ print(digest(args.database, args.delete, args.sort)[1])
elif args.cmd == 'maildigest':
- mail_digest(args.database, args.to, args.mail_from, args.delete, args.quiet)
+ mail_digest(args.database, args.to, args.mail_from, args.html, args.delete, args.quiet, args.sort)
elif args.cmd is None:
print('No action specified')
return
@@ -259,6 +325,12 @@ if __name__ == '__main__':
default = True,
help = 'do / don\'t delete current database, next call to add will create a new empty one'
)
+ subcommands[sc].add_argument(
+ '--html', '--no-html',
+ action = store_yesno,
+ default = False,
+ help = 'do / don\'t send the digest in HTML format.'
+ )
subcommands[sc].add_argument(
'--mail-from',
action = 'store',
@@ -271,6 +343,12 @@ if __name__ == '__main__':
default = False,
help = 'do / don\'t send digest if there are no ban events recorded for the named time frame'
)
+ subcommands[sc].add_argument(
+ '--sort', '--no-sort',
+ action = store_yesno,
+ default = True,
+ help = 'do / don\'t sort the digest by repeat event occurrences.'
+ )
subcommands[sc].add_argument(
'--to',
action = 'store',