Skip to content

Commit

Permalink
Merge pull request #556 from isaacphysics/hotfix/allow-mailjet-batch-…
Browse files Browse the repository at this point in the history
…to-not-send-emails

Stop MailJet from erroring when there are no emails to send
  • Loading branch information
jsharkey13 authored Aug 22, 2023
2 parents 990e552 + 21eb833 commit 8ee8b32
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 13 deletions.
27 changes: 14 additions & 13 deletions src/main/java/uk/ac/cam/cl/dtg/segue/comm/MailGunEmailManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@
*/
package uk.ac.cam.cl.dtg.segue.comm;

import com.google.api.client.util.Lists;
import com.google.common.collect.ImmutableMap;
import com.mailgun.api.v3.MailgunMessagesApi;
import com.mailgun.api.v3.MailgunTemplatesApi;
import com.mailgun.client.MailgunClient;
import com.mailgun.model.message.Message;
import com.mailgun.model.message.MessageResponse;
import com.mailgun.model.templates.TemplateRequest;
import com.mailgun.model.templates.TemplateWithMessageResponse;
import feign.FeignException;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.common.inject.Inject;
Expand All @@ -36,28 +34,23 @@
import uk.ac.cam.cl.dtg.segue.api.Constants;
import uk.ac.cam.cl.dtg.segue.dao.SegueDatabaseException;
import uk.ac.cam.cl.dtg.util.AbstractConfigLoader;
import uk.ac.cam.cl.dtg.util.PropertiesLoader;

import javax.annotation.Nullable;

import static com.mailgun.util.Constants.EU_BASE_URL;
import static uk.ac.cam.cl.dtg.segue.api.Constants.MAILGUN_DOMAIN;
import static uk.ac.cam.cl.dtg.segue.api.Constants.MAILGUN_SECRET_KEY;
import static uk.ac.cam.cl.dtg.segue.api.Constants.SegueUserPreferences;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static uk.ac.cam.cl.dtg.isaac.api.Constants.*;
import static com.mailgun.util.Constants.EU_BASE_URL;
import static uk.ac.cam.cl.dtg.segue.api.Constants.*;
import static uk.ac.cam.cl.dtg.segue.api.monitors.SegueMetrics.QUEUED_EMAIL;

public class MailGunEmailManager {
Expand Down Expand Up @@ -163,10 +156,18 @@ public Future<Optional<MessageResponse>> sendBatchEmails(final Collection<Regist
String replyTo = replyToName + " <" + replyToAddress + "> ";
String from = fromName + " <" + fromAddress + "> ";

List<String> usersToSendTo = Lists.newArrayList(recipientVariables.keySet());
if (usersToSendTo.isEmpty()) {
if (!userDTOs.isEmpty()) {
log.warn(String.format("No eligible recipients from batch of %s %s emails.", userDTOs.size(), emailType.name()));
}
return CompletableFuture.completedFuture(Optional.empty());
}

Message message = Message.builder()
.from(from)
.replyTo(replyTo)
.to(new ArrayList<>(recipientVariables.keySet()))
.to(usersToSendTo)
.template(emailContentTemplate.getId()) // We use the same template IDs in MailGun!
.subject(emailContentTemplate.getSubject())
.mailgunVariables(templateVariables)
Expand Down
110 changes: 110 additions & 0 deletions src/test/java/uk/ac/cam/cl/dtg/segue/comm/MailGunEmailManagerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/**
* Copyright 2015 Alistair Stead
*
* 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 uk.ac.cam.cl.dtg.segue.comm;

import com.google.api.client.util.Lists;
import com.google.api.client.util.Maps;
import com.mailgun.model.message.MessageResponse;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import uk.ac.cam.cl.dtg.isaac.dos.AbstractUserPreferenceManager;
import uk.ac.cam.cl.dtg.isaac.dos.PgUserPreferenceManager;
import uk.ac.cam.cl.dtg.isaac.dto.content.EmailTemplateDTO;
import uk.ac.cam.cl.dtg.isaac.dto.users.RegisteredUserDTO;
import uk.ac.cam.cl.dtg.segue.dao.ILogManager;
import uk.ac.cam.cl.dtg.segue.dao.content.GitContentManager;
import uk.ac.cam.cl.dtg.util.AbstractConfigLoader;

import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.Future;

/**
* Test class for the EmailManager class.
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest(GitContentManager.class)
@PowerMockIgnore("javax.management.*")
public class MailGunEmailManagerTest {
private AbstractConfigLoader mockPropertiesLoader;
private AbstractUserPreferenceManager userPreferenceManager;
private ILogManager logManager;

/**
* Initial configuration of tests.
*
* @throws Exception
* - test exception
*/
@Before
public final void setUp() throws Exception {
// Create dummy email preferences
userPreferenceManager = EasyMock.createMock(PgUserPreferenceManager.class);

mockPropertiesLoader = EasyMock.createMock(AbstractConfigLoader.class);
EasyMock.expect(mockPropertiesLoader.getProperty("MAILGUN_SECRET_KEY")).andReturn("testKey").anyTimes();
EasyMock.expect(mockPropertiesLoader.getProperty("MAILGUN_FROM_ADDRESS")).andReturn("no-reply@isaacphysics.org").anyTimes();
EasyMock.expect(mockPropertiesLoader.getProperty("REPLY_TO_ADDRESS")).andReturn("test-reply@test.com").anyTimes();
EasyMock.expect(mockPropertiesLoader.getProperty("MAIL_NAME")).andReturn("Isaac Physics").anyTimes();
EasyMock.replay(mockPropertiesLoader);

// Create log manager
logManager = EasyMock.createMock(ILogManager.class);
logManager.logInternalEvent(null, null, null);
EasyMock.expectLastCall().anyTimes();
}

/**
* @param template
* - id of the template
* @return - SegueDTO object
*/
public EmailTemplateDTO createDummyEmailTemplate(final String template) {

EmailTemplateDTO emailTemplateDTO = new EmailTemplateDTO();
emailTemplateDTO.setSubject("title");
emailTemplateDTO.setHtmlContent(template);
emailTemplateDTO.setPlainTextContent(template);
emailTemplateDTO.setAuthor("ags46");
emailTemplateDTO.setId("email-template-registration-confirmation");
emailTemplateDTO.setPublished(true);

return emailTemplateDTO;
}

@Test
public final void sendBatchEmails_toNoUsers_shouldNotThrowAnException() {
MailGunEmailManager mailGunEmailManager = new MailGunEmailManager(Maps.newHashMap(), mockPropertiesLoader, userPreferenceManager);
Collection<RegisteredUserDTO> emptyListOfUsers = Lists.newArrayList();
Future<Optional<MessageResponse>> response = mailGunEmailManager.sendBatchEmails(
emptyListOfUsers, createDummyEmailTemplate("test"), EmailType.ASSIGNMENTS, null, null);
assert (response.isDone());
try {
// The response should be empty as there were no users to send the email to.
// TODO a truer test would mock the MailgunClient and check that the send method was never called,
// but this would require altering the MailGunEmailManager class to allow the client to be injected.
assert (response.get().isEmpty());
} catch (Exception e) {
assert (false);
}
}
}

0 comments on commit 8ee8b32

Please sign in to comment.