diff --git a/connectors-e2e-test/connectors-e2e-test-mail/pom.xml b/connectors-e2e-test/connectors-e2e-test-mail/pom.xml deleted file mode 100644 index d0c674d137..0000000000 --- a/connectors-e2e-test/connectors-e2e-test-mail/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - 4.0.0 - - - io.camunda.connector - connectors-e2e-test-parent - ../pom.xml - 8.8.0-SNAPSHOT - - - Tests - connectors-e2e-test-mail - jar - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - - - - - io.camunda.connector - connector-email - ${project.version} - - - - com.icegreen - greenmail - 2.1.3 - test - - - - org.testcontainers - testcontainers - - - - io.camunda.connector - connectors-e2e-test-base - ${project.version} - test - - - - \ No newline at end of file diff --git a/connectors-e2e-test/connectors-e2e-test-mail/src/test/java/io/camunda/connector/e2e/InboundEmailTest.java b/connectors-e2e-test/connectors-e2e-test-mail/src/test/java/io/camunda/connector/e2e/InboundEmailTest.java deleted file mode 100644 index 5ae580b9fd..0000000000 --- a/connectors-e2e-test/connectors-e2e-test-mail/src/test/java/io/camunda/connector/e2e/InboundEmailTest.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH - * under one or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information regarding copyright - * ownership. Camunda licenses this file to you under the Apache License, - * Version 2.0; 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 io.camunda.connector.e2e; - -import static io.camunda.connector.e2e.BpmnFile.replace; -import static io.camunda.process.test.api.CamundaAssert.assertThat; -import static org.awaitility.Awaitility.await; -import static org.mockito.Mockito.when; - -import io.camunda.client.CamundaClient; -import io.camunda.client.api.search.response.ProcessDefinition; -import io.camunda.connector.e2e.app.TestConnectorRuntimeApplication; -import io.camunda.connector.runtime.inbound.search.SearchQueryClient; -import io.camunda.connector.runtime.inbound.state.ProcessImportResult; -import io.camunda.connector.runtime.inbound.state.ProcessStateStore; -import io.camunda.process.test.api.CamundaAssert; -import io.camunda.process.test.api.CamundaSpringProcessTest; -import io.camunda.zeebe.model.bpmn.BpmnModelInstance; -import io.camunda.zeebe.model.bpmn.instance.Process; -import jakarta.mail.Flags; -import jakarta.mail.MessagingException; -import java.time.Duration; -import java.util.Arrays; -import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import org.awaitility.core.ConditionTimeoutException; -import org.junit.jupiter.api.Assertions; -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.junit.jupiter.MockitoExtension; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest( - classes = {TestConnectorRuntimeApplication.class}, - properties = { - "spring.main.allow-bean-definition-overriding=true", - }, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@CamundaSpringProcessTest -@ExtendWith(MockitoExtension.class) -public class InboundEmailTest extends BaseEmailTest { - - private static final ScheduledExecutorService scheduler = - Executors.newSingleThreadScheduledExecutor(); - private static final AtomicInteger counter = new AtomicInteger(1); - @Autowired ProcessStateStore processStateStore; - @Autowired SearchQueryClient searchQueryClient; - @Mock private ProcessDefinition processDef; - @Autowired private CamundaClient camundaClient; - - @BeforeEach - public void beforeEach() { - super.reset(); - CamundaAssert.setAssertionTimeout(Duration.ofSeconds(20)); - } - - @Test - public void shouldReceiveEmailAndSetAsSeen() throws MessagingException { - var model = - replace( - "email-inbound-connector-intermediate_unseen_read.bpmn", - BpmnFile.Replace.replace("55555", super.getUnsecureImapPort())); - - mockProcessDefinition(model); - - scheduler.schedule( - () -> super.sendEmail("test@camunda.com", "test", "hey"), 2, TimeUnit.SECONDS); - - var bpmnTest = ZeebeTest.with(camundaClient).deploy(model).createInstance(); - - await().atMost(3, TimeUnit.SECONDS).until(() -> getLastReceivedEmails().length == 1); - - processStateStore.update( - new ProcessImportResult( - Map.of( - new ProcessImportResult.ProcessDefinitionIdentifier( - processDef.getProcessDefinitionId(), processDef.getTenantId()), - new ProcessImportResult.ProcessDefinitionVersion( - processDef.getProcessDefinitionKey(), processDef.getVersion())))); - - bpmnTest = bpmnTest.waitForProcessCompletion(); - - Assertions.assertTrue( - Arrays.stream(super.getLastReceivedEmails()) - .findFirst() - .get() - .getFlags() - .contains(Flags.Flag.SEEN)); - assertThat(bpmnTest.getProcessInstanceEvent()).hasVariable("subject", "test"); - assertThat(bpmnTest.getProcessInstanceEvent()).hasVariable("plainTextBody", "hey"); - } - - @Test - public void shouldThrowWhenAllMessageAreSeen() throws MessagingException { - var model = - replace( - "email-inbound-connector-intermediate_unseen_read.bpmn", - BpmnFile.Replace.replace("55555", super.getUnsecureImapPort())); - - mockProcessDefinition(model); - - scheduler.schedule( - () -> { - super.sendEmail("test@camunda.com", "test", "hey"); - try { - Arrays.stream(getLastReceivedEmails()).findFirst().get().setFlag(Flags.Flag.SEEN, true); - } catch (MessagingException e) { - throw new RuntimeException(e); - } - }, - 2, - TimeUnit.SECONDS); - - var bpmnTest = ZeebeTest.with(camundaClient).deploy(model).createInstance(); - - await().atMost(3, TimeUnit.SECONDS).until(() -> getLastReceivedEmails().length == 1); - - processStateStore.update( - new ProcessImportResult( - Map.of( - new ProcessImportResult.ProcessDefinitionIdentifier( - processDef.getProcessDefinitionId(), processDef.getTenantId()), - new ProcessImportResult.ProcessDefinitionVersion( - processDef.getProcessDefinitionKey(), processDef.getVersion())))); - - Assertions.assertThrows(ConditionTimeoutException.class, bpmnTest::waitForProcessCompletion); - } - - @Test - public void shouldReceiveEmailAndDelete() throws MessagingException { - var model = - replace( - "email-inbound-connector-intermediate_unseen_delete.bpmn", - BpmnFile.Replace.replace("55555", super.getUnsecureImapPort())); - - mockProcessDefinition(model); - - scheduler.schedule( - () -> super.sendEmail("test@camunda.com", "test", "hey"), 2, TimeUnit.SECONDS); - - var bpmnTest = ZeebeTest.with(camundaClient).deploy(model).createInstance(); - - await().atMost(3, TimeUnit.SECONDS).until(() -> getLastReceivedEmails().length == 1); - - processStateStore.update( - new ProcessImportResult( - Map.of( - new ProcessImportResult.ProcessDefinitionIdentifier( - processDef.getProcessDefinitionId(), processDef.getTenantId()), - new ProcessImportResult.ProcessDefinitionVersion( - processDef.getProcessDefinitionKey(), processDef.getVersion())))); - - bpmnTest = bpmnTest.waitForProcessCompletion(); - - Assertions.assertTrue( - Arrays.stream(super.getLastReceivedEmails()) - .findFirst() - .get() - .getFlags() - .contains(Flags.Flag.DELETED)); - assertThat(bpmnTest.getProcessInstanceEvent()).hasVariable("subject", "test"); - assertThat(bpmnTest.getProcessInstanceEvent()).hasVariable("plainTextBody", "hey"); - } - - @Test - public void shouldReceiveEmailAndMove() throws MessagingException { - var model = - replace( - "email-inbound-connector-intermediate_unseen_move.bpmn", - BpmnFile.Replace.replace("55555", super.getUnsecureImapPort())); - - mockProcessDefinition(model); - - scheduler.schedule( - () -> super.sendEmail("test@camunda.com", "test", "hey"), 2, TimeUnit.SECONDS); - - var bpmnTest = ZeebeTest.with(camundaClient).deploy(model).createInstance(); - - await().atMost(3, TimeUnit.SECONDS).until(() -> getLastReceivedEmails().length == 1); - - processStateStore.update( - new ProcessImportResult( - Map.of( - new ProcessImportResult.ProcessDefinitionIdentifier( - processDef.getProcessDefinitionId(), processDef.getTenantId()), - new ProcessImportResult.ProcessDefinitionVersion( - processDef.getProcessDefinitionKey(), processDef.getVersion())))); - - bpmnTest = bpmnTest.waitForProcessCompletion(); - - Assertions.assertEquals(2, getLastReceivedEmails().length); - Assertions.assertTrue( - Arrays.stream(getLastReceivedEmails()) - .findFirst() - .get() - .getFlags() - .contains(Flags.Flag.DELETED)); - assertThat(bpmnTest.getProcessInstanceEvent()).hasVariable("subject", "test"); - assertThat(bpmnTest.getProcessInstanceEvent()).hasVariable("plainTextBody", "hey"); - } - - private void mockProcessDefinition(BpmnModelInstance model) { - when(searchQueryClient.getProcessModel(1L)).thenReturn(model); - when(processDef.getProcessDefinitionKey()).thenReturn(1L); - when(processDef.getTenantId()) - .thenReturn(camundaClient.getConfiguration().getDefaultTenantId()); - when(processDef.getProcessDefinitionId()) - .thenReturn(model.getModelElementsByType(Process.class).stream().findFirst().get().getId()); - when(processDef.getVersion()).thenReturn(counter.getAndIncrement()); - } - - @Test - public void shouldPollEmailAndMove() throws MessagingException { - var model = - replace( - "email-inbound-connector-intermediate_all_delete.bpmn", - BpmnFile.Replace.replace("55555", super.getUnsecureImapPort())); - - mockProcessDefinition(model); - - scheduler.schedule( - () -> { - super.sendEmail("test@camunda.com", "test", "hey"); - try { - Arrays.stream(super.getLastReceivedEmails()) - .findFirst() - .get() - .setFlag(Flags.Flag.SEEN, true); - } catch (MessagingException e) { - throw new RuntimeException(e); - } - }, - 2, - TimeUnit.SECONDS); - - var bpmnTest = ZeebeTest.with(camundaClient).deploy(model).createInstance(); - - await().atMost(3, TimeUnit.SECONDS).until(() -> getLastReceivedEmails().length == 1); - - processStateStore.update( - new ProcessImportResult( - Map.of( - new ProcessImportResult.ProcessDefinitionIdentifier( - processDef.getProcessDefinitionId(), processDef.getTenantId()), - new ProcessImportResult.ProcessDefinitionVersion( - processDef.getProcessDefinitionKey(), processDef.getVersion())))); - - bpmnTest = bpmnTest.waitForProcessCompletion(); - - Assertions.assertTrue( - Arrays.stream(super.getLastReceivedEmails()) - .findFirst() - .get() - .getFlags() - .contains(Flags.Flag.DELETED)); - assertThat(bpmnTest.getProcessInstanceEvent()).hasVariable("subject", "test"); - assertThat(bpmnTest.getProcessInstanceEvent()).hasVariable("plainTextBody", "hey"); - } -} diff --git a/connectors-e2e-test/connectors-e2e-test-mail/src/test/java/io/camunda/connector/e2e/OutboundEmailTests.java b/connectors-e2e-test/connectors-e2e-test-mail/src/test/java/io/camunda/connector/e2e/OutboundEmailTests.java deleted file mode 100644 index b2d3ac2c4e..0000000000 --- a/connectors-e2e-test/connectors-e2e-test-mail/src/test/java/io/camunda/connector/e2e/OutboundEmailTests.java +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH - * under one or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information regarding copyright - * ownership. Camunda licenses this file to you under the Apache License, - * Version 2.0; 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 io.camunda.connector.e2e; - -import static io.camunda.connector.e2e.BpmnFile.replace; -import static io.camunda.process.test.api.CamundaAssert.assertThat; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import io.camunda.client.CamundaClient; -import io.camunda.connector.e2e.app.TestConnectorRuntimeApplication; -import io.camunda.process.test.api.CamundaAssert; -import io.camunda.process.test.api.CamundaSpringProcessTest; -import io.camunda.zeebe.model.bpmn.Bpmn; -import io.camunda.zeebe.model.bpmn.BpmnModelInstance; -import jakarta.mail.Message; -import java.io.File; -import java.time.Duration; -import java.util.List; -import java.util.concurrent.*; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest( - classes = {TestConnectorRuntimeApplication.class}, - properties = { - "spring.main.allow-bean-definition-overriding=true", - "camunda.connector.polling.enabled=false", - }, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@CamundaSpringProcessTest -@ExtendWith(MockitoExtension.class) -public class OutboundEmailTests extends BaseEmailTest { - - private static final ScheduledExecutorService scheduler = - Executors.newSingleThreadScheduledExecutor(); - - private static final String ELEMENT_TEMPLATE_PATH = - "../../connectors/email/element-templates/email-outbound-connector.json"; - private static final String RESULT_EXPRESSION_SEND_EMAIL = "={sent: sent}"; - private static final String RESULT_EXPRESSION_LIST_EMAIL = - "={subject1: response[1].subject, subject2 : response[2].subject }"; - private static final String RESULT_EXPRESSION_DELETE_EMAIL = - "={deleted : deleted, messageId : messageId }"; - private static final String RESULT_EXPRESSION_READ_EMAIL = - "={fromAddress : fromAddress, messageId : messageId, subject: subject, size: size, plainTextBody : plainTextBody }"; - private static final String RESULT_EXPRESSION_MOVE_EMAIL = - "={messageId : messageId, from: from, to: to }"; - @Autowired private CamundaClient camundaClient; - - private static BpmnModelInstance getBpmnModelInstance(final String serviceTaskName) { - return Bpmn.createProcess() - .executable() - .startEvent() - .serviceTask(serviceTaskName) - .endEvent() - .done(); - } - - @BeforeEach - public void beforeEach() { - super.reset(); - CamundaAssert.setAssertionTimeout(Duration.ofSeconds(10)); - } - - @Test - public void shouldSendSMTPTextEmail() { - File elementTemplate = - ElementTemplate.from(ELEMENT_TEMPLATE_PATH) - .property("authentication.type", "simple") - .property("authentication.simpleAuthenticationUsername", "test@camunda.com") - .property("authentication.simpleAuthenticationPassword", "password") - .property("protocol", "smtp") - .property("data.smtpPort", getUnsecureSmtpPort()) - .property("data.smtpHost", LOCALHOST) - .property("smtpCryptographicProtocol", "NONE") - .property("data.smtpActionDiscriminator", "sendEmailSmtp") - .property("smtpFrom", "test@camunda.com") - .property("smtpTo", "receiver@test.com") - .property("smtpSubject", "subject") - .property("contentType", "PLAIN") - .property("smtpBody", "content") - .property("resultExpression", RESULT_EXPRESSION_SEND_EMAIL) - .writeTo(new File(tempDir, "template.json")); - - BpmnModelInstance model = getBpmnModelInstance("sendEmailTask"); - BpmnModelInstance updatedModel = getBpmnModelInstance(model, elementTemplate, "sendEmailTask"); - var result = getZeebeTest(updatedModel); - - assertThat(result).isNotNull(); - assertThat(result.getProcessInstanceEvent()).hasVariable("sent", true); - - assertTrue(super.waitForNewEmails(5000, 1)); - List message = List.of(super.getLastReceivedEmails()); - assertThat(message).isNotNull(); - assertThat(getSenders(message.getFirst())).hasSize(1).first().isEqualTo("test@camunda.com"); - assertThat(getReceivers(message.getFirst())).hasSize(1).first().isEqualTo("receiver@test.com"); - assertThat(getSubject(message.getFirst())).isEqualTo("subject"); - assertThat(getPlainTextBody(message.getFirst())).isEqualTo("content"); - } - - @Test - public void shouldSendSMTPHtmlEmail() { - File elementTemplate = - ElementTemplate.from(ELEMENT_TEMPLATE_PATH) - .property("authentication.type", "simple") - .property("authentication.simpleAuthenticationUsername", "test@camunda.com") - .property("authentication.simpleAuthenticationPassword", "password") - .property("protocol", "smtp") - .property("data.smtpPort", getUnsecureSmtpPort()) - .property("data.smtpHost", LOCALHOST) - .property("smtpCryptographicProtocol", "NONE") - .property("data.smtpActionDiscriminator", "sendEmailSmtp") - .property("smtpFrom", "test@camunda.com") - .property("smtpTo", "receiver@test.com") - .property("smtpSubject", "subject") - .property("contentType", "HTML") - .property("smtpHtmlBody", "

content

") - .property("resultExpression", RESULT_EXPRESSION_SEND_EMAIL) - .writeTo(new File(tempDir, "template.json")); - - BpmnModelInstance model = getBpmnModelInstance("sendEmailTask"); - BpmnModelInstance updatedModel = getBpmnModelInstance(model, elementTemplate, "sendEmailTask"); - var result = getZeebeTest(updatedModel); - - assertThat(result).isNotNull(); - assertThat(result.getProcessInstanceEvent()).hasVariable("sent", true); - - assertTrue(super.waitForNewEmails(5000, 1)); - List message = List.of(super.getLastReceivedEmails()); - assertThat(message).isNotNull(); - assertThat(getSenders(message.getFirst())).hasSize(1).first().isEqualTo("test@camunda.com"); - assertThat(getReceivers(message.getFirst())).hasSize(1).first().isEqualTo("receiver@test.com"); - assertThat(getSubject(message.getFirst())).isEqualTo("subject"); - assertThat(getHtmlBody(message.getFirst())).isEqualTo("

content

"); - } - - @Test - public void shouldListPop3Email() { - - File elementTemplate = - ElementTemplate.from(ELEMENT_TEMPLATE_PATH) - .property("authentication.type", "simple") - .property("authentication.simpleAuthenticationUsername", "test@camunda.com") - .property("authentication.simpleAuthenticationPassword", "password") - .property("protocol", "pop3") - .property("data.pop3Port", getUnsecurePop3Port()) - .property("data.pop3Host", LOCALHOST) - .property("pop3CryptographicProtocol", "NONE") - .property("data.pop3ActionDiscriminator", "listEmailsPop3") - .property("pop3maxToBeRead", "100") - .property("pop3SortField", "SENT_DATE") - .property("pop3SortOrder", "DESC") - .property("resultExpression", RESULT_EXPRESSION_LIST_EMAIL) - .writeTo(new File(tempDir, "template.json")); - - scheduler.schedule( - () -> super.sendEmail("receiver@test.com", "subject1", "content1"), 1, SECONDS); - scheduler.schedule( - () -> super.sendEmail("receiver@test.com", "subject2", "content2"), 2, SECONDS); - - BpmnModelInstance model = getBpmnModelInstance("listEmailsTask"); - BpmnModelInstance updatedModel = getBpmnModelInstance(model, elementTemplate, "listEmailsTask"); - await().atMost(3, SECONDS).until(() -> super.getLastReceivedEmails().length == 2); - var result = getZeebeTest(updatedModel); - assertThat(result.getProcessInstanceEvent()).hasVariable("subject1", "subject2"); - assertThat(result.getProcessInstanceEvent()).hasVariable("subject2", "subject1"); - } - - @Test - public void shouldListImapEmail() { - - File elementTemplate = - ElementTemplate.from(ELEMENT_TEMPLATE_PATH) - .property("authentication.type", "simple") - .property("authentication.simpleAuthenticationUsername", "test@camunda.com") - .property("authentication.simpleAuthenticationPassword", "password") - .property("protocol", "imap") - .property("data.imapPort", getUnsecureImapPort()) - .property("data.imapHost", LOCALHOST) - .property("imapCryptographicProtocol", "NONE") - .property("data.imapActionDiscriminator", "listEmailsImap") - .property("imapMaxToBeRead", "100") - .property("imapSortField", "RECEIVED_DATE") - .property("imapSortOrder", "DESC") - .property("resultExpression", RESULT_EXPRESSION_LIST_EMAIL) - .writeTo(new File(tempDir, "template.json")); - - scheduler.schedule( - () -> super.sendEmail("receiver@test.com", "subject1", "content1"), 1, SECONDS); - scheduler.schedule( - () -> super.sendEmail("receiver@test.com", "subject2", "content2"), 2, SECONDS); - - BpmnModelInstance model = getBpmnModelInstance("listEmailsTask"); - BpmnModelInstance updatedModel = getBpmnModelInstance(model, elementTemplate, "listEmailsTask"); - await().atMost(3, SECONDS).until(() -> super.getLastReceivedEmails().length == 2); - var result = getZeebeTest(updatedModel); - - assertThat(result.getProcessInstanceEvent()).hasVariable("subject1", "subject2"); - assertThat(result.getProcessInstanceEvent()).hasVariable("subject2", "subject1"); - } - - @Test - public void shouldDeletePop3Email() { - - super.sendEmail("test@camunda.com", "subject1", "content1"); - String messageId = getLastEmailMessageId(); - File elementTemplate = - ElementTemplate.from(ELEMENT_TEMPLATE_PATH) - .property("authentication.type", "simple") - .property("authentication.simpleAuthenticationUsername", "test@camunda.com") - .property("authentication.simpleAuthenticationPassword", "password") - .property("protocol", "pop3") - .property("data.pop3Port", getUnsecurePop3Port()) - .property("data.pop3Host", LOCALHOST) - .property("pop3CryptographicProtocol", "NONE") - .property("data.pop3ActionDiscriminator", "deleteEmailPop3") - .property("pop3MessageIdDelete", messageId) - .property("resultExpression", RESULT_EXPRESSION_DELETE_EMAIL) - .writeTo(new File(tempDir, "template.json")); - - BpmnModelInstance model = getBpmnModelInstance("deleteEmailTask"); - BpmnModelInstance updatedModel = - getBpmnModelInstance(model, elementTemplate, "deleteEmailTask"); - var result = getZeebeTest(updatedModel); - assertThat(result.getProcessInstanceEvent()).hasVariable("messageId", messageId); - assertThat(result.getProcessInstanceEvent()).hasVariable("deleted", true); - } - - @Test - public void shouldDeleteImapEmail() { - - super.sendEmail("test@camunda.com", "subject1", "content1"); - String messageId = getLastEmailMessageId(); - File elementTemplate = - ElementTemplate.from(ELEMENT_TEMPLATE_PATH) - .property("authentication.type", "simple") - .property("authentication.simpleAuthenticationUsername", "test@camunda.com") - .property("authentication.simpleAuthenticationPassword", "password") - .property("protocol", "imap") - .property("data.imapPort", getUnsecureImapPort()) - .property("data.imapHost", LOCALHOST) - .property("imapCryptographicProtocol", "NONE") - .property("data.imapActionDiscriminator", "deleteEmailImap") - .property("imapMessageIdDelete", messageId) - .property("deleteEmailFolder", "INBOX") - .property("resultExpression", RESULT_EXPRESSION_DELETE_EMAIL) - .writeTo(new File(tempDir, "template.json")); - - BpmnModelInstance model = getBpmnModelInstance("deleteEmailTask"); - BpmnModelInstance updatedModel = - getBpmnModelInstance(model, elementTemplate, "deleteEmailTask"); - var result = getZeebeTest(updatedModel); - assertThat(result.getProcessInstanceEvent()).hasVariable("messageId", messageId); - assertThat(result.getProcessInstanceEvent()).hasVariable("deleted", true); - } - - @Test - public void shouldReadPop3Email() { - - super.sendEmail("test@camunda.com", "subject", "content"); - String messageId = getLastEmailMessageId(); - File elementTemplate = - ElementTemplate.from(ELEMENT_TEMPLATE_PATH) - .property("authentication.type", "simple") - .property("authentication.simpleAuthenticationUsername", "test@camunda.com") - .property("authentication.simpleAuthenticationPassword", "password") - .property("protocol", "pop3") - .property("data.pop3Port", getUnsecurePop3Port()) - .property("data.pop3Host", LOCALHOST) - .property("pop3CryptographicProtocol", "NONE") - .property("data.pop3ActionDiscriminator", "readEmailPop3") - .property("pop3MessageIdRead", messageId) - .property("resultExpression", RESULT_EXPRESSION_READ_EMAIL) - .writeTo(new File(tempDir, "template.json")); - - BpmnModelInstance model = getBpmnModelInstance("readEmailTask"); - BpmnModelInstance updatedModel = getBpmnModelInstance(model, elementTemplate, "readEmailTask"); - var result = getZeebeTest(updatedModel); - assertThat(result.getProcessInstanceEvent()).hasVariable("messageId", messageId); - assertThat(result.getProcessInstanceEvent()).hasVariable("fromAddress", "test@camunda.com"); - assertThat(result.getProcessInstanceEvent()).hasVariable("subject", "subject"); - assertThat(result.getProcessInstanceEvent()).hasVariable("size", 9); - assertThat(result.getProcessInstanceEvent()).hasVariable("plainTextBody", "content\r\n"); - } - - @Test - public void shouldReadImapEmail() { - - super.sendEmail("test@camunda.com", "subject", "content"); - String messageId = getLastEmailMessageId(); - File elementTemplate = - ElementTemplate.from(ELEMENT_TEMPLATE_PATH) - .property("authentication.type", "simple") - .property("authentication.simpleAuthenticationUsername", "test@camunda.com") - .property("authentication.simpleAuthenticationPassword", "password") - .property("protocol", "imap") - .property("data.imapPort", getUnsecureImapPort()) - .property("data.imapHost", LOCALHOST) - .property("imapCryptographicProtocol", "NONE") - .property("data.imapActionDiscriminator", "readEmailImap") - .property("imapMessageIdRead", messageId) - .property("readEmailFolder", "INBOX") - .property("resultExpression", RESULT_EXPRESSION_READ_EMAIL) - .writeTo(new File(tempDir, "template.json")); - - BpmnModelInstance model = getBpmnModelInstance("readEmailTask"); - BpmnModelInstance updatedModel = getBpmnModelInstance(model, elementTemplate, "readEmailTask"); - var result = getZeebeTest(updatedModel); - assertThat(result.getProcessInstanceEvent()).hasVariable("messageId", messageId); - assertThat(result.getProcessInstanceEvent()).hasVariable("fromAddress", "test@camunda.com"); - assertThat(result.getProcessInstanceEvent()).hasVariable("subject", "subject"); - assertThat(result.getProcessInstanceEvent()).hasVariable("size", 7); - assertThat(result.getProcessInstanceEvent()).hasVariable("plainTextBody", "content"); - } - - @Test - public void shouldMoveImapEmail() { - - super.sendEmail("test@camunda.com", "subject", "content"); - String messageId = getLastEmailMessageId(); - File elementTemplate = - ElementTemplate.from(ELEMENT_TEMPLATE_PATH) - .property("authentication.type", "simple") - .property("authentication.simpleAuthenticationUsername", "test@camunda.com") - .property("authentication.simpleAuthenticationPassword", "password") - .property("protocol", "imap") - .property("data.imapPort", getUnsecureImapPort()) - .property("data.imapHost", LOCALHOST) - .property("imapCryptographicProtocol", "NONE") - .property("data.imapActionDiscriminator", "moveEmailImap") - .property("imapMessageIdMove", messageId) - .property("data.fromFolder", "INBOX") - .property("data.toFolder", "TEST") - .property("resultExpression", RESULT_EXPRESSION_MOVE_EMAIL) - .writeTo(new File(tempDir, "template.json")); - - BpmnModelInstance model = getBpmnModelInstance("readEmailTask"); - BpmnModelInstance updatedModel = getBpmnModelInstance(model, elementTemplate, "readEmailTask"); - var result = getZeebeTest(updatedModel); - - assertThat(result.getProcessInstanceEvent()).hasVariable("messageId", messageId); - assertThat(result.getProcessInstanceEvent()).hasVariable("from", "INBOX"); - assertThat(result.getProcessInstanceEvent()).hasVariable("to", "TEST"); - } - - @Test - public void shouldSendEmailVersion1() { - var model = - replace( - "email-outbound-connector-send-email-v1.bpmn", - BpmnFile.Replace.replace("55555", super.getUnsecureSmtpPort())); - - var result = getZeebeTest(model); - - assertThat(result).isNotNull(); - assertThat(result.getProcessInstanceEvent()).hasVariable("sent", true); - - assertTrue(super.waitForNewEmails(5000, 1)); - List message = List.of(super.getLastReceivedEmails()); - assertThat(message).isNotNull(); - assertThat(getSenders(message.getFirst())).hasSize(1).first().isEqualTo("test@camunda.com"); - assertThat(getReceivers(message.getFirst())).hasSize(1).first().isEqualTo("receiver@test.com"); - assertThat(getSubject(message.getFirst())).isEqualTo("Hello"); - assertThat(getHtmlBody(message.getFirst())).isEqualTo("This is a test"); - } - - private BpmnModelInstance getBpmnModelInstance( - final BpmnModelInstance model, final File elementTemplate, final String taskName) { - return new BpmnFile(model) - .writeToFile(new File(tempDir, "test.bpmn")) - .apply(elementTemplate, taskName, new File(tempDir, "result.bpmn")); - } - - protected ZeebeTest getZeebeTest(final BpmnModelInstance updatedModel) { - return ZeebeTest.with(camundaClient) - .deploy(updatedModel) - .createInstance() - .waitForProcessCompletion(); - } -} diff --git a/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_all_delete.bpmn b/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_all_delete.bpmn deleted file mode 100644 index 76a9b9c9f7..0000000000 --- a/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_all_delete.bpmn +++ /dev/null @@ -1,64 +0,0 @@ - - - - - Flow_1vp6srd - - - Flow_0lofu08 - - - - - - - - - - - - - - - - - - - - - - - - Flow_0lofu08 - Flow_1vp6srd - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_all_move.bpmn b/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_all_move.bpmn deleted file mode 100644 index 27d4d11d4e..0000000000 --- a/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_all_move.bpmn +++ /dev/null @@ -1,65 +0,0 @@ - - - - - Flow_1vp6srd - - - Flow_0lofu08 - - - - - - - - - - - - - - - - - - - - - - - - - Flow_0lofu08 - Flow_1vp6srd - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_unseen_delete.bpmn b/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_unseen_delete.bpmn deleted file mode 100644 index 6ae220a00f..0000000000 --- a/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_unseen_delete.bpmn +++ /dev/null @@ -1,64 +0,0 @@ - - - - - Flow_1vp6srd - - - Flow_0lofu08 - - - - - - - - - - - - - - - - - - - - - - - - Flow_0lofu08 - Flow_1vp6srd - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_unseen_move.bpmn b/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_unseen_move.bpmn deleted file mode 100644 index 1b88dff42c..0000000000 --- a/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_unseen_move.bpmn +++ /dev/null @@ -1,65 +0,0 @@ - - - - - Flow_1vp6srd - - - Flow_0lofu08 - - - - - - - - - - - - - - - - - - - - - - - - - Flow_0lofu08 - Flow_1vp6srd - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_unseen_read.bpmn b/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_unseen_read.bpmn deleted file mode 100644 index ce2472e664..0000000000 --- a/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-inbound-connector-intermediate_unseen_read.bpmn +++ /dev/null @@ -1,64 +0,0 @@ - - - - - Flow_1vp6srd - - - Flow_0lofu08 - - - - - - - - - - - - - - - - - - - - - - - - Flow_0lofu08 - Flow_1vp6srd - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-outbound-connector-send-email-v1.bpmn b/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-outbound-connector-send-email-v1.bpmn deleted file mode 100644 index e7db67aad2..0000000000 --- a/connectors-e2e-test/connectors-e2e-test-mail/src/test/resources/email-outbound-connector-send-email-v1.bpmn +++ /dev/null @@ -1,67 +0,0 @@ - - - - - Flow_1krhvnz - - - - Flow_0g2casz - - - - - - - - - - - - - - - - - - - - - - - - - Flow_1krhvnz - Flow_0g2casz - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/connectors-e2e-test/pom.xml b/connectors-e2e-test/pom.xml index fe3f1d3f72..9d84334cea 100644 --- a/connectors-e2e-test/pom.xml +++ b/connectors-e2e-test/pom.xml @@ -17,7 +17,6 @@ connectors-e2e-test-base connectors-e2e-test-http - connectors-e2e-test-mail connectors-e2e-test-automation-anywhere connectors-e2e-test-kafka connectors-e2e-test-aws diff --git a/connectors/email/pom.xml b/connectors/email/pom.xml index 58e47ad6bd..9a6a7bb5e3 100644 --- a/connectors/email/pom.xml +++ b/connectors/email/pom.xml @@ -31,6 +31,12 @@ angus-mail 2.0.3 + + com.icegreen + greenmail + 2.1.3 + test + diff --git a/connectors-e2e-test/connectors-e2e-test-mail/src/test/java/io/camunda/connector/e2e/BaseEmailTest.java b/connectors/email/src/test/java/io/camunda/connector/email/integration/BaseEmailTest.java similarity index 58% rename from connectors-e2e-test/connectors-e2e-test-mail/src/test/java/io/camunda/connector/e2e/BaseEmailTest.java rename to connectors/email/src/test/java/io/camunda/connector/email/integration/BaseEmailTest.java index e90e79bd3c..65c36d7e19 100644 --- a/connectors-e2e-test/connectors-e2e-test-mail/src/test/java/io/camunda/connector/e2e/BaseEmailTest.java +++ b/connectors/email/src/test/java/io/camunda/connector/email/integration/BaseEmailTest.java @@ -1,29 +1,16 @@ /* * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH - * under one or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information regarding copyright - * ownership. Camunda licenses this file to you under the Apache License, - * Version 2.0; 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. + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. */ -package io.camunda.connector.e2e; +package io.camunda.connector.email.integration; import com.icegreen.greenmail.store.FolderException; import com.icegreen.greenmail.user.GreenMailUser; import com.icegreen.greenmail.util.GreenMail; import com.icegreen.greenmail.util.GreenMailUtil; -import jakarta.mail.Address; -import jakarta.mail.Message; -import jakarta.mail.MessagingException; -import jakarta.mail.Multipart; +import jakarta.mail.*; import jakarta.mail.internet.MimeBodyPart; import jakarta.mail.internet.MimeMessage; import java.io.File; @@ -107,6 +94,46 @@ protected static String getSubject(Message message) { } } + protected static String getBodyAsHtml(Message message) { + try { + if (message.getContent() instanceof Multipart multipart) { + for (int i = 0; i < multipart.getCount(); i++) { + MimeBodyPart bodyPart = (MimeBodyPart) multipart.getBodyPart(i); + if (bodyPart.isMimeType("text/html")) { + return (String) bodyPart.getContent(); + } + } + } + return null; + } catch (MessagingException | IOException e) { + throw new RuntimeException(e); + } + } + + protected static byte[] getBodyAsByteArray(Message message) { + try { + if (message.getContent() instanceof Multipart multipart) { + for (int i = 0; i < multipart.getCount(); i++) { + MimeBodyPart bodyPart = (MimeBodyPart) multipart.getBodyPart(i); + if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) { + return bodyPart.getInputStream().readAllBytes(); + } + } + } + return null; + } catch (MessagingException | IOException e) { + throw new RuntimeException(e); + } + } + + protected static String getEmailSubject(Message message) { + try { + return message.getSubject(); + } catch (MessagingException e) { + throw new RuntimeException(e); + } + } + protected Message[] getLastReceivedEmails() { return greenMail.getReceivedMessages(); } @@ -151,4 +178,46 @@ protected void reset() { throw new RuntimeException(e); } } + + protected String getBodyAsText(Message message) { + try { + if (message.getContent() instanceof Multipart multipart) { + for (int i = 0; i < multipart.getCount(); i++) { + MimeBodyPart bodyPart = (MimeBodyPart) multipart.getBodyPart(i); + if (bodyPart.isMimeType("text/plain")) { + return (String) bodyPart.getContent(); + } + } + } + return null; + } catch (MessagingException | IOException e) { + throw new RuntimeException(e); + } + } + + protected List getFrom(Message message) { + try { + return Arrays.stream(message.getFrom()).map(Address::toString).toList(); + } catch (MessagingException e) { + throw new RuntimeException(e); + } + } + + protected List getTo(Message message) { + try { + return Arrays.stream(message.getAllRecipients()).map(Address::toString).toList(); + } catch (MessagingException e) { + throw new RuntimeException(e); + } + } + + protected String getLastMessageId() { + Message message = getLastReceivedEmails()[0]; + try { + String messageId = message.getHeader("Message-ID")[0]; + return messageId.trim().replaceAll("[<>]", ""); + } catch (MessagingException e) { + throw new RuntimeException(e); + } + } } diff --git a/connectors/email/src/test/java/io/camunda/connector/email/integration/InboundEmailTest.java b/connectors/email/src/test/java/io/camunda/connector/email/integration/InboundEmailTest.java new file mode 100644 index 0000000000..976c0ad3e7 --- /dev/null +++ b/connectors/email/src/test/java/io/camunda/connector/email/integration/InboundEmailTest.java @@ -0,0 +1,99 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.email.integration; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.camunda.connector.api.inbound.InboundConnectorContext; +import io.camunda.connector.email.client.jakarta.inbound.JakartaEmailListener; +import io.camunda.connector.email.config.CryptographicProtocol; +import io.camunda.connector.email.config.ImapConfig; +import io.camunda.connector.email.inbound.model.EmailInboundConnectorProperties; +import io.camunda.connector.email.inbound.model.EmailListenerConfig; +import io.camunda.connector.email.inbound.model.HandlingStrategy; +import jakarta.mail.Flags; +import jakarta.mail.MessagingException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class InboundEmailTest extends BaseEmailTest { + + JakartaEmailListener jakartaEmailListener = new JakartaEmailListener(); + + private static List createEmailInboundConnectorProperties() { + ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules(); + try { + return objectMapper.readValue( + Files.readString( + Path.of("src/test/resources/integration/inbound-connector-happy-path.json")), + new TypeReference<>() {}); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @BeforeEach + public void beforeEach() { + super.reset(); + } + + @ParameterizedTest + @MethodSource("createEmailInboundConnectorProperties") + public void shouldReceiveEmail(EmailInboundConnectorProperties emailInboundConnectorProperties) + throws MessagingException { + InboundConnectorContext inboundConnectorContext = mock(InboundConnectorContext.class); + + ImapConfig pollingConfig = + new ImapConfig( + "localhost", Integer.valueOf(super.getUnsecureImapPort()), CryptographicProtocol.NONE); + + EmailInboundConnectorProperties emailInboundConnectorProperties1 = + new EmailInboundConnectorProperties( + emailInboundConnectorProperties.authentication(), + new EmailListenerConfig( + pollingConfig, + emailInboundConnectorProperties.data().folderToListen(), + emailInboundConnectorProperties.data().pollingWaitTime(), + emailInboundConnectorProperties.data().pollingConfig())); + + when(inboundConnectorContext.bindProperties(EmailInboundConnectorProperties.class)) + .thenReturn(emailInboundConnectorProperties1); + + jakartaEmailListener.startListener(inboundConnectorContext); + + super.sendEmail("camunda@test.com", "Subject", "Content"); + + verify(inboundConnectorContext, timeout(3000).times(1)).canActivate(any()); + verify(inboundConnectorContext, timeout(3000).times(1)).correlateWithResult(any()); + + assertFlagOnLastEmail( + emailInboundConnectorProperties.data().pollingConfig().handlingStrategy()); + } + + private void assertFlagOnLastEmail(HandlingStrategy handlingStrategy) throws MessagingException { + Assertions.assertTrue( + Arrays.stream(super.getLastReceivedEmails()) + .findFirst() + .get() + .getFlags() + .contains( + switch (handlingStrategy) { + case READ -> Flags.Flag.SEEN; + case DELETE, MOVE -> Flags.Flag.DELETED; + })); + } +} diff --git a/connectors/email/src/test/java/io/camunda/connector/email/integration/OutboundEmailTest.java b/connectors/email/src/test/java/io/camunda/connector/email/integration/OutboundEmailTest.java new file mode 100644 index 0000000000..7c006761c7 --- /dev/null +++ b/connectors/email/src/test/java/io/camunda/connector/email/integration/OutboundEmailTest.java @@ -0,0 +1,329 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. Licensed under a proprietary license. + * See the License.txt file for more information. You may not use this file + * except in compliance with the proprietary license. + */ +package io.camunda.connector.email.integration; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.camunda.connector.api.json.ConnectorsObjectMapperSupplier; +import io.camunda.connector.api.outbound.OutboundConnectorContext; +import io.camunda.connector.email.client.jakarta.outbound.JakartaEmailActionExecutor; +import io.camunda.connector.email.client.jakarta.utils.JakartaUtils; +import io.camunda.connector.email.response.DeleteEmailResponse; +import io.camunda.connector.email.response.ListEmailsResponse; +import io.camunda.connector.email.response.ReadEmailResponse; +import io.camunda.connector.email.response.SearchEmailsResponse; +import io.camunda.connector.test.outbound.OutboundConnectorContextBuilder; +import io.camunda.document.factory.DocumentFactory; +import io.camunda.document.factory.DocumentFactoryImpl; +import io.camunda.document.store.DocumentCreationRequest; +import io.camunda.document.store.InMemoryDocumentStore; +import jakarta.mail.Message; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class OutboundEmailTest extends BaseEmailTest { + + DocumentFactory documentFactory = new DocumentFactoryImpl(InMemoryDocumentStore.INSTANCE); + ObjectMapper objectMapper = new ObjectMapper(); + + JakartaEmailActionExecutor jakartaEmailActionExecutor = + JakartaEmailActionExecutor.create( + new JakartaUtils(), ConnectorsObjectMapperSupplier.getCopy()); + private OutboundConnectorContextBuilder contextBuilder = OutboundConnectorContextBuilder.create(); + + private static Stream getStreamFromPath(String path) { + ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules(); + try { + return objectMapper + .readValue(Files.readString(Path.of(path)), new TypeReference>() {}) + .stream() + .map(JsonNode::toString); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static Stream createEmailOutboundSmtpConnectorProperties() { + return getStreamFromPath( + "src/test/resources/integration/outbound-smtp-connector-happy-path.json"); + } + + public static Stream createEmailOutboundPop3DeleteConnectorProperties() { + return getStreamFromPath( + "src/test/resources/integration/outbound-pop3-delete-connector-happy-path.json"); + } + + public static Stream createEmailOutboundPop3SearchConnectorProperties() { + return getStreamFromPath( + "src/test/resources/integration/outbound-pop3-search-connector-happy-path.json"); + } + + public static Stream createEmailOutboundPop3ListConnectorProperties() { + return getStreamFromPath( + "src/test/resources/integration/outbound-pop3-list-connector-happy-path.json"); + } + + public static Stream createEmailOutboundPop3ReadConnectorProperties() { + return getStreamFromPath( + "src/test/resources/integration/outbound-pop3-read-connector-happy-path.json"); + } + + public static Stream createEmailOutboundImapDeleteConnectorProperties() { + return getStreamFromPath( + "src/test/resources/integration/outbound-imap-delete-connector-happy-path.json"); + } + + public static Stream createEmailOutboundImapSearchConnectorProperties() { + return getStreamFromPath( + "src/test/resources/integration/outbound-imap-search-connector-happy-path.json"); + } + + public static Stream createEmailOutboundImapListConnectorProperties() { + return getStreamFromPath( + "src/test/resources/integration/outbound-imap-list-connector-happy-path.json"); + } + + public static Stream createEmailOutboundImapReadConnectorProperties() { + return getStreamFromPath( + "src/test/resources/integration/outbound-imap-read-connector-happy-path.json"); + } + + @BeforeEach + public void beforeEach() { + super.reset(); + } + + @ParameterizedTest + @MethodSource("createEmailOutboundSmtpConnectorProperties") + public void shouldSendEmailSmtp(String emailRequest) throws IOException { + + JsonNode jsonNode = objectMapper.readValue(emailRequest, JsonNode.class); + + JsonNode jsonNodeDocumentList = jsonNode.get("data").get("smtpAction").get("attachments"); + + Path attachment = Path.of("src/test/resources/img/img.png"); + if (jsonNodeDocumentList != null) { + JsonNode jsonNodeDocument = jsonNodeDocumentList.get(0); + this.documentFactory.create( + DocumentCreationRequest.from(Files.readAllBytes(attachment)) + .documentId(jsonNodeDocument.get("documentId").asText()) + .fileName(jsonNodeDocument.get("metadata").get("fileName").asText()) + .build()); + } + + emailRequest = emailRequest.replace("{{PORT}}", super.getUnsecureSmtpPort()); + OutboundConnectorContext outboundConnectorContext = + this.contextBuilder.variables(emailRequest).build(); + + this.jakartaEmailActionExecutor.execute(outboundConnectorContext); + + Message message = Arrays.stream(super.getLastReceivedEmails()).findFirst().get(); + + JsonNode jsonNodeValue = jsonNode.get("data").get("smtpAction"); + + Assertions.assertNotNull(message); + if (jsonNodeValue.get("body") != null) { + Assertions.assertEquals(jsonNodeValue.get("body").asText(), getBodyAsText(message)); + } + Assertions.assertEquals(jsonNodeValue.get("to").asText(), getTo(message).getFirst()); + Assertions.assertEquals(jsonNodeValue.get("subject").asText(), getEmailSubject(message)); + if (jsonNodeValue.get("htmlBody") != null) { + Assertions.assertEquals(jsonNodeValue.get("htmlBody").asText(), getBodyAsHtml(message)); + } + if (jsonNodeDocumentList != null) { + Assertions.assertArrayEquals(getBodyAsByteArray(message), Files.readAllBytes(attachment)); + } + } + + @ParameterizedTest + @MethodSource("createEmailOutboundPop3DeleteConnectorProperties") + public void shouldUsePop3Delete(String emailRequest) { + super.sendEmail("test@test.com", "subject", "Content"); + String messageId = getLastMessageId(); + + emailRequest = emailRequest.replace("{{PORT}}", super.getUnsecurePop3Port()); + emailRequest = emailRequest.replace("{{MESSAGE_ID}}", messageId); + OutboundConnectorContext outboundConnectorContext = + this.contextBuilder.variables(emailRequest).build(); + + Object object = this.jakartaEmailActionExecutor.execute(outboundConnectorContext); + + Assertions.assertInstanceOf(DeleteEmailResponse.class, object); + Assertions.assertTrue(((DeleteEmailResponse) object).deleted()); + } + + @ParameterizedTest + @MethodSource("createEmailOutboundImapDeleteConnectorProperties") + public void shouldUseImapDelete(String emailRequest) { + super.sendEmail("test@test.com", "subject", "Content"); + String messageId = getLastMessageId(); + + emailRequest = emailRequest.replace("{{PORT}}", super.getUnsecureImapPort()); + emailRequest = emailRequest.replace("{{MESSAGE_ID}}", messageId); + OutboundConnectorContext outboundConnectorContext = + this.contextBuilder.variables(emailRequest).build(); + + Object object = this.jakartaEmailActionExecutor.execute(outboundConnectorContext); + + Assertions.assertInstanceOf(DeleteEmailResponse.class, object); + Assertions.assertTrue(((DeleteEmailResponse) object).deleted()); + } + + @ParameterizedTest + @MethodSource("createEmailOutboundPop3SearchConnectorProperties") + public void shouldUsePop3Search(String emailRequest) { + super.sendEmail("test@test.com", "subject", "Content"); + + emailRequest = emailRequest.replace("{{PORT}}", super.getUnsecurePop3Port()); + OutboundConnectorContext outboundConnectorContext = + this.contextBuilder.variables(emailRequest).build(); + + Object object = this.jakartaEmailActionExecutor.execute(outboundConnectorContext); + + Assertions.assertInstanceOf(List.class, object); + Object searchResult = ((List) object).getFirst(); + Assertions.assertInstanceOf(SearchEmailsResponse.class, searchResult); + Assertions.assertEquals("subject", ((SearchEmailsResponse) searchResult).subject()); + Assertions.assertEquals( + super.getLastMessageId(), ((SearchEmailsResponse) searchResult).messageId()); + } + + @ParameterizedTest + @MethodSource("createEmailOutboundImapSearchConnectorProperties") + public void shouldUseImapSearch(String emailRequest) { + super.sendEmail("test@test.com", "subject", "Content"); + + emailRequest = emailRequest.replace("{{PORT}}", super.getUnsecureImapPort()); + OutboundConnectorContext outboundConnectorContext = + this.contextBuilder.variables(emailRequest).build(); + + Object object = this.jakartaEmailActionExecutor.execute(outboundConnectorContext); + + Assertions.assertInstanceOf(List.class, object); + Object searchResult = ((List) object).getFirst(); + Assertions.assertInstanceOf(SearchEmailsResponse.class, searchResult); + Assertions.assertEquals("subject", ((SearchEmailsResponse) searchResult).subject()); + Assertions.assertEquals( + super.getLastMessageId(), ((SearchEmailsResponse) searchResult).messageId()); + } + + @ParameterizedTest + @MethodSource("createEmailOutboundPop3ListConnectorProperties") + public void shouldUsePop3List(String emailRequest) throws JsonProcessingException { + JsonNode jsonNode = objectMapper.readValue(emailRequest, JsonNode.class); + + super.sendEmail("test@test.com", "subject 1", "Content 1"); + super.sendEmail("test2@test.com", "subject 2", "Content 2"); + + emailRequest = emailRequest.replace("{{PORT}}", super.getUnsecurePop3Port()); + OutboundConnectorContext outboundConnectorContext = + this.contextBuilder.variables(emailRequest).build(); + + Object object = this.jakartaEmailActionExecutor.execute(outboundConnectorContext); + + JsonNode jsonNodeValue = jsonNode.get("data").get("pop3Action"); + + Assertions.assertInstanceOf(List.class, object); + Assertions.assertTrue(((List) object).size() < jsonNodeValue.get("maxToBeRead").asInt()); + + switch (jsonNodeValue.get("sortField").asText()) { + case "SENT_DATE" -> { + if (jsonNodeValue.get("sortOrder").asText().equals("ASC")) { + Assertions.assertEquals( + "subject 1", ((ListEmailsResponse) ((List) object).getFirst()).subject()); + Assertions.assertEquals( + "subject 2", ((ListEmailsResponse) ((List) object).get(1)).subject()); + } + } + default -> + throw new IllegalStateException( + "Unexpected value: " + jsonNodeValue.get("sortField").asText()); + } + } + + @ParameterizedTest + @MethodSource("createEmailOutboundImapListConnectorProperties") + public void shouldUseImapList(String emailRequest) throws JsonProcessingException { + JsonNode jsonNode = objectMapper.readValue(emailRequest, JsonNode.class); + + super.sendEmail("test@test.com", "subject 1", "Content 1"); + super.sendEmail("test2@test.com", "subject 2", "Content 2"); + + emailRequest = emailRequest.replace("{{PORT}}", super.getUnsecureImapPort()); + OutboundConnectorContext outboundConnectorContext = + this.contextBuilder.variables(emailRequest).build(); + + Object object = this.jakartaEmailActionExecutor.execute(outboundConnectorContext); + + JsonNode jsonNodeValue = jsonNode.get("data").get("imapAction"); + + Assertions.assertInstanceOf(List.class, object); + Assertions.assertTrue(((List) object).size() < jsonNodeValue.get("maxToBeRead").asInt()); + + switch (jsonNodeValue.get("sortField").asText()) { + case "SENT_DATE", "RECEIVED_DATE" -> { + if (jsonNodeValue.get("sortOrder").asText().equals("ASC")) { + Assertions.assertEquals( + "subject 1", ((ListEmailsResponse) ((List) object).getFirst()).subject()); + Assertions.assertEquals( + "subject 2", ((ListEmailsResponse) ((List) object).get(1)).subject()); + } + } + default -> + throw new IllegalStateException( + "Unexpected value: " + jsonNodeValue.get("sortField").asText()); + } + } + + @ParameterizedTest + @MethodSource("createEmailOutboundPop3ReadConnectorProperties") + public void shouldUsePop3Read(String emailRequest) { + super.sendEmail("test@test.com", "subject", "Content"); + String messageId = getLastMessageId(); + + emailRequest = emailRequest.replace("{{PORT}}", super.getUnsecurePop3Port()); + emailRequest = emailRequest.replace("{{MESSAGE_ID}}", messageId); + OutboundConnectorContext outboundConnectorContext = + this.contextBuilder.variables(emailRequest).build(); + + Object object = this.jakartaEmailActionExecutor.execute(outboundConnectorContext); + + Assertions.assertInstanceOf(ReadEmailResponse.class, object); + Assertions.assertEquals(((ReadEmailResponse) object).messageId(), messageId); + Assertions.assertEquals("Content\r\n", ((ReadEmailResponse) object).plainTextBody()); + Assertions.assertEquals("subject", ((ReadEmailResponse) object).subject()); + } + + @ParameterizedTest + @MethodSource("createEmailOutboundImapReadConnectorProperties") + public void shouldUseImapRead(String emailRequest) { + super.sendEmail("test@test.com", "subject", "Content"); + String messageId = getLastMessageId(); + + emailRequest = emailRequest.replace("{{PORT}}", super.getUnsecureImapPort()); + emailRequest = emailRequest.replace("{{MESSAGE_ID}}", messageId); + OutboundConnectorContext outboundConnectorContext = + this.contextBuilder.variables(emailRequest).build(); + + Object object = this.jakartaEmailActionExecutor.execute(outboundConnectorContext); + + Assertions.assertInstanceOf(ReadEmailResponse.class, object); + Assertions.assertEquals(((ReadEmailResponse) object).messageId(), messageId); + Assertions.assertEquals("Content", ((ReadEmailResponse) object).plainTextBody()); + Assertions.assertEquals("subject", ((ReadEmailResponse) object).subject()); + } +} diff --git a/connectors/email/src/test/resources/integration/inbound-connector-happy-path.json b/connectors/email/src/test/resources/integration/inbound-connector-happy-path.json new file mode 100644 index 0000000000..efe64e1623 --- /dev/null +++ b/connectors/email/src/test/resources/integration/inbound-connector-happy-path.json @@ -0,0 +1,94 @@ +[ + { + "authentication":{ + "username":"test@camunda.com", + "password":"password" + }, + "data":{ + "imapConfig":{ + "imapHost":"", + "imapPort":"", + "imapCryptographicProtocol":"NONE" + }, + "pollingWaitTime":"PT2S", + "pollingConfigDiscriminator":"allPollingConfig", + "pollingConfig":{ + "handlingStrategy":"DELETE" + } + } + }, + { + "authentication":{ + "username":"test@camunda.com", + "password":"password" + }, + "data":{ + "imapConfig":{ + "imapHost":"", + "imapPort":"", + "imapCryptographicProtocol":"NONE" + }, + "pollingWaitTime":"PT2S", + "pollingConfigDiscriminator":"allPollingConfig", + "pollingConfig":{ + "handlingStrategy":"MOVE", + "targetFolder":"testFolder" + } + } + }, + { + "authentication":{ + "username":"test@camunda.com", + "password":"password" + }, + "data":{ + "imapConfig":{ + "imapHost":"", + "imapPort":"", + "imapCryptographicProtocol":"NONE" + }, + "pollingWaitTime":"PT2S", + "pollingConfigDiscriminator":"unseenPollingConfig", + "pollingConfig":{ + "handlingStrategy":"MOVE", + "targetFolder":"testFolder" + } + } + }, + { + "authentication":{ + "username":"test@camunda.com", + "password":"password" + }, + "data":{ + "imapConfig":{ + "imapHost":"", + "imapPort":"", + "imapCryptographicProtocol":"NONE" + }, + "pollingWaitTime":"PT2S", + "pollingConfigDiscriminator":"unseenPollingConfig", + "pollingConfig":{ + "handlingStrategy":"READ" + } + } + }, + { + "authentication":{ + "username":"test@camunda.com", + "password":"password" + }, + "data":{ + "imapConfig":{ + "imapHost":"", + "imapPort":"", + "imapCryptographicProtocol":"NONE" + }, + "pollingWaitTime":"PT2S", + "pollingConfigDiscriminator":"allPollingConfig", + "pollingConfig":{ + "handlingStrategy":"DELETE" + } + } + } +] \ No newline at end of file diff --git a/connectors/email/src/test/resources/integration/outbound-imap-delete-connector-happy-path.json b/connectors/email/src/test/resources/integration/outbound-imap-delete-connector-happy-path.json new file mode 100644 index 0000000000..6dfdcf8cac --- /dev/null +++ b/connectors/email/src/test/resources/integration/outbound-imap-delete-connector-happy-path.json @@ -0,0 +1,22 @@ +[ + { + "authentication":{ + "type":"simple", + "username":"test@camunda.com", + "password":"password" + }, + "protocol":"imap", + "data":{ + "imapConfig":{ + "imapHost":"localhost", + "imapPort":"{{PORT}}", + "imapCryptographicProtocol":"NONE" + }, + "imapActionDiscriminator":"deleteEmailImap", + "imapAction":{ + "messageId":"{{MESSAGE_ID}}", + "deleteEmailFolder":"INBOX" + } + } + } +] \ No newline at end of file diff --git a/connectors/email/src/test/resources/integration/outbound-imap-list-connector-happy-path.json b/connectors/email/src/test/resources/integration/outbound-imap-list-connector-happy-path.json new file mode 100644 index 0000000000..14154ca460 --- /dev/null +++ b/connectors/email/src/test/resources/integration/outbound-imap-list-connector-happy-path.json @@ -0,0 +1,23 @@ +[ + { + "authentication":{ + "type":"simple", + "username":"test@camunda.com", + "password":"password" + }, + "protocol":"imap", + "data":{ + "imapConfig":{ + "imapHost":"localhost", + "imapPort":"{{PORT}}", + "imapCryptographicProtocol":"NONE" + }, + "imapActionDiscriminator": "listEmailsImap", + "imapAction": { + "maxToBeRead": "100", + "sortField": "RECEIVED_DATE", + "sortOrder": "ASC" + } + } + } +] \ No newline at end of file diff --git a/connectors/email/src/test/resources/integration/outbound-imap-read-connector-happy-path.json b/connectors/email/src/test/resources/integration/outbound-imap-read-connector-happy-path.json new file mode 100644 index 0000000000..86f552d6a7 --- /dev/null +++ b/connectors/email/src/test/resources/integration/outbound-imap-read-connector-happy-path.json @@ -0,0 +1,21 @@ +[ + { + "authentication":{ + "type":"simple", + "username":"test@camunda.com", + "password":"password" + }, + "protocol":"imap", + "data":{ + "imapConfig":{ + "imapHost":"localhost", + "imapPort":"{{PORT}}", + "imapCryptographicProtocol":"NONE" + }, + "imapActionDiscriminator": "readEmailImap", + "imapAction": { + "messageId": "{{MESSAGE_ID}}" + } + } + } +] \ No newline at end of file diff --git a/connectors/email/src/test/resources/integration/outbound-imap-search-connector-happy-path.json b/connectors/email/src/test/resources/integration/outbound-imap-search-connector-happy-path.json new file mode 100644 index 0000000000..b66fe98bde --- /dev/null +++ b/connectors/email/src/test/resources/integration/outbound-imap-search-connector-happy-path.json @@ -0,0 +1,25 @@ +[ + { + "authentication":{ + "type":"simple", + "username":"test@camunda.com", + "password":"password" + }, + "protocol":"imap", + "data":{ + "imapConfig":{ + "imapHost":"localhost", + "imapPort":"{{PORT}}", + "imapCryptographicProtocol":"NONE" + }, + "imapActionDiscriminator":"searchEmailsImap", + "imapAction":{ + "criteria":{ + "field":"FROM", + "value":"test@camunda.com" + }, + "deleteEmailFolder":"INBOX" + } + } + } +] \ No newline at end of file diff --git a/connectors/email/src/test/resources/integration/outbound-pop3-delete-connector-happy-path.json b/connectors/email/src/test/resources/integration/outbound-pop3-delete-connector-happy-path.json new file mode 100644 index 0000000000..b125a501d7 --- /dev/null +++ b/connectors/email/src/test/resources/integration/outbound-pop3-delete-connector-happy-path.json @@ -0,0 +1,21 @@ +[ + { + "authentication": { + "type": "simple", + "username": "test@camunda.com", + "password": "password" + }, + "protocol": "pop3", + "data": { + "pop3Config": { + "pop3Host": "localhost", + "pop3Port": "{{PORT}}", + "pop3CryptographicProtocol": "NONE" + }, + "pop3Action": { + "messageId": "{{MESSAGE_ID}}" + }, + "pop3ActionDiscriminator": "deleteEmailPop3" + } + } +] \ No newline at end of file diff --git a/connectors/email/src/test/resources/integration/outbound-pop3-list-connector-happy-path.json b/connectors/email/src/test/resources/integration/outbound-pop3-list-connector-happy-path.json new file mode 100644 index 0000000000..981a9b26e4 --- /dev/null +++ b/connectors/email/src/test/resources/integration/outbound-pop3-list-connector-happy-path.json @@ -0,0 +1,23 @@ +[ + { + "authentication":{ + "type":"simple", + "username":"test@camunda.com", + "password":"password" + }, + "protocol":"pop3", + "data":{ + "pop3Config":{ + "pop3Host":"localhost", + "pop3Port":"{{PORT}}", + "pop3CryptographicProtocol":"NONE" + }, + "pop3ActionDiscriminator":"listEmailsPop3", + "pop3Action":{ + "maxToBeRead":"100", + "sortField":"SENT_DATE", + "sortOrder":"ASC" + } + } + } +] \ No newline at end of file diff --git a/connectors/email/src/test/resources/integration/outbound-pop3-read-connector-happy-path.json b/connectors/email/src/test/resources/integration/outbound-pop3-read-connector-happy-path.json new file mode 100644 index 0000000000..6a7bca1a51 --- /dev/null +++ b/connectors/email/src/test/resources/integration/outbound-pop3-read-connector-happy-path.json @@ -0,0 +1,22 @@ +[ + { + "authentication":{ + "type":"simple", + "username":"test@camunda.com", + "password":"password" + }, + "protocol":"pop3", + "data":{ + "pop3Config":{ + "pop3Host":"localhost", + "pop3Port":"{{PORT}}", + "pop3CryptographicProtocol":"NONE" + }, + "pop3ActionDiscriminator": "readEmailPop3", + "pop3Action": { + "messageId": "{{MESSAGE_ID}}" + } + } + } +] + diff --git a/connectors/email/src/test/resources/integration/outbound-pop3-search-connector-happy-path.json b/connectors/email/src/test/resources/integration/outbound-pop3-search-connector-happy-path.json new file mode 100644 index 0000000000..6ff64fd34d --- /dev/null +++ b/connectors/email/src/test/resources/integration/outbound-pop3-search-connector-happy-path.json @@ -0,0 +1,24 @@ +[ + { + "authentication":{ + "type":"simple", + "username":"test@camunda.com", + "password":"password" + }, + "protocol":"pop3", + "data":{ + "pop3Config":{ + "pop3Host":"localhost", + "pop3Port":"{{PORT}}", + "pop3CryptographicProtocol":"NONE" + }, + "pop3ActionDiscriminator":"searchEmailsPop3", + "pop3Action":{ + "criteria":{ + "field":"FROM", + "value":"test@camunda.com" + } + } + } + } +] \ No newline at end of file diff --git a/connectors/email/src/test/resources/integration/outbound-smtp-connector-happy-path.json b/connectors/email/src/test/resources/integration/outbound-smtp-connector-happy-path.json new file mode 100644 index 0000000000..57ef1d7ffc --- /dev/null +++ b/connectors/email/src/test/resources/integration/outbound-smtp-connector-happy-path.json @@ -0,0 +1,110 @@ +[ + { + "authentication":{ + "type":"simple", + "username":"test@camunda.com", + "password":"password" + }, + "protocol":"smtp", + "data":{ + "smtpConfig":{ + "smtpHost":"localhost", + "smtpPort":"{{PORT}}", + "smtpCryptographicProtocol":"NONE" + }, + "smtpActionDiscriminator":"sendEmailSmtp", + "smtpAction":{ + "from":"camunda.connectors@camunda.com", + "to":"camunda.operate@camunda.com", + "subject":"Hey", + "body":"Content" + } + } + }, + { + "authentication":{ + "type":"simple", + "username":"test@camunda.com", + "password":"password" + }, + "protocol":"smtp", + "data":{ + "smtpConfig":{ + "smtpHost":"localhost", + "smtpPort":"{{PORT}}", + "smtpCryptographicProtocol":"NONE" + }, + "smtpActionDiscriminator":"sendEmailSmtp", + "smtpAction":{ + "contentType":"HTML", + "from":"camunda.connectors@camunda.com", + "to":"camunda.operate@camunda.com", + "subject":"Hey", + "htmlBody":"

Hey

" + } + } + }, + { + "authentication":{ + "type":"simple", + "username":"test@camunda.com", + "password":"password" + }, + "protocol":"smtp", + "data":{ + "smtpConfig":{ + "smtpHost":"localhost", + "smtpPort":"{{PORT}}", + "smtpCryptographicProtocol":"NONE" + }, + "smtpActionDiscriminator":"sendEmailSmtp", + "smtpAction":{ + "contentType":"MULTIPART", + "from":"camunda.connectors@camunda.com", + "to":"camunda.operate@camunda.com", + "subject":"Hey", + "body":"Content", + "htmlBody":"

Hey

" + } + } + }, + { + "authentication":{ + "type":"simple", + "username":"test@camunda.com", + "password":"password" + }, + "protocol":"smtp", + "data":{ + "smtpConfig":{ + "smtpHost":"localhost", + "smtpPort":"{{PORT}}", + "smtpCryptographicProtocol":"NONE" + }, + "smtpActionDiscriminator":"sendEmailSmtp", + "smtpAction":{ + "contentType":"MULTIPART", + "from":"camunda.connectors@camunda.com", + "to":"camunda.operate@camunda.com", + "subject":"Hey", + "body":"Content", + "htmlBody":"

Hey

", + "attachments":[ + { + "camunda.document.type":"camunda", + "storeId":"in-memory", + "documentId":"2ea3bfcc-7683-4cb6-c0ce-8052ca1d6da0", + "contentHash" : "2472332", + "metadata":{ + "contentType":"image/png", + "fileName":"test.png", + "size":66497, + "customProperties":{} + } + } + ] + } + } + } +] +