<div data-component="DocsIntegrationDocPage" class="docs-integration-doc-page" data-integration-title="MuleSoft Integration">
<img class="docs-integration-banner" src="/assets/integration-banners/mulesoft.svg" alt="MuleSoft and MailSlurp integration banner" loading="eager" decoding="async" />
<div class="docs-integration-content">

Test email flows in **MuleSoft Anypoint** using MailSlurp's disposable email addresses. This guide covers both flow-based (HTTP Connectors + DataWeave + MUnit) and Java SDK approaches for automation QA developers.

## Quick Links

- [Example Projects on GitHub](https://github.com/mailslurp/examples)
- [Flow-Based Example (MUnit + DataWeave)](https://github.com/mailslurp/examples/tree/master/mulesoft-anypoint-munit-otp-test)
- [Java SDK Example (JUnit + MailSlurp SDK)](https://github.com/mailslurp/examples/tree/master/mulesoft-anypoint-java-selenium-test)
- [MailSlurp API Documentation](/docs/api/)
- [Sign Up Free](https://app.mailslurp.com/sign-up/)

## Overview

MuleSoft developers can test email workflows using MailSlurp in two ways:

| Approach | Best For | Tools |
|----------|----------|-------|
| **Flow-Based** | MuleSoft idioms, visual design, enterprise patterns | HTTP Connector + DataWeave + MUnit |
| **Java SDK** | Direct API access, plain JUnit tests | MailSlurp Java Client + JUnit |

Both approaches use real email addresses that can receive and send emails during automated tests.

## Why MailSlurp for MuleSoft Testing?

- **Real Email Addresses** - Create disposable inboxes on-demand via API
- **API-First** - REST endpoints for all email operations (no IMAP/SMTP complexity)
- **OTP & Verification Flows** - Wait for emails with timeouts, extract codes with regex
- **Zero Configuration** - No mail servers to set up or maintain
- **MUnit Compatible** - Mock external services while using real email delivery
- **DataWeave Ready** - JSON responses work seamlessly with DataWeave transformations

## Setup

### Get an API Key

1. [Sign up for a free MailSlurp account](https://app.mailslurp.com/sign-up/)
2. Copy your API key from the dashboard
3. Store it securely (environment variable or secrets manager)

### Add Dependencies

#### Flow-Based (MUnit + HTTP Connector)

Add to `pom.xml`:

```xml
<dependencies>
    <!-- Mule Runtime -->
    <dependency>
        <groupId>org.mule.connectors</groupId>
        <artifactId>mule-http-connector</artifactId>
        <version>1.10.3</version>
        <classifier>mule-plugin</classifier>
    </dependency>

    <!-- DataWeave for transformations -->
    <dependency>
        <groupId>com.mulesoft.muleesb.modules</groupId>
        <artifactId>mule-module-ee-core</artifactId>
        <version>3.9.0</version>
    </dependency>

    <!-- MUnit for testing -->
    <dependency>
        <groupId>com.mulesoft.munit</groupId>
        <artifactId>munit-runner</artifactId>
        <version>3.3.1</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>com.mulesoft.munit</groupId>
        <artifactId>munit-tools</artifactId>
        <version>3.3.1</version>
        <scope>test</scope>
    </dependency>

    <!-- Java Module for Selenium integration -->
    <dependency>
        <groupId>org.mule.modules</groupId>
        <artifactId>mule-java-module</artifactId>
        <version>1.2.13</version>
        <classifier>mule-plugin</classifier>
    </dependency>

    <!-- Selenium WebDriver for browser automation -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.18.1</version>
    </dependency>
</dependencies>
```

#### Java SDK (JUnit + MailSlurp Client)

Add to `pom.xml`:

```xml
<dependencies>
    <!-- MailSlurp Java Client -->
    <dependency>
        <groupId>com.mailslurp</groupId>
        <artifactId>mailslurp-client-java</artifactId>
        <version>17.0.0</version>
    </dependency>

    <!-- JUnit for testing -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>

    <!-- Selenium WebDriver -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.18.1</version>
    </dependency>

    <!-- SLF4J Logging -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>2.0.5</version>
    </dependency>
</dependencies>
```

## Flow-Based Approach (MuleSoft Idioms)

The flow-based approach uses **native MuleSoft patterns**: visual flows, HTTP Connector, DataWeave transformations, and MUnit tests.

### Architecture

```
┌─────────────────────────────────────────────────────────────────┐
│                  otp-email-verification-flow                    │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────┐    ┌──────────────────┐    ┌──────────────┐   │
│  │ HTTP POST   │───▶│ DataWeave        │───▶│ Java Invoke  │   │
│  │ /inboxes    │    │ Extract inbox ID │    │ Browser      │   │
│  └─────────────┘    │ & email address  │    │ Signup       │   │
│                     └──────────────────┘    └──────────────┘   │
│                                                     │          │
│                                                     ▼          │
│  ┌─────────────┐    ┌──────────────────┐    ┌──────────────┐   │
│  │ HTTP GET    │◀───│ Wait for email   │◀───│              │   │
│  │ /waitFor... │    │                  │    │              │   │
│  └─────────────┘    └──────────────────┘    └──────────────┘   │
│         │                                                      │
│         ▼                                                      │
│  ┌──────────────────┐    ┌──────────────┐    ┌─────────────┐   │
│  │ DataWeave        │───▶│ Java Invoke  │───▶│ Success     │   │
│  │ Extract OTP      │    │ Enter Code   │    │ Response    │   │
│  │ using regex      │    │ & Login      │    │             │   │
│  └──────────────────┘    └──────────────┘    └─────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

### Configuration

Create `src/main/resources/config.yaml`:

```yaml
mailslurp:
  apiKey: "${MAILSLURP_API_KEY}"

test:
  password: "test-password"
```

### HTTP Request Configuration

Configure the MailSlurp API connection in your Mule flow XML:

```xml
<!-- HTTP Request Configuration for MailSlurp API -->
<http:request-config name="MailSlurp_HTTP_Config"
                      doc:name="HTTP Request configuration">
    <http:request-connection host="api.mailslurp.com"
                             protocol="HTTPS"
                             port="443"
                             connectionIdleTimeout="60000" />
</http:request-config>
```

### Step 1: Create Inbox

Use the HTTP Connector to create a real email inbox:

```xml
<flow name="otp-email-verification-flow">
    <!-- Create MailSlurp Inbox -->
    <http:request method="POST"
                  doc:name="Create Inbox"
                  config-ref="MailSlurp_HTTP_Config"
                  path="/inboxes">
        <http:headers>
            <![CDATA[#[{
                "x-api-key": p('mailslurp.apiKey'),
                "Content-Type": "application/json"
            }]]]>
        </http:headers>
    </http:request>

    <!-- Parse inbox response using DataWeave -->
    <ee:transform doc:name="Extract Inbox Details">
        <ee:message>
            <ee:set-payload><![CDATA[%dw 2.0
output application/java
var inboxResponse = payload
---
{
    inboxId: inboxResponse.id,
    emailAddress: inboxResponse.emailAddress
}]]></ee:set-payload>
        </ee:message>
        <ee:variables>
            <ee:set-variable variableName="inboxId"><![CDATA[%dw 2.0
output application/java
---
payload.id]]></ee:set-variable>
            <ee:set-variable variableName="emailAddress"><![CDATA[%dw 2.0
output application/java
---
payload.emailAddress]]></ee:set-variable>
        </ee:variables>
    </ee:transform>

    <logger level="INFO"
            message='#["Created inbox: " ++ vars.emailAddress]' />
</flow>
```

**API Response:**

```json
{
  "id": "abc-123-def-456",
  "emailAddress": "test-abc123@mailslurp.net",
  "createdAt": "2024-01-15T10:30:00.000Z"
}
```

### Step 2: Wait for Email

Use the `waitForLatestEmail` endpoint to wait for incoming emails:

```xml
<!-- Wait for confirmation email -->
<http:request method="GET"
              doc:name="Wait For Email"
              config-ref="MailSlurp_HTTP_Config"
              path="/waitForLatestEmail">
    <http:headers>
        <![CDATA[#[{
            "x-api-key": p('mailslurp.apiKey')
        }]]]>
    </http:headers>
    <http:query-params>
        <![CDATA[#[{
            "inboxId": vars.inboxId,
            "timeout": "60000",
            "unreadOnly": "true"
        }]]]>
    </http:query-params>
