Skip to content

Commit 4f11f6c

Browse files
committed
Email service tests
1 parent e0e17d3 commit 4f11f6c

File tree

2 files changed

+287
-2
lines changed

2 files changed

+287
-2
lines changed

x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/EmailService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.util.function.Predicate;
3535
import java.util.stream.Collectors;
3636
import java.util.stream.Stream;
37+
3738
import javax.mail.MessagingException;
3839
import javax.mail.internet.InternetAddress;
3940
import javax.net.ssl.SSLSocketFactory;
@@ -365,8 +366,8 @@ static boolean recipientAddressInAllowList(Email email, Set<String> allowedRecip
365366
}
366367

367368
final Set<String> recipients = getRecipients(email, false);
368-
final Predicate<String> matchesAnyAllowedRecipient = recipient -> recipients.stream()
369-
.anyMatch(allowedDomain -> Regex.simpleMatch(allowedDomain, recipient, true));
369+
final Predicate<String> matchesAnyAllowedRecipient = recipient -> allowedRecipientPatterns.stream()
370+
.anyMatch(pattern -> Regex.simpleMatch(pattern, recipient, true));
370371
return recipients.stream().allMatch(matchesAnyAllowedRecipient);
371372
}
372373

x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/EmailServiceTests.java

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.List;
2222
import java.util.Properties;
2323
import java.util.Set;
24+
2425
import javax.mail.MessagingException;
2526

2627
import static org.hamcrest.Matchers.containsInAnyOrder;
@@ -68,6 +69,31 @@ public void testSend() throws Exception {
6869
assertThat(sent.account(), is("account1"));
6970
}
7071

72+
public void testDomainAndRecipientAllowCantBeSetAtSameTime() {
73+
Settings settings = Settings.builder()
74+
.putList("xpack.notification.email.account.domain_allowlist", "bar.com")
75+
.putList("xpack.notification.email.recipient_allowlist", "*[email protected]")
76+
.build();
77+
78+
IllegalArgumentException e = expectThrows(
79+
IllegalArgumentException.class,
80+
() -> new EmailService(
81+
settings,
82+
null,
83+
mock(SSLService.class),
84+
new ClusterSettings(Settings.EMPTY, new HashSet<>(EmailService.getSettings()))
85+
)
86+
);
87+
88+
assertThat(
89+
e.getMessage(),
90+
containsString(
91+
"Cannot set both [xpack.notification.email.recipient_allowlist] and "
92+
+ "[xpack.notification.email.account.domain_allowlist] to a non [\"*\"] value at the same time."
93+
)
94+
);
95+
}
96+
7197
public void testAccountSmtpPropertyConfiguration() {
7298
Settings settings = Settings.builder()
7399
.put("xpack.notification.email.account.account1.smtp.host", "localhost")
@@ -321,6 +347,264 @@ public void testChangeDomainAllowListSetting() throws UnsupportedEncodingExcepti
321347
assertThat(e2.getMessage(), containsString("port out of range"));
322348
}
323349

