Skip to content

Email API

The Email class represents a decrypted email with all content and metadata. Email objects are largely immutable after construction.

public class Email

An email contains standard properties (from, to, subject, body) plus additional metadata like authentication results (SPF, DKIM, DMARC) and extracted content (links, attachments).

Content availability:

  • Emails from inbox.listEmails(), inbox.getEmail(), and waitForEmail() have full content
  • Use inbox.listEmailsMetadataOnly() if you only need metadata (returns EmailMetadata objects)
PropertyTypeDescription
idStringUnique email identifier
fromStringSender email address
toList<String>Recipient addresses
subjectStringEmail subject line
receivedAtInstantWhen email was received
isReadbooleanRead status
public String getId()
public String getFrom()
public List<String> getTo()
public String getSubject()
public Instant getReceivedAt()
public boolean isRead()
PropertyTypeDescription
textStringPlain text body (may be null)
htmlStringHTML body (may be null)
public String getText() // May return null
public String getHtml() // May return null

Note: Both may be null if the email doesn’t contain that content type (e.g., plain text only or HTML only emails).

PropertyTypeDescription
linksList<String>URLs extracted from content
attachmentsList<Attachment>File attachments
authResultsAuthResultsSPF/DKIM/DMARC results
spamAnalysisSpamAnalysisResultSpam analysis results
headersMap<String, String>Raw email headers
metadataMap<String, Object>Additional metadata
public List<String> getLinks()
public List<Attachment> getAttachments()
public AuthResults getAuthResults() // May return null
public SpamAnalysisResult getSpamAnalysis() // May return null
public Map<String, String> getHeaders()
public Map<String, Object> getMetadata()
public Boolean isSpam() // Returns true/false if analyzed, null if not
public Double getSpamScore() // Returns score if analyzed, null if not

Marks this email as read.

public void markAsRead()

Updates both the server state and the local isRead() flag.

Throws:

  • ApiException - on API errors
  • NetworkException - on network connectivity issues

Deletes this email from the inbox.

public void delete()

Throws:

  • ApiException - on API errors
  • NetworkException - on network connectivity issues

Gets the raw RFC822 MIME content.

public String getRaw()

Returns: Raw email string including all headers

Throws:

  • ApiException - on API errors
  • NetworkException - on network connectivity issues

Represents an email attachment.

public class Attachment
PropertyTypeDescription
filenameStringOriginal filename
contentTypeStringMIME type
sizeintSize in bytes
contentbyte[]Decrypted content
public String getFilename()
public String getContentType()
public int getSize()
public byte[] getContent() // Returns defensive copy, may be null

Saves the attachment content to a file.

public void saveTo(Path path) throws IOException

Parameters:

  • path - Destination file path

Throws:

  • IOException - on write errors
  • IllegalStateException - if content is not available
for (Attachment att : email.getAttachments()) {
System.out.printf("File: %s (%s, %d bytes)%n",
att.getFilename(),
att.getContentType(),
att.getSize());
// Save to disk
att.saveTo(Path.of("/tmp", att.getFilename()));
// Or process in memory
byte[] content = att.getContent();
}

Email authentication validation results.

public class AuthResults
public SpfResult getSpf()
public List<DkimResult> getDkim()
public DmarcResult getDmarc()
public ReverseDnsResult getReverseDns()

Returns a summary of passed and failed authentication checks.

public AuthValidation validate()

Returns: AuthValidation with lists of passed and failed checks

Example:

AuthResults auth = email.getAuthResults();
if (auth != null) {
AuthValidation validation = auth.validate();
System.out.println("Passed: " + validation.getPassed());
System.out.println("Failed: " + validation.getFailed());
}

Summary of authentication check results.

public class AuthValidation
MethodReturn TypeDescription
getPassed()List<String>List of passed checks (e.g., [“SPF”, “DKIM”])
getFailed()List<String>List of failed checks with reasons
getFailures()List<String>Alias for getFailed()
isFullyAuthenticated()booleanTrue if all checks passed
isPassed()booleanAlias for isFullyAuthenticated()
hasSpf()booleanTrue if SPF passed
hasDkim()booleanTrue if DKIM passed
hasDmarc()booleanTrue if DMARC passed
hasReverseDns()booleanTrue if reverse DNS passed

Example:

AuthValidation validation = auth.validate();
if (validation.isFullyAuthenticated()) {
System.out.println("All authentication checks passed!");
} else {
System.out.println("Failed checks: " + validation.getFailed());
}
// Check specific results
if (validation.hasSpf() && validation.hasDkim()) {
System.out.println("SPF and DKIM both passed");
}

SPF (Sender Policy Framework) validation result.