</http:request>
```

**API Response:**

```json
{
  "id": "email-789",
  "subject": "Please confirm your email address",
  "from": "noreply@example.com",
  "to": ["test-abc123@mailslurp.net"],
  "body": "Your verification code is:\n\n123456",
  "createdAt": "2024-01-15T10:31:00.000Z"
}
```

### Step 3: Extract OTP with DataWeave

Use **DataWeave regex** to extract verification codes:

```xml
<ee:transform doc:name="Extract OTP Code">
    <ee:message>
        <ee:set-payload><![CDATA[%dw 2.0
output application/java
import * from dw::core::Strings

var emailBody = payload.body default ""
// Extract 6-digit code at end of line
var codeMatch = emailBody scan /([0-9]{6})$/

---
{
    emailSubject: payload.subject,
    emailBody: emailBody,
    otpCode: if (sizeOf(codeMatch) > 0) codeMatch[0][1] else null
}]]></ee:set-payload>
    </ee:message>
    <ee:variables>
        <ee:set-variable variableName="otpCode"><![CDATA[%dw 2.0
output application/java
import * from dw::core::Strings

var emailBody = payload.body default ""
var codeMatch = emailBody scan /([0-9]{6})$/

---
if (sizeOf(codeMatch) > 0) codeMatch[0][1] else null]]></ee:set-variable>
    </ee:variables>
