diff --git a/app/email/ui/pom.xml b/app/email/ui/pom.xml
index a1cc12a617..8eb8919a9f 100644
--- a/app/email/ui/pom.xml
+++ b/app/email/ui/pom.xml
@@ -23,7 +23,31 @@
core-ui
5.0.3-SNAPSHOT
-
+
+ org.testfx
+ testfx-core
+ 4.0.18
+ test
+
+
+ org.testfx
+ testfx-junit5
+ 4.0.18
+ test
+
+
+ junit
+ junit
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ ${junit.version}
+ test
+
+
diff --git a/app/email/ui/src/main/java/org/phoebus/applications/email/ui/EmailDialogController.java b/app/email/ui/src/main/java/org/phoebus/applications/email/ui/EmailDialogController.java
index ff398adb13..4cda6fec5f 100644
--- a/app/email/ui/src/main/java/org/phoebus/applications/email/ui/EmailDialogController.java
+++ b/app/email/ui/src/main/java/org/phoebus/applications/email/ui/EmailDialogController.java
@@ -24,6 +24,9 @@
import org.phoebus.applications.email.EmailApp;
import org.phoebus.email.EmailPreferences;
import org.phoebus.email.EmailService;
+import org.phoebus.framework.macros.MacroHandler;
+import org.phoebus.framework.macros.MacroOrSystemProvider;
+import org.phoebus.framework.macros.Macros;
import org.phoebus.framework.preferences.PhoebusPreferenceService;
import org.phoebus.ui.javafx.FilesTab;
import org.phoebus.ui.javafx.ImagesTab;
@@ -58,6 +61,8 @@ public class EmailDialogController {
final Preferences prefs = PhoebusPreferenceService.userNodeForClass(EmailApp.class);
+ private final MacroOrSystemProvider systemMacros = new MacroOrSystemProvider(new Macros());
+
private static final String TEXT_PLAIN = "text/plain";
private static final String TEXT_HTML = "text/html";
@@ -183,12 +188,17 @@ public void send(Event event) {
@FXML
public void initialize() {
+ String to = EmailPreferences.to;
+ if(to == null || to.isBlank())
+ to = prefs.get(LAST_TO, "");
- txtTo.setText(prefs.get(LAST_TO, ""));
- if(EmailPreferences.from == null || EmailPreferences.from.isBlank())
- txtFrom.setText(prefs.get(LAST_FROM, ""));
- else
- txtFrom.setText(EmailPreferences.from);
+ txtTo.setText(substituteSystemMacros(to));
+
+ String from = EmailPreferences.from;
+ if(from == null || from.isBlank())
+ from = prefs.get(LAST_FROM, "");
+
+ txtFrom.setText(substituteSystemMacros(from));
txtFrom.setPromptText("Enter your email address");
txtTo.setPromptText("Enter receipient's email address(es)");
@@ -277,6 +287,18 @@ public void setAttachmets(final List files)
att_files.setFiles(files);
}
+ private String substituteSystemMacros(String input) {
+ String output;
+ try {
+ output = MacroHandler.replace(systemMacros, input);
+ } catch (Exception ignored) {
+ logger.warning("Failed macro expansion in email address field. Using original string");
+ output = input;
+ }
+
+ return output;
+ }
+
private void recomputeTextArea() {
simpleTextVBox.setVisible(choiceBox.getValue().equals(TEXT_PLAIN));
simpleTextVBox.setManaged(choiceBox.getValue().equals(TEXT_PLAIN));
diff --git a/app/email/ui/src/test/java/org/phoebus/applications/email/ui/EmailDialogControllerTestUI.java b/app/email/ui/src/test/java/org/phoebus/applications/email/ui/EmailDialogControllerTestUI.java
new file mode 100644
index 0000000000..7df2d23976
--- /dev/null
+++ b/app/email/ui/src/test/java/org/phoebus/applications/email/ui/EmailDialogControllerTestUI.java
@@ -0,0 +1,75 @@
+package org.phoebus.applications.email.ui;
+
+import javafx.fxml.FXMLLoader;
+import javafx.stage.Stage;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import org.phoebus.applications.email.EmailApp;
+import org.phoebus.email.EmailPreferences;
+import org.testfx.framework.junit5.ApplicationTest;
+
+import java.io.IOException;
+
+class EmailDialogControllerTestUI extends ApplicationTest {
+
+ EmailDialogController controller;
+
+ @Override
+ public void start(Stage stage) throws IOException
+ {
+ final FXMLLoader loader = new FXMLLoader();
+ loader.setLocation(EmailApp.class.getResource("ui/EmailDialog.fxml"));
+ loader.load();
+ controller = loader.getController();
+ }
+
+ @BeforeEach
+ public void setup() {
+ System.setProperty("test_key1", "test_value1");
+ System.setProperty("test_key2", "test_value2");
+ System.setProperty("test_recursive1", "$(test_recursive2)");
+ System.setProperty("test_recursive2", "$(test_recursive1)");
+ }
+
+ @AfterEach
+ public void tearDown() {
+ System.clearProperty("test_key1");
+ System.clearProperty("test_key2");
+ System.clearProperty("test_recursive1");
+ System.clearProperty("test_recursive2");
+ }
+
+ @Test
+ void testEmailAddressSubstitutions() {
+ EmailPreferences.to = "$(test_key1)@place";
+ EmailPreferences.from = "$(test_key2)@other";
+ controller.initialize();
+
+ Assertions.assertEquals("test_value1@place", controller.txtTo.getText());
+ Assertions.assertEquals("test_value2@other", controller.txtFrom.getText());
+ }
+
+ @Test
+ void testEmailAddressSubstitutionsWithIncorrectProperties() {
+ EmailPreferences.to = "$(nonexistent)@place";
+ EmailPreferences.from = "$(test_key2@other";
+ controller.initialize();
+
+ Assertions.assertEquals("$(nonexistent)@place", controller.txtTo.getText());
+ Assertions.assertEquals("$(test_key2@other", controller.txtFrom.getText());
+ }
+
+ @Test
+ void testEmailAddressSubstitutionsWithRecursiveProperties() {
+ EmailPreferences.to = "$(test_recursive1)@place";
+ EmailPreferences.from = "$(test_recursive2)@other";
+ controller.initialize();
+
+ Assertions.assertEquals("$(test_recursive1)@place", controller.txtTo.getText());
+ Assertions.assertEquals("$(test_recursive2)@other", controller.txtFrom.getText());
+ }
+}
diff --git a/core/email/src/main/java/org/phoebus/email/EmailPreferences.java b/core/email/src/main/java/org/phoebus/email/EmailPreferences.java
index 354665f5ca..7115dca044 100644
--- a/core/email/src/main/java/org/phoebus/email/EmailPreferences.java
+++ b/core/email/src/main/java/org/phoebus/email/EmailPreferences.java
@@ -22,6 +22,7 @@ public class EmailPreferences
@Preference public static String username;
@Preference public static String password;
@Preference public static String from;
+ @Preference public static String to;
/** @return Is email supported? */
public static final boolean isEmailSupported()
diff --git a/core/email/src/main/resources/email_preferences.properties b/core/email/src/main/resources/email_preferences.properties
index 7e44660053..44297fbc76 100644
--- a/core/email/src/main/resources/email_preferences.properties
+++ b/core/email/src/main/resources/email_preferences.properties
@@ -17,5 +17,12 @@ password=
# Default address to be used for {mailheader}`From:`.
#
-# If left empty then the last used {mailheader}`From` address is used.
+# If left empty then the last used {mailheader}`From` address is used. System or environment
+# variable macro substitution is applied to this field.
from=
+
+# Default address to be used for {mailheader}`To:`.
+#
+# If left empty then the last used {mailheader}`To` address is used. System or environment
+# variable macro substitution is applied to this field.
+to=