From 25d43511f60d64305d10a6675e2dff7bf0425b48 Mon Sep 17 00:00:00 2001 From: gbrodman Date: Wed, 18 Dec 2019 17:08:06 -0500 Subject: [PATCH] Add BCC capabilities to the Spec11 reports (#418) * Add BCC capabilities to the Spec11 reports --- .../registry/config/RegistryConfig.java | 14 ++++++++ .../config/RegistryConfigSettings.java | 1 + .../registry/config/files/default-config.yaml | 5 +++ .../reporting/spec11/Spec11EmailUtils.java | 22 +++++++++---- .../spec11/Spec11EmailUtilsTest.java | 32 ++++++++++--------- .../google/registry/util/EmailMessage.java | 10 ++++-- .../registry/util/SendEmailService.java | 4 +-- .../registry/util/SendEmailServiceTest.java | 18 +++++++---- 8 files changed, 75 insertions(+), 31 deletions(-) diff --git a/core/src/main/java/google/registry/config/RegistryConfig.java b/core/src/main/java/google/registry/config/RegistryConfig.java index e73eb4eb7..a876daee5 100644 --- a/core/src/main/java/google/registry/config/RegistryConfig.java +++ b/core/src/main/java/google/registry/config/RegistryConfig.java @@ -917,6 +917,20 @@ public final class RegistryConfig { return parseEmailAddress(config.misc.spec11OutgoingEmailAddress); } + /** + * Returns the email addresses to which we will BCC Spec11 emails. + * + * @see google.registry.reporting.spec11.Spec11EmailUtils + */ + @Provides + @Config("spec11BccEmailAddresses") + public static ImmutableList provideSpec11BccEmailAddresses( + RegistryConfigSettings config) { + return config.misc.spec11BccEmailAddresses.stream() + .map(RegistryConfig::parseEmailAddress) + .collect(toImmutableList()); + } + /** * Returns the name of the registry, for use in spec 11 emails. * diff --git a/core/src/main/java/google/registry/config/RegistryConfigSettings.java b/core/src/main/java/google/registry/config/RegistryConfigSettings.java index 089276b3b..4c4405e12 100644 --- a/core/src/main/java/google/registry/config/RegistryConfigSettings.java +++ b/core/src/main/java/google/registry/config/RegistryConfigSettings.java @@ -193,6 +193,7 @@ public class RegistryConfigSettings { public String sheetExportId; public String alertRecipientEmailAddress; public String spec11OutgoingEmailAddress; + public List spec11BccEmailAddresses; public int asyncDeleteDelaySeconds; public int transientFailureRetries; } diff --git a/core/src/main/java/google/registry/config/files/default-config.yaml b/core/src/main/java/google/registry/config/files/default-config.yaml index 1a6590f99..4005fff5f 100644 --- a/core/src/main/java/google/registry/config/files/default-config.yaml +++ b/core/src/main/java/google/registry/config/files/default-config.yaml @@ -389,6 +389,11 @@ misc: # to be a deliverable email address to handle replies from registrars as well. spec11OutgoingEmailAddress: abuse@example.com + # Addresses to which we will BCC all Spec11 email reports, in case one + # wishes to examine the output. + spec11BccEmailAddresses: + - abuse@example.com + # How long to delay processing of asynchronous deletions. This should always # be longer than eppResourceCachingSeconds, to prevent deleted contacts or # hosts from being used on domains. diff --git a/core/src/main/java/google/registry/reporting/spec11/Spec11EmailUtils.java b/core/src/main/java/google/registry/reporting/spec11/Spec11EmailUtils.java index 9b124ca73..0cb7783c7 100644 --- a/core/src/main/java/google/registry/reporting/spec11/Spec11EmailUtils.java +++ b/core/src/main/java/google/registry/reporting/spec11/Spec11EmailUtils.java @@ -58,6 +58,7 @@ public class Spec11EmailUtils { private final SendEmailService emailService; private final InternetAddress outgoingEmailAddress; + private final ImmutableList spec11BccEmailAddresses; private final InternetAddress alertRecipientAddress; private final ImmutableList spec11WebResources; private final String registryName; @@ -67,10 +68,12 @@ public class Spec11EmailUtils { SendEmailService emailService, @Config("alertRecipientEmailAddress") InternetAddress alertRecipientAddress, @Config("spec11OutgoingEmailAddress") InternetAddress spec11OutgoingEmailAddress, + @Config("spec11BccEmailAddresses") ImmutableList spec11BccEmailAddresses, @Config("spec11WebResources") ImmutableList spec11WebResources, @Config("registryName") String registryName) { this.emailService = emailService; this.outgoingEmailAddress = spec11OutgoingEmailAddress; + this.spec11BccEmailAddresses = spec11BccEmailAddresses; this.alertRecipientAddress = alertRecipientAddress; this.spec11WebResources = spec11WebResources; this.registryName = registryName; @@ -125,11 +128,18 @@ public class Spec11EmailUtils { private RegistrarThreatMatches filterOutNonPublishedMatches( RegistrarThreatMatches registrarThreatMatches) { - ImmutableList filteredMatches = registrarThreatMatches.threatMatches().stream() - .filter(threatMatch -> - ofy().load().type(DomainBase.class).filter("fullyQualifiedDomainName", - threatMatch.fullyQualifiedDomainName()).first().now().shouldPublishToDns() - ).collect(toImmutableList()); + ImmutableList filteredMatches = + registrarThreatMatches.threatMatches().stream() + .filter( + threatMatch -> + ofy() + .load() + .type(DomainBase.class) + .filter("fullyQualifiedDomainName", threatMatch.fullyQualifiedDomainName()) + .first() + .now() + .shouldPublishToDns()) + .collect(toImmutableList()); return RegistrarThreatMatches.create(registrarThreatMatches.clientId(), filteredMatches); } @@ -146,7 +156,7 @@ public class Spec11EmailUtils { .setContentType(MediaType.HTML_UTF_8) .setFrom(outgoingEmailAddress) .addRecipient(getEmailAddressForRegistrar(registrarThreatMatches.clientId())) - .setBcc(outgoingEmailAddress) + .setBccs(spec11BccEmailAddresses) .build()); } diff --git a/core/src/test/java/google/registry/reporting/spec11/Spec11EmailUtilsTest.java b/core/src/test/java/google/registry/reporting/spec11/Spec11EmailUtilsTest.java index 3ecf8e36c..8c0285157 100644 --- a/core/src/test/java/google/registry/reporting/spec11/Spec11EmailUtilsTest.java +++ b/core/src/test/java/google/registry/reporting/spec11/Spec11EmailUtilsTest.java @@ -118,6 +118,8 @@ public class Spec11EmailUtilsTest { emailService, new InternetAddress("my-receiver@test.com"), new InternetAddress("abuse@test.com"), + ImmutableList.of( + new InternetAddress("abuse@test.com"), new InternetAddress("bcc@test.com")), FAKE_RESOURCES, "Super Cool Registry"); @@ -142,7 +144,7 @@ public class Spec11EmailUtilsTest { capturedContents.get(0), "abuse@test.com", "the.registrar@example.com", - Optional.of("abuse@test.com"), + ImmutableList.of("abuse@test.com", "bcc@test.com"), "Super Cool Registry Monthly Threat Detector [2018-07-15]", String.format(MONTHLY_EMAIL_FORMAT, "a.comMALWARE"), Optional.of(MediaType.HTML_UTF_8)); @@ -150,7 +152,7 @@ public class Spec11EmailUtilsTest { capturedContents.get(1), "abuse@test.com", "new.registrar@example.com", - Optional.of("abuse@test.com"), + ImmutableList.of("abuse@test.com", "bcc@test.com"), "Super Cool Registry Monthly Threat Detector [2018-07-15]", String.format( MONTHLY_EMAIL_FORMAT, @@ -160,7 +162,7 @@ public class Spec11EmailUtilsTest { capturedContents.get(2), "abuse@test.com", "my-receiver@test.com", - Optional.empty(), + ImmutableList.of(), "Spec11 Pipeline Success 2018-07-15", "Spec11 reporting completed successfully.", Optional.empty()); @@ -180,7 +182,7 @@ public class Spec11EmailUtilsTest { capturedMessages.get(0), "abuse@test.com", "the.registrar@example.com", - Optional.of("abuse@test.com"), + ImmutableList.of("abuse@test.com", "bcc@test.com"), "Super Cool Registry Daily Threat Detector [2018-07-15]", String.format(DAILY_EMAIL_FORMAT, "a.comMALWARE"), Optional.of(MediaType.HTML_UTF_8)); @@ -188,7 +190,7 @@ public class Spec11EmailUtilsTest { capturedMessages.get(1), "abuse@test.com", "new.registrar@example.com", - Optional.of("abuse@test.com"), + ImmutableList.of("abuse@test.com", "bcc@test.com"), "Super Cool Registry Daily Threat Detector [2018-07-15]", String.format( DAILY_EMAIL_FORMAT, @@ -198,7 +200,7 @@ public class Spec11EmailUtilsTest { capturedMessages.get(2), "abuse@test.com", "my-receiver@test.com", - Optional.empty(), + ImmutableList.of(), "Spec11 Pipeline Success 2018-07-15", "Spec11 reporting completed successfully.", Optional.empty()); @@ -225,7 +227,7 @@ public class Spec11EmailUtilsTest { capturedContents.get(0), "abuse@test.com", "new.registrar@example.com", - Optional.of("abuse@test.com"), + ImmutableList.of("abuse@test.com", "bcc@test.com"), "Super Cool Registry Monthly Threat Detector [2018-07-15]", String.format(MONTHLY_EMAIL_FORMAT, "c.comMALWARE"), Optional.of(MediaType.HTML_UTF_8)); @@ -233,7 +235,7 @@ public class Spec11EmailUtilsTest { capturedContents.get(1), "abuse@test.com", "my-receiver@test.com", - Optional.empty(), + ImmutableList.of(), "Spec11 Pipeline Success 2018-07-15", "Spec11 reporting completed successfully.", Optional.empty()); @@ -270,7 +272,7 @@ public class Spec11EmailUtilsTest { capturedMessages.get(0), "abuse@test.com", "the.registrar@example.com", - Optional.of("abuse@test.com"), + ImmutableList.of("abuse@test.com", "bcc@test.com"), "Super Cool Registry Monthly Threat Detector [2018-07-15]", String.format(MONTHLY_EMAIL_FORMAT, "a.comMALWARE"), Optional.of(MediaType.HTML_UTF_8)); @@ -278,7 +280,7 @@ public class Spec11EmailUtilsTest { capturedMessages.get(1), "abuse@test.com", "new.registrar@example.com", - Optional.of("abuse@test.com"), + ImmutableList.of("abuse@test.com", "bcc@test.com"), "Super Cool Registry Monthly Threat Detector [2018-07-15]", String.format( MONTHLY_EMAIL_FORMAT, @@ -288,7 +290,7 @@ public class Spec11EmailUtilsTest { capturedMessages.get(2), "abuse@test.com", "my-receiver@test.com", - Optional.empty(), + ImmutableList.of(), "Spec11 Emailing Failure 2018-07-15", "Emailing Spec11 reports failed due to expected", Optional.empty()); @@ -302,7 +304,7 @@ public class Spec11EmailUtilsTest { contentCaptor.getValue(), "abuse@test.com", "my-receiver@test.com", - Optional.empty(), + ImmutableList.of(), "Spec11 Pipeline Alert: 2018-07", "Alert!", Optional.empty()); @@ -351,7 +353,7 @@ public class Spec11EmailUtilsTest { EmailMessage message, String from, String recipient, - Optional replyTo, + ImmutableList bccs, String subject, String body, Optional contentType) @@ -363,8 +365,8 @@ public class Spec11EmailUtilsTest { .setSubject(subject) .setBody(body); - if (replyTo.isPresent()) { - expectedContentBuilder.setBcc(new InternetAddress(replyTo.get())); + for (String bcc : bccs) { + expectedContentBuilder.addBcc(new InternetAddress(bcc)); } contentType.ifPresent(expectedContentBuilder::setContentType); assertThat(message).isEqualTo(expectedContentBuilder.build()); diff --git a/util/src/main/java/google/registry/util/EmailMessage.java b/util/src/main/java/google/registry/util/EmailMessage.java index e06660c2d..3e6aa5519 100644 --- a/util/src/main/java/google/registry/util/EmailMessage.java +++ b/util/src/main/java/google/registry/util/EmailMessage.java @@ -29,7 +29,7 @@ public abstract class EmailMessage { public abstract String body(); public abstract ImmutableList recipients(); public abstract InternetAddress from(); - public abstract Optional bcc(); + public abstract ImmutableList bccs(); public abstract Optional contentType(); public abstract Optional attachment(); @@ -55,17 +55,23 @@ public abstract class EmailMessage { public abstract Builder setBody(String body); public abstract Builder setRecipients(Collection recipients); public abstract Builder setFrom(InternetAddress from); - public abstract Builder setBcc(InternetAddress bcc); + public abstract Builder setBccs(Collection bccs); public abstract Builder setContentType(MediaType contentType); public abstract Builder setAttachment(Attachment attachment); abstract ImmutableList.Builder recipientsBuilder(); + abstract ImmutableList.Builder bccsBuilder(); public Builder addRecipient(InternetAddress value) { recipientsBuilder().add(value); return this; } + public Builder addBcc(InternetAddress bcc) { + bccsBuilder().add(bcc); + return this; + } + public abstract EmailMessage build(); } diff --git a/util/src/main/java/google/registry/util/SendEmailService.java b/util/src/main/java/google/registry/util/SendEmailService.java index 6654f9cea..362083d51 100644 --- a/util/src/main/java/google/registry/util/SendEmailService.java +++ b/util/src/main/java/google/registry/util/SendEmailService.java @@ -78,8 +78,8 @@ public class SendEmailService { attachmentPart.setFileName(attachment.filename()); multipart.addBodyPart(attachmentPart); } - if (emailMessage.bcc().isPresent()) { - msg.addRecipient(RecipientType.BCC, emailMessage.bcc().get()); + for (InternetAddress bcc : emailMessage.bccs()) { + msg.addRecipient(RecipientType.BCC, bcc); } msg.setContent(multipart); msg.saveChanges(); diff --git a/util/src/test/java/google/registry/util/SendEmailServiceTest.java b/util/src/test/java/google/registry/util/SendEmailServiceTest.java index 4123f23e8..e9d932918 100644 --- a/util/src/test/java/google/registry/util/SendEmailServiceTest.java +++ b/util/src/test/java/google/registry/util/SendEmailServiceTest.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import com.google.common.collect.ImmutableList; import com.google.common.net.MediaType; import google.registry.testing.FakeClock; import google.registry.testing.FakeSleeper; @@ -44,8 +45,7 @@ import org.mockito.junit.MockitoRule; @RunWith(JUnit4.class) public class SendEmailServiceTest { - @Rule - public final MockitoRule mocks = MockitoJUnit.rule(); + @Rule public final MockitoRule mocks = MockitoJUnit.rule(); private final Retrier retrier = new Retrier(new FakeSleeper(new FakeClock()), 2); private final TransportEmailSender wrapper = mock(TransportEmailSender.class); @@ -74,12 +74,19 @@ public class SendEmailServiceTest { @Test public void testSuccess_bcc() throws Exception { - EmailMessage content = createBuilder().setBcc(new InternetAddress("bcc@example.com")).build(); + EmailMessage content = + createBuilder() + .setBccs( + ImmutableList.of( + new InternetAddress("bcc@example.com"), + new InternetAddress("bcc2@example.com"))) + .build(); sendEmailService.sendEmail(content); Message message = getMessage(); assertThat(message.getRecipients(RecipientType.BCC)) .asList() - .containsExactly(new InternetAddress("bcc@example.com")); + .containsExactly( + new InternetAddress("bcc@example.com"), new InternetAddress("bcc2@example.com")); } @Test @@ -87,8 +94,7 @@ public class SendEmailServiceTest { EmailMessage content = createBuilder().setContentType(MediaType.HTML_UTF_8).build(); sendEmailService.sendEmail(content); Message message = getMessage(); - assertThat(getInternalContent(message).getContentType()) - .isEqualTo("text/html; charset=utf-8"); + assertThat(getInternalContent(message).getContentType()).isEqualTo("text/html; charset=utf-8"); } @Test