</ee:transform>

<logger level="INFO"
        message='#["Extracted OTP code: " ++ (vars.otpCode default "NOT FOUND")]' />

<!-- Validate OTP was found -->
<choice doc:name="Validate OTP">
    <when expression="#[vars.otpCode == null]">
        <raise-error type="APP:OTP_NOT_FOUND"
                     description="Could not extract OTP code from email body" />
    </when>
</choice>
```

**DataWeave Regex Patterns:**

| Pattern | Matches | Example |
|---------|---------|---------|
| `([0-9]{6})$` | 6-digit code at end of line | "Your code: 123456" |
| `code is:\s*(\d{6})` | Code after "code is:" | "Your code is: 456789" |
| `verification:\s*([A-Z0-9]{8})` | 8-char alphanumeric | "Verification: ABC12345" |

### Step 4: Success Response

Return structured JSON with test results:

```xml
<ee:transform doc:name="Success Response">
    <ee:message>
        <ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
    success: true,
    message: "OTP Email Verification Test Passed",
    details: {
        emailAddress: vars.emailAddress,
        inboxId: vars.inboxId,
        otpCodeVerified: true
    }
}]]></ee:set-payload>
    </ee:message>
</ee:transform>
```

### Error Handling

Add comprehensive error handling to your flow:

```xml
<error-handler>
    <on-error-propagate enableNotifications="true"
                        logException="true">
        <!-- Cleanup resources -->
        <try doc:name="Try Close Browser">
            <java:invoke instance="#[vars.browserHelper]"
                        class="com.smoketest.selenium.BrowserHelper"
                        method="closeBrowser()" />
            <error-handler>
                <on-error-continue enableNotifications="false"
                                   logException="false" />
            </error-handler>
        </try>

        <!-- Error response -->
        <ee:transform doc:name="Error Response">
            <ee:message>
                <ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
    success: false,
    message: "OTP Email Verification Test Failed",
    error: {
        type: error.errorType.identifier,
        description: error.description,
        detailedDescription: error.detailedDescription
    }
}]]></ee:set-payload>
            </ee:message>
        </ee:transform>
    </on-error-propagate>
