mirror of
https://github.com/google/nomulus
synced 2026-07-09 09:37:04 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c6f62dcffd | |||
| ee66805d2e | |||
| d7a3c0c439 | |||
| 45666773ee | |||
| b8b5152336 | |||
| 0f6302e92b |
@@ -158,6 +158,12 @@ public final class RegistryConfig {
|
||||
return config.registryPolicy.contactAndHostRoidSuffix;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("isEmailSendingEnabled")
|
||||
public static boolean provideIsEmailSendingEnabled(RegistryConfigSettings config) {
|
||||
return config.misc.isEmailSendingEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* The e-mail address for questions about integrating with the registry. Used in the
|
||||
* "contact-us" section of the registrar console.
|
||||
|
||||
@@ -205,6 +205,7 @@ public class RegistryConfigSettings {
|
||||
/** Miscellaneous configuration that doesn't quite fit in anywhere else. */
|
||||
public static class Misc {
|
||||
public String sheetExportId;
|
||||
public boolean isEmailSendingEnabled;
|
||||
public String alertRecipientEmailAddress;
|
||||
// TODO(b/279671974): remove below field after migration
|
||||
public String newAlertRecipientEmailAddress;
|
||||
|
||||
@@ -432,6 +432,9 @@ misc:
|
||||
# to. Leave this null to disable syncing.
|
||||
sheetExportId: null
|
||||
|
||||
# Whether emails may be sent. For Prod and Sandbox this should be true.
|
||||
isEmailSendingEnabled: false
|
||||
|
||||
# Address we send alert summary emails to.
|
||||
alertRecipientEmailAddress: email@example.com
|
||||
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<sessions-enabled>true</sessions-enabled>
|
||||
<instance-class>B4_1G</instance-class>
|
||||
<manual-scaling>
|
||||
<instances>12</instances>
|
||||
<instances>24</instances>
|
||||
</manual-scaling>
|
||||
|
||||
<system-properties>
|
||||
|
||||
@@ -14,19 +14,24 @@
|
||||
|
||||
package google.registry.groups;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.Iterables.toArray;
|
||||
|
||||
import com.google.api.client.http.HttpResponseException;
|
||||
import com.google.api.services.gmail.Gmail;
|
||||
import com.google.api.services.gmail.model.Message;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.EmailMessage;
|
||||
import google.registry.util.EmailMessage.Attachment;
|
||||
import google.registry.util.Retrier;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Predicate;
|
||||
import javax.inject.Inject;
|
||||
import javax.mail.Address;
|
||||
import javax.mail.BodyPart;
|
||||
@@ -38,23 +43,30 @@ import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeBodyPart;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.internet.MimeMultipart;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
/** Sends {@link EmailMessage EmailMessages} through Google Workspace using {@link Gmail}. */
|
||||
public final class GmailClient {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private final Gmail gmail;
|
||||
private final Retrier retrier;
|
||||
private final boolean isEmailSendingEnabled;
|
||||
private final InternetAddress outgoingEmailAddressWithUsername;
|
||||
private final InternetAddress replyToEmailAddress;
|
||||
|
||||
@Inject
|
||||
GmailClient(
|
||||
Gmail gmail,
|
||||
Retrier retrier,
|
||||
@Config("isEmailSendingEnabled") boolean isEmailSendingEnabled,
|
||||
@Config("gSuiteNewOutgoingEmailAddress") String gSuiteOutgoingEmailAddress,
|
||||
@Config("gSuiteOutgoingEmailDisplayName") String gSuiteOutgoingEmailDisplayName,
|
||||
@Config("replyToEmailAddress") InternetAddress replyToEmailAddress) {
|
||||
|
||||
this.gmail = gmail;
|
||||
this.retrier = retrier;
|
||||
this.isEmailSendingEnabled = isEmailSendingEnabled;
|
||||
this.replyToEmailAddress = replyToEmailAddress;
|
||||
try {
|
||||
this.outgoingEmailAddressWithUsername =
|
||||
@@ -70,15 +82,25 @@ public final class GmailClient {
|
||||
* <p>If the sender as specified by {@link EmailMessage#from} differs from the caller's identity,
|
||||
* the caller must have delegated `send` authority to the sender.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Message sendEmail(EmailMessage emailMessage) {
|
||||
Message message = toGmailMessage(toMimeMessage(emailMessage));
|
||||
try {
|
||||
// "me" is reserved word for the authorized user of the Gmail API.
|
||||
return gmail.users().messages().send("me", message).execute();
|
||||
} catch (IOException e) {
|
||||
throw new EmailException(e);
|
||||
public void sendEmail(EmailMessage emailMessage) {
|
||||
if (!isEmailSendingEnabled) {
|
||||
logger.atInfo().log(
|
||||
String.format(
|
||||
"Email with subject %s would have been sent to recipients %s",
|
||||
emailMessage.subject().substring(0, Math.min(emailMessage.subject().length(), 15)),
|
||||
String.join(
|
||||
" , ",
|
||||
emailMessage.recipients().stream()
|
||||
.map(ia -> ia.toString())
|
||||
.collect(toImmutableSet()))));
|
||||
return;
|
||||
}
|
||||
Message message = toGmailMessage(toMimeMessage(emailMessage));
|
||||
// Unlike other Cloud APIs such as GCS and SecretManager, Gmail does not retry on errors.
|
||||
retrier.callWithRetry(
|
||||
// "me" is reserved word for the authorized user of the Gmail API.
|
||||
() -> this.gmail.users().messages().send("me", message).execute(),
|
||||
RetriableGmailExceptionPredicate.INSTANCE);
|
||||
}
|
||||
|
||||
static Message toGmailMessage(MimeMessage message) {
|
||||
@@ -86,10 +108,7 @@ public final class GmailClient {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
message.writeTo(buffer);
|
||||
byte[] rawMessageBytes = buffer.toByteArray();
|
||||
String encodedEmail = Base64.encodeBase64URLSafeString(rawMessageBytes);
|
||||
Message gmailMessage = new Message();
|
||||
gmailMessage.setRaw(encodedEmail);
|
||||
return gmailMessage;
|
||||
return new Message().encodeRaw(rawMessageBytes);
|
||||
} catch (MessagingException | IOException e) {
|
||||
throw new EmailException(e);
|
||||
}
|
||||
@@ -135,4 +154,41 @@ public final class GmailClient {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a Gmail API exception may be retried.
|
||||
*
|
||||
* <p>See <a href="https://developers.google.com/gmail/api/guides/handle-errors">online doc</a>
|
||||
* for details.
|
||||
*/
|
||||
static class RetriableGmailExceptionPredicate implements Predicate<Throwable> {
|
||||
|
||||
static RetriableGmailExceptionPredicate INSTANCE = new RetriableGmailExceptionPredicate();
|
||||
|
||||
private static final int USAGE_LIMIT_EXCEEDED = 403;
|
||||
private static final int TOO_MANY_REQUESTS = 429;
|
||||
private static final int BACKEND_ERROR = 500;
|
||||
|
||||
private static final ImmutableSet<String> TRANSIENT_OVERAGE_REASONS =
|
||||
ImmutableSet.of("userRateLimitExceeded", "rateLimitExceeded");
|
||||
|
||||
@Override
|
||||
public boolean test(Throwable e) {
|
||||
if (e instanceof HttpResponseException) {
|
||||
return testHttpResponse((HttpResponseException) e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean testHttpResponse(HttpResponseException e) {
|
||||
int statusCode = e.getStatusCode();
|
||||
if (statusCode == TOO_MANY_REQUESTS || statusCode == BACKEND_ERROR) {
|
||||
return true;
|
||||
}
|
||||
if (statusCode == USAGE_LIMIT_EXCEEDED) {
|
||||
return TRANSIENT_OVERAGE_REASONS.contains(e.getStatusMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,12 +31,12 @@ import com.google.template.soy.tofu.SoyTofu;
|
||||
import com.google.template.soy.tofu.SoyTofu.Renderer;
|
||||
import google.registry.beam.spec11.ThreatMatch;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.groups.GmailClient;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.reporting.spec11.soy.Spec11EmailSoyInfo;
|
||||
import google.registry.util.EmailMessage;
|
||||
import google.registry.util.SendEmailService;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
@@ -56,8 +56,7 @@ public class Spec11EmailUtils {
|
||||
Spec11EmailSoyInfo.getInstance().getFileName()))
|
||||
.build()
|
||||
.compileToTofu();
|
||||
|
||||
private final SendEmailService emailService;
|
||||
private final GmailClient gmailClient;
|
||||
private final InternetAddress outgoingEmailAddress;
|
||||
private final ImmutableList<InternetAddress> spec11BccEmailAddresses;
|
||||
private final InternetAddress alertRecipientAddress;
|
||||
@@ -66,13 +65,13 @@ public class Spec11EmailUtils {
|
||||
|
||||
@Inject
|
||||
Spec11EmailUtils(
|
||||
SendEmailService emailService,
|
||||
@Config("alertRecipientEmailAddress") InternetAddress alertRecipientAddress,
|
||||
GmailClient gmailClient,
|
||||
@Config("newAlertRecipientEmailAddress") InternetAddress alertRecipientAddress,
|
||||
@Config("spec11OutgoingEmailAddress") InternetAddress spec11OutgoingEmailAddress,
|
||||
@Config("spec11BccEmailAddresses") ImmutableList<InternetAddress> spec11BccEmailAddresses,
|
||||
@Config("spec11WebResources") ImmutableList<String> spec11WebResources,
|
||||
@Config("registryName") String registryName) {
|
||||
this.emailService = emailService;
|
||||
this.gmailClient = gmailClient;
|
||||
this.outgoingEmailAddress = spec11OutgoingEmailAddress;
|
||||
this.spec11BccEmailAddresses = spec11BccEmailAddresses;
|
||||
this.alertRecipientAddress = alertRecipientAddress;
|
||||
@@ -151,7 +150,7 @@ public class Spec11EmailUtils {
|
||||
String subject,
|
||||
RegistrarThreatMatches registrarThreatMatches)
|
||||
throws MessagingException {
|
||||
emailService.sendEmail(
|
||||
gmailClient.sendEmail(
|
||||
EmailMessage.newBuilder()
|
||||
.setSubject(subject)
|
||||
.setBody(getContent(date, soyTemplateInfo, registrarThreatMatches))
|
||||
@@ -191,7 +190,7 @@ public class Spec11EmailUtils {
|
||||
/** Sends an e-mail indicating the state of the spec11 pipeline, with a given subject and body. */
|
||||
void sendAlertEmail(String subject, String body) {
|
||||
try {
|
||||
emailService.sendEmail(
|
||||
gmailClient.sendEmail(
|
||||
EmailMessage.newBuilder()
|
||||
.setFrom(outgoingEmailAddress)
|
||||
.addRecipient(alertRecipientAddress)
|
||||
|
||||
@@ -14,10 +14,13 @@
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static google.registry.model.tld.TldYamlUtils.getObjectMapper;
|
||||
import static google.registry.model.tld.Tlds.assertTldsExist;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import google.registry.model.tld.Tld;
|
||||
import java.util.List;
|
||||
|
||||
@@ -31,9 +34,10 @@ final class GetTldCommand implements Command {
|
||||
private List<String> mainParameters;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
public void run() throws JsonProcessingException {
|
||||
ObjectMapper mapper = getObjectMapper();
|
||||
for (String tld : assertTldsExist(mainParameters)) {
|
||||
System.out.println(Tld.get(tld));
|
||||
System.out.println(mapper.writeValueAsString(Tld.get(tld)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.groups;
|
||||
|
||||
import static com.google.common.net.MediaType.CSV_UTF_8;
|
||||
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.api.client.http.HttpResponseException;
|
||||
import com.google.api.services.gmail.Gmail;
|
||||
import com.google.api.services.gmail.Gmail.Users;
|
||||
import com.google.api.services.gmail.Gmail.Users.Messages;
|
||||
import com.google.api.services.gmail.Gmail.Users.Messages.Send;
|
||||
import com.google.api.services.gmail.model.Message;
|
||||
import google.registry.groups.GmailClient.RetriableGmailExceptionPredicate;
|
||||
import google.registry.util.EmailMessage;
|
||||
import google.registry.util.EmailMessage.Attachment;
|
||||
import google.registry.util.Retrier;
|
||||
import google.registry.util.SystemSleeper;
|
||||
import java.io.OutputStream;
|
||||
import javax.mail.Message.RecipientType;
|
||||
import javax.mail.Part;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.internet.MimeMultipart;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.testcontainers.shaded.com.google.common.collect.ImmutableList;
|
||||
|
||||
/** Unit tests for {@link GmailClient}. */
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class GmailClientTest {
|
||||
|
||||
@Mock private Gmail gmail;
|
||||
@Mock private HttpResponseException httpResponseException;
|
||||
|
||||
private GmailClient getGmailClient(boolean isExternalEmailAllowed) throws Exception {
|
||||
return new GmailClient(
|
||||
gmail,
|
||||
new Retrier(new SystemSleeper(), 3),
|
||||
isExternalEmailAllowed,
|
||||
"from@example.com",
|
||||
"My sender",
|
||||
new InternetAddress("replyTo@example.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendEmail_sentWhenAllowed() throws Exception {
|
||||
EmailMessage message =
|
||||
EmailMessage.create(
|
||||
"subject",
|
||||
"body",
|
||||
new InternetAddress("from@example.com"),
|
||||
new InternetAddress("to@example.com"));
|
||||
Send gSend = mock(Send.class);
|
||||
Messages gMessages = mock(Messages.class);
|
||||
Users gUsers = mock(Users.class);
|
||||
when(gmail.users()).thenReturn(gUsers);
|
||||
when(gUsers.messages()).thenReturn(gMessages);
|
||||
when(gMessages.send(anyString(), any())).thenReturn(gSend);
|
||||
getGmailClient(true).sendEmail(message);
|
||||
verify(gmail, times(1)).users();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendEmail_notSentWhenNotAllowed() throws Exception {
|
||||
EmailMessage message =
|
||||
EmailMessage.create(
|
||||
"subject",
|
||||
"body",
|
||||
new InternetAddress("from@example.com"),
|
||||
new InternetAddress("to@example.com"));
|
||||
getGmailClient(false).sendEmail(message);
|
||||
verifyNoInteractions(gmail);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toMimeMessage_fullMessage() throws Exception {
|
||||
InternetAddress fromAddr = new InternetAddress("from@example.com", "My sender");
|
||||
InternetAddress toAddr = new InternetAddress("to@example.com");
|
||||
InternetAddress ccAddr = new InternetAddress("cc@example.com");
|
||||
InternetAddress bccAddr = new InternetAddress("bcc@example.com");
|
||||
EmailMessage emailMessage =
|
||||
EmailMessage.newBuilder()
|
||||
.setFrom(fromAddr)
|
||||
.setRecipients(ImmutableList.of(toAddr))
|
||||
.setSubject("My subject")
|
||||
.setBody("My body")
|
||||
.addCc(ccAddr)
|
||||
.addBcc(bccAddr)
|
||||
.setAttachment(
|
||||
Attachment.newBuilder()
|
||||
.setFilename("filename")
|
||||
.setContent("foo,bar\nbaz,qux")
|
||||
.setContentType(CSV_UTF_8)
|
||||
.build())
|
||||
.build();
|
||||
MimeMessage mimeMessage = getGmailClient(true).toMimeMessage(emailMessage);
|
||||
assertThat(mimeMessage.getFrom()).asList().containsExactly(fromAddr);
|
||||
assertThat(mimeMessage.getRecipients(RecipientType.TO)).asList().containsExactly(toAddr);
|
||||
assertThat(mimeMessage.getRecipients(RecipientType.CC)).asList().containsExactly(ccAddr);
|
||||
assertThat(mimeMessage.getRecipients(RecipientType.BCC)).asList().containsExactly(bccAddr);
|
||||
assertThat(mimeMessage.getSubject()).isEqualTo("My subject");
|
||||
assertThat(mimeMessage.getContent()).isInstanceOf(MimeMultipart.class);
|
||||
MimeMultipart parts = (MimeMultipart) mimeMessage.getContent();
|
||||
Part body = parts.getBodyPart(0);
|
||||
assertThat(body.getContentType()).isEqualTo(PLAIN_TEXT_UTF_8.toString());
|
||||
assertThat(body.getContent()).isEqualTo("My body");
|
||||
Part attachment = parts.getBodyPart(1);
|
||||
assertThat(attachment.getContentType()).startsWith(CSV_UTF_8.toString());
|
||||
assertThat(attachment.getContentType()).endsWith("name=filename");
|
||||
assertThat(attachment.getContent()).isEqualTo("foo,bar\nbaz,qux");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toGmailMessage() throws Exception {
|
||||
MimeMessage mimeMessage = mock(MimeMessage.class);
|
||||
byte[] data = "My content".getBytes(UTF_8);
|
||||
doAnswer(
|
||||
new Answer() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
OutputStream os = invocation.getArgument(0);
|
||||
os.write(data);
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.when(mimeMessage)
|
||||
.writeTo(any(OutputStream.class));
|
||||
Message gmailMessage = GmailClient.toGmailMessage(mimeMessage);
|
||||
assertThat(gmailMessage.decodeRaw()).isEqualTo(data);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRetriable_trueIfNotHttpResponseException() {
|
||||
assertThat(RetriableGmailExceptionPredicate.INSTANCE.test(new Exception())).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isHttpResponseExceptionRetriable_trueIf500() {
|
||||
when(httpResponseException.getStatusCode()).thenReturn(500);
|
||||
assertThat(RetriableGmailExceptionPredicate.INSTANCE.test(httpResponseException)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isHttpResponseExceptionRetriable_trueIf429() {
|
||||
when(httpResponseException.getStatusCode()).thenReturn(429);
|
||||
assertThat(RetriableGmailExceptionPredicate.INSTANCE.test(httpResponseException)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isHttpResponseExceptionRetriable_trueIf403WithRateLimitOverage() {
|
||||
when(httpResponseException.getStatusCode()).thenReturn(403);
|
||||
when(httpResponseException.getStatusMessage()).thenReturn("rateLimitExceeded");
|
||||
assertThat(RetriableGmailExceptionPredicate.INSTANCE.test(httpResponseException)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isHttpResponseExceptionRetriable_trueIf403WithUserRateLimitOverage() {
|
||||
when(httpResponseException.getStatusCode()).thenReturn(403);
|
||||
when(httpResponseException.getStatusMessage()).thenReturn("userRateLimitExceeded");
|
||||
assertThat(RetriableGmailExceptionPredicate.INSTANCE.test(httpResponseException)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isHttpResponseExceptionRetriable_falseIf403WithLongLastingOverage() {
|
||||
when(httpResponseException.getStatusCode()).thenReturn(403);
|
||||
when(httpResponseException.getStatusMessage()).thenReturn("dailyLimitExceeded");
|
||||
assertThat(RetriableGmailExceptionPredicate.INSTANCE.test(httpResponseException)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isHttpResponseExceptionRetriable_falseIfBadRequest() {
|
||||
when(httpResponseException.getStatusCode()).thenReturn(400);
|
||||
assertThat(RetriableGmailExceptionPredicate.INSTANCE.test(httpResponseException)).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -27,14 +27,13 @@ import static google.registry.testing.DatabaseHelper.persistActiveHost;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.groups.GmailClient;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
@@ -42,7 +41,6 @@ import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationT
|
||||
import google.registry.reporting.spec11.soy.Spec11EmailSoyInfo;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.util.EmailMessage;
|
||||
import google.registry.util.SendEmailService;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -51,10 +49,14 @@ import javax.mail.internet.InternetAddress;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
/** Unit tests for {@link Spec11EmailUtils}. */
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class Spec11EmailUtilsTest {
|
||||
|
||||
private static final ImmutableList<String> FAKE_RESOURCES = ImmutableList.of("foo");
|
||||
@@ -98,9 +100,8 @@ class Spec11EmailUtilsTest {
|
||||
final JpaIntegrationTestExtension jpa =
|
||||
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
|
||||
|
||||
private SendEmailService emailService;
|
||||
@Mock private GmailClient gmailClient;
|
||||
private Spec11EmailUtils emailUtils;
|
||||
private Spec11RegistrarThreatMatchesParser parser;
|
||||
private ArgumentCaptor<EmailMessage> contentCaptor;
|
||||
private final LocalDate date = new LocalDate(2018, 7, 15);
|
||||
|
||||
@@ -109,13 +110,10 @@ class Spec11EmailUtilsTest {
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
emailService = mock(SendEmailService.class);
|
||||
parser = mock(Spec11RegistrarThreatMatchesParser.class);
|
||||
when(parser.getRegistrarThreatMatches(date)).thenReturn(sampleThreatMatches());
|
||||
contentCaptor = ArgumentCaptor.forClass(EmailMessage.class);
|
||||
emailUtils =
|
||||
new Spec11EmailUtils(
|
||||
emailService,
|
||||
gmailClient,
|
||||
new InternetAddress("my-receiver@test.com"),
|
||||
new InternetAddress("abuse@test.com"),
|
||||
ImmutableList.of(
|
||||
@@ -138,7 +136,7 @@ class Spec11EmailUtilsTest {
|
||||
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
|
||||
sampleThreatMatches());
|
||||
// We inspect individual parameters because Message doesn't implement equals().
|
||||
verify(emailService, times(3)).sendEmail(contentCaptor.capture());
|
||||
verify(gmailClient, times(3)).sendEmail(contentCaptor.capture());
|
||||
List<EmailMessage> capturedContents = contentCaptor.getAllValues();
|
||||
validateMessage(
|
||||
capturedContents.get(0),
|
||||
@@ -176,7 +174,7 @@ class Spec11EmailUtilsTest {
|
||||
"Super Cool Registry Daily Threat Detector [2018-07-15]",
|
||||
sampleThreatMatches());
|
||||
// We inspect individual parameters because Message doesn't implement equals().
|
||||
verify(emailService, times(3)).sendEmail(contentCaptor.capture());
|
||||
verify(gmailClient, times(3)).sendEmail(contentCaptor.capture());
|
||||
List<EmailMessage> capturedMessages = contentCaptor.getAllValues();
|
||||
validateMessage(
|
||||
capturedMessages.get(0),
|
||||
@@ -217,7 +215,7 @@ class Spec11EmailUtilsTest {
|
||||
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
|
||||
sampleThreatMatches());
|
||||
// We inspect individual parameters because Message doesn't implement equals().
|
||||
verify(emailService, times(2)).sendEmail(contentCaptor.capture());
|
||||
verify(gmailClient, times(2)).sendEmail(contentCaptor.capture());
|
||||
List<EmailMessage> capturedContents = contentCaptor.getAllValues();
|
||||
validateMessage(
|
||||
capturedContents.get(0),
|
||||
@@ -250,7 +248,7 @@ class Spec11EmailUtilsTest {
|
||||
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
|
||||
sampleThreatMatches());
|
||||
// We inspect individual parameters because Message doesn't implement equals().
|
||||
verify(emailService, times(3)).sendEmail(contentCaptor.capture());
|
||||
verify(gmailClient, times(3)).sendEmail(contentCaptor.capture());
|
||||
List<EmailMessage> capturedContents = contentCaptor.getAllValues();
|
||||
validateMessage(
|
||||
capturedContents.get(0),
|
||||
@@ -289,7 +287,7 @@ class Spec11EmailUtilsTest {
|
||||
doThrow(new RuntimeException(new MessagingException("expected")))
|
||||
.doNothing()
|
||||
.doNothing()
|
||||
.when(emailService)
|
||||
.when(gmailClient)
|
||||
.sendEmail(contentCaptor.capture());
|
||||
RuntimeException thrown =
|
||||
assertThrows(
|
||||
@@ -305,7 +303,7 @@ class Spec11EmailUtilsTest {
|
||||
.isEqualTo("Emailing Spec11 reports failed, first exception:");
|
||||
assertThat(thrown).hasCauseThat().hasMessageThat().isEqualTo("expected");
|
||||
// Verify we sent an e-mail alert
|
||||
verify(emailService, times(3)).sendEmail(contentCaptor.capture());
|
||||
verify(gmailClient, times(3)).sendEmail(contentCaptor.capture());
|
||||
List<EmailMessage> capturedMessages = contentCaptor.getAllValues();
|
||||
validateMessage(
|
||||
capturedMessages.get(0),
|
||||
@@ -338,7 +336,7 @@ class Spec11EmailUtilsTest {
|
||||
@Test
|
||||
void testSuccess_sendAlertEmail() throws Exception {
|
||||
emailUtils.sendAlertEmail("Spec11 Pipeline Alert: 2018-07", "Alert!");
|
||||
verify(emailService).sendEmail(contentCaptor.capture());
|
||||
verify(gmailClient).sendEmail(contentCaptor.capture());
|
||||
validateMessage(
|
||||
contentCaptor.getValue(),
|
||||
"abuse@test.com",
|
||||
@@ -363,7 +361,7 @@ class Spec11EmailUtilsTest {
|
||||
Spec11EmailSoyInfo.MONTHLY_SPEC_11_EMAIL,
|
||||
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
|
||||
sampleThreatMatches());
|
||||
verify(emailService, times(3)).sendEmail(contentCaptor.capture());
|
||||
verify(gmailClient, times(3)).sendEmail(contentCaptor.capture());
|
||||
assertThat(contentCaptor.getAllValues().get(0).recipients())
|
||||
.containsExactly(new InternetAddress("johndoe@theregistrar.com"));
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.tools;
|
||||
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.createTlds;
|
||||
import static google.registry.testing.TestDataHelper.loadFile;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
@@ -28,6 +29,7 @@ class GetTldCommandTest extends CommandTestCase<GetTldCommand> {
|
||||
void testSuccess() throws Exception {
|
||||
createTld("xn--q9jyb4c");
|
||||
runCommand("xn--q9jyb4c");
|
||||
assertInStdout(loadFile(getClass(), "tld.yaml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
tldStr: "xn--q9jyb4c"
|
||||
roidSuffix: "Q9JYB4C"
|
||||
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
|
||||
dnsWriters:
|
||||
- "VoidDnsWriter"
|
||||
numDnsPublishLocks: 1
|
||||
dnsAPlusAaaaTtl: null
|
||||
dnsNsTtl: null
|
||||
dnsDsTtl: null
|
||||
tldUnicode: "みんな"
|
||||
driveFolderId: null
|
||||
tldType: "REAL"
|
||||
invoicingEnabled: false
|
||||
tldStateTransitions:
|
||||
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
|
||||
creationTime: "2022-09-01T00:00:00.000Z"
|
||||
reservedListNames: []
|
||||
premiumListName: "xn--q9jyb4c"
|
||||
escrowEnabled: false
|
||||
dnsPaused: false
|
||||
addGracePeriodLength: 432000000
|
||||
anchorTenantAddGracePeriodLength: 2592000000
|
||||
autoRenewGracePeriodLength: 3888000000
|
||||
redemptionGracePeriodLength: 2592000000
|
||||
renewGracePeriodLength: 432000000
|
||||
transferGracePeriodLength: 432000000
|
||||
automaticTransferLength: 432000000
|
||||
pendingDeleteLength: 432000000
|
||||
currency: "USD"
|
||||
createBillingCost:
|
||||
currency: "USD"
|
||||
amount: 13.00
|
||||
restoreBillingCost:
|
||||
currency: "USD"
|
||||
amount: 17.00
|
||||
serverStatusChangeBillingCost:
|
||||
currency: "USD"
|
||||
amount: 19.00
|
||||
registryLockOrUnlockBillingCost:
|
||||
currency: "USD"
|
||||
amount: 0.00
|
||||
renewBillingCostTransitions:
|
||||
"1970-01-01T00:00:00.000Z":
|
||||
currency: "USD"
|
||||
amount: 11.00
|
||||
lordnUsername: null
|
||||
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
|
||||
allowedRegistrantContactIds: []
|
||||
allowedFullyQualifiedHostNames: []
|
||||
defaultPromoTokens: []
|
||||
idnTables: []
|
||||
eapFeeSchedule:
|
||||
"1970-01-01T00:00:00.000Z":
|
||||
currency: "USD"
|
||||
amount: 0.00
|
||||
Reference in New Issue
Block a user