Elements version 3.8+
EmailService is a first-class platform service for sending transactional email via SMTP. It is available to platform code through normal Guice injection and to plugin developers through the standard element injection mechanism.
Interface #
package dev.getelements.elements.sdk.service.email;
public interface EmailService {
void send(String from, String to, String subject, String body, boolean html);
}
| Parameter | Description |
|---|---|
from | Sender address. Pass null or blank to use the configured DEFAULT_FROM. |
to | Recipient address. |
subject | Subject line. |
body | Message body – plain text or HTML depending on the html flag. |
html | true -> text/html false -> text/plain |
Throws InvalidDataException if SMTP is not configured (i.e. SMTP_HOST is blank).
Platform configuration #
Configure the platform-level SMTP connection via system defines (JVM properties or environment variables). These apply to the entire server and to any code running outside an element context.
| Constant key | Default | Description |
|---|---|---|
dev.getelements.elements.email.smtp.host | (blank – disabled) | SMTP hostname. Leave blank to disable email at the platform level. |
dev.getelements.elements.email.smtp.port | 587 | SMTP port. |
dev.getelements.elements.email.smtp.starttls | true | Enable STARTTLS. |
dev.getelements.elements.email.smtp.user | (blank) | SMTP username. |
dev.getelements.elements.email.smtp.password | (blank) | SMTP password. |
dev.getelements.elements.email.default.from | (blank) | Default sender address used when from is null. |
Example (passing as JVM system properties on startup):
-Ddev.getelements.elements.email.smtp.host=smtp.sendgrid.net
-Ddev.getelements.elements.email.smtp.port=587
-Ddev.getelements.elements.email.smtp.starttls=true
-Ddev.getelements.elements.email.smtp.user=apikey
-Ddev.getelements.elements.email.smtp.password=SG.xxxxx
-Ddev.getelements.elements.email.default.from=noreply@mygame.com
Using EmailService in platform code #
Once SMTP is configured, inject EmailService anywhere in the platform service layer:
import dev.getelements.elements.sdk.service.email.EmailService;
import jakarta.inject.Inject;
public class MyPlatformService {
private EmailService emailService;
public void notifyUser(String userEmail, String message) {
emailService.send(null, userEmail, "Notification", message, false);
}
@Inject
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
}
For UNSCOPED platform code inject with @Named(Constants.UNSCOPED):
@Inject @Named(Constants.UNSCOPED)
public void setEmailService(EmailService emailService) { ... }
Using EmailService inside a custom Element #
EmailService is bound in the platform Guice injector and is visible to element child injectors. Inject it directly – no additional ELM dependency is needed.
import dev.getelements.elements.sdk.service.email.EmailService;
import jakarta.inject.Inject;
public class WelcomeEmailService {
private EmailService emailService;
public void sendWelcome(String toAddress, String displayName) {
final var body = "<h2>Welcome, " + displayName + "!</h2>"
+ "<p>Thanks for joining. Good luck out there.</p>";
emailService.send(null, toAddress, "Welcome to the game!", body, true);
}
@Inject
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
}
SMTP is configured at the platform level (see above) and shared across all elements.
Graceful degradation #
If SMTP_HOST is blank the service logs a warning and any call to EmailService.send() throws InvalidDataException with the message "Email service is not configured (SMTP_HOST is blank)." – no NPE, no silent failure.
This means you can start the server and configure SMTP later without any crash on startup.
Warning
If DEFAULT_FROM is not configured and null or blank is passed as the from argument, the message will be sent with a blank From header. Most SMTP servers will reject this with a 5xx error. Always set DEFAULT_FROM in production, or ensure every call to send() provides an explicit from address.
See also #
- Email Verification – built-in email-based UID verification using
EmailVerificationService, including token lifecycle, REST endpoints, and custom templates.
Overriding the mail transport (advanced) #
To replace the default SMTP implementation entirely – for example, to use a cloud-native sending SDK – rebind EmailService in your element’s Guice module:
public class MyGameElementModule extends AbstractModule {
@Override
protected void configure() {
bind(EmailService.class).to(MyCustomEmailService.class);
}
}
MyCustomEmailService implements dev.getelements.elements.sdk.service.email.EmailService and can use any transport mechanism. The binding in the element’s child injector takes precedence over the platform binding for all code within that element.