</error-handler>
```

### MUnit Tests

Test your flow with MUnit:

```xml
<mule xmlns:munit="http://www.mulesoft.org/schema/mule/munit"
      xmlns:munit-tools="http://www.mulesoft.org/schema/mule/munit-tools"
      xmlns:http="http://www.mulesoft.org/schema/mule/http"
      xmlns="http://www.mulesoft.org/schema/mule/core">

    <munit:config name="otp-email-test-suite" />

    <munit:test name="otp-email-verification-flow-test"
                description="Test OTP email verification flow">
        <munit:execution>
            <!-- Execute the flow -->
            <flow-ref name="otp-email-verification-flow" />
        </munit:execution>

        <munit:validation>
            <!-- Assert success -->
            <munit-tools:assert-that
                expression="#[payload.success]"
                is="#[MunitTools::equalTo(true)]" />

            <!-- Assert OTP was verified -->
            <munit-tools:assert-that
                expression="#[payload.details.otpCodeVerified]"
                is="#[MunitTools::equalTo(true)]" />

            <!-- Assert email address is present -->
            <munit-tools:assert-that
                expression="#[payload.details.emailAddress]"
                is="#[MunitTools::notNullValue()]" />

            <!-- Assert inbox ID is present -->
            <munit-tools:assert-that
                expression="#[payload.details.inboxId]"
                is="#[MunitTools::notNullValue()]" />
        </munit:validation>
    </munit:test>

</mule>
```

### Running MUnit Tests

```bash
# Run all MUnit tests
mvn test

# Run specific test suite
mvn test -Dmunit.test=otp-email-test-suite

# Run specific test
mvn test -Dmunit.test=otp-email-test-suite#otp-email-verification-flow-test

# With verbose output
mvn test -X
```

## Java SDK Approach

The Java SDK approach uses the **MailSlurp Java client** for direct API access with standard JUnit tests.

### Configuration

Setup the MailSlurp client:

```java
import com.mailslurp.clients.ApiClient;
import com.mailslurp.clients.Configuration;
import com.mailslurp.apis.InboxControllerApi;
import com.mailslurp.apis.WaitForControllerApi;

public class EmailTest {
    private static final String MAILSLURP_API_KEY =
        System.getenv("MAILSLURP_API_KEY");

    private static ApiClient mailslurpClient;

    @BeforeClass
    public static void setup() {
        // Configure MailSlurp client
        mailslurpClient = Configuration.getDefaultApiClient();
        mailslurpClient.setApiKey(MAILSLURP_API_KEY);
        mailslurpClient.setConnectTimeout(60000);
    }
}
```

### Step 1: Create Inbox

```java
import com.mailslurp.models.InboxDto;

@Test
public void test_createInbox() throws ApiException {
    // Create a new inbox
    InboxControllerApi inboxApi = new InboxControllerApi(mailslurpClient);
    InboxDto inbox = inboxApi.createInboxWithDefaults().execute();

    // Verify inbox was created
    assertNotNull(inbox.getId());
    assertTrue(inbox.getEmailAddress().contains("@mailslurp"));

    System.out.println("Created inbox: " + inbox.getEmailAddress());
    // Example: "test-abc123@mailslurp.net"
}
```

### Step 2: Wait for Email

```java
import com.mailslurp.models.Email;

@Test
public void test_waitForEmail() throws ApiException {
    // Wait for email with timeout
    WaitForControllerApi waitApi = new WaitForControllerApi(mailslurpClient);
    Email email = waitApi.waitForLatestEmail()
        .inboxId(inbox.getId())
        .timeout(60000L)
        .unreadOnly(true)
        .execute();

    // Verify email was received
    assertNotNull(email.getId());
    assertTrue(email.getSubject().contains("confirmation"));

    System.out.println("Received email: " + email.getSubject());
}
```

### Step 3: Extract OTP Code

```java
import java.util.regex.Pattern;
import java.util.regex.Matcher;

