mirror of
https://github.com/draga79/NotiMail.git
synced 2024-09-19 11:04:20 +02:00
Added some basic logging support
This commit is contained in:
parent
a295865987
commit
efdcb112fb
1 changed files with 30 additions and 8 deletions
38
NotiMail.py
38
NotiMail.py
|
@ -69,9 +69,15 @@ import sqlite3
|
||||||
import datetime
|
import datetime
|
||||||
import signal
|
import signal
|
||||||
import sys
|
import sys
|
||||||
|
import logging
|
||||||
from email import policy
|
from email import policy
|
||||||
from email.parser import BytesParser
|
from email.parser import BytesParser
|
||||||
|
|
||||||
|
# Setup logging
|
||||||
|
logging.basicConfig(filename='notimail.log',
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(levelname)s - %(message)s')
|
||||||
|
|
||||||
class DatabaseHandler:
|
class DatabaseHandler:
|
||||||
def __init__(self, db_name="processed_emails.db"):
|
def __init__(self, db_name="processed_emails.db"):
|
||||||
self.connection = sqlite3.connect(db_name)
|
self.connection = sqlite3.connect(db_name)
|
||||||
|
@ -119,23 +125,21 @@ class EmailProcessor:
|
||||||
return BytesParser(policy=policy.default).parsebytes(raw_email)
|
return BytesParser(policy=policy.default).parsebytes(raw_email)
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
print("Fetching the latest email...")
|
logging.info("Fetching the latest email...")
|
||||||
for message in self.fetch_unseen_emails():
|
for message in self.fetch_unseen_emails():
|
||||||
uid = message.decode('utf-8')
|
uid = message.decode('utf-8')
|
||||||
if self.db_handler.is_email_notified(uid):
|
if self.db_handler.is_email_notified(uid):
|
||||||
print(f"Email UID {uid} already processed and notified, skipping...")
|
logging.info(f"Email UID {uid} already processed and notified, skipping...")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
_, msg = self.mail.uid('fetch', message, '(BODY.PEEK[])')
|
_, msg = self.mail.uid('fetch', message, '(BODY.PEEK[])')
|
||||||
for response_part in msg:
|
for response_part in msg:
|
||||||
if isinstance(response_part, tuple):
|
if isinstance(response_part, tuple):
|
||||||
email_message = self.parse_email(response_part[1])
|
email_message = self.parse_email(response_part[1])
|
||||||
print('From:', email_message.get('From'))
|
sender = email_message.get('From')
|
||||||
print('Subject:', email_message.get('Subject'))
|
subject = email_message.get('Subject')
|
||||||
print('Body:', email_message.get_payload())
|
logging.info(f"Processing Email - UID: {uid}, Sender: {sender}, Subject: {subject}")
|
||||||
print('------')
|
|
||||||
notifier.send_notification(email_message.get('From'), email_message.get('Subject'))
|
notifier.send_notification(email_message.get('From'), email_message.get('Subject'))
|
||||||
# Add UID to database to ensure it is not processed in future runs
|
|
||||||
self.db_handler.add_email(uid, 1)
|
self.db_handler.add_email(uid, 1)
|
||||||
|
|
||||||
# Delete entries older than 7 days
|
# Delete entries older than 7 days
|
||||||
|
@ -164,10 +168,13 @@ class NTFYNotificationProvider(NotificationProvider):
|
||||||
)
|
)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
print(f"Notification sent successfully to {ntfy_url}!")
|
print(f"Notification sent successfully to {ntfy_url}!")
|
||||||
|
logging.info(f"Notification sent successfully to {ntfy_url} via ntfy")
|
||||||
else:
|
else:
|
||||||
print(f"Failed to send notification to {ntfy_url}. Status Code:", response.status_code)
|
print(f"Failed to send notification to {ntfy_url}. Status Code:", response.status_code)
|
||||||
|
logging.error(f"Failed to send notification to {ntfy_url} via NTFY. Status Code: {response.status_code}")
|
||||||
except requests.RequestException as e:
|
except requests.RequestException as e:
|
||||||
print(f"An error occurred while sending notification to {ntfy_url}: {str(e)}")
|
print(f"An error occurred while sending notification to {ntfy_url}: {str(e)}")
|
||||||
|
logging.error(f"An error occurred while sending notification to {ntfy_url} via NTFY: {str(e)}")
|
||||||
finally:
|
finally:
|
||||||
time.sleep(5) # Ensure a delay between notifications
|
time.sleep(5) # Ensure a delay between notifications
|
||||||
|
|
||||||
|
@ -193,10 +200,13 @@ class PushoverNotificationProvider(NotificationProvider):
|
||||||
response = requests.post(self.pushover_url, data=data)
|
response = requests.post(self.pushover_url, data=data)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
print("Notification sent successfully via Pushover!")
|
print("Notification sent successfully via Pushover!")
|
||||||
|
logging.info(f"Notification sent successfully via Pushover")
|
||||||
else:
|
else:
|
||||||
print(f"Failed to send notification via Pushover. Status Code:", response.status_code)
|
print(f"Failed to send notification via Pushover. Status Code:", response.status_code)
|
||||||
|
logging.error(f"Failed to send notification to via Pushover. Status Code: {response.status_code}")
|
||||||
except requests.RequestException as e:
|
except requests.RequestException as e:
|
||||||
print(f"An error occurred while sending notification via Pushover: {str(e)}")
|
print(f"An error occurred while sending notification via Pushover: {str(e)}")
|
||||||
|
logging.error(f"An error occurred while sending notification via Pushover: {str(e)}")
|
||||||
|
|
||||||
class GotifyNotificationProvider(NotificationProvider):
|
class GotifyNotificationProvider(NotificationProvider):
|
||||||
def __init__(self, gotify_url, gotify_token):
|
def __init__(self, gotify_url, gotify_token):
|
||||||
|
@ -222,11 +232,13 @@ class GotifyNotificationProvider(NotificationProvider):
|
||||||
response = requests.post(url_with_token, json=payload)
|
response = requests.post(url_with_token, json=payload)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
print("Notification sent successfully via Gotify!")
|
print("Notification sent successfully via Gotify!")
|
||||||
|
logging.info(f"Notification sent successfully via Gotify")
|
||||||
else:
|
else:
|
||||||
print(f"Failed to send notification via Gotify. Status Code: {response.status_code}")
|
print(f"Failed to send notification via Gotify. Status Code: {response.status_code}")
|
||||||
print(f"Response: {response.text}") # Print the response body
|
logging.error(f"Failed to send notification via Gotify. Status Code: {response.status_code}")
|
||||||
except requests.RequestException as e:
|
except requests.RequestException as e:
|
||||||
print(f"An error occurred while sending notification via Gotify: {str(e)}")
|
print(f"An error occurred while sending notification via Gotify: {str(e)}")
|
||||||
|
logging.error(f"An error occurred while sending notification via Gotify: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
class Notifier:
|
class Notifier:
|
||||||
|
@ -257,6 +269,7 @@ class IMAPHandler:
|
||||||
|
|
||||||
def idle(self):
|
def idle(self):
|
||||||
print("IDLE mode started. Waiting for new email...")
|
print("IDLE mode started. Waiting for new email...")
|
||||||
|
logging.info(f"IDLE mode started. Waiting for new email...")
|
||||||
try:
|
try:
|
||||||
tag = self.mail._new_tag().decode()
|
tag = self.mail._new_tag().decode()
|
||||||
self.mail.send(f'{tag} IDLE\r\n'.encode('utf-8'))
|
self.mail.send(f'{tag} IDLE\r\n'.encode('utf-8'))
|
||||||
|
@ -271,17 +284,21 @@ class IMAPHandler:
|
||||||
self.mail.readline()
|
self.mail.readline()
|
||||||
except imaplib.IMAP4.abort as e:
|
except imaplib.IMAP4.abort as e:
|
||||||
print(f"Connection closed by server: {str(e)}")
|
print(f"Connection closed by server: {str(e)}")
|
||||||
|
logging.error(f"Connection closed by server: {str(e)}")
|
||||||
notifier.send_notification("Script Error", f"Connection closed by server: {str(e)}")
|
notifier.send_notification("Script Error", f"Connection closed by server: {str(e)}")
|
||||||
raise ConnectionAbortedError("Connection lost. Trying to reconnect...")
|
raise ConnectionAbortedError("Connection lost. Trying to reconnect...")
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
print("Socket timeout during IDLE, re-establishing connection...")
|
print("Socket timeout during IDLE, re-establishing connection...")
|
||||||
|
loggin.info(f"Socket timeout during IDLE, re-establishing connection...")
|
||||||
raise ConnectionAbortedError("Socket timeout. Trying to reconnect...")
|
raise ConnectionAbortedError("Socket timeout. Trying to reconnect...")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"An error occurred: {str(e)}")
|
print(f"An error occurred: {str(e)}")
|
||||||
|
logging.info(f"An error occurred: {str(e)}")
|
||||||
notifier.send_notification("Script Error", f"An error occurred: {str(e)}")
|
notifier.send_notification("Script Error", f"An error occurred: {str(e)}")
|
||||||
raise
|
raise
|
||||||
finally:
|
finally:
|
||||||
print("IDLE mode stopped.")
|
print("IDLE mode stopped.")
|
||||||
|
logging.info(f"IDLE mode stopped.")
|
||||||
|
|
||||||
def process_emails(self):
|
def process_emails(self):
|
||||||
processor = EmailProcessor(self.mail)
|
processor = EmailProcessor(self.mail)
|
||||||
|
@ -322,12 +339,14 @@ socket.setdefaulttimeout(600) # e.g., 600 seconds or 10 minutes
|
||||||
|
|
||||||
def shutdown_handler(signum, frame):
|
def shutdown_handler(signum, frame):
|
||||||
print("Shutdown signal received. Cleaning up...")
|
print("Shutdown signal received. Cleaning up...")
|
||||||
|
logging.info(f"Shutdown signal received. Cleaning up...")
|
||||||
try:
|
try:
|
||||||
handler.mail.logout()
|
handler.mail.logout()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
processor.db_handler.close()
|
processor.db_handler.close()
|
||||||
print("Cleanup complete. Exiting.")
|
print("Cleanup complete. Exiting.")
|
||||||
|
logging.info(f"Cleanup complete. Exiting.")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
# Register the signal handlers
|
# Register the signal handlers
|
||||||
|
@ -335,6 +354,7 @@ signal.signal(signal.SIGTERM, shutdown_handler)
|
||||||
signal.signal(signal.SIGINT, shutdown_handler)
|
signal.signal(signal.SIGINT, shutdown_handler)
|
||||||
|
|
||||||
print("Script started. Press Ctrl+C to stop it anytime.")
|
print("Script started. Press Ctrl+C to stop it anytime.")
|
||||||
|
logging.info(f"Script started. Press Ctrl+C to stop it anytime.")
|
||||||
handler = IMAPHandler(host, email_user, email_pass)
|
handler = IMAPHandler(host, email_user, email_pass)
|
||||||
processor = EmailProcessor(None) # Creating an instance for graceful shutdown handling
|
processor = EmailProcessor(None) # Creating an instance for graceful shutdown handling
|
||||||
|
|
||||||
|
@ -350,9 +370,11 @@ try:
|
||||||
time.sleep(30) # wait for 30 seconds before trying to reconnect
|
time.sleep(30) # wait for 30 seconds before trying to reconnect
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"An unexpected error occurred: {str(e)}")
|
print(f"An unexpected error occurred: {str(e)}")
|
||||||
|
logging.error(f"An unexpected error occurred: {str(e)}")
|
||||||
notifier.send_notification("Script Error", f"An unexpected error occurred: {str(e)}")
|
notifier.send_notification("Script Error", f"An unexpected error occurred: {str(e)}")
|
||||||
finally:
|
finally:
|
||||||
print("Logging out and closing the connection...")
|
print("Logging out and closing the connection...")
|
||||||
|
logging.info(f"Logging out and closing the connection...")
|
||||||
try:
|
try:
|
||||||
handler.mail.logout()
|
handler.mail.logout()
|
||||||
except:
|
except:
|
||||||
|
|
Loading…
Reference in a new issue