2121import org .apache .logging .log4j .LogManager ;
2222import org .labkey .api .settings .AppProps ;
2323import org .labkey .api .util .ContextListener ;
24+ import org .labkey .api .util .EmailTransportProvider ;
2425import org .labkey .api .util .MailHelper ;
2526import org .labkey .api .util .ShutdownListener ;
2627import org .labkey .api .util .SmtpTransportProvider ;
@@ -59,52 +60,27 @@ public static void setInstance(DumbsterManager instance)
5960
6061 SimpleSmtpServer _server ;
6162
63+ // The transport provider that was active before the recorder installed its own; restored on stop().
64+ private EmailTransportProvider _previousProvider ;
65+
6266 public boolean start ()
6367 {
64- if (!(MailHelper .getActiveProvider () instanceof SmtpTransportProvider ))
65- {
66- _log .error ("Mail recorder cannot be started: active mail provider is not SmtpTransportProvider" );
67- return false ;
68- }
69-
7068 if (_server != null && !_server .isStopped ())
7169 {
7270 // We're already running, no need to spin up another, but reset the list of messages
7371 _server .clearEmails ();
7472 return true ;
7573 }
7674
77- int port ;
78- ServerSocket socket = null ;
79- try
75+ int port = -1 ;
76+ try (ServerSocket socket = new ServerSocket (0 ))
8077 {
81- socket = new ServerSocket (0 );
8278 port = socket .getLocalPort ();
8379 }
84- catch (IOException e )
85- {
86- _log .error ("Failed to open a server socket" , e );
87- return false ;
88- }
89- finally
80+ catch (IOException ignored )
9081 {
91- try
92- {
93- if (socket != null )
94- socket .close ();
95- }
96- catch (IOException ignored ) {}
9782 }
9883
99- Properties props = new Properties ();
100- props .setProperty ("mail.smtp.host" , "localhost" );
101- props .setProperty ("mail.smtp.user" , "Anonymous" );
102- props .setProperty ("mail.smtp.port" , Integer .toString (port ));
103- Session session = Session .getInstance (props );
104-
105- _log .info ("Switching MailHelper to use port {}" , port );
106- MailHelper .setSmtpSession (session );
107-
10884 _log .info ("Connecting mail recorder to port {}" , port );
10985 _server = SimpleSmtpServer .start (port );
11086 if (_server .isStopped ())
@@ -113,18 +89,34 @@ public boolean start()
11389 _server = null ;
11490 return false ;
11591 }
92+
93+ // Install our own SMTP provider pointed at the local capture server and make it the active provider, rather
94+ // than mutating another provider's session state. All outgoing email is captured regardless of how the server's
95+ // real email transport (SMTP, Microsoft Graph, etc.) is configured.
96+ Properties props = new Properties ();
97+ props .setProperty ("mail.smtp.host" , "localhost" );
98+ props .setProperty ("mail.smtp.user" , "Anonymous" );
99+ props .setProperty ("mail.smtp.port" , Integer .toString (port ));
100+
101+ SmtpTransportProvider recorderProvider = new SmtpTransportProvider ();
102+ recorderProvider .configure (props );
103+
104+ _log .info ("Switching MailHelper to the mail recorder on port {}" , port );
105+ _previousProvider = MailHelper .getActiveProvider ();
106+ MailHelper .setActiveProvider (recorderProvider );
107+
116108 ContextListener .addShutdownListener (this );
117109 return true ;
118110 }
119111
120112 public void stop ()
121113 {
122- // Stop the server, if there is one, but leave it around for
123- // viewing until the next call to start() overwrites.
114+ // Stop the server, if there is one, but leave it around for viewing until the next call to start() overwrites.
124115 if (_server != null )
125116 {
126117 _log .info ("Reverting MailHelper to {} configuration" , AppProps .getInstance ().getWebappConfigurationFilename ());
127- MailHelper .setSmtpSession (null );
118+ MailHelper .setActiveProvider (_previousProvider );
119+ _previousProvider = null ;
128120
129121 _server .stop ();
130122 ContextListener .removeShutdownListener (this );
0 commit comments