@Test
public void test_extractOTP() {
    // Extract 6-digit OTP from email body
    String emailBody = email.getBody();
    Pattern pattern = Pattern.compile("([0-9]{6})$", Pattern.MULTILINE);
    Matcher matcher = pattern.matcher(emailBody);

    assertTrue("Email body should contain 6-digit code", matcher.find());
    String otpCode = matcher.group(1);

    assertEquals("OTP should be 6 digits", 6, otpCode.length());
    System.out.println("Extracted OTP: " + otpCode);
}
```

### Complete JUnit Test Example

```java
package com.smoketest.selenium;

import com.mailslurp.apis.InboxControllerApi;
import com.mailslurp.apis.WaitForControllerApi;
import com.mailslurp.clients.ApiClient;
import com.mailslurp.clients.ApiException;
import com.mailslurp.clients.Configuration;
import com.mailslurp.models.Email;
import com.mailslurp.models.InboxDto;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;

import static org.junit.Assert.*;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class OtpEmailVerificationTest {

    private static final String MAILSLURP_API_KEY =
        System.getenv("MAILSLURP_API_KEY");
    private static final Long TIMEOUT_MILLIS = 60000L;

    private static ApiClient mailslurpClient;
    private static InboxDto inbox;
    private static Email email;
    private static String confirmationCode;

    @BeforeClass
    public static void setup() {
        assertNotNull("MAILSLURP_API_KEY must be set", MAILSLURP_API_KEY);

        mailslurpClient = Configuration.getDefaultApiClient();
        mailslurpClient.setApiKey(MAILSLURP_API_KEY);
        mailslurpClient.setConnectTimeout(TIMEOUT_MILLIS.intValue());
    }

    @Test
    public void test1_createInbox() throws ApiException {
        System.out.println("Creating MailSlurp inbox...");

        InboxControllerApi inboxApi = new InboxControllerApi(mailslurpClient);
        inbox = inboxApi.createInboxWithDefaults().execute();

        assertNotNull(inbox.getId());
        assertTrue(inbox.getEmailAddress().contains("@mailslurp"));

        System.out.println("Created inbox: " + inbox.getEmailAddress());
    }

    @Test
    public void test2_receiveEmail() throws ApiException {
        System.out.println("Waiting for confirmation email...");

        WaitForControllerApi waitApi = new WaitForControllerApi(mailslurpClient);
        email = waitApi.waitForLatestEmail()
            .inboxId(inbox.getId())
            .timeout(TIMEOUT_MILLIS)
            .unreadOnly(true)
            .execute();

        assertTrue("Email subject should contain confirmation",
            email.getSubject().contains("confirm"));

        System.out.println("Received: " + email.getSubject());
    }

    @Test
    public void test3_extractOTP() {
        System.out.println("Extracting OTP code...");

        Pattern p = Pattern.compile("([0-9]{6})$", Pattern.MULTILINE);
        Matcher matcher = p.matcher(email.getBody());

        assertTrue("Email should contain 6-digit code", matcher.find());
        confirmationCode = matcher.group(1);

        assertEquals("Code should be 6 digits", 6, confirmationCode.length());
        System.out.println("Extracted OTP: " + confirmationCode);
    }
}
```

## Common Patterns

### Pattern 1: Create Inbox & Send Email

```xml
<!-- Flow-Based -->
<flow name="send-email-flow">
    <!-- Create inbox -->
    <http:request method="POST" path="/inboxes"
                  config-ref="MailSlurp_HTTP_Config">
        <http:headers>#[{"x-api-key": p('mailslurp.apiKey')}]</http:headers>
    </http:request>

    <!-- Extract email address -->
    <ee:transform>
        <ee:variables>
            <ee:set-variable variableName="emailAddress">
                <![CDATA[%dw 2.0
output application/java
---
payload.emailAddress]]>
            </ee:set-variable>
        </ee:variables>
    </ee:transform>

    <!-- Send email to inbox -->
    <http:request method="POST" path="/send-email"
                  config-ref="MailSlurp_HTTP_Config">
        <http:headers>#[{"x-api-key": p('mailslurp.apiKey')}]</http:headers>
        <http:body><![CDATA[#[%dw 2.0
output application/json
---
{
    to: [vars.emailAddress],
    subject: "Test Email",
    body: "Hello from MuleSoft!"
}]]]></http:body>
    </http:request>
