diff --git a/docs/index.md b/docs/index.md index 6a0ba865..62d6aad9 100755 --- a/docs/index.md +++ b/docs/index.md @@ -2,6 +2,8 @@ Welcome to the official NetAlertX documentation! NetAlertX is a powerful tool designed to simplify the management and monitoring of your network. Below, you will find guides and resources to help you set up, configure, and troubleshoot your NetAlertX instance. +![Preview](./img/devices_split.png) + ## In-App Help NetAlertX provides contextual help within the application: @@ -13,6 +15,8 @@ NetAlertX provides contextual help within the application: ## Installation Guides +The app can be installed different ways, with the best support of the docker-based deployments. This includes the Home Assistant and Unraid installation approaches. See details below. + ### Docker (Fully Supported) NetAlertX is fully supported in Docker environments, allowing for easy setup and configuration. Follow the official guide to get started: @@ -21,12 +25,25 @@ NetAlertX is fully supported in Docker environments, allowing for easy setup and This guide will take you through the process of setting up NetAlertX using Docker Compose or standalone Docker commands. +### Home Assistant (Fully Supported) + +You can install NetAlertX also as a Home Assistant addon [![Home Assistant](https://img.shields.io/badge/Repo-blue?logo=home-assistant&style=for-the-badge&color=0aa8d2&logoColor=fff&label=Add)](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Falexbelgium%2Fhassio-addons) via the [alexbelgium/hassio-addons](https://github.com/alexbelgium/hassio-addons/) repository. This is only possible if you run a supervised instance of Home Assistant. If not, you can still run NetAlertX in a separate Docker container and follow this guide to configure MQTT. + +- [[Installation] Home Assistant](https://github.com/alexbelgium/hassio-addons/tree/master/netalertx) + +### Unraid (Partial Support) + +The Unraid template was created by the community, so it's only partially supported. Alternatively, here is [another version of the Unraid template](https://github.com/jokob-sk/NetAlertX-unraid). + +- [[Installation] Unraid App](https://unraid.net/community/apps) + ### Bare-Metal Installation (Experimental) -If you prefer to run NetAlertX on your own hardware, you can try the experimental bare-metal installation. Please note that this method is still under development, and we're looking for maintainers to help improve it. +If you prefer to run NetAlertX on your own hardware, you can try the experimental bare-metal installation. Please note that this method is still under development, and are looking for maintainers to help improve it. - [Bare-Metal Installation Guide](./HW_INSTALL.md) + --- ## Help and Support @@ -66,14 +83,10 @@ To keep up with the latest changes and updates to NetAlertX, please refer to the Make sure to follow the project on GitHub to get notifications for new releases and important updates. --- +## Additional info -## Additional Resources - -- **Configuration Tips**: Learn how to optimize NetAlertX for your network setup. -- **Advanced Features**: Explore advanced functionalities like plugin development and custom configurations. - **Documentation Index**: Check out the full [documentation index](https://github.com/jokob-sk/NetAlertX/tree/main/docs) for all the guides available. -We hope you find this documentation helpful. If you have any suggestions or improvements, please don’t hesitate to contribute! +If you have any suggestions or improvements, please don’t hesitate to contribute! ---- NetAlertX is actively maintained. You can find the source code, report bugs, or request new features on our [GitHub page](https://github.com/jokob-sk/NetAlertX). diff --git a/front/plugins/_publisher_email/config.json b/front/plugins/_publisher_email/config.json index 6e15c052..42aff9d3 100755 --- a/front/plugins/_publisher_email/config.json +++ b/front/plugins/_publisher_email/config.json @@ -658,7 +658,7 @@ "description": [ { "language_code": "en_us", - "string": "Email address to which the notification will be send to." + "string": "Email address to which the notification will be send to. You can enter multiple emails separated by a comma (,)." }, { "language_code": "es_es", diff --git a/front/plugins/_publisher_email/email_smtp.py b/front/plugins/_publisher_email/email_smtp.py index 8cc0c001..a55207e7 100755 --- a/front/plugins/_publisher_email/email_smtp.py +++ b/front/plugins/_publisher_email/email_smtp.py @@ -119,44 +119,54 @@ def send(pHTML, pText): subject, from_email, to_email, message_html, message_text = sanitize_email_content('NetAlertX Report', get_setting_value("SMTP_REPORT_FROM"), get_setting_value("SMTP_REPORT_TO"), pHTML, pText) - # Compose email - msg = MIMEMultipart('alternative') - msg['Subject'] = subject - msg['From'] = from_email - msg['To'] = to_email - msg['Date'] = formatdate(localtime=True) - - msg.attach (MIMEText (message_text, 'plain')) - msg.attach (MIMEText (message_html, 'html')) - - # Set a timeout for the SMTP connection (in seconds) - smtp_timeout = 30 - - mylog('debug', ['Trying to open connection to ' + str(get_setting_value('SMTP_SERVER')) + ':' + str(get_setting_value('SMTP_PORT'))]) - - if get_setting_value("LOG_LEVEL") == 'debug': - - send_email(msg,smtp_timeout) + emails = [] + # handle multiple emails + if ',' in to_email: + emails = [e.strip() for e in to_email.split(',')] else: + emails.append(to_email.strip()) + + for mail_addr in emails: + + # Compose email + msg = MIMEMultipart('alternative') + msg['Subject'] = subject + msg['From'] = from_email + msg['To'] = mail_addr + msg['Date'] = formatdate(localtime=True) + + msg.attach (MIMEText (message_text, 'plain')) + msg.attach (MIMEText (message_html, 'html')) + + # Set a timeout for the SMTP connection (in seconds) + smtp_timeout = 30 + + mylog('debug', ['Trying to open connection to ' + str(get_setting_value('SMTP_SERVER')) + ':' + str(get_setting_value('SMTP_PORT'))]) + + if get_setting_value("LOG_LEVEL") == 'debug': - try: send_email(msg,smtp_timeout) - - except smtplib.SMTPAuthenticationError as e: - mylog('none', [' ERROR: Couldn\'t connect to the SMTP server (SMTPAuthenticationError)']) - mylog('none', [' ERROR: Double-check your SMTP_USER and SMTP_PASS settings.)']) - mylog('none', [' ERROR: ', str(e)]) - except smtplib.SMTPServerDisconnected as e: - mylog('none', [' ERROR: Couldn\'t connect to the SMTP server (SMTPServerDisconnected)']) - mylog('none', [' ERROR: ', str(e)]) - except socket.gaierror as e: - mylog('none', [' ERROR: Could not resolve hostname (socket.gaierror)']) - mylog('none', [' ERROR: ', str(e)]) - except ssl.SSLError as e: - mylog('none', [' ERROR: Could not establish SSL connection (ssl.SSLError)']) - mylog('none', [' ERROR: Are you sure you need SMTP_FORCE_SSL enabled? Check your SMTP provider docs.']) - mylog('none', [' ERROR: ', str(e)]) + + else: + + try: + send_email(msg,smtp_timeout) + + except smtplib.SMTPAuthenticationError as e: + mylog('none', [' ERROR: Couldn\'t connect to the SMTP server (SMTPAuthenticationError)']) + mylog('none', [' ERROR: Double-check your SMTP_USER and SMTP_PASS settings.)']) + mylog('none', [' ERROR: ', str(e)]) + except smtplib.SMTPServerDisconnected as e: + mylog('none', [' ERROR: Couldn\'t connect to the SMTP server (SMTPServerDisconnected)']) + mylog('none', [' ERROR: ', str(e)]) + except socket.gaierror as e: + mylog('none', [' ERROR: Could not resolve hostname (socket.gaierror)']) + mylog('none', [' ERROR: ', str(e)]) + except ssl.SSLError as e: + mylog('none', [' ERROR: Could not establish SSL connection (ssl.SSLError)']) + mylog('none', [' ERROR: Are you sure you need SMTP_FORCE_SSL enabled? Check your SMTP provider docs.']) + mylog('none', [' ERROR: ', str(e)]) # ---------------------------------------------------------------------------------- def send_email(msg,smtp_timeout): diff --git a/front/plugins/website_monitor/script.py b/front/plugins/website_monitor/script.py index dc289ee8..ce275169 100755 --- a/front/plugins/website_monitor/script.py +++ b/front/plugins/website_monitor/script.py @@ -54,16 +54,27 @@ def check_services_health(site): mylog('verbose', [f'[{pluginName}] Checking {site}']) requests.packages.urllib3.disable_warnings(InsecureRequestWarning) + try: resp = requests.get(site, verify=False, timeout=get_setting_value('WEBMON_RUN_TIMEOUT')) latency = resp.elapsed.total_seconds() status = resp.status_code - except requests.exceptions.SSLError: - status = 503 + except SSLError: + status = 495 # SSL Certificate Error (non-standard, but more meaningful than 503) latency = 99999 - except: - status = 503 + mylog('debug', [f'[{pluginName}] SSL error while checking {site}']) + except Timeout: + status = 504 # Gateway Timeout latency = 99999 + mylog('debug', [f'[{pluginName}] Timeout while checking {site}']) + except RequestException as e: + status = 520 # Web server is returning an unknown error (Cloudflare-style) + latency = 99999 + mylog('debug', [f'[{pluginName}] Request error while checking {site}: {e}']) + except Exception as e: + status = 500 # Internal Server Error (fallback) + latency = 99999 + mylog('debug', [f'[{pluginName}] Unexpected error while checking {site}: {e}']) mylog('verbose', [f'[{pluginName}] Result for {site} (status|latency) : {status}|{latency}']) diff --git a/server/graphql_server/graphql_schema.py b/server/graphql_server/graphql_schema.py index 5437d0a4..83bff5a6 100755 --- a/server/graphql_server/graphql_schema.py +++ b/server/graphql_server/graphql_schema.py @@ -120,12 +120,10 @@ class Query(ObjectType): device["devIsRandomMac"] = 1 if is_random_mac(device["devMac"]) else 0 device["devParentChildrenCount"] = get_number_of_children(device["devMac"], devices_data) device["devIpLong"] = format_ip_long(device.get("devLastIP", "")) - mylog('verbose', f'[graphql_schema] devices_data: {devices_data}') - # Apply sorting if options are provided if options: diff --git a/server/plugin.py b/server/plugin.py index 85ab4cc9..d31d3f63 100755 --- a/server/plugin.py +++ b/server/plugin.py @@ -102,11 +102,11 @@ class plugin_manager: # Process each event type if event == 'test': - handle_test(param) + self.handle_test(param) executed_events.append(f"test with param {param}") execution_log.finalize_event("test") elif event == 'run': - handle_run(param) + self.handle_run(param) executed_events.append(f"run with param {param}") execution_log.finalize_event("run") elif event == 'update_api': @@ -151,11 +151,11 @@ class plugin_manager: sample_json = json.loads(get_file_content(reportTemplatesPath + 'webhook_json_sample.json'))[0]["body"]["attachments"][0]["text"] # Create fake notification - notification = Notification_obj(db) + notification = Notification_obj(self.db) notificationObj = notification.create(sample_json, "") # Run test - handle_run(runType) + self.handle_run(runType) # Remove sample notification notificationObj.remove(notificationObj.GUID)