Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to specify CC and BCC recipients in mail configuration #305

Merged
merged 1 commit into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ Example of a notification in Telegram
"password": "",
"securityProtocol": null,
"from": "",
"recipient": "",
"to": "",
"cc": "",
"bcc": "",
"templatePath": "/templates/html.ftl"
},
"discord": {
Expand Down Expand Up @@ -140,7 +142,9 @@ Example:
"password": "password",
"securityProtocol": "SSL",
"from": "test@gmail.com",
"recipient": "test1@gmail.com",
"to": "test1@gmail.com",
"cc": "testCC1@gmail.com, testCC2@gmail.com",
"bcc": "testBCC1@gmail.com, testBCC2@gmail.com",
"templatePath": "/templates/html_custom.ftl"
}
}
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ Languages: 🇬🇧 🇫🇷 🇷🇺 🇺🇦 🇧🇾 🇨🇳
"password": "",
"securityProtocol": null,
"from": "",
"recipient": "",
"to": "",
"cc": "",
"bcc": "",
"templatePath": "/templates/html.ftl"
},
"discord": {
Expand Down Expand Up @@ -158,7 +160,9 @@ Languages: 🇬🇧 🇫🇷 🇷🇺 🇺🇦 🇧🇾 🇨🇳
"password": "password",
"securityProtocol": "SSL",
"from": "test@gmail.com",
"recipient": "test1@gmail.com",
"to": "test1@gmail.com",
"cc": "testCC1@gmail.com, testCC2@gmail.com",
"bcc": "testBCC1@gmail.com, testBCC2@gmail.com",
"templatePath": "/templates/html_custom.ftl"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

import guru.qa.allure.notifications.clients.Notifier;
import guru.qa.allure.notifications.config.mail.Mail;
import guru.qa.allure.notifications.exceptions.MessageBuildException;
import guru.qa.allure.notifications.exceptions.MessagingException;
import guru.qa.allure.notifications.template.MessageTemplate;
import guru.qa.allure.notifications.template.data.MessageData;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Email implements Notifier {
private final Mail mail;
private final Letter letter;
Expand All @@ -17,9 +20,7 @@ public Email(Mail mail) {

@Override
public void sendText(MessageData messageData) throws MessagingException {
letter.from(mail.getFrom())
.to(mail.getRecipient())
.subject(messageData.getProject())
getBaseLetter(messageData)
.text(new MessageTemplate(messageData).createMessageFromTemplate(mail.getTemplatePath()))
.send();
}
Expand All @@ -28,11 +29,31 @@ public void sendText(MessageData messageData) throws MessagingException {
public void sendPhoto(MessageData messageData, byte[] chartImage) throws MessagingException {
String message = "<img src='cid:image'/><br/>" + new MessageTemplate(messageData).createMessageFromTemplate(
mail.getTemplatePath());
letter.from(mail.getFrom())
.to(mail.getRecipient())
.subject(messageData.getProject())
getBaseLetter(messageData)
.text(message)
.image(chartImage)
.send();
}

private Letter getBaseLetter(MessageData messageData) throws MessageBuildException {
return letter.from(mail.getFrom())
.to(getTo())
.cc(mail.getCc())
.bcc(mail.getBcc())
.subject(messageData.getProject());
}

private String getTo() {
String mailTo = mail.getRecipient();
if (null != mailTo) {
log.warn("Deprecated \"recipient\" field found in configuration file, use \"to\" field instead.");
if (null != mail.getTo()) {
throw new IllegalArgumentException("Ambiguous configuration fields \"recipient\" and \"to\" found, "
+ "use only \"to\" field instead.");
}
} else {
mailTo = mail.getTo();
}
return mailTo;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package guru.qa.allure.notifications.clients.mail;

import static jakarta.mail.Message.RecipientType;

import guru.qa.allure.notifications.config.mail.Mail;
import guru.qa.allure.notifications.exceptions.MessageBuildException;
import guru.qa.allure.notifications.exceptions.MessageSendException;
Expand Down Expand Up @@ -35,7 +37,7 @@ public Letter to(final String to) throws MessageBuildException {
log.info("Setting recipients...");
try {
letter.setRecipients(
Message.RecipientType.TO,
RecipientType.TO,
MailUtil.recipients(to)
);
} catch (MessagingException e) {
Expand All @@ -45,6 +47,30 @@ public Letter to(final String to) throws MessageBuildException {
return this;
}

public Letter cc(final String cc) throws MessageBuildException {
return setRecipientsWithTypeIfPresentedInConfig(RecipientType.CC, cc);
}

public Letter bcc(final String bcc) throws MessageBuildException {
return setRecipientsWithTypeIfPresentedInConfig(RecipientType.BCC, bcc);
}

private Letter setRecipientsWithTypeIfPresentedInConfig(RecipientType type, String recipients)
throws MessageBuildException {
try {
if (null != recipients) {
letter.setRecipients(
type,
MailUtil.recipients(recipients)
);
}
} catch (MessagingException e) {
throw new MessageBuildException(String.format("Unable to set recipients %s with type %s!",
recipients, type), e);
}
return this;
}

public Letter subject(final String subject) throws MessageBuildException {
log.info("Setting subject...");
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ public class Mail {
private SecurityProtocol securityProtocol;
@SerializedName("from")
private String from;
@SerializedName("to")
private String to;
@SerializedName("cc")
private String cc;
@SerializedName("bcc")
private String bcc;
@SerializedName("recipient")
private String recipient;
@SerializedName("templatePath")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package guru.qa.allure.notifications.clients.mail;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mockConstruction;
import static org.mockito.Mockito.verify;

import java.util.function.Consumer;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockedConstruction;
import org.mockito.junit.jupiter.MockitoExtension;

import guru.qa.allure.notifications.config.base.Base;
import guru.qa.allure.notifications.config.mail.Mail;
import guru.qa.allure.notifications.exceptions.MessagingException;
import guru.qa.allure.notifications.template.data.MessageData;

@ExtendWith(MockitoExtension.class)
class EmailTests {
private static final String FROM = "testFROM@gmail.com";
private static final String TO = "testTO@gmail.com";
private static final String CC = "testCC@gmail.com, testCC2@gmail.com";
private static final String BCC = "testBCC@gmail.com";
private static final String PROJECT = "LETTER PROJECT";
private static final String EMPTY_TEMPLATE_PATH = "/guru/qa/allure/notifications/template/emptyTemplate.ftl";
private static final String TEXT_FROM_TEMPLATE = "for test purposes";
private static final byte[] IMG = new byte[1];

private static final Base BASE = new Base();

@Mock private Letter letter;
@Mock private MessageData messageData;

@BeforeEach
void beforeEach()
{
BASE.setProject(PROJECT);
lenient().when(messageData.getProject()).thenReturn(PROJECT);
}

private void mockLetter(Consumer<Letter> letterConsumer) {
try (MockedConstruction<Letter> letterMock = mockConstruction(Letter.class,
(mock, context) -> {
lenient().when(mock.from(FROM)).thenReturn(letter);
lenient().when(letter.to(TO)).thenReturn(letter);
lenient().when(letter.cc(CC)).thenReturn(letter);
lenient().when(letter.bcc(BCC)).thenReturn(letter);
lenient().when(letter.subject(PROJECT)).thenReturn(letter);
lenient().when(letter.text(anyString())).thenReturn(letter);
lenient().when(letter.image(IMG)).thenReturn(letter);
})) {
letterConsumer.accept(letter);
}
}

@Test
void shouldSendText() {
Mail mail = createMailWithoutRecipient();
mail.setTo(TO);

mockLetter(l -> {
Email email = new Email(mail);
try {
email.sendText(messageData);
verify(l).to(TO);
verify(l).cc(CC);
verify(l).bcc(BCC);
verify(l).subject(PROJECT);
verify(l).text(TEXT_FROM_TEMPLATE);
verify(l).send();
} catch (MessagingException e) {
throw new RuntimeException(e);
}
});
}

@Test
void shouldSendTextWithDeprecatedRecipientField() {
Mail mail = createMailWithoutRecipient();
mail.setRecipient(TO);

mockLetter(l -> {
Email email = new Email(mail);
try {
email.sendText(messageData);
verify(l).to(TO);
} catch (MessagingException e) {
throw new RuntimeException(e);
}
});
}

@Test
void shouldThrowExceptionIfAmbiguousRecipientFieldsUsing() {
Mail mail = createMailWithoutRecipient();
mail.setRecipient(TO);
mail.setTo(TO);

mockLetter(l -> {
Email email = new Email(mail);
Exception exception = assertThrows(IllegalArgumentException.class, () -> email.sendText(messageData));
assertEquals("Ambiguous configuration fields \"recipient\" and \"to\" found, "
+ "use only \"to\" field instead.", exception.getMessage());
});
}

@Test
void shouldSendTextWithChart() {
Mail mail = createMailWithoutRecipient();
mail.setTo(TO);

mockLetter(l -> {
Email email = new Email(mail);
try {
email.sendPhoto(messageData, IMG);
verify(l).to(TO);
verify(l).cc(CC);
verify(l).bcc(BCC);
verify(l).subject(PROJECT);
verify(l).text("<img src='cid:image'/><br/>" + TEXT_FROM_TEMPLATE);
verify(l).image(IMG);
verify(l).send();
} catch (MessagingException e) {
throw new RuntimeException(e);
}
});
}

private Mail createMailWithoutRecipient() {
Mail mail = new Mail();
mail.setTemplatePath(EMPTY_TEMPLATE_PATH);
mail.setFrom(FROM);
mail.setCc(CC);
mail.setBcc(BCC);
return mail;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package guru.qa.allure.notifications.clients.mail;

import static org.mockito.Mockito.mockConstruction;
import static org.mockito.Mockito.verify;
import static jakarta.mail.Message.RecipientType;
import static org.mockito.Mockito.verifyNoInteractions;

import java.util.function.Consumer;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedConstruction;
import org.mockito.junit.jupiter.MockitoExtension;

import guru.qa.allure.notifications.config.mail.Mail;
import guru.qa.allure.notifications.exceptions.MessageBuildException;
import guru.qa.allure.notifications.util.MailUtil;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;

@ExtendWith(MockitoExtension.class)
class LetterTests {
private static final String CC = "testCC1@gmail.com, testCC2@gmail.com";
private static final String BCC = "testBCC@gmail.com";

private final Mail mail = new Mail();
private Letter letter;

@BeforeEach
void beforeEach()
{
mail.setFrom("from");
mail.setHost("host");
mail.setPort("port");
}

private void mockMessage(Consumer<Message> messageConsumer) {
try (MockedConstruction<MimeMessage> messageMock = mockConstruction(MimeMessage.class)) {
letter = new Letter(mail);
Message message = messageMock.constructed().get(0);
messageConsumer.accept(message);
}
}

@Test
void shouldSetCcBccIfPresent() {
mockMessage(m -> {
try {
letter.cc(CC);
letter.bcc(BCC);
verify(m).setRecipients(RecipientType.CC, MailUtil.recipients(CC));
verify(m).setRecipients(RecipientType.BCC, MailUtil.recipients(BCC));
} catch (MessagingException | MessageBuildException e) {
throw new RuntimeException(e);
}
});
}

@Test
void shouldNotSetCcBccIfNotPresent() {
mockMessage(m -> {
try {
letter.bcc(null);
letter.cc(null);
} catch (MessageBuildException e) {
throw new RuntimeException(e);
}
verifyNoInteractions(m);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
for test purposes