</flow>
```

```java
// Java SDK
@Test
public void testSendEmail() throws ApiException {
    // Create inbox
    InboxControllerApi inboxApi = new InboxControllerApi(mailslurpClient);
    InboxDto inbox = inboxApi.createInboxWithDefaults().execute();

    // Send email
    SendEmailOptions options = new SendEmailOptions()
        .to(Arrays.asList(inbox.getEmailAddress()))
        .subject("Test Email")
        .body("Hello from MuleSoft!");

    inboxApi.sendEmail(inbox.getId(), options).execute();

    // Wait for email
    WaitForControllerApi waitApi = new WaitForControllerApi(mailslurpClient);
    Email email = waitApi.waitForLatestEmail()
        .inboxId(inbox.getId())
        .timeout(30000L)
        .execute();

    assertEquals("Test Email", email.getSubject());
}
```

### Pattern 2: Extract Links from Email

```xml
<!-- DataWeave: Extract first URL -->
<ee:transform>
    <ee:set-payload><![CDATA[%dw 2.0
output application/java
import * from dw::core::Strings

var emailBody = payload.body
var urlMatch = emailBody scan /(https?:\/\/[^\s]+)/

---
{
    firstUrl: if (sizeOf(urlMatch) > 0) urlMatch[0][1] else null
}]]></ee:set-payload>
</ee:transform>
```

```java
// Java: Extract first URL
Pattern p = Pattern.compile("(https?://[^\\s]+)");
Matcher matcher = p.matcher(email.getBody());

if (matcher.find()) {
    String url = matcher.group(1);
    System.out.println("Found URL: " + url);
}
```

### Pattern 3: Wait for Multiple Emails

```java
// Wait for multiple emails with unread-only filter
WaitForControllerApi waitApi = new WaitForControllerApi(mailslurpClient);

// Wait for first email
Email email1 = waitApi.waitForLatestEmail()
    .inboxId(inbox.getId())
    .timeout(60000L)
    .unreadOnly(true)
    .execute();

// Wait for second email (first one is now marked read)
Email email2 = waitApi.waitForLatestEmail()
    .inboxId(inbox.getId())
    .timeout(60000L)
    .unreadOnly(true)
    .execute();

// Get all emails
InboxControllerApi inboxApi = new InboxControllerApi(mailslurpClient);
PageEmailProjection emails = inboxApi.getEmails()
    .inboxId(inbox.getId())
    .execute();

System.out.println("Total emails: " + emails.getTotalElements());
```

## Best Practices

### 1. Use Environment Variables for API Keys

**Never hardcode API keys** in your Mule flows or Java code.

```xml
<!-- config.yaml -->
mailslurp:
  apiKey: "${MAILSLURP_API_KEY}"
```

```bash
# Set environment variable
export MAILSLURP_API_KEY=your_api_key_here
mvn test
```

### 2. Set Appropriate Timeouts

Email delivery is typically fast, but account for network delays:

```xml
<!-- MuleSoft: 60 second timeout -->
<http:query-params>
    <![CDATA[#[{
        "inboxId": vars.inboxId,
        "timeout": "60000"
    }]]]>
</http:query-params>
```

```java
// Java: 60 second timeout
email = waitApi.waitForLatestEmail()
    .inboxId(inbox.getId())
    .timeout(60000L)
    .execute();
```

### 3. Clean Up Resources

Always clean up browser sessions and resources in error handlers:

```xml
<error-handler>
    <on-error-propagate>
        <try>
            <java:invoke method="closeBrowser()"
                        instance="#[vars.browserHelper]" />
            <error-handler>
                <on-error-continue />
            </error-handler>
        </try>
    </on-error-propagate>
