@@ -299,46 +299,77 @@ public EmailSent send(Email email, Authentication auth, Profile profile, String
299299 "failed to send email with subject ["
300300 + email .subject ()
301301 + "] and recipient domains "
302- + getRecipientDomains (email )
302+ + getRecipients (email , true )
303303 + ", one or more recipients is not specified in the domain allow list setting ["
304304 + SETTING_DOMAIN_ALLOWLIST .getKey ()
305305 + "]."
306306 );
307307 }
308+ if (recipientAddressInAllowList (email , this .allowedRecipientPatterns ) == false ) {
309+ throw new IllegalArgumentException (
310+ "failed to send email with subject ["
311+ + email .subject ()
312+ + "] and recipients "
313+ + getRecipients (email , false )
314+ + ", one or more recipients is not specified in the domain allow list setting ["
315+ + SETTING_RECIPIENT_ALLOW_PATTERNS .getKey ()
316+ + "]."
317+ );
318+ }
308319 return send (email , auth , profile , account );
309320 }
310321
311322 // Visible for testing
312- static Set <String > getRecipientDomains (Email email ) {
313- return Stream .concat (
323+ static Set <String > getRecipients (Email email , boolean domainsOnly ) {
324+ var stream = Stream .concat (
314325 Optional .ofNullable (email .to ()).map (addrs -> Arrays .stream (addrs .toArray ())).orElse (Stream .empty ()),
315326 Stream .concat (
316327 Optional .ofNullable (email .cc ()).map (addrs -> Arrays .stream (addrs .toArray ())).orElse (Stream .empty ()),
317328 Optional .ofNullable (email .bcc ()).map (addrs -> Arrays .stream (addrs .toArray ())).orElse (Stream .empty ())
318329 )
319- )
320- .map (InternetAddress ::getAddress )
321- // Pull out only the domain of the email address, so [email protected] -> bar.com 322- .map (emailAddress -> emailAddress .substring (emailAddress .lastIndexOf ('@' ) + 1 ))
323- .collect (Collectors .toSet ());
330+ ).map (InternetAddress ::getAddress );
331+
332+ if (domainsOnly ) {
333+ // Pull out only the domain of the email address, so [email protected] 334+ stream = stream .map (emailAddress -> emailAddress .substring (emailAddress .lastIndexOf ('@' ) + 1 ));
335+ }
336+
337+ return stream .collect (Collectors .toSet ());
324338 }
325339
326340 // Visible for testing
327341 static boolean recipientDomainsInAllowList (Email email , Set <String > allowedDomainSet ) {
328- if (allowedDomainSet .size () == 0 ) {
342+ if (allowedDomainSet .isEmpty () ) {
329343 // Nothing is allowed
330344 return false ;
331345 }
332346 if (allowedDomainSet .contains ("*" )) {
333347 // Don't bother checking, because there is a wildcard all
334348 return true ;
335349 }
336- final Set <String > domains = getRecipientDomains (email );
350+ final Set <String > domains = getRecipients (email , true );
337351 final Predicate <String > matchesAnyAllowedDomain = domain -> allowedDomainSet .stream ()
338352 .anyMatch (allowedDomain -> Regex .simpleMatch (allowedDomain , domain , true ));
339353 return domains .stream ().allMatch (matchesAnyAllowedDomain );
340354 }
341355
356+ // Visible for testing
357+ static boolean recipientAddressInAllowList (Email email , Set <String > allowedRecipientPatterns ) {
358+ if (allowedRecipientPatterns .isEmpty ()) {
359+ // Nothing is allowed
360+ return false ;
361+ }
362+ if (allowedRecipientPatterns .contains ("*" )) {
363+ // Don't bother checking, because there is a wildcard all
364+ return true ;
365+ }
366+
367+ final Set <String > recipients = getRecipients (email , false );
368+ final Predicate <String > matchesAnyAllowedRecipient = recipient -> recipients .stream ()
369+ .anyMatch (allowedDomain -> Regex .simpleMatch (allowedDomain , recipient , true ));
370+ return recipients .stream ().allMatch (matchesAnyAllowedRecipient );
371+ }
372+
342373 private static EmailSent send (Email email , Authentication auth , Profile profile , Account account ) throws MessagingException {
343374 assert account != null ;
344375 try {
0 commit comments