quarkusio/quarkus · error · IllegalArgumentException
Unable to send an email
Error message
Unable to send an email
What it means
MutinyMailerImpl.validate() catches IllegalArgumentException from address parsing when an email address is invalid. When logInvalidRecipients is enabled (quarkus.mailer.log-invalid-recipients=true), it logs and rethrows with the generic message "Unable to send an email", preserving the original exception (which contains the offending address) as the cause.
Source
Thrown at extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MutinyMailerImpl.java:247
private void validate(List<String> to, List<String> cc, List<String> bcc) {
try {
for (String email : to) {
new EmailAddress(email);
}
for (String email : cc) {
new EmailAddress(email);
}
for (String email : bcc) {
new EmailAddress(email);
}
} catch (IllegalArgumentException e) {
// One of the email addresses is invalid
if (logInvalidRecipients) {
// We are allowed to log the invalid email address
// The exception message contains the invalid email address.
LOGGER.warn("Unable to send an email", e);
throw new IllegalArgumentException("Unable to send an email", e);
} else {
// Do not print the invalid email address.
LOGGER.warn("Unable to send an email, an email address is invalid");
throw new IllegalArgumentException("Unable to send an email, an email address is invalid");
}
}
}
private MultiMap toMultimap(Map<String, List<String>> headers) {
MultiMap mm = MultiMap.caseInsensitiveMultiMap();
headers.forEach(mm::add);
return mm;
}
private Uni<MailAttachment> toMailAttachment(Attachment attachment) {
MailAttachment attach = MailAttachment.create();
attach.setName(attachment.getName());
attach.setContentId(attachment.getContentId());View on GitHub (pinned to e1c734241f)
Solutions
- Validate/normalize email addresses before building the Mail (regex or a validation library like Commons Validator / Hibernate Validator @Email).
- Inspect the cause of the exception — it names the invalid address; fix that specific value.
- If addresses come from user input, add form-level validation and reject invalid input early.
- Trim whitespace and ensure the "Name <addr>" syntax is correct for display-name addresses.
Example fix
// before
String to = request.getEmail(); // unchecked
mailer.send(Mail.withText(to, subject, body));
// after
String to = request.getEmail().trim();
if (to.matches("^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$")) {
mailer.send(Mail.withText(to, subject, body));
} else {
throw new WebApplicationException("Invalid recipient", 400);
} Defensive patterns
Strategy: validation
Validate before calling
private static final Pattern EMAIL = Pattern.compile("^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$");
if (!EMAIL.matcher(recipient.trim()).matches()) {
throw new IllegalArgumentException("Invalid recipient: " + recipient);
} Type guard
static boolean isValidEmail(String address) {
return address != null && !address.isBlank() && EMAIL.matcher(address.trim()).matches();
} Try / catch
try {
mailer.send(mail).await().indefinitely();
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Unable to send an email")) {
LOG.errorf(e, "Email address rejected; cause names the invalid address");
}
throw e;
} Prevention
- Validate all recipient fields (to/cc/bcc/from/reply-to) before building Mail
- Trim and normalize user-supplied addresses at the boundary
- Use bean validation (@Email) on DTOs carrying addresses
- Enable log-invalid-recipients in dev/test to see offending values
When it happens
Trigger: Sending a mail whose to/cc/bcc/from/reply-to address fails address validation (e.g. "not-an-email", missing domain, unbalanced quotes) while log-invalid-recipients is true.
Common situations: User-supplied addresses with typos or stray whitespace/characters; addresses assembled by string concatenation (e.g. name <email> with malformed name part); test data with placeholder addresses like "foo@bar" missing TLD depending on parser strictness.
Related errors
- Unable to send an email, an email address is invalid
- The `mails` parameter must not be `null`
- An attachment must contain either a file or a raw data
- Name cannot start with '/':${name}
- Predicate already set
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/c7d4b83210151197.
Report an issue: GitHub.