1
0
mirror of https://github.com/google/nomulus synced 2026-04-27 11:35:20 +00:00

Remove appengine-based email client (#2354)

Remove email classes that depend on AppEngine API. They have been
replaced by the gmail-based client.

Remove `EmailMessage.from` method, which is no longer used.
There is a fixed sender address for the entire domain, and is
set by the gmail client.

The configs remain to be cleaned up. There is a bug (b/279671974) that
tracks it.
This commit is contained in:
Weimin Yu
2024-03-06 22:26:12 -05:00
committed by GitHub
parent 1cac9c9684
commit df4e345961
28 changed files with 21 additions and 514 deletions

View File

@@ -82,7 +82,6 @@ public class RelockDomainAction implements Runnable {
private final long oldUnlockRevisionId;
private final int previousAttempts;
private final InternetAddress alertRecipientAddress;
private final InternetAddress gSuiteOutgoingEmailAddress;
private final String supportEmail;
private final GmailClient gmailClient;
private final DomainLockUtils domainLockUtils;
@@ -93,7 +92,6 @@ public class RelockDomainAction implements Runnable {
@Parameter(OLD_UNLOCK_REVISION_ID_PARAM) long oldUnlockRevisionId,
@Parameter(PREVIOUS_ATTEMPTS_PARAM) int previousAttempts,
@Config("newAlertRecipientEmailAddress") InternetAddress alertRecipientAddress,
@Config("gSuiteOutgoingEmailAddress") InternetAddress gSuiteOutgoingEmailAddress,
@Config("supportEmail") String supportEmail,
GmailClient gmailClient,
DomainLockUtils domainLockUtils,
@@ -101,7 +99,6 @@ public class RelockDomainAction implements Runnable {
this.oldUnlockRevisionId = oldUnlockRevisionId;
this.previousAttempts = previousAttempts;
this.alertRecipientAddress = alertRecipientAddress;
this.gSuiteOutgoingEmailAddress = gSuiteOutgoingEmailAddress;
this.supportEmail = supportEmail;
this.gmailClient = gmailClient;
this.domainLockUtils = domainLockUtils;
@@ -217,7 +214,6 @@ public class RelockDomainAction implements Runnable {
supportEmail);
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setFrom(gSuiteOutgoingEmailAddress)
.setBody(body)
.setSubject(String.format("Error re-locking domain %s", oldLock.getDomainName()))
.setRecipients(getEmailRecipients(oldLock.getRegistrarId()))
@@ -247,7 +243,6 @@ public class RelockDomainAction implements Runnable {
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setFrom(gSuiteOutgoingEmailAddress)
.setBody(body)
.setSubject(String.format("Successful re-lock of domain %s", oldLock.getDomainName()))
.setRecipients(getEmailRecipients(oldLock.getRegistrarId()))
@@ -266,7 +261,6 @@ public class RelockDomainAction implements Runnable {
.build();
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setFrom(gSuiteOutgoingEmailAddress)
.setBody(body)
.setSubject(String.format("Error re-locking domain %s", oldLock.getDomainName()))
.setRecipients(allRecipients)
@@ -276,7 +270,6 @@ public class RelockDomainAction implements Runnable {
private void sendUnknownRevisionIdAlertEmail() {
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setFrom(gSuiteOutgoingEmailAddress)
.setBody(String.format(RELOCK_UNKNOWN_ID_FAILURE_EMAIL_TEMPLATE, oldUnlockRevisionId))
.setSubject("Error re-locking domain")
.setRecipients(ImmutableSet.of(alertRecipientAddress))

View File

@@ -72,21 +72,18 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
private final String expirationWarningEmailBodyText;
private final GmailClient gmailClient;
private final String expirationWarningEmailSubjectText;
private final InternetAddress gSuiteOutgoingEmailAddress;
private final Response response;
@Inject
public SendExpiringCertificateNotificationEmailAction(
@Config("expirationWarningEmailBodyText") String expirationWarningEmailBodyText,
@Config("expirationWarningEmailSubjectText") String expirationWarningEmailSubjectText,
@Config("gSuiteOutgoingEmailAddress") InternetAddress gSuiteOutgoingEmailAddress,
GmailClient gmailClient,
CertificateChecker certificateChecker,
Response response) {
this.certificateChecker = certificateChecker;
this.expirationWarningEmailSubjectText = expirationWarningEmailSubjectText;
this.gmailClient = gmailClient;
this.gSuiteOutgoingEmailAddress = gSuiteOutgoingEmailAddress;
this.expirationWarningEmailBodyText = expirationWarningEmailBodyText;
this.response = response;
}
@@ -172,7 +169,6 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
}
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setFrom(gSuiteOutgoingEmailAddress)
.setSubject(expirationWarningEmailSubjectText)
.setBody(
getEmailBody(

View File

@@ -118,7 +118,6 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
private final String dnsUpdateFailRegistryName;
private final Lazy<InternetAddress> registrySupportEmail;
private final Lazy<InternetAddress> registryCcEmail;
private final InternetAddress gSuiteOutgoingEmailAddress;
@Inject
public PublishDnsUpdatesAction(
@@ -136,7 +135,6 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
@Config("dnsUpdateFailRegistryName") String dnsUpdateFailRegistryName,
@Config("registrySupportEmail") Lazy<InternetAddress> registrySupportEmail,
@Config("registryCcEmail") Lazy<InternetAddress> registryCcEmail,
@Config("gSuiteOutgoingEmailAddress") InternetAddress gSuiteOutgoingEmailAddress,
@Header(CLOUD_TASKS_RETRY_HEADER) int retryCount,
DnsWriterProxy dnsWriterProxy,
DnsMetrics dnsMetrics,
@@ -167,7 +165,6 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
this.dnsUpdateFailRegistryName = dnsUpdateFailRegistryName;
this.registrySupportEmail = registrySupportEmail;
this.registryCcEmail = registryCcEmail;
this.gSuiteOutgoingEmailAddress = gSuiteOutgoingEmailAddress;
}
private void recordActionResult(ActionStatus status) {
@@ -309,7 +306,6 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
.setSubject(dnsUpdateFailEmailSubjectText)
.setRecipients(recipients)
.addBcc(registryCcEmail.get())
.setFrom(gSuiteOutgoingEmailAddress)
.build());
} else {

View File

@@ -79,9 +79,6 @@ public final class GmailClient {
/**
* Sends {@code emailMessage} using {@link Gmail}.
*
* <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.
*/
public void sendEmail(EmailMessage emailMessage) {
if (!isEmailSendingEnabled) {

View File

@@ -37,7 +37,6 @@ public class BillingEmailUtils {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final GmailClient gmailClient;
private final YearMonth yearMonth;
private final InternetAddress outgoingEmailAddress;
private final InternetAddress alertRecipientAddress;
private final ImmutableList<InternetAddress> invoiceEmailRecipients;
private final Optional<InternetAddress> replyToEmailAddress;
@@ -51,7 +50,6 @@ public class BillingEmailUtils {
BillingEmailUtils(
GmailClient gmailClient,
YearMonth yearMonth,
@Config("gSuiteOutgoingEmailAddress") InternetAddress outgoingEmailAddress,
@Config("newAlertRecipientEmailAddress") InternetAddress alertRecipientAddress,
@Config("invoiceEmailRecipients") ImmutableList<InternetAddress> invoiceEmailRecipients,
@Config("invoiceReplyToEmailAddress") Optional<InternetAddress> replyToEmailAddress,
@@ -62,7 +60,6 @@ public class BillingEmailUtils {
GcsUtils gcsUtils) {
this.gmailClient = gmailClient;
this.yearMonth = yearMonth;
this.outgoingEmailAddress = outgoingEmailAddress;
this.alertRecipientAddress = alertRecipientAddress;
this.invoiceEmailRecipients = invoiceEmailRecipients;
this.replyToEmailAddress = replyToEmailAddress;
@@ -94,7 +91,6 @@ public class BillingEmailUtils {
"<p>Use the following link to download %s invoice for the domain registry -"
+ " <a href=\"%s\">invoice</a>.</p>",
yearMonth, fileUrl))
.setFrom(outgoingEmailAddress)
.setRecipients(invoiceEmailRecipients)
.setReplyToEmailAddress(replyToEmailAddress)
.setContentType(MediaType.HTML_UTF_8)
@@ -115,7 +111,6 @@ public class BillingEmailUtils {
.setSubject(String.format("Billing Pipeline Alert: %s", yearMonth))
.setBody(body)
.addRecipient(alertRecipientAddress)
.setFrom(outgoingEmailAddress)
.build());
} catch (Throwable e) {
throw new RuntimeException("The alert e-mail system failed.", e);

View File

@@ -82,7 +82,6 @@ public final class IcannReportingStagingAction implements Runnable {
@Inject IcannReportingStager stager;
@Inject Retrier retrier;
@Inject Response response;
@Inject @Config("gSuiteOutgoingEmailAddress") InternetAddress sender;
@Inject
@Config("newAlertRecipientEmailAddress")
@@ -115,7 +114,6 @@ public final class IcannReportingStagingAction implements Runnable {
"Completed staging the following %d ICANN reports:\n%s",
manifestedFiles.size(), Joiner.on('\n').join(manifestedFiles)))
.addRecipient(recipient)
.setFrom(sender)
.build());
response.setStatus(SC_OK);
@@ -139,8 +137,7 @@ public final class IcannReportingStagingAction implements Runnable {
"ICANN Monthly report staging summary [FAILURE]",
String.format(
"Staging failed due to %s, check logs for more details.", getRootCause(e)),
recipient,
sender));
recipient));
response.setStatus(SC_INTERNAL_SERVER_ERROR);
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
response.setPayload(

View File

@@ -86,7 +86,6 @@ public final class IcannReportingUploadAction implements Runnable {
@Inject IcannHttpReporter icannReporter;
@Inject Retrier retrier;
@Inject Response response;
@Inject @Config("gSuiteOutgoingEmailAddress") InternetAddress sender;
@Inject
@Config("newAlertRecipientEmailAddress")
@@ -297,7 +296,7 @@ public final class IcannReportingUploadAction implements Runnable {
(e) ->
String.format("%s - %s", e.getKey(), e.getValue() ? "SUCCESS" : "FAILURE"))
.collect(Collectors.joining("\n")));
gmailClient.sendEmail(EmailMessage.create(subject, body, recipient, sender));
gmailClient.sendEmail(EmailMessage.create(subject, body, recipient));
}
private byte[] readBytesFromGcs(BlobId reportFilename) throws IOException {

View File

@@ -173,7 +173,6 @@ public class Spec11EmailUtils {
.setSubject(subject)
.setBody(getEmailBody(date, soyTemplateInfo, registrarThreatMatches))
.setContentType(MediaType.HTML_UTF_8)
.setFrom(outgoingEmailAddress)
.addRecipient(getEmailAddressForRegistrar(registrarThreatMatches.clientId()))
.setBccs(spec11BccEmailAddresses)
.build());
@@ -216,7 +215,6 @@ public class Spec11EmailUtils {
try {
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setFrom(outgoingEmailAddress)
.addRecipient(alertRecipientAddress)
.setBody(body)
.setSubject(subject)

View File

@@ -35,21 +35,14 @@ import javax.mail.internet.InternetAddress;
public class SendEmailUtils {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final InternetAddress gSuiteOutgoingEmailAddress;
private final String gSuiteOutgoingEmailDisplayName;
private final GmailClient gmailClient;
private final ImmutableList<String> registrarChangesNotificationEmailAddresses;
@Inject
public SendEmailUtils(
@Config("gSuiteOutgoingEmailAddress") InternetAddress gSuiteOutgoingEmailAddress,
@Config("gSuiteOutgoingEmailDisplayName") String gSuiteOutgoingEmailDisplayName,
@Config("registrarChangesNotificationEmailAddresses")
ImmutableList<String> registrarChangesNotificationEmailAddresses,
GmailClient gmailClient) {
this.gSuiteOutgoingEmailAddress = gSuiteOutgoingEmailAddress;
this.gSuiteOutgoingEmailDisplayName = gSuiteOutgoingEmailDisplayName;
this.gmailClient = gmailClient;
this.registrarChangesNotificationEmailAddresses = registrarChangesNotificationEmailAddresses;
}
@@ -71,9 +64,6 @@ public class SendEmailUtils {
Optional<String> bcc,
ImmutableList<String> additionalAddresses) {
try {
InternetAddress from =
new InternetAddress(
gSuiteOutgoingEmailAddress.getAddress(), gSuiteOutgoingEmailDisplayName);
ImmutableList<InternetAddress> recipients =
Stream.concat(
registrarChangesNotificationEmailAddresses.stream(), additionalAddresses.stream())
@@ -95,11 +85,7 @@ public class SendEmailUtils {
return false;
}
EmailMessage.Builder emailMessage =
EmailMessage.newBuilder()
.setBody(body)
.setSubject(subject)
.setRecipients(recipients)
.setFrom(from);
EmailMessage.newBuilder().setBody(body).setSubject(subject).setRecipients(recipients);
if (bcc.isPresent()) {
try {
InternetAddress bccInternetAddress = new InternetAddress(bcc.get(), true);

View File

@@ -29,7 +29,6 @@ import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gson.Gson;
import google.registry.config.RegistryConfig.Config;
import google.registry.flows.domain.DomainFlowUtils;
import google.registry.groups.GmailClient;
import google.registry.model.domain.RegistryLock;
@@ -85,7 +84,6 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc
private final AuthenticatedRegistrarAccessor registrarAccessor;
private final GmailClient gmailClient;
private final DomainLockUtils domainLockUtils;
private final InternetAddress gSuiteOutgoingEmailAddress;
@Inject
RegistryLockPostAction(
@@ -94,15 +92,13 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc
AuthResult authResult,
AuthenticatedRegistrarAccessor registrarAccessor,
GmailClient gmailClient,
DomainLockUtils domainLockUtils,
@Config("gSuiteOutgoingEmailAddress") InternetAddress gSuiteOutgoingEmailAddress) {
DomainLockUtils domainLockUtils) {
this.req = req;
this.jsonActionRunner = jsonActionRunner;
this.authResult = authResult;
this.registrarAccessor = registrarAccessor;
this.gmailClient = gmailClient;
this.domainLockUtils = domainLockUtils;
this.gSuiteOutgoingEmailAddress = gSuiteOutgoingEmailAddress;
}
@Override
@@ -174,7 +170,6 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc
.setBody(body)
.setSubject(String.format("Registry %s verification", action))
.setRecipients(recipients)
.setFrom(gSuiteOutgoingEmailAddress)
.build());
} catch (AddressException | URISyntaxException e) {
throw new RuntimeException(e); // caught above -- this is so we can run in a transaction

View File

@@ -44,7 +44,6 @@ import google.registry.ui.server.SendEmailUtils;
import google.registry.util.EmailMessage;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.mail.internet.InternetAddress;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.joda.time.DateTime;
@@ -89,8 +88,6 @@ public class CheckBulkComplianceActionTest {
loggerToIntercept.addHandler(logHandler);
sendEmailUtils =
new SendEmailUtils(
new InternetAddress("outgoing@registry.example"),
"UnitTest Registry",
ImmutableList.of("notification@test.example", "notification2@test.example"),
gmailClient);
createTld("tld");

View File

@@ -258,7 +258,6 @@ public class RelockDomainActionTest {
+ "contact support at support@example.com if you have any questions.")
.setRecipients(
ImmutableSet.of(new InternetAddress("Marla.Singer.RegistryLock@crr.com")))
.setFrom(new InternetAddress("outgoing@example.com"))
.build();
verify(gmailClient).sendEmail(expectedEmail);
}
@@ -292,7 +291,6 @@ public class RelockDomainActionTest {
.setSubject("Error re-locking domain example.tld")
.setBody(body)
.setRecipients(recipients)
.setFrom(new InternetAddress("outgoing@example.com"))
.build();
verify(gmailClient).sendEmail(expectedEmail);
}
@@ -321,12 +319,10 @@ public class RelockDomainActionTest {
private RelockDomainAction createAction(Long oldUnlockRevisionId, int previousAttempts)
throws Exception {
InternetAddress alertRecipientAddress = new InternetAddress("alerts@example.com");
InternetAddress gSuiteOutgoingAddress = new InternetAddress("outgoing@example.com");
return new RelockDomainAction(
oldUnlockRevisionId,
previousAttempts,
alertRecipientAddress,
gSuiteOutgoingAddress,
"support@example.com",
gmailClient,
domainLockUtils,

View File

@@ -98,7 +98,6 @@ class SendExpiringCertificateNotificationEmailActionTest {
new SendExpiringCertificateNotificationEmailAction(
EXPIRATION_WARNING_EMAIL_BODY_TEXT,
EXPIRATION_WARNING_EMAIL_SUBJECT_TEXT,
new InternetAddress("test@example.com"),
sendEmailService,
certificateChecker,
response);

View File

@@ -87,7 +87,6 @@ public class PublishDnsUpdatesActionTest {
private final DnsMetrics dnsMetrics = mock(DnsMetrics.class);
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
private PublishDnsUpdatesAction action;
private InternetAddress outgoingRegistry;
private Lazy<InternetAddress> registrySupportEmail;
private Lazy<InternetAddress> registryCcEmail;
private final GmailClient emailService = mock(GmailClient.class);
@@ -96,7 +95,6 @@ public class PublishDnsUpdatesActionTest {
void beforeEach() throws Exception {
createTld("xn--q9jyb4c");
createTld("com");
outgoingRegistry = new InternetAddress("outgoing@registry.example");
registrySupportEmail = Lazies.of(new InternetAddress("registry@test.com"));
registryCcEmail = Lazies.of(new InternetAddress("registry-cc@test.com"));
persistResource(
@@ -159,7 +157,6 @@ public class PublishDnsUpdatesActionTest {
"awesomeRegistry",
registrySupportEmail,
registryCcEmail,
outgoingRegistry,
retryCount,
new DnsWriterProxy(ImmutableMap.of("correctWriter", dnsWriter)),
dnsMetrics,

View File

@@ -75,7 +75,6 @@ public class GmailClientTest {
EmailMessage.create(
"subject",
"body",
new InternetAddress("from@example.com"),
new InternetAddress("to@example.com"));
Send gSend = mock(Send.class);
Messages gMessages = mock(Messages.class);
@@ -93,7 +92,6 @@ public class GmailClientTest {
EmailMessage.create(
"subject",
"body",
new InternetAddress("from@example.com"),
new InternetAddress("to@example.com"));
getGmailClient(false).sendEmail(message);
verifyNoInteractions(gmail);
@@ -107,7 +105,6 @@ public class GmailClientTest {
InternetAddress bccAddr = new InternetAddress("bcc@example.com");
EmailMessage emailMessage =
EmailMessage.newBuilder()
.setFrom(fromAddr)
.setRecipients(ImmutableList.of(toAddr))
.setSubject("My subject")
.setBody("My body")
@@ -148,7 +145,6 @@ public class GmailClientTest {
InternetAddress replyToAddr = new InternetAddress("some-addr@another.com");
EmailMessage emailMessage =
EmailMessage.newBuilder()
.setFrom(fromAddr)
.setRecipients(ImmutableList.of(toAddr))
.setReplyToEmailAddress(replyToAddr)
.setSubject("My subject")

View File

@@ -55,7 +55,6 @@ class BillingEmailUtilsTest {
return new BillingEmailUtils(
gmailClient,
new YearMonth(2017, 10),
new InternetAddress("my-sender@test.com"),
new InternetAddress("my-receiver@test.com"),
ImmutableList.of(
new InternetAddress("hello@world.com"), new InternetAddress("hola@mundo.com")),
@@ -75,7 +74,6 @@ class BillingEmailUtilsTest {
EmailMessage emailMessage = contentCaptor.getValue();
EmailMessage expectedContent =
EmailMessage.newBuilder()
.setFrom(new InternetAddress("my-sender@test.com"))
.setRecipients(
ImmutableList.of(
new InternetAddress("hello@world.com"), new InternetAddress("hola@mundo.com")))
@@ -126,7 +124,6 @@ class BillingEmailUtilsTest {
private void validateAlertMessage(EmailMessage emailMessage, String body)
throws MessagingException {
assertThat(emailMessage.from()).isEqualTo(new InternetAddress("my-sender@test.com"));
assertThat(emailMessage.recipients())
.containsExactly(new InternetAddress("my-receiver@test.com"));
assertThat(emailMessage.subject()).isEqualTo("Billing Pipeline Alert: 2017-10");

View File

@@ -63,7 +63,6 @@ class IcannReportingStagingActionTest {
action.response = response;
action.stager = stager;
action.retrier = new Retrier(new FakeSleeper(new FakeClock()), 3);
action.sender = new InternetAddress("sender@example.com");
action.recipient = new InternetAddress("recipient@example.com");
action.gmailClient = mock(GmailClient.class);
action.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
@@ -94,8 +93,7 @@ class IcannReportingStagingActionTest {
EmailMessage.create(
"ICANN Monthly report staging summary [SUCCESS]",
"Completed staging the following 2 ICANN reports:\na\nb",
new InternetAddress("recipient@example.com"),
new InternetAddress("sender@example.com")));
new InternetAddress("recipient@example.com")));
assertUploadTaskEnqueued();
}
@@ -110,8 +108,7 @@ class IcannReportingStagingActionTest {
EmailMessage.create(
"ICANN Monthly report staging summary [SUCCESS]",
"Completed staging the following 4 ICANN reports:\na\nb\nc\nd",
new InternetAddress("recipient@example.com"),
new InternetAddress("sender@example.com")));
new InternetAddress("recipient@example.com")));
assertUploadTaskEnqueued();
}
@@ -129,8 +126,7 @@ class IcannReportingStagingActionTest {
EmailMessage.create(
"ICANN Monthly report staging summary [SUCCESS]",
"Completed staging the following 4 ICANN reports:\na\nb\nc\nd",
new InternetAddress("recipient@example.com"),
new InternetAddress("sender@example.com")));
new InternetAddress("recipient@example.com")));
assertUploadTaskEnqueued();
}
@@ -153,8 +149,7 @@ class IcannReportingStagingActionTest {
"ICANN Monthly report staging summary [FAILURE]",
"Staging failed due to google.registry.bigquery.BigqueryJobFailureException: "
+ "BigqueryJobFailureException: Expected failure, check logs for more details.",
new InternetAddress("recipient@example.com"),
new InternetAddress("sender@example.com")));
new InternetAddress("recipient@example.com")));
// Assert no upload task enqueued
cloudTasksHelper.assertNoTasksEnqueued("retryable-cron-tasks");
}

View File

@@ -78,7 +78,6 @@ class IcannReportingUploadActionTest {
action.retrier = new Retrier(new FakeSleeper(new FakeClock()), 3);
action.reportingBucket = "basin";
action.gmailClient = gmailClient;
action.sender = new InternetAddress("sender@example.com");
action.recipient = new InternetAddress("recipient@example.com");
action.response = response;
action.clock = clock;
@@ -136,8 +135,7 @@ class IcannReportingUploadActionTest {
+ "foo-transactions-200606.csv - SUCCESS\n"
+ "tld-activity-200606.csv - FAILURE\n"
+ "tld-transactions-200606.csv - SUCCESS",
new InternetAddress("recipient@example.com"),
new InternetAddress("sender@example.com")));
new InternetAddress("recipient@example.com")));
}
@Test
@@ -169,8 +167,7 @@ class IcannReportingUploadActionTest {
"Report Filename - Upload status:\n"
+ "tld-activity-200512.csv - SUCCESS\n"
+ "tld-transactions-200512.csv - SUCCESS",
new InternetAddress("recipient@example.com"),
new InternetAddress("sender@example.com")));
new InternetAddress("recipient@example.com")));
}
@Test
@@ -215,8 +212,7 @@ class IcannReportingUploadActionTest {
+ "foo-transactions-200606.csv - SUCCESS\n"
+ "tld-activity-200606.csv - FAILURE\n"
+ "tld-transactions-200606.csv - SUCCESS",
new InternetAddress("recipient@example.com"),
new InternetAddress("sender@example.com")));
new InternetAddress("recipient@example.com")));
}
@Test
@@ -275,8 +271,7 @@ class IcannReportingUploadActionTest {
+ "foo-transactions-200606.csv - SUCCESS\n"
+ "tld-activity-200606.csv - FAILURE\n"
+ "tld-transactions-200606.csv - SUCCESS",
new InternetAddress("recipient@example.com"),
new InternetAddress("sender@example.com")));
new InternetAddress("recipient@example.com")));
}
@Test
@@ -345,8 +340,7 @@ class IcannReportingUploadActionTest {
+ "foo-transactions-200606.csv - SUCCESS\n"
+ "tld-activity-200606.csv - FAILURE\n"
+ "tld-transactions-200606.csv - SUCCESS",
new InternetAddress("recipient@example.com"),
new InternetAddress("sender@example.com")));
new InternetAddress("recipient@example.com")));
Cursor newActivityCursor =
loadByKey(Cursor.createScopedVKey(CursorType.ICANN_UPLOAD_ACTIVITY, Tld.get("new")));

View File

@@ -161,7 +161,6 @@ class Spec11EmailUtilsTest {
List<EmailMessage> capturedContents = contentCaptor.getAllValues();
validateMessage(
capturedContents.get(0),
"abuse@test.com",
"the.registrar@example.com",
ImmutableList.of("abuse@test.com", "bcc@test.com"),
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
@@ -169,7 +168,6 @@ class Spec11EmailUtilsTest {
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedContents.get(1),
"abuse@test.com",
"new.registrar@example.com",
ImmutableList.of("abuse@test.com", "bcc@test.com"),
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
@@ -179,7 +177,6 @@ class Spec11EmailUtilsTest {
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedContents.get(2),
"abuse@test.com",
"my-receiver@test.com",
ImmutableList.of(),
"Spec11 Pipeline Success 2018-07-15",
@@ -199,7 +196,6 @@ class Spec11EmailUtilsTest {
List<EmailMessage> capturedMessages = contentCaptor.getAllValues();
validateMessage(
capturedMessages.get(0),
"abuse@test.com",
"the.registrar@example.com",
ImmutableList.of("abuse@test.com", "bcc@test.com"),
"Super Cool Registry Daily Threat Detector [2018-07-15]",
@@ -207,7 +203,6 @@ class Spec11EmailUtilsTest {
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedMessages.get(1),
"abuse@test.com",
"new.registrar@example.com",
ImmutableList.of("abuse@test.com", "bcc@test.com"),
"Super Cool Registry Daily Threat Detector [2018-07-15]",
@@ -217,7 +212,6 @@ class Spec11EmailUtilsTest {
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedMessages.get(2),
"abuse@test.com",
"my-receiver@test.com",
ImmutableList.of(),
"Spec11 Pipeline Success 2018-07-15",
@@ -240,7 +234,6 @@ class Spec11EmailUtilsTest {
List<EmailMessage> capturedContents = contentCaptor.getAllValues();
validateMessage(
capturedContents.get(0),
"abuse@test.com",
"new.registrar@example.com",
ImmutableList.of("abuse@test.com", "bcc@test.com"),
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
@@ -248,7 +241,6 @@ class Spec11EmailUtilsTest {
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedContents.get(1),
"abuse@test.com",
"my-receiver@test.com",
ImmutableList.of(),
"Spec11 Pipeline Success 2018-07-15",
@@ -273,7 +265,6 @@ class Spec11EmailUtilsTest {
List<EmailMessage> capturedContents = contentCaptor.getAllValues();
validateMessage(
capturedContents.get(0),
"abuse@test.com",
"the.registrar@example.com",
ImmutableList.of("abuse@test.com", "bcc@test.com"),
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
@@ -281,7 +272,6 @@ class Spec11EmailUtilsTest {
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedContents.get(1),
"abuse@test.com",
"new.registrar@example.com",
ImmutableList.of("abuse@test.com", "bcc@test.com"),
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
@@ -291,7 +281,6 @@ class Spec11EmailUtilsTest {
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedContents.get(2),
"abuse@test.com",
"my-receiver@test.com",
ImmutableList.of(),
"Spec11 Pipeline Success 2018-07-15",
@@ -328,7 +317,6 @@ class Spec11EmailUtilsTest {
List<EmailMessage> capturedMessages = contentCaptor.getAllValues();
validateMessage(
capturedMessages.get(0),
"abuse@test.com",
"the.registrar@example.com",
ImmutableList.of("abuse@test.com", "bcc@test.com"),
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
@@ -336,7 +324,6 @@ class Spec11EmailUtilsTest {
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedMessages.get(1),
"abuse@test.com",
"new.registrar@example.com",
ImmutableList.of("abuse@test.com", "bcc@test.com"),
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
@@ -346,7 +333,6 @@ class Spec11EmailUtilsTest {
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedMessages.get(2),
"abuse@test.com",
"my-receiver@test.com",
ImmutableList.of(),
"Spec11 Emailing Failure 2018-07-15",
@@ -360,7 +346,6 @@ class Spec11EmailUtilsTest {
verify(gmailClient).sendEmail(contentCaptor.capture());
validateMessage(
contentCaptor.getValue(),
"abuse@test.com",
"my-receiver@test.com",
ImmutableList.of(),
"Spec11 Pipeline Alert: 2018-07",
@@ -409,7 +394,6 @@ class Spec11EmailUtilsTest {
private void validateMessage(
EmailMessage message,
String from,
String recipient,
ImmutableList<String> bccs,
String subject,
@@ -418,7 +402,6 @@ class Spec11EmailUtilsTest {
throws MessagingException {
EmailMessage.Builder expectedContentBuilder =
EmailMessage.newBuilder()
.setFrom(new InternetAddress(from))
.addRecipient(new InternetAddress(recipient))
.setSubject(subject)
.setBody(body);

View File

@@ -39,8 +39,6 @@ class SendEmailUtilsTest {
private void setRecipients(ImmutableList<String> recipients) throws Exception {
sendEmailUtils =
new SendEmailUtils(
new InternetAddress("outgoing@registry.example"),
"outgoing display name",
recipients,
gmailClient);
}
@@ -141,7 +139,6 @@ class SendEmailUtilsTest {
EmailMessage.newBuilder()
.setSubject("Welcome to the Internet")
.setBody("It is a dark and scary place.")
.setFrom(new InternetAddress("outgoing@registry.example"))
.addBcc(new InternetAddress("bar@example.com"))
.setRecipients(recipientBuilder.build())
.build();
@@ -186,7 +183,6 @@ class SendEmailUtilsTest {
EmailMessage.newBuilder()
.setSubject("Welcome to the Internet")
.setBody("It is a dark and scary place.")
.setFrom(new InternetAddress("outgoing@registry.example"))
.setRecipients(recipientBuilder.build())
.build();
assertThat(emailMessage).isEqualTo(expectedContent);

View File

@@ -47,7 +47,6 @@ import google.registry.ui.server.SendEmailUtils;
import google.registry.util.EmailMessage;
import google.registry.util.RegistryEnvironment;
import java.util.Optional;
import javax.mail.internet.InternetAddress;
import javax.servlet.http.HttpServletRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
@@ -94,8 +93,6 @@ public final class ConsoleOteSetupActionTest {
action.authResult = AuthResult.createUser(UserAuthInfo.create(user, false));
action.sendEmailUtils =
new SendEmailUtils(
new InternetAddress("outgoing@registry.example"),
"UnitTest Registry",
ImmutableList.of("notification@test.example", "notification2@test.example"),
gmailClient);
action.logoFilename = "logo.png";

View File

@@ -48,7 +48,6 @@ import google.registry.ui.server.SendEmailUtils;
import google.registry.util.EmailMessage;
import google.registry.util.RegistryEnvironment;
import java.util.Optional;
import javax.mail.internet.InternetAddress;
import javax.servlet.http.HttpServletRequest;
import org.joda.money.CurrencyUnit;
import org.junit.jupiter.api.BeforeEach;
@@ -95,8 +94,6 @@ final class ConsoleRegistrarCreatorActionTest {
action.authResult = AuthResult.createUser(UserAuthInfo.create(user, false));
action.sendEmailUtils =
new SendEmailUtils(
new InternetAddress("outgoing@registry.example"),
"UnitTest Registry",
ImmutableList.of("notification@test.example", "notification2@test.example"),
gmailClient);
action.logoFilename = "logo.png";

View File

@@ -16,8 +16,6 @@ package google.registry.ui.server.registrar;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.monitoring.metrics.contrib.LongMetricSubject.assertThat;
import static google.registry.config.RegistryConfig.getGSuiteOutgoingEmailAddress;
import static google.registry.config.RegistryConfig.getGSuiteOutgoingEmailDisplayName;
import static google.registry.request.auth.AuthenticatedRegistrarAccessor.Role.ADMIN;
import static google.registry.request.auth.AuthenticatedRegistrarAccessor.Role.OWNER;
import static google.registry.security.JsonHttpTestUtils.createJsonPayload;
@@ -106,8 +104,6 @@ public abstract class RegistrarSettingsActionTestCase {
new JsonActionRunner(ImmutableMap.of(), new JsonResponse(new ResponseImpl(rsp)));
action.sendEmailUtils =
new SendEmailUtils(
getGSuiteOutgoingEmailAddress(),
getGSuiteOutgoingEmailDisplayName(),
ImmutableList.of("notification@test.example", "notification2@test.example"),
gmailClient);
action.registrarConsoleMetrics = new RegistrarConsoleMetrics();

View File

@@ -91,8 +91,6 @@ final class RegistryLockPostActionTest {
private User userWithoutPermission;
private User userWithLockPermission;
private InternetAddress outgoingAddress;
private Domain domain;
private RegistryLockPostAction action;
@@ -109,8 +107,6 @@ final class RegistryLockPostActionTest {
createTld("tld");
domain = persistResource(DatabaseHelper.newDomain("example.tld"));
outgoingAddress = new InternetAddress("domain-registry@example.com");
when(mockRequest.getServerName()).thenReturn("registrarconsole.tld");
action =
@@ -502,7 +498,6 @@ final class RegistryLockPostActionTest {
EmailMessage sentMessage = emailCaptor.getValue();
assertThat(sentMessage.subject()).matches("Registry (un)?lock verification");
assertThat(sentMessage.body()).matches(EMAIL_MESSAGE_TEMPLATE);
assertThat(sentMessage.from()).isEqualTo(new InternetAddress("domain-registry@example.com"));
assertThat(sentMessage.recipients()).containsExactly(new InternetAddress(recipient));
}
@@ -524,12 +519,6 @@ final class RegistryLockPostActionTest {
"adminreg",
new CloudTasksHelper(clock).getTestCloudTasksUtils());
return new RegistryLockPostAction(
mockRequest,
jsonActionRunner,
authResult,
registrarAccessor,
gmailClient,
domainLockUtils,
outgoingAddress);
mockRequest, jsonActionRunner, authResult, registrarAccessor, gmailClient, domainLockUtils);
}
}

View File

@@ -22,7 +22,12 @@ import java.util.Collection;
import java.util.Optional;
import javax.mail.internet.InternetAddress;
/** Value class representing the content and metadata of an email. */
/**
* Value class representing the content and metadata of an email.
*
* <p>The sender address and display name are set by the email client and are not customizable by
* the user.
*/
@AutoValue
public abstract class EmailMessage {
@@ -30,13 +35,11 @@ public abstract class EmailMessage {
return new AutoValue_EmailMessage.Builder();
}
public static EmailMessage create(
String subject, String body, InternetAddress recipient, InternetAddress from) {
public static EmailMessage create(String subject, String body, InternetAddress recipient) {
return newBuilder()
.setSubject(subject)
.setBody(body)
.setRecipients(ImmutableList.of(recipient))
.setFrom(from)
.build();
}
@@ -46,9 +49,6 @@ public abstract class EmailMessage {
public abstract ImmutableSet<InternetAddress> recipients();
// TODO(b/279671974): remove `from` after migration.
public abstract InternetAddress from();
/** Optional return email address that overrides the default. */
public abstract Optional<InternetAddress> replyToEmailAddress();
@@ -70,8 +70,6 @@ public abstract class EmailMessage {
public abstract Builder setRecipients(Collection<InternetAddress> recipients);
public abstract Builder setFrom(InternetAddress from);
public abstract Builder setReplyToEmailAddress(InternetAddress replyToEmailAddress);
public abstract Builder setReplyToEmailAddress(Optional<InternetAddress> replyToEmailAddress);

View File

@@ -1,111 +0,0 @@
// Copyright 2017 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.util;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Iterables.toArray;
import com.google.common.base.Ascii;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.util.EmailMessage.Attachment;
import java.io.IOException;
import java.util.Properties;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
/**
* Wrapper around javax.mail's email creation and sending functionality. Encompasses a retry policy
* as well.
*/
@Singleton
public class SendEmailService {
private final Retrier retrier;
private final TransportEmailSender transportEmailSender;
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final ImmutableSet<String> ALLOWED_ENVS =
ImmutableSet.of("PRODUCTION", "UNITTEST");
@Inject
SendEmailService(Retrier retrier, TransportEmailSender transportEmailSender) {
this.retrier = retrier;
this.transportEmailSender = transportEmailSender;
}
/**
* Converts the provided message content into a {@link javax.mail.Message} and sends it with retry
* on transient failures.
*/
public void sendEmail(EmailMessage emailMessage) {
if (!ALLOWED_ENVS.contains(
Ascii.toUpperCase(System.getProperty("google.registry.environment", "UNITTEST")))) {
logger.atInfo().log(
"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())));
} else {
retrier.callWithRetry(
() -> {
Message msg =
new MimeMessage(
Session.getDefaultInstance(new Properties(), /* authenticator= */ null));
msg.setFrom(emailMessage.from());
msg.addRecipients(
RecipientType.TO, toArray(emailMessage.recipients(), InternetAddress.class));
msg.setSubject(emailMessage.subject());
Multipart multipart = new MimeMultipart();
BodyPart bodyPart = new MimeBodyPart();
bodyPart.setContent(
emailMessage.body(),
emailMessage.contentType().orElse(MediaType.PLAIN_TEXT_UTF_8).toString());
multipart.addBodyPart(bodyPart);
if (emailMessage.attachment().isPresent()) {
Attachment attachment = emailMessage.attachment().get();
BodyPart attachmentPart = new MimeBodyPart();
attachmentPart.setContent(attachment.content(), attachment.contentType().toString());
attachmentPart.setFileName(attachment.filename());
multipart.addBodyPart(attachmentPart);
}
msg.addRecipients(RecipientType.BCC, toArray(emailMessage.bccs(), Address.class));
msg.addRecipients(RecipientType.CC, toArray(emailMessage.ccs(), Address.class));
msg.setContent(multipart);
msg.saveChanges();
transportEmailSender.sendMessage(msg);
},
IOException.class,
MessagingException.class);
}
}
}

View File

@@ -1,34 +0,0 @@
// Copyright 2019 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.util;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Transport;
/** Wrapper for sending email so that we can test {@link google.registry.util.SendEmailService}. */
@Singleton
class TransportEmailSender {
@Inject
TransportEmailSender() {}
/** Sends a message using default App Engine transport. */
void sendMessage(Message msg) throws MessagingException {
Transport.send(msg);
}
}

View File

@@ -1,227 +0,0 @@
// Copyright 2019 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.util;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
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;
import google.registry.util.EmailMessage.Attachment;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMultipart;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.junit.jupiter.MockitoExtension;
/** Unit tests for {@link SendEmailService}. */
@ExtendWith(MockitoExtension.class)
class SendEmailServiceTest {
private final Retrier retrier = new Retrier(new FakeSleeper(new FakeClock()), 2);
private final TransportEmailSender wrapper = mock(TransportEmailSender.class);
private final SendEmailService sendEmailService = new SendEmailService(retrier, wrapper);
@Captor private ArgumentCaptor<Message> messageCaptor;
@Test
void testSuccess_simple() throws Exception {
EmailMessage content = createBuilder().build();
sendEmailService.sendEmail(content);
Message message = getMessage();
assertThat(message.getAllRecipients())
.asList()
.containsExactly(new InternetAddress("fake@example.com"));
assertThat(message.getFrom())
.asList()
.containsExactly(new InternetAddress("registry@example.com"));
assertThat(message.getRecipients(RecipientType.BCC)).isNull();
assertThat(message.getSubject()).isEqualTo("Subject");
assertThat(message.getContentType()).startsWith("multipart/mixed");
assertThat(getInternalContent(message).getContent().toString()).isEqualTo("body");
assertThat(getInternalContent(message).getContentType()).isEqualTo("text/plain; charset=utf-8");
assertThat(((MimeMultipart) message.getContent()).getCount()).isEqualTo(1);
}
@Test
void testSuccess_addBccs() throws Exception {
EmailMessage.Builder contentBuilder =
EmailMessage.newBuilder()
.setFrom(new InternetAddress("test@example.com"))
.setSubject("test subject")
.setBody("test body");
for (String email :
ImmutableList.of("bcc@example.com", "bcc1@example.com", "bcc2@example.com")) {
contentBuilder.addBcc(new InternetAddress(email));
}
sendEmailService.sendEmail(contentBuilder.build());
assertThat(getMessage().getRecipients(RecipientType.BCC))
.asList()
.containsExactly(
new InternetAddress("bcc@example.com"),
new InternetAddress("bcc1@example.com"),
new InternetAddress("bcc2@example.com"));
}
@Test
void testSuccess_setBccs() throws Exception {
EmailMessage content =
createBuilder()
.setBccs(
ImmutableList.of(
new InternetAddress("bcc@example.com"),
new InternetAddress("bcc2@example.com")))
.build();
sendEmailService.sendEmail(content);
assertThat(getMessage().getRecipients(RecipientType.BCC))
.asList()
.containsExactly(
new InternetAddress("bcc@example.com"), new InternetAddress("bcc2@example.com"));
}
@Test
void testSuccess_emptyBcc() throws Exception {
sendEmailService.sendEmail(createBuilder().setBccs(ImmutableList.of()).build());
assertThat(getMessage().getRecipients(RecipientType.BCC)).isNull();
}
@Test
void testSuccess_addCcs() throws Exception {
EmailMessage.Builder contentBuilder = EmailMessage.newBuilder();
contentBuilder
.setFrom(new InternetAddress("test@example.com"))
.setSubject("test subject")
.setBody("test body");
for (String email : ImmutableList.of("cc@example.com", "cc1@example.com", "cc2@example.com")) {
contentBuilder.addCc(new InternetAddress(email));
}
sendEmailService.sendEmail(contentBuilder.build());
assertThat(getMessage().getRecipients(RecipientType.CC))
.asList()
.containsExactly(
new InternetAddress("cc@example.com"),
new InternetAddress("cc1@example.com"),
new InternetAddress("cc2@example.com"));
}
@Test
void testSuccess_setCcs() throws Exception {
EmailMessage content =
createBuilder()
.setCcs(
ImmutableList.of(
new InternetAddress("cc@example.com"), new InternetAddress("cc2@example.com")))
.build();
sendEmailService.sendEmail(content);
assertThat(getMessage().getRecipients(RecipientType.CC))
.asList()
.containsExactly(
new InternetAddress("cc@example.com"), new InternetAddress("cc2@example.com"));
}
@Test
void testSuccess_emptyCC() throws Exception {
sendEmailService.sendEmail(createBuilder().setCcs(ImmutableList.of()).build());
assertThat(getMessage().getRecipients(RecipientType.CC)).isNull();
}
@Test
void testSuccess_contentType() throws Exception {
sendEmailService.sendEmail(createBuilder().setContentType(MediaType.HTML_UTF_8).build());
assertThat(getInternalContent(getMessage()).getContentType())
.isEqualTo("text/html; charset=utf-8");
}
@Test
void testSuccess_attachment() throws Exception {
EmailMessage content =
createBuilder()
.setAttachment(
Attachment.newBuilder()
.setFilename("filename")
.setContent("foo,bar\nbaz,qux")
.setContentType(MediaType.CSV_UTF_8)
.build())
.build();
sendEmailService.sendEmail(content);
Message message = getMessage();
assertThat(((MimeMultipart) message.getContent()).getCount()).isEqualTo(2);
BodyPart attachment = ((MimeMultipart) message.getContent()).getBodyPart(1);
assertThat(attachment.getContent()).isEqualTo("foo,bar\nbaz,qux");
assertThat(attachment.getContentType()).endsWith("name=filename");
}
@Test
void testSuccess_retry() throws Exception {
doThrow(new MessagingException("hi"))
.doNothing()
.when(wrapper)
.sendMessage(messageCaptor.capture());
sendEmailService.sendEmail(createBuilder().build());
assertThat(messageCaptor.getValue().getSubject()).isEqualTo("Subject");
}
@Test
void testFailure_wrongExceptionType() throws Exception {
doThrow(new RuntimeException("this is a runtime exception")).when(wrapper).sendMessage(any());
RuntimeException thrown =
assertThrows(
RuntimeException.class, () -> sendEmailService.sendEmail(createBuilder().build()));
assertThat(thrown).hasMessageThat().isEqualTo("this is a runtime exception");
}
@Test
void testFailure_tooManyTries() throws Exception {
doThrow(new MessagingException("hi"))
.doThrow(new MessagingException("second"))
.when(wrapper)
.sendMessage(any());
RuntimeException thrown =
assertThrows(
RuntimeException.class, () -> sendEmailService.sendEmail(createBuilder().build()));
assertThat(thrown).hasCauseThat().hasMessageThat().isEqualTo("second");
assertThat(thrown).hasCauseThat().isInstanceOf(MessagingException.class);
}
private EmailMessage.Builder createBuilder() throws Exception {
return EmailMessage.newBuilder()
.setFrom(new InternetAddress("registry@example.com"))
.addRecipient(new InternetAddress("fake@example.com"))
.setSubject("Subject")
.setBody("body");
}
private Message getMessage() throws MessagingException {
verify(wrapper).sendMessage(messageCaptor.capture());
return messageCaptor.getValue();
}
private BodyPart getInternalContent(Message message) throws Exception {
return ((MimeMultipart) message.getContent()).getBodyPart(0);
}
}