initial commit of bin scripts into git
This commit is contained in:
182
node-collector-mail-synth-transaction
Executable file
182
node-collector-mail-synth-transaction
Executable file
@@ -0,0 +1,182 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
|
||||
import smtplib, imaplib
|
||||
import random
|
||||
import logging
|
||||
from datetime import datetime
|
||||
import os, time, shutil
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
def days_between(d1, d2):
|
||||
return abs((d2 - d1).days)
|
||||
|
||||
def need_to_rotate_log(logfile):
|
||||
# the log file contains the date per line, so get first line of log, it is
|
||||
# when the log started
|
||||
try:
|
||||
file_obj = open(logfile, 'r')
|
||||
except:
|
||||
return 0
|
||||
Lines = file_obj.readlines()
|
||||
first_line = Lines[0]
|
||||
file_obj.close()
|
||||
|
||||
# get just the data to convert
|
||||
m = re.search('(\d+:\d+:\d+ \d+-\d+-\d+) .*', first_line)
|
||||
start_of_file = datetime. strptime(m.group(1), '%H:%M:%S %d-%m-%y')
|
||||
now = datetime.now()
|
||||
log_file_age_days = days_between(now, start_of_file )
|
||||
return log_file_age_days > 7
|
||||
|
||||
# function that sends a message using smtp to port 467
|
||||
def SendMessage( server, username, password, nonce, f ):
|
||||
msg='To: {} \r\nFrom: {}\r\nSubject: Test from python\r\nDate: \r\nTEST {}'.format( username, username, str(nonce))
|
||||
|
||||
# connect to mail server
|
||||
try:
|
||||
logging.info( "about to smtp_sll" );
|
||||
s = smtplib.SMTP_SSL(host=server)
|
||||
conn_time = time.time_ns();
|
||||
logging.info( "about to login" );
|
||||
s.login(username,password)
|
||||
login_time = time.time_ns();
|
||||
logging.info( "about to send" );
|
||||
s.sendmail( username, username, msg)
|
||||
send_time = time.time_ns();
|
||||
logging.info( "sent" );
|
||||
except smtplib.SMTPConnectError as e:
|
||||
logging.error( "Failed to connect to {} ({})".format(server, e.strerror))
|
||||
print('node_mail_synth_trans{what="mail_working"} 0', file=f )
|
||||
except smtplib.SMTPAuthenticationError as e:
|
||||
logging.error( "Failed to autheticate to {} with user: {} ({})".format(server, username, e.strerror))
|
||||
print('node_mail_synth_trans{what="mail_working"} 0', file=f )
|
||||
except smtplib.SMTPRecipientsRefused as e:
|
||||
logging.error( "Recipient failed {} : ({})".format(username, e.strerror))
|
||||
print('node_mail_synth_trans{what="mail_working"} 0', file=f )
|
||||
except smtplib.SMTPException as e:
|
||||
logging.error( "Generic SMTP exception, not one I cared about ({})".format(e.strerror))
|
||||
print('node_mail_synth_trans{what="mail_working"} 0', file=f )
|
||||
finally:
|
||||
if s:
|
||||
s.quit()
|
||||
quit_time = time.time_ns();
|
||||
logging.info("Successfully sent email: %d" % nonce )
|
||||
smtp_elapsed=(quit_time-start_time)/1000000
|
||||
logging.info("Time to send (ms): "+ str(smtp_elapsed))
|
||||
print('node_mail_synth_trans{what="smtp_time_in_ms"} %d' % smtp_elapsed, file=f)
|
||||
print('node_mail_synth_trans{what="smtp_working"} 1', file=f )
|
||||
|
||||
# function that searches for message just sent in imap, and deletes it
|
||||
def ReceiveMessage( server, username, password, nonce, start_time, f ):
|
||||
try:
|
||||
imap_start_time = time.time_ns();
|
||||
conn = imaplib.IMAP4_SSL(server)
|
||||
imap_conn_time = time.time_ns();
|
||||
except imaplib.IMAP4.error as e:
|
||||
logging.error( "IMAP: Failed to connect ({})".format(e.strerror))
|
||||
print('node_mail_synth_trans{what="mail_working"} 0', file=f )
|
||||
|
||||
try:
|
||||
conn.login(username,password)
|
||||
imap_login_time = time.time_ns();
|
||||
except imaplib.IMAP4.error as e:
|
||||
logging.error( "IMAP: failed to login ({})".format(e.strerror))
|
||||
print('node_mail_synth_trans{what="mail_working"} 0', file=f )
|
||||
|
||||
try:
|
||||
conn.select('Inbox')
|
||||
search_str="TEST " + str(nonce)
|
||||
typ, data = conn.search(None,'(BODY "' + search_str + '")' )
|
||||
imap_search_time = time.time_ns();
|
||||
|
||||
if data[0] == b'':
|
||||
raise Exception("search returned no data")
|
||||
for num in data[0].split():
|
||||
typ, data = conn.fetch(num,'(RFC822)')
|
||||
conn.store(num, '+FLAGS', '\\Deleted')
|
||||
imap_retr_time = time.time_ns();
|
||||
conn.expunge()
|
||||
imap_del_time = time.time_ns();
|
||||
except imaplib.IMAP4.error as e:
|
||||
logging.error( "IMAP: Could not find email {}".format(e.strerror))
|
||||
print('node_mail_synth_trans{what="mail_working"} 0', file=f )
|
||||
finally:
|
||||
if conn:
|
||||
conn.close()
|
||||
imap_close_time = time.time_ns();
|
||||
# adding a 1 second sleep because my logs say it is deleting emails, but the emails are still in my folder, and also deleting ANY TEST emails, so if a subsequent run
|
||||
# works, it gets rid of the old ones that did fail for some reason
|
||||
time.sleep(1)
|
||||
conn.select('Inbox')
|
||||
search_str="TEST "
|
||||
typ, data = conn.search(None,'(BODY "' + search_str + '")' )
|
||||
# if there is still data, something didn't delete as expected, so
|
||||
# just clean it up
|
||||
if data[0] != b'':
|
||||
for num in data[0].split():
|
||||
typ, data = conn.fetch(num,'(RFC822)')
|
||||
conn.store(num, '+FLAGS', '\\Deleted')
|
||||
conn.expunge()
|
||||
conn.logout()
|
||||
imap_elapsed=(imap_close_time-imap_start_time)/1000000
|
||||
total_elapsed=(imap_close_time-start_time)/1000000 - 5000
|
||||
logging.info("time to recv email: %d" % imap_elapsed )
|
||||
logging.info("Successfully found and deleted email: %d" % nonce)
|
||||
print('node_mail_synth_trans{what="imap_time_in_ms"} %d' % imap_elapsed, file=f)
|
||||
print('node_mail_synth_trans{what="total_time_in_ms"} %d' % total_elapsed, file=f)
|
||||
print('node_mail_synth_trans{what="imap_working"} 1', file=f )
|
||||
print('node_mail_synth_trans{what="mail_working"} 1', file=f )
|
||||
|
||||
def Fail2BanCount():
|
||||
try:
|
||||
o = subprocess.run(["sudo", "/bin/docker", "exec", "mail", "fail2ban"], stdout=subprocess.PIPE, text=True )
|
||||
logging.info( f"Fail2ban returned: '{str(o.stdout.strip())}' ")
|
||||
out=str(o.stdout.strip()).split('\n')[1]
|
||||
ip_addresses = re.findall(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', out)
|
||||
unique_ip_count = len(set(ip_addresses))
|
||||
print( 'node_mail_synth_trans{what="fail2ban_cnt"} ' + str(unique_ip_count), file=f )
|
||||
except Exception as e:
|
||||
logging.error( f"Fail2ban: failed to get output for fail2ban ({e})" )
|
||||
print('node_mail_synth_trans{what="fail2ban_cnt"} 0', file=f )
|
||||
|
||||
# login using travel as its never really used (if I do anything dumb, it should
|
||||
# have no real impact on mail that matters)
|
||||
server='mail.depaoli.id.au'
|
||||
username='travel@depaoli.id.au'
|
||||
password='%fId0bPIE0Y2JZTzODJ%#p9V'
|
||||
|
||||
# set up unique message to send
|
||||
nonce = random.randint(1,99999999)
|
||||
|
||||
# open file for writing prometheus formatted data into
|
||||
f = open('/srv/docker/container/node-exporter/textfile_collector/mail.prom', 'w')
|
||||
|
||||
# put required help/type text in
|
||||
print('# HELP node_mail_synth_trans details of last synthetic mail transaction (full send/recv of an email)', file=f)
|
||||
print('# TYPE node_mail_synth_trans gauge', file=f )
|
||||
|
||||
# check for time, if its been a week or so, rotate the log
|
||||
logfile='/var/tmp/mail-tester.log'
|
||||
if( need_to_rotate_log(logfile) ):
|
||||
print( 'Rotating log file, its a week old (deletes file from 2 weeks ago)' )
|
||||
shutil.move( logfile, logfile + '.1' )
|
||||
|
||||
# also set up an actual log file while I am learning python / testing this out
|
||||
logging.basicConfig(filename=logfile, format='%(asctime)s - %(message)s', datefmt='%H:%M:%S %d-%m-%y', level=logging.INFO)
|
||||
|
||||
# all the time_ns() calls are just timestamps to compare back to this one for
|
||||
# relative time elapsed for operations, good for graphing in prometheus
|
||||
start_time = time.time_ns();
|
||||
logging.info("start up for: %d" % nonce );
|
||||
|
||||
SendMessage( server, username, password, nonce, f )
|
||||
logging.info("waiting 5 seconds for email to actually be delivered")
|
||||
time.sleep(5)
|
||||
ReceiveMessage( server, username, password, nonce, start_time, f )
|
||||
|
||||
Fail2BanCount()
|
||||
|
||||
# close output file (used for prometheus)
|
||||
f.close()
|
||||
Reference in New Issue
Block a user