</error-handler>
```

```java
@AfterClass
public static void cleanup() {
    if (driver != null) {
        driver.quit();
    }
}
```

### 4. Use DataWeave for Complex Transformations

DataWeave is more powerful than Java regex for complex data extraction:

```xml
<ee:transform>
    <ee:set-payload><![CDATA[%dw 2.0
output application/java
import * from dw::core::Strings

var body = payload.body
var codeMatch = body scan /verification code:\s*([0-9]{6})/
var linkMatch = body scan /(https:\/\/[^\s]+verify[^\s]+)/
var expiryMatch = body scan /expires in (\d+) (hours|minutes)/

---
{
    verificationCode: if (sizeOf(codeMatch) > 0) codeMatch[0][1] else null,
    verificationLink: if (sizeOf(linkMatch) > 0) linkMatch[0][1] else null,
    expiryValue: if (sizeOf(expiryMatch) > 0) expiryMatch[0][1] else null,
    expiryUnit: if (sizeOf(expiryMatch) > 0) expiryMatch[0][2] else null
}]]></ee:set-payload>
</ee:transform>
```

### 5. Use MUnit Mocking for Unit Tests

Mock external services while testing your flows:

```xml
<munit:test name="test-with-mocked-email">
    <munit:behavior>
        <!-- Mock the HTTP request to return test data -->
        <munit-tools:mock-when processor="http:request">
            <munit-tools:with-attributes>
                <munit-tools:with-attribute attributeName="doc:name"
                                            whereValue="Wait For Email" />
            </munit-tools:with-attributes>
            <munit-tools:then-return>
                <munit-tools:payload value='#[{
                    "id": "test-email-123",
                    "subject": "Test Confirmation",
                    "body": "Your code: 123456"
                }]' mediaType="application/json" />
            </munit-tools:then-return>
        </munit-tools:mock-when>
    </munit:behavior>

    <munit:execution>
        <flow-ref name="otp-email-verification-flow" />
    </munit:execution>

    <munit:validation>
        <munit-tools:assert-equals
            actual="#[vars.otpCode]"
            expected="123456" />
    </munit:validation>
</munit:test>
```

## Troubleshooting

### API Key Not Set

**Error:**
```
401 Unauthorized
```

**Solution:**
Ensure `MAILSLURP_API_KEY` environment variable is set:

```bash
export MAILSLURP_API_KEY=your_api_key_here
echo $MAILSLURP_API_KEY  # Verify it's set
```

### Email Not Received

**Error:**
```
Timeout waiting for email
```

**Solutions:**

1. **Check inbox ID is correct**
```java
System.out.println("Waiting for inbox: " + inbox.getId());
```

2. **Increase timeout**
```xml
<http:query-params>
    #[{ "timeout": "120000" }]  <!-- 2 minutes -->
</http:query-params>
```

3. **Check email was actually sent**
```java
// List all emails in inbox
PageEmailProjection emails = inboxApi.getEmails()
    .inboxId(inbox.getId())
    .execute();
System.out.println("Total emails: " + emails.getTotalElements());
```

### OTP Not Extracted

**Error:**
```
OTP code is null
```

**Solutions:**

1. **Print email body to debug**
```xml
<logger level="INFO" message='#["Email body: " ++ payload.body]' />
```

2. **Test regex pattern**
```java
String emailBody = "Your verification code is:\n\n123456";
Pattern p = Pattern.compile("([0-9]{6})$", Pattern.MULTILINE);
Matcher m = p.matcher(emailBody);
if (m.find()) {
    System.out.println("Found: " + m.group(1));
}
```

3. **Adjust regex for your email format**

Common patterns:
- End of line: `([0-9]{6})$`
- After text: `code:\s*([0-9]{6})`
- Surrounded by spaces: `\s([0-9]{6})\s`
- Any 6 digits: `([0-9]{6})`

### MUnit Tests Timeout

**Error:**
```
Flow execution timeout
```

**Solution:**
Increase MUnit timeout in `munit:test`:

```xml
<munit:test name="otp-test"
            description="Test OTP flow"
            timeOut="120000">  <!-- 2 minutes -->