350+
public void testRecipientAddressInAllowList_EmptyAllowedPatterns() throws UnsupportedEncodingException {
351+
Email email = createTestEmail("[email protected]", "[email protected]");
352+
Set<String> allowedPatterns = Set.of();
353+
assertThat(EmailService.recipientAddressInAllowList(email, allowedPatterns), is(false));
354+
}
355+
356+
public void testRecipientAddressInAllowList_WildcardPattern() throws UnsupportedEncodingException {
357+
Email email = createTestEmail("[email protected]", "[email protected]");
358+
Set<String> allowedPatterns = Set.of("*");
359+
assertThat(EmailService.recipientAddressInAllowList(email, allowedPatterns), is(true));
360+
}
361+
362+
public void testRecipientAddressInAllowList_SpecificPattern() throws UnsupportedEncodingException {
363+
Email email = createTestEmail("[email protected]", "[email protected]");
364+
Set<String> allowedPatterns = Set.of("[email protected]");
365+
assertThat(EmailService.recipientAddressInAllowList(email, allowedPatterns), is(false));
366+
}
367+
368+
public void testRecipientAddressInAllowList_MultiplePatterns() throws UnsupportedEncodingException {
369+
Email email = createTestEmail("[email protected]", "[email protected]");
370+
Set<String> allowedPatterns = Set.of("[email protected]", "[email protected]");
371+
assertThat(EmailService.recipientAddressInAllowList(email, allowedPatterns), is(true));
372+
}
373+
374+
public void testRecipientAddressInAllowList_MixedCasePatterns() throws UnsupportedEncodingException {
375+
Email email = createTestEmail("[email protected]", "[email protected]");
376+
Set<String> allowedPatterns = Set.of("[email protected]", "[email protected]");
377+
assertThat(EmailService.recipientAddressInAllowList(email, allowedPatterns), is(true));
378+
}
379+
380+
public void testRecipientAddressInAllowList_PartialWildcardPrefixPattern() throws UnsupportedEncodingException {
381+
Email email = createTestEmail("[email protected]", "[email protected]");
382+
Set<String> allowedPatterns = Set.of("foo@*", "baz@*");
383+
assertThat(EmailService.recipientAddressInAllowList(email, allowedPatterns), is(true));
384+
}
385+
386+
public void testRecipientAddressInAllowList_PartialWildcardSuffixPattern() throws UnsupportedEncodingException {
387+
Email email = createTestEmail("[email protected]", "[email protected]");
388+
Set<String> allowedPatterns = Set.of("*@bar.com", "*@potato.com");
389+
assertThat(EmailService.recipientAddressInAllowList(email, allowedPatterns), is(true));
390+
}
391+
392+
public void testRecipientAddressInAllowList_DisallowedCCAddressesFails() throws UnsupportedEncodingException {
393+
Email email = new Email(
394+
"id",
395+
new Email.Address("[email protected]", "Sender"),
396+
createAddressList("[email protected]"),
397+
randomFrom(Email.Priority.values()),
398+
ZonedDateTime.now(),
399+
createAddressList("[email protected]"),
400+
createAddressList("[email protected]", "[email protected]"),
401+
null,
402+
"subject",
403+
"body",
404+
"htmlbody",
405+
Collections.emptyMap()
406+
);
407+
Set<String> allowedPatterns = Set.of("[email protected]", "[email protected]");
408+
assertThat(EmailService.recipientAddressInAllowList(email, allowedPatterns), is(false));
409+
}
410+
411+
public void testRecipientAddressInAllowList_DisallowedBCCAddressesFails() throws UnsupportedEncodingException {
412+
Email email = new Email(
413+
"id",
414+
new Email.Address("[email protected]", "Sender"),
415+
createAddressList("[email protected]"),
416+
randomFrom(Email.Priority.values()),
417+
ZonedDateTime.now(),
418+
createAddressList("[email protected]"),
419+
null,
420+
createAddressList("[email protected]", "[email protected]"),
421+
"subject",
422+
"body",
423+
"htmlbody",
424+
Collections.emptyMap()
425+
);
426+
Set<String> allowedPatterns = Set.of("[email protected]", "[email protected]");
427+
assertThat(EmailService.recipientAddressInAllowList(email, allowedPatterns), is(false));
428+
}
429+
430+
public void testAllowedRecipient() throws Exception {
431+
Email email = new Email(
432+
"id",
433+
new Email.Address("[email protected]", "Mr. Foo Man"),
434+
createAddressList("[email protected]", "[email protected]"),
435+
randomFrom(Email.Priority.values()),
436+
ZonedDateTime.now(),
437+
createAddressList("[email protected]"),
438+
null,
439+
null,
440+
"subject",
441+
"body",
442+
"htmlbody",
443+
Collections.emptyMap()
444+
);
445+
assertTrue(EmailService.recipientAddressInAllowList(email, Set.of("*")));
446+
assertFalse(EmailService.recipientAddressInAllowList(email, Set.of()));
447+
assertFalse(EmailService.recipientAddressInAllowList(email, Set.of("")));
448+
assertTrue(EmailService.recipientAddressInAllowList(email, Set.of("[email protected]", "*[email protected]")));
449+
assertTrue(EmailService.recipientAddressInAllowList(email, Set.of("[email protected]", "*.com")));
450+
assertTrue(EmailService.recipientAddressInAllowList(email, Set.of("*.CoM")));
451+
452+
// Invalid email in CC doesn't blow up
453+
email = new Email(
454+
"id",
455+
new Email.Address("[email protected]", "Mr. Foo Man"),
456+
createAddressList("[email protected]", "[email protected]"),
457+
randomFrom(Email.Priority.values()),
458+
ZonedDateTime.now(),
459+
createAddressList("[email protected]"),
460+
createAddressList("badEmail"),
461+
null,
462+
"subject",
463+
"body",
464+
"htmlbody",
465+
Collections.emptyMap()
466+
);
467+
assertFalse(EmailService.recipientAddressInAllowList(email, Set.of("*@other.com", "*[email protected]")));
468+
469+
// Check CC
470+
email = new Email(
471+
"id",
472+
new Email.Address("[email protected]", "Mr. Foo Man"),
473+
createAddressList("[email protected]", "[email protected]"),
474+
randomFrom(Email.Priority.values()),
475+
ZonedDateTime.now(),
476+
createAddressList("[email protected]"),
477+
createAddressList("[email protected]"),
478+
null,
479+
"subject",
480+
"body",
481+
"htmlbody",
482+
Collections.emptyMap()
483+
);
484+
assertTrue(EmailService.recipientAddressInAllowList(email, Set.of("*@other.com", "*@bar.com")));
485+
assertFalse(EmailService.recipientAddressInAllowList(email, Set.of("*[email protected]")));
486+
487+
// Check BCC
488+
email = new Email(
489+
"id",
490+
new Email.Address("[email protected]", "Mr. Foo Man"),
491+
createAddressList("[email protected]", "[email protected]"),
492+
randomFrom(Email.Priority.values()),
493+
ZonedDateTime.now(),
494+
createAddressList("[email protected]"),
495+
null,
496+
createAddressList("[email protected]"),
497+
"subject",
498+
"body",
499+
"htmlbody",
500+
Collections.emptyMap()
501+
);
502+
assertTrue(EmailService.recipientAddressInAllowList(email, Set.of("*@other.com", "*@bar.com")));
503+
assertFalse(EmailService.recipientAddressInAllowList(email, Set.of("*[email protected]")));
504+
}
505+
506+
public void testSendEmailWithRecipientNotInAllowList() throws Exception {
507+
service.updateAllowedRecipientPatterns(Collections.singletonList(randomFrom("*@bar.*", "*@bar.com", "*b*")));
508+
Email email = new Email(
509+
"id",
510+
new Email.Address("[email protected]", "Mr. Foo Man"),
511+
createAddressList("[email protected]", "[email protected]"),
512+
randomFrom(Email.Priority.values()),
513+
ZonedDateTime.now(),
514+
createAddressList("[email protected]", "[email protected]"),
515+
null,
516+
null,
517+
"subject",
518+
"body",
519+
"htmlbody",
520+
Collections.emptyMap()
521+
);
522+
when(account.name()).thenReturn("account1");
523+
Authentication auth = new Authentication("user", new Secret("passwd".toCharArray()));
524+
Profile profile = randomFrom(Profile.values());
525+
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> service.send(email, auth, profile, "account1"));
526+
assertThat(
527+
e.getMessage(),
528+
containsString(
529+
"failed to send email with subject [subject] and recipients [[email protected], [email protected]], "
530+
+ "one or more recipients is not specified in the domain allow list setting "
531+
+ "[xpack.notification.email.recipient_allowlist]."
532+
)
533+
);
534+
}
535+
536+
public void testChangeRecipientAllowListSetting() throws UnsupportedEncodingException, MessagingException {
537+
Settings settings = Settings.builder()
538+
.put("xpack.notification.email.account.account1.foo", "bar")
539+
// Setting a random SMTP server name and an invalid port so that sending emails is guaranteed to fail:
540+
.put("xpack.notification.email.account.account1.smtp.host", randomAlphaOfLength(10))
541+
.put("xpack.notification.email.account.account1.smtp.port", -100)
542+
.putList("xpack.notification.email.recipient_allowlist", "*[email protected]")
543+
.build();
544+
ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, new HashSet<>(EmailService.getSettings()));
545+
EmailService emailService = new EmailService(settings, null, mock(SSLService.class), clusterSettings);
546+
Email email = new Email(
547+
"id",
548+
new Email.Address("[email protected]", "Mr. Foo Man"),
549+
createAddressList("[email protected]", "[email protected]"),
550+
randomFrom(Email.Priority.values()),
551+
ZonedDateTime.now(),
552+
createAddressList("[email protected]", "[email protected]"),
553+
null,
554+
null,
555+
"subject",
556+
"body",
557+
"htmlbody",
558+
Collections.emptyMap()
559+
);
560+
when(account.name()).thenReturn("account1");
561+
Authentication auth = new Authentication("user", new Secret("passwd".toCharArray()));
562+
Profile profile = randomFrom(Profile.values());
563+
564+
// This send will fail because one of the recipients ("[email protected]") is in a domain that is not in the allowed list
565+
IllegalArgumentException e1 = expectThrows(
566+
IllegalArgumentException.class,
567+
() -> emailService.send(email, auth, profile, "account1")
568+
);
569+
assertThat(
570+
e1.getMessage(),
571+
containsString(
572+
"failed to send email with subject [subject] and recipients [[email protected], [email protected]], "
573+
+ "one or more recipients is not specified in the domain allow list setting "
574+
+ "[xpack.notification.email.recipient_allowlist]."
575+
)
576+
);
577+
578+
// Now dynamically add "invalid.com" to the list of allowed domains:
579+
Settings newSettings = Settings.builder()
580+
.putList("xpack.notification.email.recipient_allowlist", "*@bar.com", "*@invalid.com")
581+
.build();
582+
clusterSettings.applySettings(newSettings);
583+
// Still expect an exception because we're not actually sending the email, but it's no longer because the domain isn't allowed:
584+
IllegalArgumentException e2 = expectThrows(
585+
IllegalArgumentException.class,
586+
() -> emailService.send(email, auth, profile, "account1")
587+
);
588+
assertThat(e2.getMessage(), containsString("port out of range"));
589+
}
590+
591+
private Email createTestEmail(String... recipients) throws UnsupportedEncodingException {
592+
return new Email(
593+
"id",
594+
new Email.Address("[email protected]", "Sender"),
595+
createAddressList(recipients),
596+
randomFrom(Email.Priority.values()),
597+
ZonedDateTime.now(),
598+
createAddressList(recipients),
599+
null,
600+
null,
601+
"subject",
602+
"body",
603+
"htmlbody",
604+
Collections.emptyMap()
605+
);
606+
}
607+
324608
private static Email.AddressList createAddressList(String... emails) throws UnsupportedEncodingException {
325609
List<Email.Address> addresses = new ArrayList<>();
326610
for (String email : emails) {

0 commit comments

Comments
 (0)