kestra-io / kestra-io/plugin-email

`MailSend`: required fields `from`/`to` (and `host`) are not validated — omitting them fails at runtime

Open Beginner friendly
#70 0 comments 0 reactions 0 assignees View on GitHub
area/plugin good first issue kind/quick-win
Dominant language
Java
Stars
2
Forks
3
Avg merge
17h 35m
Merged PRs (30d)
5

Description

### Describe the issue

## Summary

`MailSend` treats `from` and `to` as required — `buildEmail()` calls `orElseThrow()` on both — but neither carries `@NotNull`. Omitting one therefore fails at run time with a raw `NoSuchElementException` instead of being rejected at flow validation. `host` similarly has no `@NotNull` and, when omitted, is passed to the mailer as `null` and fails at connection time.

Found during a documentation audit; docs branch adds "Required." to the `from`/`to` descriptions but the validation gap is a code fix.

## Details

**`src/main/java/io/kestra/plugin/email/MailSend.java`**

- `from` (L253-254) and `to` (L260-261) have `@PluginProperty(...)` but no `@NotNull`.
- `buildEmail()` (L379-381) requires them:
```java
EmailPopulatingBuilder builder = EmailBuilder.startingBlank()
.to(runContext.render(to).as(String.class).orElseThrow())
.from(runContext.render(from).as(String.class).orElseThrow())
```
- `host` (L193-194) has no `@NotNull` either; `run()` renders it with `.orElse(null)` and passes it to `MailerBuilder.withSMTPServer(host, ...)`, so a missing host fails only when the connection is attempted. (Examples 2 and 3 in the task omit `host`/credentials, relying on plugin defaults.)

## Impact

- A flow missing `from` or `to` passes validation, then throws a raw `NoSuchElementException` at execution — an opaque error rather than a clear "field is required" validation failure.
- A flow missing `host` (without plugin defaults) fails at connection time rather than validation.

## Suggested fix

- Add `@NotNull` to `from` and `to` (and consider `host`, unless it is intentionally optional so it can be supplied via plugin defaults).

## Verification

Reproduced by unit tests — `buildEmail()` throws before any SMTP connection, so no mail server is required. Both pass against current `main`:

```java
package io.kestra.plugin.email;

import java.util.NoSuchElementException;

import org.junit.jupiter.api.Test;

import io.kestra.core.junit.annotations.KestraTest;
import io.kestra.core.models.property.Property;
import io.kestra.core.runners.RunContext;
import io.kestra.core.runners.RunContextFactory;

import jakarta.inject.Inject;

import static org.junit.jupiter.api.Assertions.assertThrows;

@KestraTest
class DocReviewBugVerificationTest {

@Inject
private RunContextFactory runContextFactory;

@Test
void missingTo_throwsNoSuchElementExceptionAtRuntime() {
RunContext runContext = runContextFactory.of();
MailSend task = MailSend.builder()
.from(Property.ofValue("from@mail.com"))
.host(Property.ofValue("smtp.example.com"))
.port(Property.ofValue(465))
.subject(Property.ofValue("subject"))
.htmlTextContent(Property.ofValue("body"))
// no `to`
.build();
assertThrows(NoSuchElementException.class, () -> task.run(runContext));
}

@Test
void missingFrom_throwsNoSuchElementExceptionAtRuntime() {
RunContext runContext = runContextFactory.of();
MailSend task = MailSend.builder()
.to(Property.ofValue("to@mail.com"))
.host(Property.ofValue("smtp.example.com"))
.port(Property.ofValue(465))
.subject(Property.ofValue("subject"))
.htmlTextContent(Property.ofValue("body"))
// no `from`
.build();
assertThrows(NoSuchElementException.class, () -> task.run(runContext));
}
}
```

Result: both tests pass — omitting `from` or `to` throws `NoSuchElementException` from `buildEmail()` at run time.

### Environment

- Kestra Version: develop

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in src/main/java/io/kestra/plugin/email/MailSend.java by inspecting the from, to, and host properties and the buildEmail() and run() paths. Use the supplied DocReviewBugVerificationTest cases as the starting verification, then confirm that missing required fields are rejected during validation rather than producing runtime failures.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
88/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.