pentaho/pentaho-kettle · error · KettleException
MailConnection.Error.SavingAttachedFiles
Error message
MailConnection.Error.SavingAttachedFiles
What it means
The attachment-saving path (saveMessageAttachedFiles and its multipart handling) wraps exceptions from getMessage().getContent() and handleMultipart() into a KettleException with MailConnection.Error.SavingAttachedFiles, including message number and target folder. It means message content or its attachments could not be read/saved.
Solutions
- Check the chained cause — MessagingException during getContent means malformed MIME; skip or re-fetch that message.
- Ensure the destination folder exists and is writable before saving attachments.
- Sanitize attachment filenames from Content-Disposition headers (strip path separators and illegal chars).
- Verify enough disk space for all attachments; process messages in batches.
Example fix
// before
String name = part.getFileName(); // may contain '/' or be null
writeToDisk(name, part.getInputStream());
// after
String name = BaseMessages sanitized: part.getFileName() == null ? "unnamed" : part.getFileName().replaceAll("[/\\\\:*?\"<>|]", "_");
writeToDisk(name, part.getInputStream()); Defensive patterns
Strategy: try-catch
Validate before calling
java.io.File dir = new java.io.File(targetFolder);
if (!dir.isDirectory()) dir.mkdirs();
if (!dir.canWrite()) throw new KettleException("No write permission: " + targetFolder);
// pre-check free space if attachments can be large Try / catch
try {
mailConnection.saveMessageAttachedFiles(pattern, targetFolder);
} catch (KettleException e) {
logError("Attachment save failed for message " + msgNr + ": " + e.getCause().getMessage(), e);
// optionally skip this message and continue
} Prevention
- Skip-and-log corrupted/non-MIME messages instead of failing the whole job
- Sanitize attachment filenames from Content-Disposition headers
- Pre-create and permission the attachment directory
- Watch disk usage when saving large attachments in bulk
When it happens
Trigger: During MailConnection use, content = getMessage().getContent() throws (MessagingException/IOException reading body parts) or handleMultipart fails writing an attachment file.
Common situations: Corrupted or non-MIME message bodies, nested multiparts with unsupported encodings, attachment filenames with illegal path characters, target folder missing or unwritable, disk full while saving large attachments.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- MailConnection.Error.CountingAttachedFiles
- MailConnection.Error.SavingMessageContent
- Cannot open control file
- Cannot open data file
- ChangeFileEncoding.Error.CreatingFile
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/53bcc6d280952918.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/email-messages/impl/src/main/java/org/pentaho/di/job/entries/getpop/MailConnection.java:930
/**
* Save attached files to a folder.
*
* @param foldername
* the target foldername
* @param pattern
* regular expression to filter on files
* @throws KettleException
*/
public void saveAttachedFiles( String foldername, Pattern pattern ) throws KettleException {
Object content = null;
try {
content = getMessage().getContent();
if ( content instanceof Multipart ) {
handleMultipart( foldername, (Multipart) content, pattern );
}
} catch ( Exception e ) {
throw new KettleException( BaseMessages.getString( PKG, "MailConnection.Error.SavingAttachedFiles", ""
+ this.message.getMessageNumber(), foldername ), e );
} finally {
if ( content != null ) {
content = null;
}
}
}
private void handleMultipart( String foldername, Multipart multipart, Pattern pattern ) throws KettleException {
try {
for ( int i = 0, n = multipart.getCount(); i < n; i++ ) {
handlePart( foldername, multipart.getBodyPart( i ), pattern );
}
} catch ( Exception e ) {
throw new KettleException( e );
}
}
View on GitHub (pinned to f3058517a1)