def message(self, msg): global ANSWER_WAIT_MSG, READ_WAIT_MSG if self.i_answer_obj: # Условие логирование для режима answer print(f"\n\nIM {cmd_time('date')}") print( "----------------------------------------------------------------------------" ) msg_list = str(msg).split( '"') # Преобразование сообщения в список для логирования msg_list_from = msg_list[1].split('/')[0] # Определение отправителя msg_list_to = msg_list[3] # Определение получателя for el in msg_list: if "<body>" in el: READ_WAIT_MSG = el.split("body")[1][ 1:-2] # Определение текста в сообщении if READ_WAIT_MSG == ANSWER_WAIT_MSG: # Логирование print(f"READ {cmd_time()}") print(f"FROM: {msg_list_from}") print(f" TO: {msg_list_to}") print(f" MSG: {READ_WAIT_MSG}") self.disconnect() # Запись лога в csv файл # protocol;time;resource;size;from;to;msg;error; log_csv( f"IM-read;{cmd_time()};;;{msg_list_from};{msg_list_to};{READ_WAIT_MSG};;" )
def terminal_test( protocol: str, servers_list: list, ): # Функция для теста telnet и ssh соединений. Сам тест происходит с помощью putty. Аргументы: # protocol - для нужен определения протокола(telnet, ssh) и логирования; # servers_list - список серверных адресов для теста. # Логирование. print(f"\n\n{protocol}") print( "----------------------------------------------------------------------------" ) # Определение протокола путём длинны аргумента protocol flag = "-telnet" if len(protocol) > 3 else "-ssh" # Итерация по элементам списка servers_list for el in servers_list: print(f"{cmd_time()}\n{protocol} {el}") # Логирование. # Метод для выполнения команды в консоли, который НЕ ожидает завершения команды и переходит к следующей строке. # Команда для соединения по указанному протоколу через putty >>> putty -ssh 195.144.107.198 subprocess.Popen(["putty", flag, el]) time.sleep(10) # Пауза 10 секунд. # Исключение для завершения процесса putty в зависимости от ОС try: # Windows # Метод для выполнения команды в консоли, который ожидает завершения команды. subprocess.run(["taskkill", "/IM", "putty.exe", "/F"]) # Запись лога в csv файл # protocol;time;resource;size;from;to;msg;error; log_csv(f"{protocol};{cmd_time()};{el};;;;;;") except FileNotFoundError: # Linux # Метод для выполнения команды в консоли, который ожидает завершения команды. subprocess.run(["pkill", "putty"]) # Логирование. msg_error = "***** TERM: CONTROL ERROR - NOT WINDOWS *****" print(msg_error) # Запись лога в csv файл # protocol;time;resource;size;from;to;msg;error; log_csv(f"{protocol};{cmd_time()};{el};;;;;{msg_error};") print() if el != servers_list[-1] else None # Логирование. print( "----------------------------------------------------------------------------" ) print(f"{protocol} end")
def web_test(protocol: str, website_list: list): # Функция для теста web соединений. Аргументы: # protocol - нужен для логирования; # website_list - список сайтов для теста. # selenium.common.exceptions.SessionNotCreatedException: # Логирование. print(f"\n\n{protocol}") print( "----------------------------------------------------------------------------" ) print("Open browser", end=" ") # Запуск webdriver для chrome chromedriver_autoinstaller.install() # Вывод версии chrome + лечит WARNING:urllib3.connectionpool:Retrying print(f"CHROME v{chromedriver_autoinstaller.get_chrome_version()}") # Инициализируем драйвер браузера. После этой команды будет открыто новое окно браузера. driver = webdriver.Chrome() time.sleep(5) # Пауза 5 секунд. # Итерации по элементам списка website_list. for el in website_list: print(f"\n{cmd_time()}\n{protocol} {el}") # Логирование. # Исключение для перенаправления ошибки заблокированных ресурсов. try: # Метод get сообщает браузеру, что нужно открыть сайт по указанной ссылке. driver.get(el) # Запись лога в csv файл # protocol;time;resource;size;from;to;msg;error; log_csv(f"{protocol};{cmd_time()};{el};;;;;;") except common.exceptions.WebDriverException: msg_error = "***** WEB: CONTROL ERROR - NOT ANSWER *****" print(msg_error) # Логирование. # Запись лога в csv файл # protocol;time;resource;size;from;to;msg;error; log_csv(f"{protocol};{cmd_time()};{el};;;;;{msg_error};") time.sleep(10) # Пауза 10 секунд. # Метод для закрытия окна браузера. driver.quit() # Логирование. print("\nClose browser") print( "----------------------------------------------------------------------------" ) return print(f"{protocol} end")
def sender_msg(self): self.send_message(mto=self.recipient, mbody=self.msg, mtype='chat') # Отправка сообщения # Логирование print(f"SEND {cmd_time()}") print(f"FROM: {self.jid}") print(f" TO: {self.recipient}") print(f" MSG: {self.msg}") self.disconnect() # Отключение от сервера # Запись лога в csv файл # protocol;time;resource;size;from;to;msg;error; log_csv( f"IM-send;{cmd_time()};;;{self.jid};{self.recipient};{self.msg};;")
def send_email(list_from: list, list_to: list, list_msg: list, list_cc=None, list_bcc=None): # Все данные в списках должны иметь строковый тип # list_from список отправителя, формат: [email , pass, почтовый сервера, порт почтового сервера] # list_to список получателя, формат: [email №1, ..., email №n] # list_msg список для формирования письма, формат: [тема письма, текст письма, относительный путь к файлу] # list_cc (необязательный аргумент) список адресов копии, формат: [email №1, ..., email №n] # list_bcc (необязательный аргумент) список адресов скрытой копии, формат: [email №1, ..., email №n] global I_FIRST if list_cc is None: list_cc = [] if list_bcc is None: list_bcc = [] # Формирование тела письма msg = MIMEMultipart(boundary="/") # Создаем сообщение msg["From"] = list_from[0] # Добавление отправителя msg["To"] = ", ".join(list_to) # Добавление получателей msg["Cc"] = ", ".join(list_cc) # Добавление копии msg["Bcc"] = ", ".join(list_bcc) # Добавление скрытой копии msg["Subject"] = f"{list_msg[0]} {cmd_time() if len(list_msg) != 4 else ''}" # Добавление темы сообщения msg.attach(MIMEText(list_msg[1], "plain")) # Добавляем в сообщение текст if I_FIRST and len(list_msg) <= 3: # Логирование msg_TO = f"TO:{list_to}" msg_TO += f" CC:{list_cc}" if len(list_cc) != 0 else "" msg_TO += f" BCC:{list_bcc}" if len(list_bcc) != 0 else "" msg_TEXT = f"SUB:{list_msg[0]} TEXT:{list_msg[1]}" msg_TEXT += f" FILE:{list_msg[2]}" if len(list_msg) > 2 else "" # Запись лога в csv файл # protocol;time;resource;size;from;to;msg;error; log_csv(f"EMAIL-SMTP;{cmd_time()};;;{list_from[0]};{msg_TO}; {msg_TEXT} ;;") # Условие для определения вложения у письма if len(list_msg) == 3: filepath = f"./email/{list_msg[2]}" # Путь к файлу. Файлы для отправки должны лежать в ./email/ filename = f"{list_msg[2]}" # Только имя файла with open(filepath, "rb") as fp: file = MIMEBase("application", "pdf") # Используем общий MIME-тип file.set_payload(fp.read()) # Добавляем содержимое общего типа (полезную нагрузку) fp.close() encoders.encode_base64(file) # Содержимое должно кодироваться как Base64 file.add_header("Content-Disposition", "attachment", filename=filename) # Добавляем заголовки msg.attach(file) # Присоединяем файл к сообщению # Условие для отправки письма о выполненном тесте elif len(list_msg) == 4: # Добавляем к письму файл DOCX filepath_docx = f"./logs_in_docx/{list_msg[2]}" # Путь к файлу filename_docx = f"{list_msg[2]}" # Только имя файла with open(filepath_docx, "rb") as fp: file_docx = MIMEBase("application", "docx") # Используем общий MIME-тип file_docx.set_payload(fp.read()) # Добавляем содержимое общего типа (полезную нагрузку) fp.close() encoders.encode_base64(file_docx) # Содержимое должно кодироваться как Base64 file_docx.add_header("Content-Disposition", "attachment", filename=filename_docx) # Добавляем заголовки msg.attach(file_docx) # Присоединяем файл к сообщению # Добавляем к письму файл CSV filepath_csv = f"./logs/{list_msg[3]}" # Путь к файлу filename_csv = f"{list_msg[3]}" # Только имя файла with open(filepath_csv, "rb") as fp: file_csv = MIMEBase("application", "csv") # Используем общий MIME-тип file_csv.set_payload(fp.read()) # Добавляем содержимое общего типа (полезную нагрузку) fp.close() encoders.encode_base64(file_csv) # Содержимое должно кодироваться как Base64 file_csv.add_header("Content-Disposition", "attachment", filename=filename_csv) # Добавляем заголовки msg.attach(file_csv) # Присоединяем файл к сообщению server = smtplib.SMTP(list_from[2], int(list_from[3])) # Создаем объект SMTP (сервер, порт) # server.set_debuglevel(1) # Системные логи, дебагер server.starttls() if list_from[2] != "mail.nic.ru" else None # Начинаем шифрованный обмен по TLS, нужен для яндекса server.login(list_from[0], list_from[1]) # Получаем доступ (email, пароль) server.send_message(msg) # Отправляем сообщение # Убираем лог при отправке письма с тестовыми файлами if len(list_msg) == 4: server.quit() # Выходим return # Логирование print(f"SEND {cmd_time()}") print(f"FROM: {msg['From']}") print(f" TO: {msg['To']}") print(f" CC: {msg['Cc']}") if len(list_cc) != 0 else None print(f" BCC: {msg['Bcc']}") if len(list_bcc) != 0 else None print(f" SUB: {msg['Subject']}") print(f"TEXT: {list_msg[1]}") print(f"FILE: {list_msg[2]}") if len(list_msg) > 2 else None server.quit() # Выходим return
def read_email(info_email: list, protocol: str): # info_email список el: str in [email, pass, server] # protocol либо "POP3", либо "IMAP" global I_FIRST, NEW_MILES, STOP_READ_EMAIL, __COUNT_SUBJECTS # Указывается максимальное количество писем в ящике. # Если больше, то более поздние письма удаляются до тех пор, # пока не останется указанное количество писем. max_mails_in_box = 10 # Вечный цикл мониторинга новых писем while True: # Условие для завершения функции if STOP_READ_EMAIL == 55 and I_FIRST: print(f"*** THE COLONEL's NO ONE WRITES! {cmd_time()} ***") STOP_READ_EMAIL = 0 return if protocol == "POP3": # Подключаемся к серверу, для Яндекса нужен SSL server = poplib.POP3(info_email[2]) if I_FIRST else poplib.POP3_SSL(info_email[2]) # server.set_debuglevel(1) # Системный лог, дебагер server.user(info_email[0]) # Email server.pass_(info_email[1]) # Пароль # Количество писем в ящике mails = int(server.stat()[0]) elif protocol == "IMAP": server = imaplib.IMAP4_SSL(info_email[2]) server.debug = True server.login(info_email[0], info_email[1]) # Выводит список папок в почтовом ящике. server.select("inbox") # Подключаемся к папке "входящие" dir_inbox = server.search(None, "ALL")[1] # Запрос о наполненности ящика id_list = dir_inbox[0].split() # Получаем сроку номеров писем mails = int(id_list[-1]) if len(id_list) != 0 else 0 # Берем последний ID else: print(f"***** PROTOCOL: POP3 or IMAP {cmd_time()} *****") return time.sleep(5) # Условие для начального поиска новых писем, т.е. присваивается количество писем на данный момент. if NEW_MILES is None or NEW_MILES > mails: NEW_MILES = mails # Условие для определения новых писем if NEW_MILES < mails: NEW_MILES = mails else: # Действие при отсутствии писем до STOP_READ_EMAIL проходов STOP_READ_EMAIL += 1 # print_in_log(f"Loop EMAIL №{STOP_READ_EMAIL} {cmd_time()}") server.quit() if protocol == "POP3" else server.close() # Закрываем соединение continue # Обработка сообщения if protocol == "POP3": lines = server.retr(NEW_MILES)[1] # Получаем тело сообщения # b'\r\n'.join(lines) Подготавливаем сообщение к декодированию. # decode('utf-8') Декодируем сообщение по UTF-8 -> str # split("--/") создаём список на основе декодированного сообщения, элементы списка делятся по маркеру "--/" msg_content = b'\r\n'.join(lines).decode('utf-8').split("--/") # Защита от ошибок при получении письма не от функции send_email if len(msg_content) < 3: print("***** EMAIL: CONTROL ERROR - Not AUTO mail *****") continue else: # для IMAP: *server.fetch(latest_email_id, "(RFC822)")[1][0]][1] Подготавливаем сообщение к декодированию # путём распаковки tuple decode('utf-8') Декодируем сообщение по UTF-8 -> str split("--/") создаём список на # основе декодированного сообщения, элементы списка делятся по маркеру "--/" Тело письма в необработанном # виде включает в себя заголовки и альтернативные полезные нагрузки msg_content = [*server.fetch(str(mails), "(RFC822)")[1][0]][1].decode("utf-8").split("--/") # Тело письма # Защита от ошибок при получении письма не от функции send_email if len(msg_content) < 3: print("***** EMAIL: CONTROL ERROR - Not AUTO mail *****") continue msg_head = message_from_string(msg_content[0]) # Преобразуем str -> dict # Декодируем сообщение base64 -> UTF-8 -> str msg_text = base64.b64decode("".join(msg_content[1].split()[7:])).decode('utf-8') # Условие для определения вложенного файла и присвоение его имени msg_file = msg_content[2].split()[8][10:-1] if len(msg_content) > 3 else None msg_subject_decode = str() for el in (msg_head.get('Subject')).split(): # Декодируем тему сообщения base64 -> UTF-8 -> str msg_subject_decode += base64.b64decode(el[10:-2]).decode('utf-8') if not I_FIRST and __COUNT_SUBJECTS: __COUNT_SUBJECTS = False print(f"\n\nEMAIL {cmd_time('date')}") print("--------------------------------------------------------------------------") print(f"READ {cmd_time()} {protocol}") print(f"FROM: {msg_head.get('From')}") # Вытаскиваем значение по ключу print(f" TO: {msg_head.get('To')}") # Вытаскиваем значение по ключу # Вытаскиваем значение по ключу если оно есть print(f" CC: {msg_head.get('Cc')}") if msg_head.get('Cc') != (None or "") else None # Вытаскиваем значение по ключу если оно есть print(f" BCC: {msg_head.get('Bcc')}") if msg_head.get('Bcc') is not None else None print(f" SUB: {msg_subject_decode}") print(f"TEXT: {msg_text}") print(f"FILE: {msg_file}") if msg_file is not None else None # Имя вложенного файла если оно есть if I_FIRST: # Логирование msg_TO = f"TO:{msg_head.get('To')}" msg_TO += f" CC: {msg_head.get('Cc')}" if msg_head.get('Cc') != (None or "") else "" msg_TO += f" BCC: {msg_head.get('Bcc')}" if msg_head.get('Bcc') is not None else "" msg_TEXT = f"SUB:{msg_subject_decode} TEXT:{msg_text}" msg_TEXT += f" FILE:{msg_file}" if msg_file is not None else "" # Запись лога в csv файл # protocol;time;resource;size;from;to;msg;error; log_csv(f"EMAIL-{protocol};{cmd_time()};;;{msg_head.get('From')};{msg_TO}; {msg_TEXT} ;;") # pop3 Удаление старых писем if mails > max_mails_in_box and protocol == "POP3": # print_in_log(":::::::::::::::::::::::::::::::::::::::::::::::::") for i in range(mails - max_mails_in_box): server.dele(i + 1) # print_in_log(f"Delete mail №{i + 1}") # print_in_log(":::::::::::::::::::::::::::::::::::::::::::::::::") # imap Удаление старых писем elif mails > max_mails_in_box and protocol == "IMAP": # print_in_log(":::::::::::::::::::::::::::::::::::::::::::::::::") for i in range(mails - max_mails_in_box): server.store(str(i + 1), '+FLAGS', '\\Deleted') # print_in_log(f"Delete mail №{i+1}") # print_in_log(":::::::::::::::::::::::::::::::::::::::::::::::::") server.quit() if protocol == "POP3" else server.close() # Закрываем соединение STOP_READ_EMAIL = 0 NEW_MILES = None return
def ftp_test(download_list: list): # Функция для теста ftp загрузки. Аргументы: # download_list - список ресурсов для скачивания по ftp. # Логирование. print("\n\nFTP") print( "----------------------------------------------------------------------------" ) try: shutil.rmtree("./FTP_573") # Удаление папки для экономии места except FileNotFoundError: pass os.mkdir("FTP_573") # Создание пустой папки # Индикатор процесса для ftp тестов def bar_progress(current, total, width=100): percent_download = round(current / total * width, 1) progress_message = f"Downloading: {percent_download}% [{current} / {total}] bytes" # Don't use print() as it will print in new line every time. sys.stdout.write("\r" + progress_message) sys.stdout.flush() # Итерация по элементам списка download_list. for link in download_list: # Логирование. print(f"\n{cmd_time()}\nFTP {link}") print( f"Download {link[28:]}" ) # el[28:] - название файла, удаляется ftp://alta.ru/packets/distr/ # Запись лога в csv файл # protocol;time;resource;size;from;to;msg;error; log_csv(f"FTP;{cmd_time()};{link};0;;;;;") os.chdir("FTP_573") # Меняем рабочую директорию # Метод для выполнения команды в консоли, который ожидает завершения команды. # Команда для скачивания файлов >>> wget ftp://alta.ru/packets/distr/ts.zip # В версиях python >= 3.9 идёт ошибка # 'utf-8' codec can't decode byte 0xc0 in position 4: invalid start byte wget.download(link, bar=bar_progress) os.chdir("../") # Меняем рабочую директорию # Логирование print() file_size = os.path.getsize(f"./FTP_573/{link[28:]}") if len(str(file_size)) < 10: file_size_mb_or_gb = str(round(file_size / (1024**2), 1)) + " MB" else: file_size_mb_or_gb = str(round(file_size / (1024**3), 1)) + " GB" print( f"End {cmd_time()} {link[28:]} {file_size_mb_or_gb} ({file_size} B)" ) # Запись лога в csv файл # protocol;time;resource;size;from;to;msg;error; log_csv( f"FTP;{cmd_time()};{link};{file_size_mb_or_gb} ({file_size} B);;;;;" ) time.sleep(60) # Пауза 60 секунд. # Логирование. print( "----------------------------------------------------------------------------" ) print("FTP end")