```

### Chrome Not Found (Selenium)

**Error:**
```
Cannot find Chrome binary
```

**Solution:**
Install Chrome or specify ChromeDriver path:

```java
System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
ChromeOptions options = new ChromeOptions();
options.setBinary("/path/to/chrome");
```

## Example Projects

### Flow-Based MUnit Example

Complete working example with visual Mule flows:

- **GitHub:** [mulesoft-anypoint-munit-otp-test](https://github.com/mailslurp/examples/tree/master/mulesoft-anypoint-munit-otp-test)
- **Features:**
  - Visual flow design in Anypoint Studio
  - HTTP Connector for MailSlurp API
  - DataWeave transformations
  - MUnit test suite with assertions
  - Selenium browser automation via Java Module

```bash
git clone https://github.com/mailslurp/examples.git
cd examples/mulesoft-anypoint-munit-otp-test

# Set API key
export MAILSLURP_API_KEY=your_api_key_here

# Run tests
mvn test

# Open in Anypoint Studio
# File → Import → Anypoint Studio project from File System
```

### Java SDK JUnit Example

Plain Java approach with MailSlurp client:

- **GitHub:** [mulesoft-anypoint-java-selenium-test](https://github.com/mailslurp/examples/tree/master/mulesoft-anypoint-java-selenium-test)
- **Features:**
  - Pure Java JUnit tests
  - MailSlurp Java client library
  - Selenium WebDriver integration
  - Standard Maven project structure

```bash
cd examples/mulesoft-anypoint-java-selenium-test

export MAILSLURP_API_KEY=your_api_key_here
mvn test
```

## API Reference

### Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/inboxes` | POST | Create a new email inbox |
| `/waitForLatestEmail` | GET | Wait for next email with timeout |
| `/send-email` | POST | Send email from inbox |
| `/inboxes/{inboxId}/emails` | GET | List all emails in inbox |

### Common Query Parameters

| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| `inboxId` | UUID | Target inbox ID | Required |
| `timeout` | Long | Wait timeout (ms) | 60000 |
| `unreadOnly` | Boolean | Only return unread emails | false |
| `since` | Date | Emails after this date | null |

### Authentication

All API requests require an API key via the `x-api-key` header:

```xml
<http:headers>
    <![CDATA[#[{ "x-api-key": p('mailslurp.apiKey') }]]]>
</http:headers>
```

```java
ApiClient client = Configuration.getDefaultApiClient();
client.setApiKey("your-api-key-here");
```

## DataWeave Quick Reference

### Extract 6-Digit Code

```dataweave
%dw 2.0
import * from dw::core::Strings
var body = payload.body
var match = body scan /([0-9]{6})$/
---
if (sizeOf(match) > 0) match[0][1] else null
```

### Extract URL

```dataweave
%dw 2.0
import * from dw::core::Strings
var body = payload.body
var match = body scan /(https?:\/\/[^\s]+)/
---
if (sizeOf(match) > 0) match[0][1] else null
```

### Extract Multiple Values

```dataweave
%dw 2.0
import * from dw::core::Strings
var body = payload.body
---
{
    code: (body scan /code:\s*([0-9]{6})/)[0][1],
    link: (body scan /(https:\/\/verify[^\s]+)/)[0][1],
    expiry: (body scan /expires:\s*(\d+)\s*(minutes|hours)/)[0][1]
}
```

### Parse HTML Email

```dataweave
%dw 2.0
import * from dw::core::Strings
var html = payload.body
// Strip HTML tags
var plainText = html replace /<[^>]+>/g with ""
// Extract from plain text
var code = (plainText scan /([0-9]{6})/)[0][1]
---
{ otpCode: code }
```

## Further Resources

- [MailSlurp Dashboard](https://app.mailslurp.com)
- [API Documentation](/docs/api/)
- [More Examples](https://github.com/mailslurp/examples)
- [Support Forum](https://www.mailslurp.com/support/)

## Support

Need help? Contact us:

- **Email:** [support@mailslurp.com](mailto:support@mailslurp.com)
- **Discord:** [Join our community](https://discord.gg/mailslurp)
- **GitHub Issues:** [mailslurp/examples](https://github.com/mailslurp/examples/issues)

---

*Last updated: February 2026*

</div>
</div>

