pentaho/pentaho-kettle · error · JavaScriptException

sendMail

Error message

sendMail: {e.toString()}

What it means

Thrown by the sendMail JavaScript function when the underlying javax.mail send fails. After building a MimeMessage (SMTP host, from, recipients, subject, body) the function calls Transport.send(msg); any MessagingException or address problem is caught and re-thrown as 'sendMail: ' + e.toString(), so the text after the prefix contains the real Java exception (e.g. UnknownHostException, AuthenticationFailedException).

Solutions

  1. Read the text after 'sendMail: ' — it names the underlying Java exception; fix accordingly.
  2. Verify the SMTP hostname and that the port is reachable (telnet host 25) from the Kettle server.
  3. If the server requires auth or TLS, use the Mail step or add mail.smtp.auth/mail.smtp.starttls session properties instead of sendMail().
  4. Validate recipient address syntax before calling; strip whitespace and semicolons not accepted by InternetAddress.

Example fix

// before (host unreachable)
sendMail("smtp.wronghost.local", from, to, subject, body)
// after (verify first)
if ( smtpHost != null && smtpHost.indexOf(".") >= 0 ) sendMail(smtpHost, from, to, subject, body)
Defensive patterns

Strategy: try-catch

Validate before calling

// JS
function safeSendMail(host, from, to, subj, body) {
  if (!host || !from || !to || subj == null || body == null) return false;
  try { sendMail(host, from, to, subj, body); return true; } catch (e) { return false; }
}

Type guard

function canSendMail(args) { return args.length === 5 && args.every(function(a){ return a != null; }); }

Try / catch

try { sendMail(host, from, to, subj, body); } catch (e) { logError("sendMail failed: " + e); }

Prevention

When it happens

Trigger: Calling sendMail(smtpHost, from, recipients, subject, body) where the SMTP host is unresolvable, the server rejects the connection or authentication, a recipient address is malformed, or the mail session cannot be established.

Common situations: Wrong SMTP host/port in a Kettle job's JavaScript step; corporate firewall blocking port 25; unauthenticated relaying now required (550 relay denied); typo'd recipient addresses; missing mail.jar/activation dependencies in older setups.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/8a166808b8c3b52a. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/scriptvalues_mod/ScriptValuesAddedFunctions.java:1279

        // Get Recipients
        String[] strArrRecipients = ( (String) ArgList[2] ).split( "," );

        InternetAddress[] addressTo = new InternetAddress[strArrRecipients.length];
        for ( int i = 0; i < strArrRecipients.length; i++ ) {
          addressTo[i] = new InternetAddress( strArrRecipients[i] );
        }
        msg.setRecipients( Message.RecipientType.TO, addressTo );

        // Optional : You can also set your custom headers in the Email if you Want
        msg.addHeader( "MyHeaderName", "myHeaderValue" );

        // Setting the Subject and Content Type
        msg.setSubject( (String) ArgList[3] );
        msg.setContent( ArgList[4], "text/plain" );
        Transport.send( msg );
      } catch ( Exception e ) {
        throw Context.reportRuntimeError( "sendMail: " + e.toString() );
      }
    } else {
      throw Context.reportRuntimeError( "The function call sendMail requires 5 arguments." );
    }
  }

  public static String upper( Context actualContext, Scriptable actualObject, Object[] ArgList,
    Function FunctionContext ) {
    String sRC = "";
    if ( ArgList.length == 1 ) {
      try {
        if ( isNull( ArgList[0] ) ) {
          return null;
        } else if ( isUndefined( ArgList[0] ) ) {
          return (String) Context.getUndefinedValue();
        }
        sRC = Context.toString( ArgList[0] );
        sRC = sRC.toUpperCase();

View on GitHub (pinned to f3058517a1)