PropertyTypeDescription
resultStringpass, fail, softfail, neutral, none, temperror, permerror, skipped
domainStringChecked domain
ipStringIP address of the sending server
detailsStringAdditional explanation about the result
public String getResult()
public String getDomain()
public String getIp()
public String getDetails()

DKIM (DomainKeys Identified Mail) signature result.

PropertyTypeDescription
resultStringpass, fail, none, skipped
domainStringSigning domain
selectorStringDKIM selector used
signatureStringDKIM signature information
public String getResult()
public String getDomain()
public String getSelector()
public String getSignature()

Note: AuthResults.getDkim() returns a List<DkimResult> since emails can have multiple DKIM signatures.

DMARC (Domain-based Message Authentication) result.

PropertyTypeDescription
resultStringpass, fail, none, skipped
domainStringFrom domain
policyStringnone, quarantine, reject
alignedBooleanWhether SPF/DKIM align with the From header domain
public String getResult()
public String getDomain()
public String getPolicy()
public Boolean getAligned() // May return null
public boolean isAligned() // Returns true if aligned, false otherwise

Reverse DNS verification result.

PropertyTypeDescription
resultStringResult: pass, fail, none, skipped
ipStringIP address of the sending server
hostnameStringResolved hostname from PTR record
StatusMeaning
passPTR record matches and resolves correctly
failPTR record doesn’t match or doesn’t resolve
noneNo PTR record found
skippedCheck was skipped (inbox has emailAuth: false)
public String getResult()
public boolean isVerified() // Convenience: returns true if result is "pass"
public String getIp()
public String getHostname()
Email email = inbox.waitForEmail();
System.out.println("ID: " + email.getId());
System.out.println("From: " + email.getFrom());
System.out.println("To: " + email.getTo());
System.out.println("Subject: " + email.getSubject());
System.out.println("Received: " + email.getReceivedAt());
System.out.println("Read: " + email.isRead());
// Content (check for null)
if (email.getText() != null) {
System.out.println("Text body:\n" + email.getText());
}
if (email.getHtml() != null) {
System.out.println("HTML body:\n" + email.getHtml());
}
List<String> links = email.getLinks();
System.out.println("Found " + links.size() + " links");
// Find specific link
Optional<String> resetLink = links.stream()
.filter(l -> l.contains("/reset-password"))
.findFirst();
if (resetLink.isPresent()) {
String url = resetLink.get();
System.out.println("Reset link: " + url);
// Navigate to URL or extract token
}
// Find all links matching a pattern
List<String> confirmLinks = links.stream()
.filter(l -> l.contains("/confirm") || l.contains("/verify"))
.collect(Collectors.toList());
List<Attachment> attachments = email.getAttachments();
if (attachments.isEmpty()) {
System.out.println("No attachments");
} else {
for (Attachment att : attachments) {
System.out.printf("Attachment: %s (%s, %d bytes)%n",
att.getFilename(),
att.getContentType(),
att.getSize());
// Save to temp directory
Path dest = Path.of(System.getProperty("java.io.tmpdir"), att.getFilename());
att.saveTo(dest);
System.out.println("Saved to: " + dest);
}
}
AuthResults auth = email.getAuthResults();
if (auth == null) {
System.out.println("No authentication results available");
return;
}
// Check individual results
if (auth.getSpf() != null) {
System.out.println("SPF: " + auth.getSpf().getResult() +
" (domain: " + auth.getSpf().getDomain() + ")");
}
if (auth.getDkim() != null && !auth.getDkim().isEmpty()) {
for (DkimResult dkim : auth.getDkim()) {
System.out.println("DKIM: " + dkim.getResult() +
" (domain: " + dkim.getDomain() +
", selector: " + dkim.getSelector() + ")");
}
}
if (auth.getDmarc() != null) {
System.out.println("DMARC: " + auth.getDmarc().getResult() +
" (policy: " + auth.getDmarc().getPolicy() + ")");
}
if (auth.getReverseDns() != null) {
System.out.println("Reverse DNS: " + auth.getReverseDns().getResult() +
" (ip: " + auth.getReverseDns().getIp() +
", hostname: " + auth.getReverseDns().getHostname() + ")");
}
// Use validation summary
AuthValidation validation = auth.validate();
System.out.println("Passed checks: " + validation.getPassed());
System.out.println("Failed checks: " + validation.getFailed());
System.out.println("Fully authenticated: " + validation.isFullyAuthenticated());
Map<String, String> headers = email.getHeaders();
// Get specific header
String contentType = headers.get("Content-Type");
if (contentType != null) {
System.out.println("Content-Type: " + contentType);
}
String messageId = headers.get("Message-ID");
String inReplyTo = headers.get("In-Reply-To");
// List all headers
System.out.println("All headers:");
headers.forEach((name, value) ->
System.out.println(" " + name + ": " + value)
);
// Check and update read status
if (!email.isRead()) {
// Process email
processEmail(email);
// Mark as read
email.markAsRead();
System.out.println("Marked as read");
}
// Delete when done
email.delete();
System.out.println("Email deleted");
// Get raw MIME content
String raw = email.getRaw();
System.out.println("Raw email length: " + raw.length() + " bytes");
// Parse with javax.mail or similar
// MimeMessage message = new MimeMessage(session, new ByteArrayInputStream(raw.getBytes()));

