Added multi folder support, command line enhancements for printing/checking the config.ini settings, --list-folders will list all the IMAP folders of configured accounts, general improvements in logging and documentation

This commit is contained in:
Stefano Marinelli 2023-10-24 09:49:20 +02:00
parent 25ed446d89
commit a5884402ff
4 changed files with 181 additions and 33 deletions

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
NotiMail NotiMail
Version: 0.11 Version: 0.12
Author: Stefano Marinelli <stefano@dragas.it> Author: Stefano Marinelli <stefano@dragas.it>
License: BSD 3-Clause License License: BSD 3-Clause License
@ -80,6 +80,9 @@ from email.parser import BytesParser
# Argument parsing to get the config file # Argument parsing to get the config file
parser = argparse.ArgumentParser(description='NotiMail Notification Service.') parser = argparse.ArgumentParser(description='NotiMail Notification Service.')
parser.add_argument('-c', '--config', type=str, default='config.ini', help='Path to the configuration file.') parser.add_argument('-c', '--config', type=str, default='config.ini', help='Path to the configuration file.')
parser.add_argument('--print-config', action='store_true', help='Print the configuration options from config.ini')
parser.add_argument('--test-config', action='store_true', help='Test the configuration options to ensure they work properly')
parser.add_argument('--list-folders', action='store_true', help='List all IMAP folders of the configured mailboxes')
args = parser.parse_args() args = parser.parse_args()
# Configuration reading # Configuration reading
@ -275,17 +278,18 @@ class Notifier:
class IMAPHandler: class IMAPHandler:
def __init__(self, host, email_user, email_pass): def __init__(self, host, email_user, email_pass, folder="inbox"):
self.host = host self.host = host
self.email_user = email_user self.email_user = email_user
self.email_pass = email_pass self.email_pass = email_pass
self.folder = folder
self.mail = None self.mail = None
def connect(self): def connect(self):
try: try:
self.mail = imaplib.IMAP4_SSL(self.host, 993) self.mail = imaplib.IMAP4_SSL(self.host, 993)
self.mail.login(self.email_user, self.email_pass) self.mail.login(self.email_user, self.email_pass)
self.mail.select('inbox') self.mail.select(self.folder)
except imaplib.IMAP4.error as e: except imaplib.IMAP4.error as e:
print(f"Cannot connect: {str(e)}") print(f"Cannot connect: {str(e)}")
notifier.send_notification("Script Error", f"Cannot connect: {str(e)}") notifier.send_notification("Script Error", f"Cannot connect: {str(e)}")
@ -293,7 +297,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"[{self.email_user}] IDLE mode started. Waiting for new email...") logging.info(f"[{self.email_user} - {self.folder}] 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'))
@ -333,7 +337,7 @@ class IMAPHandler:
class MultiIMAPHandler: class MultiIMAPHandler:
def __init__(self, accounts): def __init__(self, accounts):
self.accounts = accounts self.accounts = accounts
self.handlers = [IMAPHandler(account['Host'], account['EmailUser'], account['EmailPass']) for account in accounts] self.handlers = [IMAPHandler(account['Host'], account['EmailUser'], account['EmailPass'], account['Folder']) for account in accounts]
def run(self): def run(self):
threads = [] threads = []
@ -349,8 +353,8 @@ class MultiIMAPHandler:
@staticmethod @staticmethod
def monitor_account(handler): def monitor_account(handler):
print(f"Monitoring {handler.email_user}") print(f"Monitoring {handler.email_user} - Folder: {handler.folder}")
logging.info(f"Monitoring {handler.email_user}") logging.info(f"Monitoring {handler.email_user} - Folder: {handler.folder}")
while True: # Add a loop to keep retrying on connection loss while True: # Add a loop to keep retrying on connection loss
try: try:
handler.connect() handler.connect()
@ -393,12 +397,15 @@ def multi_account_main():
# Check for new format [EMAIL:accountX] # Check for new format [EMAIL:accountX]
for section in config.sections(): for section in config.sections():
if section.startswith("EMAIL:"): if section.startswith("EMAIL:"):
account = { folders = config[section].get('Folders', 'inbox').split(', ')
'EmailUser': config[section]['EmailUser'], for folder in folders:
'EmailPass': config[section]['EmailPass'], account = {
'Host': config[section]['Host'] 'EmailUser': config[section]['EmailUser'],
} 'EmailPass': config[section]['EmailPass'],
accounts.append(account) 'Host': config[section]['Host'],
'Folder': folder
}
accounts.append(account)
providers = [] providers = []
@ -444,6 +451,97 @@ def multi_account_main():
except: except:
pass pass
if __name__ == "__main__": def print_config():
multi_account_main() """
Function to print the configuration options from config.ini
"""
for section in config.sections():
print(f"[{section}]")
for key, value in config[section].items():
print(f"{key} = {value}")
print()
def test_config():
"""
Function to test the configuration options
"""
# Test Email accounts
for section in config.sections():
if section.startswith("EMAIL:"):
print(f"Testing {section}...")
handler = IMAPHandler(config[section]['Host'], config[section]['EmailUser'], config[section]['EmailPass'])
try:
handler.connect()
print(f"Connection successful for {section}")
handler.mail.logout() # Explicitly logging out after testing
except Exception as e:
print(f"Connection failed for {section}. Reason: {str(e)}")
# Testing NTFY Notification Provider
if 'NTFY' in config:
print("Testing NTFY Notification Provider...")
ntfy_data = []
for key in config['NTFY']:
if key.startswith("url"):
url = config['NTFY'][key]
token_key = "token" + key[3:]
token = config['NTFY'].get(token_key, None)
ntfy_data.append((url, token))
ntfy_provider = NTFYNotificationProvider(ntfy_data)
try:
ntfy_provider.send_notification("Test Sender", "Test Notification from NotiMail")
print("Test notification sent successfully via NTFY!")
except Exception as e:
print(f"Failed to send test notification via NTFY. Reason: {str(e)}")
# Testing Pushover Notification Provider
if 'PUSHOVER' in config:
print("Testing Pushover Notification Provider...")
pushover_provider = PushoverNotificationProvider(config['PUSHOVER']['ApiToken'], config['PUSHOVER']['UserKey'])
try:
pushover_provider.send_notification("Test Sender", "Test Notification from NotiMail")
print("Test notification sent successfully via Pushover!")
except Exception as e:
print(f"Failed to send test notification via Pushover. Reason: {str(e)}")
# Testing Gotify Notification Provider
if 'GOTIFY' in config:
print("Testing Gotify Notification Provider...")
gotify_provider = GotifyNotificationProvider(config['GOTIFY']['Url'], config['GOTIFY']['Token'])
try:
gotify_provider.send_notification("Test Sender", "Test Notification from NotiMail")
print("Test notification sent successfully via Gotify!")
except Exception as e:
print(f"Failed to send test notification via Gotify. Reason: {str(e)}")
print("Testing done!")
def list_imap_folders():
"""
Function to list all IMAP folders of the configured mailboxes
"""
for section in config.sections():
if section.startswith("EMAIL:"):
print(f"Listing folders for {section}...")
handler = IMAPHandler(config[section]['Host'], config[section]['EmailUser'], config[section]['EmailPass'])
try:
handler.connect()
typ, folders = handler.mail.list()
for folder in folders:
print(folder.decode())
handler.mail.logout() # Explicitly logging out after listing folders
except Exception as e:
print(f"Failed to list folders for {section}. Reason: {str(e)}")
if __name__ == "__main__":
if args.print_config:
print_config()
elif args.test_config:
test_config()
elif args.list_folders:
list_imap_folders()
else:
multi_account_main()

View file

@ -1,6 +1,6 @@
# NotiMail 📧 # NotiMail 📧
**Version 0.11 is here, read the changelog for more information!** **Version 0.12 is here, read the changelog for more information!**
**Development is ongoing, and the project is in the early alpha stage - things may break!** **Development is ongoing, and the project is in the early alpha stage - things may break!**
@ -10,18 +10,19 @@ Mobile devices often use IMAP IDLE, maintaining a persistent connection to ensur
## Features 🌟 ## Features 🌟
- **Monitors Multiple Emails on the Server**: With version 0.9, NotiMail can now monitor multiple email accounts. Ensure you never miss an email regardless of which account it's sent to. - **Monitors Multiple Emails on the Server**: From version 0.9 onwards, NotiMail can monitor multiple email accounts. Ensure you never miss an email regardless of which account it's sent to.
- **Processes and Notifies**: Once a new email is detected, NotiMail swiftly processes its details. - **Monitors Multiple Folders per Account**: With version 0.12, you can configure NotiMail to monitor multiple folders for each email account. Whether it's your 'inbox', 'junk', or any other folder, stay informed with NotiMail.
- **Leverages Multiple Push Providers for Alerts**: Rather than having your device always on alert, NotiMail sends notifications via multiple push providers, ensuring you're promptly informed. - **Processes and Notifies**: Once a new email is detected, NotiMail swiftly processes its details.
- **Database Integration**: NotiMail uses an SQLite3 database to store and manage processed email UIDs, preventing repeated processing. - **Leverages Multiple Push Providers for Alerts**: Rather than having your device always on alert, NotiMail sends notifications via multiple push providers, ensuring you're promptly informed.
- **Built for Resilience**: With connectivity hiccups in mind, NotiMail ensures you're always the first to know. - **Database Integration**: NotiMail uses an SQLite3 database to store and manage processed email UIDs, preventing repeated processing.
- **Multiple And Different Push providers supported**: You can use one or more of the supported Push providers - all support authentication, which currently include ntfy, Gotify and Pushover. - **Built for Resilience**: With connectivity hiccups in mind, NotiMail ensures you're always the first to know.
- **Multiple And Different Push providers supported**: You can use one or more of the supported Push providers - all support authentication, which currently include ntfy, Gotify, and Pushover.
## Benefits 🚀 ## Benefits 🚀
@ -136,6 +137,21 @@ With that, you should have NotiMail up and running on your system! Enjoy a more
## Changelog ## Changelog
### Version 0.12
#### New Features:
- **Multiple Folder Monitoring**: From this version onwards, NotiMail supports monitoring multiple folders for each configured email account. This allows users to, for example, monitor both the 'inbox' and 'junk' folders simultaneously. Each folder is treated as a separate connection, ensuring robust and comprehensive monitoring.
- **Configuration Validation**: Introduced command-line functions to validate the config.ini file. This ensures that your settings are correctly configured before you start the NotiMail service.
- **Notification Provider Testing**: You can now test the notification providers by sending a test notification to verify their correct setup and functioning.
- **IMAP Folder Listing**: Added a feature to list all IMAP folders of the configured mailboxes, providing better insights and facilitating precise folder monitoring.
#### Changes:
- **Configuration (`config.ini`)**: Introduced the ability to specify multiple folders for each email account using the `Folders` configuration key. If not specified, it defaults to the 'inbox' folder.
- **Logging Enhancements**: All logging and print statements now include the folder name, providing a clearer understanding of ongoing operations per folder.
- **Codebase**: Enhanced error handling, and improved logging to provide clearer insights into the application's operations.
### Version 0.11 ### Version 0.11
#### New Features: #### New Features:

View file

@ -6,25 +6,27 @@ DataBaseLocation = /var/cache/notimail/processed_emails.db
EmailUser = your@address.com EmailUser = your@address.com
EmailPass = YourPassword EmailPass = YourPassword
Host = mail.server.com Host = mail.server.com
#Folders = inbox, sent
#[EMAIL:account2] #[EMAIL:account2]
#EmailUser = your@address.com #EmailUser = your@address.com
#EmailPass = YourPassword #EmailPass = YourPassword
#Host = mail.server.com #Host = mail.server.com
#Folders = inbox, sent
#If your provider is NTFY, uncomment the following lines and configure #If your provider is NTFY, uncomment the following lines and configure. If using NTFY, also uncomment the [NTFY] line
#[NTFY] #[NTFY]
#Url1 = https://ntfy.sh/TOPIC1 #Url1 = https://ntfy.sh/TOPIC1
#Token1 = Optional token to send notifications to protected topics #Token1 = Optional token to send notifications to protected topics
#Url2 = https://ntfy.sh/TOPIC2 #Url2 = https://ntfy.sh/TOPIC2
#Token2 = Optional token to send notifications to protected topics #Token2 = Optional token to send notifications to protected topics
#If your provider is PUSHOVER, uncomment the following lines and configure #If your provider is PUSHOVER, uncomment the following lines and configure. If using PUSHOVER, also uncomment the [PUSHOVER] line
#[PUSHOVER] #[PUSHOVER]
#ApiToken = YOUR_PUSHOVER_API_TOKEN #ApiToken = YOUR_PUSHOVER_API_TOKEN
#UserKey = YOUR_PUSHOVER_USER_KEY #UserKey = YOUR_PUSHOVER_USER_KEY
#If your provider is GOTIFY, uncomment the following lines and configure #If your provider is GOTIFY, uncomment the following lines and configure. If using GOTIFY, also uncomment the [GOTIFY] line
#[GOTIFY] #[GOTIFY]
#Url = https://gotify.example.com/message #Url = https://gotify.example.com/message
#Token = your_gotify_token #Token = your_gotify_token

View file

@ -1,28 +1,44 @@
.\" Man page for NotiMail .\" Man page for NotiMail
.TH MAN 1 "23 October 2023" .TH MAN 1 "24 October 2023"
.SH NAME .SH NAME
NotiMail \- Monitor email inbox(es) and send HTTP POST notifications upon new email arrivals. NotiMail \- Monitor email inbox(es) and send notifications upon new email arrivals using various providers.
.SH SYNOPSIS .SH SYNOPSIS
.B notimail .B notimail
[\fB-c\fR \fICONFIG\fR] [\fB-c\fR \fICONFIG\fR]
[\fB--check-config\fR]
[\fB--test-config\fR]
[\fB--list-folders\fR]
.SH DESCRIPTION .SH DESCRIPTION
NotiMail is a script designed to monitor one or more email inbox(es) using the IMAP IDLE feature and send notifications via HTTP POST requests when a new email arrives. The script can connect to multiple email servers and send notifications to different platforms, including NTFY, Pushover, and Gotify. NotiMail is a script designed to monitor one or more email inboxes using the IMAP IDLE feature. It sends notifications when a new email arrives. The script can connect to multiple email servers and send notifications to different platforms, including NTFY, Pushover, and Gotify.
.P .P
Key features: Key features:
.RS .RS
.IP "*" .IP "*"
Monitors one or more email inboxes using IMAP IDLE. Monitors one or more email inboxes using IMAP IDLE.
.IP "*" .IP "*"
Supports monitoring of multiple folders per email account.
.IP "*"
Sends notifications containing the sender and subject of new emails. Sends notifications containing the sender and subject of new emails.
.IP "*" .IP "*"
Maintains a SQLite database to ensure that emails are not processed repeatedly. Maintains a SQLite database to ensure that emails are not processed repeatedly.
.IP "*" .IP "*"
Supports multiple notification providers: NTFY, Pushover, and Gotify. Supports multiple notification providers: NTFY, Pushover, and Gotify.
.IP "*"
Provides command-line functionalities to validate, test, and list IMAP folders.
.RE .RE
.SH OPTIONS .SH OPTIONS
.TP .TP
\fB-c\fR, \fB--config\fR \fICONFIG\fR \fB-c\fR, \fB--config\fR \fICONFIG\fR
Specify the path to the configuration file. Defaults to \fIconfig.ini\fR. Specify the path to the configuration file. Defaults to \fIconfig.ini\fR.
.TP
\fB--check-config\fR
Check and print the configurations set in the `config.ini` file.
.TP
\fB--test-config\fR
Test if the configurations set in the `config.ini` file are working properly.
.TP
\fB--list-folders\fR
List all the IMAP folders of the configured mailboxes.
.SH CONFIGURATION .SH CONFIGURATION
Configuration data is read from a file named \fIconfig.ini\fR. Ensure it's correctly set up before running the script. The configuration file has multiple sections: Configuration data is read from a file named \fIconfig.ini\fR. Ensure it's correctly set up before running the script. The configuration file has multiple sections:
.P .P
@ -40,6 +56,8 @@ The email address.
The password for the email address. The password for the email address.
.IP Host: .IP Host:
The email server. The email server.
.IP Folders:
A comma-separated list of folders to monitor.
.IP "[NTFY]:" .IP "[NTFY]:"
Configuration for the NTFY notification provider. Configuration for the NTFY notification provider.
.IP UrlX: .IP UrlX:
@ -98,10 +116,24 @@ notimail
.IP "" .IP ""
notimail \-c /path/to/custom_config.ini notimail \-c /path/to/custom_config.ini
.RE .RE
3. Checking the current configuration:
.RS
.IP ""
notimail --check-config
.RE
4. Testing the configuration settings:
.RS
.IP ""
notimail --test-config
.RE
5. Listing IMAP folders of the configured mailboxes:
.RS
.IP ""
notimail --list-folders
.RE
.SH AUTHOR .SH AUTHOR
Stefano Marinelli <stefano@dragas.it> Stefano Marinelli <stefano@dragas.it>
.SH LICENSE .SH LICENSE
BSD 3-Clause License. See the source distribution for details. BSD 3-Clause License. See the source distribution for details.
.SH SEE ALSO .SH SEE ALSO
IMAP IDLE, SQLite3, NTFY, Pushover, Gotify. IMAP IDLE, SQLite3, NTFY, Pushover, Gotify.