This is an automated email from the ASF dual-hosted git repository.

dominikriemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to refs/heads/dev by this push:
     new 984651fcf5 feat: Extend email error hints (#4676)
984651fcf5 is described below

commit 984651fcf52aa81899c22c69d641515ca82503c1
Author: Dominik Riemer <[email protected]>
AuthorDate: Thu Jul 2 14:46:04 2026 +0200

    feat: Extend email error hints (#4676)
---
 .../impl/admin/EmailConfigurationResource.java     | 58 +++++++++++++++++++++-
 ui/deployment/i18n/de.json                         | 18 ++++++-
 ui/deployment/i18n/en.json                         | 18 ++++++-
 ui/deployment/i18n/pl.json                         | 18 ++++++-
 .../email-configuration.component.ts               | 34 ++++++++++---
 ui/src/scss/sp/sp-theme.scss                       |  6 +++
 6 files changed, 138 insertions(+), 14 deletions(-)

diff --git 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/EmailConfigurationResource.java
 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/EmailConfigurationResource.java
index 4bd6cf8a63..263307f255 100644
--- 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/EmailConfigurationResource.java
+++ 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/EmailConfigurationResource.java
@@ -28,6 +28,8 @@ import 
org.apache.streampipes.storage.api.system.ISpCoreConfigurationStorage;
 import 
org.apache.streampipes.user.management.encryption.SecretEncryptionManager;
 
 import org.simplejavamail.MailException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
@@ -39,12 +41,21 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import jakarta.mail.MessagingException;
+
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Set;
 
 @RestController
 @RequestMapping("/api/v2/admin/mail-config")
 public class EmailConfigurationResource extends 
AbstractAuthGuardedRestResource {
 
+  private static final Logger LOG = 
LoggerFactory.getLogger(EmailConfigurationResource.class);
+
   private final ISpCoreConfigurationStorage configurationStorage;
 
   public EmailConfigurationResource(ISpCoreConfigurationStorage 
coreConfigurationStorage) {
@@ -100,7 +111,52 @@ public class EmailConfigurationResource extends 
AbstractAuthGuardedRestResource
       new MailTester(coreConfiguration).sendTestMail(config);
       return ok();
     } catch (MailException | IllegalArgumentException | IOException e) {
-      throw new SpMessageException(HttpStatus.BAD_REQUEST, 
Notifications.error(e.getMessage()));
+      var mailExceptionDetails = getMailExceptionDetails(e);
+      LOG.warn("Unable to send test email. {}", mailExceptionDetails, e);
+      throw new SpMessageException(
+          HttpStatus.BAD_REQUEST,
+          Notifications.error(
+              "Unable to send test email",
+              "Please verify the SMTP server, port, transport strategy, 
credentials, proxy settings, "
+                  + "and recipient address. Server response: " + 
mailExceptionDetails));
+    }
+  }
+
+  private String getMailExceptionDetails(Exception e) {
+    return String.join(" Cause: ", extractExceptionMessages(e));
+  }
+
+  private List<String> extractExceptionMessages(Throwable throwable) {
+    var messages = new ArrayList<String>();
+    Set<Throwable> visited = Collections.newSetFromMap(new 
IdentityHashMap<>());
+    collectExceptionMessages(throwable, messages, visited);
+    return messages;
+  }
+
+  private void collectExceptionMessages(Throwable throwable,
+                                        List<String> messages,
+                                        Set<Throwable> visited) {
+    if (throwable == null || !visited.add(throwable)) {
+      return;
+    }
+
+    addExceptionMessage(throwable, messages);
+    collectExceptionMessages(throwable.getCause(), messages, visited);
+
+    if (throwable instanceof MessagingException messagingException) {
+      collectExceptionMessages(messagingException.getNextException(), 
messages, visited);
+    }
+  }
+
+  private void addExceptionMessage(Throwable throwable,
+                                   List<String> messages) {
+    var message = throwable.getMessage();
+    if (message == null || message.isBlank()) {
+      message = throwable.getClass().getSimpleName();
+    }
+
+    if (!messages.contains(message)) {
+      messages.add(message);
     }
   }
 }
diff --git a/ui/deployment/i18n/de.json b/ui/deployment/i18n/de.json
index 84202ba498..5f37866fe6 100644
--- a/ui/deployment/i18n/de.json
+++ b/ui/deployment/i18n/de.json
@@ -221,6 +221,7 @@
   "Configure labels which can be assigned to assets and other resources": 
"Labels konfigurieren, die Assets und anderen Ressourcen zugewiesen werden 
können",
   "Configure schema": "Schema konfigurieren",
   "Configure trusted and rejected OPC-UA certificates": "Konfiguration der 
vertrauenswürdigen und abgelehnten OPC-UA Zertifikate",
+  "Configured": "Konfiguriert",
   "Confirm password": "Passwort bestätigen",
   "Connect Adapter": "Adapter anschließen",
   "Connection could not be established.": "Die Verbindung konnte nicht 
hergestellt werden.",
@@ -232,7 +233,9 @@
   "Copyright notice": "Copyright-Hinweis",
   "Could not change email address.": "Die E-Mail-Adresse konnte nicht geändert 
werden.",
   "Could not change the password.": "Das Passwort konnte nicht geändert 
werden.",
+  "Could not load running instances": "Laufende Instanzen konnten nicht 
geladen werden",
   "Could not send email": "E-Mail konnte nicht versendet werden",
+  "Could not send test email.": "Test-E-Mail konnte nicht versendet werden.",
   "Could not upload file": "Datei konnte nicht hochgeladen werden",
   "Count": "Anzahl",
   "Create": "Erstellen",
@@ -417,7 +420,6 @@
   "Error in line {{rowNumber}}. Value for \"{{property}}\" is not set.": 
"Fehler in Zeile {{rowNumber}}. Wert für \"{{property}}\" ist nicht gesetzt.",
   "Error in line {{rowNumber}}. Value for \"{{property}}\" is not supported.": 
"Fehler in Zeile {{rowNumber}}. Wert für \"{{property}}\" wird nicht 
unterstützt.",
   "Error while uploading application package": "Fehler beim Hochladen des 
Anwendungspakets",
-  "Error: {{message}} with cause {{cause}}": "Fehler: {{message}} mit Ursache 
{{cause}}",
   "Event Aggregation": "Aggregation",
   "Event Transformation Configuration has changed": "Die Transformation von 
Events wurde geändert",
   "Events": "Ereignisse",
@@ -557,6 +559,7 @@
   "Installation": "Installation",
   "Installed": "Installiert",
   "Installing": "Wird installiert",
+  "Instance ID": "Instanz-ID",
   "Internally managed by {{appName}}": "Intern verwaltet von {{appName}}",
   "Interval [sec]": "Intervall [sec]",
   "Interval in seconds in which an event must arrive": "Sekundenintervall, in 
dem ein Ereignis eintreffen muss",
@@ -745,6 +748,8 @@
   "No more information": "Keine weiteren Informationen",
   "No nodes selected yet": "Noch keine Knoten ausgewählt",
   "No numeric or boolean fields available.": "Keine numerischen oder 
booleschen Felder verfügbar.",
+  "No running adapters": "Keine laufenden Adapter",
+  "No running pipeline elements": "Keine laufenden Pipeline-Elemente",
   "No table rows match the current filter.": "Keine Tabellenzeilen entsprechen 
dem aktuellen Filter.",
   "Node Details": "Details zum Knoten",
   "None": "Keine",
@@ -768,6 +773,9 @@
   "Order": "Sortieren",
   "Original": "Original",
   "Original (Parsed)": "Original (geparst)",
+  "Orphaned": "Verwaist",
+  "Orphaned adapter instance": "Verwaiste Adapterinstanz",
+  "Orphaned pipeline element instance": "Verwaiste Pipeline-Element-Instanz",
   "Others Label": "Beschriftung für Sonstige",
   "Output Topics": "Output-Topics",
   "Output stream": "Ausgabestream",
@@ -792,6 +800,7 @@
   "Pipeline Name": "Name der Pipeline",
   "Pipeline as code": "Pipeline als Code",
   "Pipeline description must not have more than 80 characters.": "Die 
Pipeline-Beschreibung darf nicht mehr als 80 Zeichen umfassen.",
+  "Pipeline elements": "Pipeline-Elemente",
   "Pipeline health monitoring discovered the following issues:": "Die 
Zustandsüberwachung der Pipeline hat folgende Probleme festgestellt:",
   "Pipeline name can only contain letters, numbers, dashes (-), and 
underscores (_).": "Pipeline-Namen dürfen nur Buchstaben, Zahlen, Bindestriche 
(-) und Unterstriche (_) enthalten.",
   "Pipeline name cannot start or end with a space.": "Der Name der Pipeline 
darf nicht mit einem Leerzeichen beginnen oder enden.",
@@ -861,6 +870,7 @@
   "Registration process": "Registrierungsprozess",
   "Reject": "Ablehnen",
   "Related Pipeline": "Zugehörige Pipelines",
+  "Relation": "Beziehung",
   "Reload": "Neu laden",
   "Reload Sample": "Beispieldaten aktualisieren",
   "Reload items": "Items neu laden",
@@ -870,7 +880,9 @@
   "Remove Duplicates": "Duplikate entfernen",
   "Remove Duplicates Time Window": "Zeitintervall",
   "Remove Mapping": "Mapping entfernen",
+  "Remove all instances": "Alle Instanzen entfernen",
   "Remove export provider configuration": "Konfiguration des Exportanbieters 
entfernen",
+  "Remove instance from service": "Instanz aus dem Dienst entfernen",
   "Remove node": "Knoten entfernen",
   "Rename file": "Datei umbenennen",
   "Rename files": "Dateien umbenennen",
@@ -911,6 +923,7 @@
   "Run adapter": "Adapter ausführen",
   "Run or adjust the query to see a row preview.": "Führen Sie die Abfrage aus 
oder passen Sie sie an, um eine Zeilenvorschau zu sehen.",
   "Running": "Gestartet",
+  "Running instances": "Laufende Instanzen",
   "Runtime Name": "Laufzeitname",
   "Runtime name": "Laufzeitname",
   "Runtime type": "Laufzeittyp",
@@ -986,6 +999,7 @@
   "Settings for externally-managed users cannot be changed": "Einstellungen 
für extern verwaltete Benutzer können nicht geändert werden",
   "Settings of externally-managed users cannot be changed.": "Die 
Einstellungen von extern verwalteten Benutzern können nicht geändert werden.",
   "Settings to connect to a mail server": "Einstellungen zur Verbindung mit 
einem Mailserver",
+  "Shared transformation templates": "Geteilte Transformationsvorlagen",
   "Shortcuts": "Shortcuts",
   "Show": "Anzeigen",
   "Show API documentation link on login page": "Link zur API-Dokumentation auf 
der Login-Seite anzeigen",
@@ -1017,7 +1031,6 @@
   "Show tooltip": "Tooltip anzeigen",
   "Show values as labels": "Werte als Beschriftung anzeigen",
   "Shows the distribution of numerical data": "Zeigt die Verteilung der 
numerischen Daten",
-  "Shared transformation templates": "Geteilte Transformationsvorlagen",
   "Simple filters below are kept for fallback, but the advanced filter is 
currently used for queries.": "Die einfachen Filter unten bleiben als 
Rückfalloption erhalten, aber derzeit wird der erweiterte Filter für Abfragen 
verwendet.",
   "Single": "Einzeln",
   "Site": "Standort",
@@ -1255,6 +1268,7 @@
   "View Topics": "Topics anzeigen",
   "View mode": "Ansicht",
   "View pipeline as code": "Pipeline als Code anzeigen",
+  "View running instances": "Laufende Instanzen anzeigen",
   "View service details": "Service-Details anzeigen",
   "View the documentation for a full user guide.": "Siehe die Dokumentation 
fur ein vollstandiges Benutzerhandbuch.",
   "View the documentation of the API. Here you can see all provided endpoints 
and how to query them.": "Anzeigen der API-Dokumentation. Bereitgestellte 
Endpunkte und Funktionen einsehen.",
diff --git a/ui/deployment/i18n/en.json b/ui/deployment/i18n/en.json
index aee28aa99d..20f4d098be 100644
--- a/ui/deployment/i18n/en.json
+++ b/ui/deployment/i18n/en.json
@@ -221,6 +221,7 @@
   "Configure labels which can be assigned to assets and other resources": null,
   "Configure schema": null,
   "Configure trusted and rejected OPC-UA certificates": null,
+  "Configured": null,
   "Confirm password": null,
   "Connect Adapter": null,
   "Connection could not be established.": null,
@@ -232,7 +233,9 @@
   "Copyright notice": null,
   "Could not change email address.": null,
   "Could not change the password.": null,
+  "Could not load running instances": null,
   "Could not send email": null,
+  "Could not send test email.": null,
   "Could not upload file": null,
   "Count": null,
   "Create": null,
@@ -417,7 +420,6 @@
   "Error in line {{rowNumber}}. Value for \"{{property}}\" is not set.": 
"Error in line {{rowNumber}}. Value for \"{{property}}\" is not set.",
   "Error in line {{rowNumber}}. Value for \"{{property}}\" is not supported.": 
"Error in line {{rowNumber}}. Value for \"{{property}}\" is not supported.",
   "Error while uploading application package": null,
-  "Error: {{message}} with cause {{cause}}": "Error: {{message}} with cause 
{{cause}}",
   "Event Aggregation": null,
   "Event Transformation Configuration has changed": null,
   "Events": null,
@@ -557,6 +559,7 @@
   "Installation": null,
   "Installed": null,
   "Installing": null,
+  "Instance ID": null,
   "Internally managed by {{appName}}": "Internally managed by {{appName}}",
   "Interval [sec]": null,
   "Interval in seconds in which an event must arrive": null,
@@ -745,6 +748,8 @@
   "No more information": null,
   "No nodes selected yet": null,
   "No numeric or boolean fields available.": null,
+  "No running adapters": null,
+  "No running pipeline elements": null,
   "No table rows match the current filter.": null,
   "Node Details": null,
   "None": null,
@@ -768,6 +773,9 @@
   "Order": null,
   "Original": null,
   "Original (Parsed)": null,
+  "Orphaned": null,
+  "Orphaned adapter instance": null,
+  "Orphaned pipeline element instance": null,
   "Others Label": null,
   "Output Topics": null,
   "Output stream": null,
@@ -792,6 +800,7 @@
   "Pipeline Name": null,
   "Pipeline as code": null,
   "Pipeline description must not have more than 80 characters.": null,
+  "Pipeline elements": null,
   "Pipeline health monitoring discovered the following issues:": null,
   "Pipeline name can only contain letters, numbers, dashes (-), and 
underscores (_).": null,
   "Pipeline name cannot start or end with a space.": null,
@@ -861,6 +870,7 @@
   "Registration process": null,
   "Reject": null,
   "Related Pipeline": null,
+  "Relation": null,
   "Reload": null,
   "Reload Sample": null,
   "Reload items": null,
@@ -870,7 +880,9 @@
   "Remove Duplicates": null,
   "Remove Duplicates Time Window": null,
   "Remove Mapping": null,
+  "Remove all instances": null,
   "Remove export provider configuration": null,
+  "Remove instance from service": null,
   "Remove node": null,
   "Rename file": null,
   "Rename files": null,
@@ -911,6 +923,7 @@
   "Run adapter": null,
   "Run or adjust the query to see a row preview.": null,
   "Running": null,
+  "Running instances": null,
   "Runtime Name": null,
   "Runtime name": null,
   "Runtime type": null,
@@ -986,6 +999,7 @@
   "Settings for externally-managed users cannot be changed": null,
   "Settings of externally-managed users cannot be changed.": null,
   "Settings to connect to a mail server": null,
+  "Shared transformation templates": null,
   "Shortcuts": null,
   "Show": null,
   "Show API documentation link on login page": null,
@@ -1017,7 +1031,6 @@
   "Show tooltip": null,
   "Show values as labels": null,
   "Shows the distribution of numerical data": null,
-  "Shared transformation templates": null,
   "Simple filters below are kept for fallback, but the advanced filter is 
currently used for queries.": null,
   "Single": null,
   "Site": null,
@@ -1255,6 +1268,7 @@
   "View Topics": null,
   "View mode": null,
   "View pipeline as code": null,
+  "View running instances": null,
   "View service details": null,
   "View the documentation for a full user guide.": null,
   "View the documentation of the API. Here you can see all provided endpoints 
and how to query them.": null,
diff --git a/ui/deployment/i18n/pl.json b/ui/deployment/i18n/pl.json
index 21d57673be..c548ab39cd 100644
--- a/ui/deployment/i18n/pl.json
+++ b/ui/deployment/i18n/pl.json
@@ -221,6 +221,7 @@
   "Configure labels which can be assigned to assets and other resources": 
"Skonfiguruj etykiety, które mogą być przypisywane do zasobów i innych zasobów",
   "Configure schema": "Skonfiguruj schemat",
   "Configure trusted and rejected OPC-UA certificates": "Skonfiguruj zaufane i 
odrzucone certyfikaty OPC-UA",
+  "Configured": "Skonfigurowane",
   "Confirm password": "Potwierdź hasło",
   "Connect Adapter": "Podłącz adapter",
   "Connection could not be established.": "Nie udało się nawiązać połączenia.",
@@ -232,7 +233,9 @@
   "Copyright notice": "Informacja o prawach autorskich",
   "Could not change email address.": "Nie udało się zmienić adresu e-mail.",
   "Could not change the password.": "Nie udało się zmienić hasła.",
+  "Could not load running instances": "Nie można załadować uruchomionych 
instancji",
   "Could not send email": "Nie można wysłać e-maila",
+  "Could not send test email.": "Nie można wysłać testowej wiadomości e-mail.",
   "Could not upload file": "Nie udało się przesłać pliku",
   "Count": "Liczba",
   "Create": "Utwórz",
@@ -417,7 +420,6 @@
   "Error in line {{rowNumber}}. Value for \"{{property}}\" is not set.": "Błąd 
w wierszu {{rowNumber}}. Wartość dla \",{{property}}\", nie została ustawiona.",
   "Error in line {{rowNumber}}. Value for \"{{property}}\" is not supported.": 
"Błąd w wierszu {{rowNumber}}. Wartość dla \",{{property}}\", nie jest 
obsługiwana.",
   "Error while uploading application package": "Błąd podczas przesyłania 
pakietu aplikacji",
-  "Error: {{message}} with cause {{cause}}": "Błąd: {{message}} z powodu 
{{cause}}",
   "Event Aggregation": "Agregacja",
   "Event Transformation Configuration has changed": "Konfiguracja 
transformacji zdarzeń została zmieniona",
   "Events": "Zdarzenia",
@@ -557,6 +559,7 @@
   "Installation": "Instalacja",
   "Installed": "Zainstalowane",
   "Installing": "Instalowanie",
+  "Instance ID": "ID instancji",
   "Internally managed by {{appName}}": "Zarządzane wewnętrznie przez 
{{appName}}",
   "Interval [sec]": "Interwał [s]",
   "Interval in seconds in which an event must arrive": "Interwał w sekundach, 
w którym musi nadejść zdarzenie",
@@ -745,6 +748,8 @@
   "No more information": "Brak dalszych informacji",
   "No nodes selected yet": "Nie wybrano jeszcze żadnych węzłów",
   "No numeric or boolean fields available.": "Brak dostępnych pól liczbowych 
lub logicznych.",
+  "No running adapters": "Brak uruchomionych adapterów",
+  "No running pipeline elements": "Brak uruchomionych elementów strumienia",
   "No table rows match the current filter.": "Żaden wiersz tabeli nie pasuje 
do bieżącego filtra.",
   "Node Details": "Szczegóły węzła",
   "None": "Brak",
@@ -768,6 +773,9 @@
   "Order": "Kolejność",
   "Original": "Oryginalne",
   "Original (Parsed)": "Oryginał (przetworzony)",
+  "Orphaned": "Osierocone",
+  "Orphaned adapter instance": "Osierocona instancja adaptera",
+  "Orphaned pipeline element instance": "Osierocona instancja elementu 
strumienia",
   "Others Label": "Etykieta dla pozostałych",
   "Output Topics": "Tematy wyjściowe",
   "Output stream": "Strumień wyjściowy",
@@ -792,6 +800,7 @@
   "Pipeline Name": "Nazwa strumienia",
   "Pipeline as code": "Strumień jako kod",
   "Pipeline description must not have more than 80 characters.": "Opis 
strumieni nie może mieć więcej niż 80 znaków.",
+  "Pipeline elements": "Elementy strumienia",
   "Pipeline health monitoring discovered the following issues:": 
"Monitorowanie kondycji strumienia wykryło następujące problemy:",
   "Pipeline name can only contain letters, numbers, dashes (-), and 
underscores (_).": "Nazwa strumieni może zawierać tylko litery, cyfry, myślniki 
(-) i podkreślenia (_).",
   "Pipeline name cannot start or end with a space.": "Nazwa strumienia nie 
może zaczynać się ani kończyć spacją.",
@@ -861,6 +870,7 @@
   "Registration process": "Proces rejestracji",
   "Reject": "Odrzuć",
   "Related Pipeline": "Powiązany strumień",
+  "Relation": "Relacja",
   "Reload": "Przeładuj",
   "Reload Sample": "Wczytaj próbkę ponownie",
   "Reload items": "Przeładuj elementy",
@@ -870,7 +880,9 @@
   "Remove Duplicates": "Usuń duplikaty",
   "Remove Duplicates Time Window": "Okno czasowe",
   "Remove Mapping": "Usuń mapowanie",
+  "Remove all instances": "Usuń wszystkie instancje",
   "Remove export provider configuration": "Usuń konfigurację eksportera",
+  "Remove instance from service": "Usuń instancję z usługi",
   "Remove node": "Usuń węzeł",
   "Rename file": "Zmień nazwę pliku",
   "Rename files": "Zmień nazwy plików",
@@ -911,6 +923,7 @@
   "Run adapter": "Uruchom adapter",
   "Run or adjust the query to see a row preview.": "Uruchom lub dostosuj 
zapytanie, aby zobaczyć podgląd wierszy.",
   "Running": "Działa",
+  "Running instances": "Uruchomione instancje",
   "Runtime Name": "Nazwa czasu wykonania",
   "Runtime name": "Nazwa czasu wykonania",
   "Runtime type": "Typ czasu wykonania",
@@ -986,6 +999,7 @@
   "Settings for externally-managed users cannot be changed": "Ustawienia 
użytkowników 'external' nie mogą być zmieniane",
   "Settings of externally-managed users cannot be changed.": "Ustawienia 
użytkowników 'external' nie mogą być zmienione.",
   "Settings to connect to a mail server": "Ustawienia połączenia z serwerem 
poczty",
+  "Shared transformation templates": "Współdzielone szablony transformacji",
   "Shortcuts": "Skroty",
   "Show": "Pokaż",
   "Show API documentation link on login page": "Pokaż link do dokumentacji API 
na stronie logowania",
@@ -1017,7 +1031,6 @@
   "Show tooltip": "Pokaż podpowiedź",
   "Show values as labels": "Pokaż wartości jako etykiety",
   "Shows the distribution of numerical data": "Pokazuje rozkład danych 
numerycznych",
-  "Shared transformation templates": "Współdzielone szablony transformacji",
   "Simple filters below are kept for fallback, but the advanced filter is 
currently used for queries.": "Poniższe proste filtry są zachowane jako opcja 
zapasowa, ale obecnie do zapytań używany jest filtr zaawansowany.",
   "Single": "Pojedynczy",
   "Site": "Lokalizacja",
@@ -1255,6 +1268,7 @@
   "View Topics": "Wyświetl tematy",
   "View mode": "Tryb wyświetlania",
   "View pipeline as code": "Zobacz strumień jako kod",
+  "View running instances": "Wyświetl uruchomione instancje",
   "View service details": "Zobacz szczegóły usługi",
   "View the documentation for a full user guide.": "Zobacz dokumentacje, aby 
uzyskac pelny przewodnik uzytkownika.",
   "View the documentation of the API. Here you can see all provided endpoints 
and how to query them.": "Wyświetl dokumentację API. Tutaj zobaczysz wszystkie 
udostępnione endpointy i sposób ich użycia.",
diff --git 
a/ui/src/app/configuration/email-configuration/email-configuration.component.ts 
b/ui/src/app/configuration/email-configuration/email-configuration.component.ts
index c84b3d009c..d4d0a0efa4 100644
--- 
a/ui/src/app/configuration/email-configuration/email-configuration.component.ts
+++ 
b/ui/src/app/configuration/email-configuration/email-configuration.component.ts
@@ -16,6 +16,7 @@
  *
  */
 
+import { HttpErrorResponse } from '@angular/common/http';
 import { Component, OnInit, inject } from '@angular/core';
 import {
     FormsModule,
@@ -244,14 +245,33 @@ export class EmailConfigurationComponent implements 
OnInit {
             error => {
                 this.sendingTestMailInProgress = false;
                 this.sendingTestMailSuccess = false;
-                this.sendingEmailErrorMessage = this.translateService.instant(
-                    `Error: {{message}} with cause {{cause}}`,
-                    {
-                        message: error.error.localizedMessage,
-                        cause: error.error.cause.localizedMessage,
-                    },
-                );
+                this.sendingEmailErrorMessage =
+                    this.extractTestMailErrorMessage(error);
             },
         );
     }
+
+    private extractTestMailErrorMessage(error: HttpErrorResponse): string {
+        const notification = error.error?.notifications?.[0];
+        const message = [notification?.title, notification?.description]
+            .filter(
+                (messagePart, index, messageParts) =>
+                    messagePart && messageParts.indexOf(messagePart) === index,
+            )
+            .join('. ');
+        const cause =
+            notification?.additionalInformation ||
+            error.error?.localizedMessage ||
+            error.error?.cause?.localizedMessage;
+
+        if (message && cause && message !== cause) {
+            return `${message} ${cause}`;
+        }
+
+        return (
+            message ||
+            cause ||
+            this.translateService.instant('Could not send test email.')
+        );
+    }
 }
diff --git a/ui/src/scss/sp/sp-theme.scss b/ui/src/scss/sp/sp-theme.scss
index 7406dad58f..e2cff563f6 100644
--- a/ui/src/scss/sp/sp-theme.scss
+++ b/ui/src/scss/sp/sp-theme.scss
@@ -141,6 +141,8 @@ html {
 
     .mat-mdc-menu-panel {
         min-width: 10rem;
+        width: max-content;
+        max-width: min(22rem, calc(100vw - 2rem));
         border: 1px solid var(--color-border-subtle);
         overflow: hidden;
     }
@@ -155,6 +157,7 @@ html {
         box-sizing: border-box;
         border-radius: var(--radius-xs);
         margin: 0 var(--space-xs);
+        white-space: nowrap;
         transition:
             background-color var(--motion-duration-fast)
                 var(--motion-easing-standard),
@@ -170,6 +173,9 @@ html {
     }
 
     .mat-mdc-menu-item-text {
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
         line-height: 1.25rem;
     }
 

Reply via email to