Spam analysis results from Rspamd integration.

public class SpamAnalysisResult
PropertyTypeDescription
statusSpamAnalysisStatusAnalysis status (ANALYZED, SKIPPED, ERROR)
scoreDoubleOverall spam score (null if not analyzed)
requiredScoreDoubleThreshold for spam classification
actionSpamActionRecommended action
isSpamBooleanWhether email is classified as spam
symbolsList<SpamSymbol>Individual triggered rules
processingTimeMsLongAnalysis time in milliseconds
infoStringAdditional info (skip reason or error message)
MethodReturn TypeDescription
getStatus()SpamAnalysisStatusReturns the analysis status
getScore()DoubleReturns spam score (null if not analyzed)
getRequiredScore()DoubleReturns threshold score
getAction()SpamActionReturns recommended action
isSpam()BooleanReturns true if spam, false if ham, null if unknown
getSymbols()List<SpamSymbol>Returns triggered rules (never null)
getProcessingTimeMs()LongReturns processing time in milliseconds
getInfo()StringReturns info message (skip/error reason)
isAnalyzed()booleanReturns true if status is ANALYZED
getSpamIndicators()List<SpamSymbol>Returns positive-score symbols (spam indicators)
getLegitimacyIndicators()List<SpamSymbol>Returns negative-score symbols (ham indicators)
SpamAnalysisResult spam = email.getSpamAnalysis();
if (spam != null && spam.isAnalyzed()) {
System.out.println("Score: " + spam.getScore() + " / " + spam.getRequiredScore());
System.out.println("Is spam: " + spam.isSpam());
System.out.println("Action: " + spam.getAction());
// Show top spam indicators
for (SpamSymbol symbol : spam.getSpamIndicators()) {
System.out.printf(" %s: +%.1f%n", symbol.getName(), symbol.getScore());
}
}

Status of spam analysis.

public enum SpamAnalysisStatus
ValueDescription
ANALYZEDEmail was successfully analyzed by Rspamd
SKIPPEDAnalysis was skipped (disabled globally or per-inbox)
ERRORAnalysis failed (Rspamd unavailable, timeout, etc.)

Recommended action from Rspamd based on spam score thresholds.

public enum SpamAction
ValueDescription
NO_ACTIONEmail is clean, deliver normally
GREYLISTTemporarily reject and retry later
ADD_HEADERAdd spam headers but deliver the email
REWRITE_SUBJECTModify subject to indicate spam
SOFT_REJECTTemporary rejection (4xx SMTP code)
REJECTPermanent rejection (5xx SMTP code)

Represents an individual spam rule/symbol that triggered during analysis.

public class SpamSymbol
PropertyTypeDescription
nameStringRule identifier (e.g., DKIM_SIGNED)
scoredoubleScore contribution (positive = spam, negative = ham)
descriptionStringHuman-readable explanation (may be null)
optionsList<String>Additional context or matched values
MethodReturn TypeDescription
getName()StringReturns the rule identifier
getScore()doubleReturns the score contribution
getDescription()StringReturns description (may be null)
getOptions()List<String>Returns options (never null)
SymbolTypical ScoreMeaning
DKIM_SIGNED-0.1Email has valid DKIM signature
SPF_ALLOW-0.2SPF check passed
FORGED_SENDER+3.0Sender address appears forged
RCVD_IN_SBL+6.5Sender in Spamhaus blocklist
SpamAnalysisResult spam = email.getSpamAnalysis();
if (spam != null && spam.getSymbols() != null) {
System.out.println("Triggered rules:");
for (SpamSymbol symbol : spam.getSymbols()) {
String sign = symbol.getScore() >= 0 ? "+" : "";
System.out.printf(" %s: %s%.1f%n",
symbol.getName(), sign, symbol.getScore());
if (symbol.getDescription() != null) {
System.out.println(" " + symbol.getDescription());
}
}
}
  • Email objects are largely immutable after construction
  • The isRead flag uses volatile for thread-safe reads
  • Methods that modify state (markAsRead(), delete()) make API calls
  • All collection properties return immutable copies