How to send email from Java Callout

Not applicable

We need to send emails from within Java Callouts and currently fail to do so. We are receiving the following error on the message processor when trying to send SMTP emails:

javax.mail.NoSuchProviderException: Unable to load class for provider: protocol=smtp; type=javax.mail.Provider$Type@aee111a; class=com.sun.mail.smtp.SMTPTransport; vendor=Oracle 
at javax.mail.Session.getService(Session.java:494) 

We tried adding activation and java-mail-api jar to our proxy but we get the same error.

What do we need to do?
Solved Solved
3 3 889
1 ACCEPTED SOLUTION

Are you using Edge SaaS ? If so, it's possible that the JVM security policy for a Java callout prohibits the loading of the SMTP class. Without access to the message processor logs, I cannot know for sure, but this is what it seems like. It's not a matter of availability of the java-mail-api JAR, etc.

I will try some tests on my own. In the meantime, a possible workaround may be to use an HTTP-accessible mail service.

EDIT:

Upon further review I think this should work for you. I've tested this. I produced my own Java callout that uses SMTP to send an email, synchronously. It works on my Edge SaaS organization.

The callout code looks like this:

public ExecutionResult execute(MessageContext msgCtxt, ExecutionContext exeCtxt) {
  ExecutionResult calloutResult = ExecutionResult.ABORT;
  boolean debug = getDebug();

  try {
    final String messageText = getMessageText(msgCtxt);
    final String subjectText = getSubjectText(msgCtxt);
    final String host = getHost(msgCtxt);
    final String port = getPort(msgCtxt);
    final String authUsername = getUsername(msgCtxt);
    final String authPassword = getPassword(msgCtxt);
    final String toUsername = getTo(msgCtxt);


    Properties props = new Properties();
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.host", host); // eg, "smtp.gmail.com"
    props.put("mail.smtp.port", port); // eg, "587"


    Session session =
        Session.getInstance(props,
                            new javax.mail.Authenticator() {
                                protected PasswordAuthentication getPasswordAuthentication() {
                                    return new PasswordAuthentication(authUsername, authPassword);
                                }
                            });


    Message message = new MimeMessage(session);
    message.setFrom(new InternetAddress(authUsername));
    message.setRecipients(Message.RecipientType.TO,
                          InternetAddress.parse(toUsername));
    message.setSubject(subjectText);
    message.setText(messageText);
    Transport.send(message);
    calloutResult = ExecutionResult.SUCCESS;
  }
  ...

The JARs I included into this proxy bundle are:

  • javax.mail-1.6.0.jar
  • commons-lang3-3.6.jar (for ExceptionUtils)
  • activation-1.1.jar
  • edge-custom-smtpmail-1.0.1.jar (my custom jar)

It's not sufficient to add javax.mail-api-x.y.z.jar to the bundle. That JAR is good to satisfy compilation requirements. What you need is javax.mail-x.y.z.jar . The maven dependency i used was:

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.0</version>
</dependency>

<!-- NOT SUFFICIENT FOR RUNTIME 

<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>javax.mail-api</artifactId>
    <version>1.6.0</version>
</dependency>

-->

View solution in original post

3 REPLIES 3

Are you using Edge SaaS ? If so, it's possible that the JVM security policy for a Java callout prohibits the loading of the SMTP class. Without access to the message processor logs, I cannot know for sure, but this is what it seems like. It's not a matter of availability of the java-mail-api JAR, etc.

I will try some tests on my own. In the meantime, a possible workaround may be to use an HTTP-accessible mail service.

EDIT:

Upon further review I think this should work for you. I've tested this. I produced my own Java callout that uses SMTP to send an email, synchronously. It works on my Edge SaaS organization.

The callout code looks like this:

public ExecutionResult execute(MessageContext msgCtxt, ExecutionContext exeCtxt) {
  ExecutionResult calloutResult = ExecutionResult.ABORT;
  boolean debug = getDebug();

  try {
    final String messageText = getMessageText(msgCtxt);
    final String subjectText = getSubjectText(msgCtxt);
    final String host = getHost(msgCtxt);
    final String port = getPort(msgCtxt);
    final String authUsername = getUsername(msgCtxt);
    final String authPassword = getPassword(msgCtxt);
    final String toUsername = getTo(msgCtxt);


    Properties props = new Properties();
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.host", host); // eg, "smtp.gmail.com"
    props.put("mail.smtp.port", port); // eg, "587"


    Session session =
        Session.getInstance(props,
                            new javax.mail.Authenticator() {
                                protected PasswordAuthentication getPasswordAuthentication() {
                                    return new PasswordAuthentication(authUsername, authPassword);
                                }
                            });


    Message message = new MimeMessage(session);
    message.setFrom(new InternetAddress(authUsername));
    message.setRecipients(Message.RecipientType.TO,
                          InternetAddress.parse(toUsername));
    message.setSubject(subjectText);
    message.setText(messageText);
    Transport.send(message);
    calloutResult = ExecutionResult.SUCCESS;
  }
  ...

The JARs I included into this proxy bundle are:

  • javax.mail-1.6.0.jar
  • commons-lang3-3.6.jar (for ExceptionUtils)
  • activation-1.1.jar
  • edge-custom-smtpmail-1.0.1.jar (my custom jar)

It's not sufficient to add javax.mail-api-x.y.z.jar to the bundle. That JAR is good to satisfy compilation requirements. What you need is javax.mail-x.y.z.jar . The maven dependency i used was:

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.0</version>
</dependency>

<!-- NOT SUFFICIENT FOR RUNTIME 

<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>javax.mail-api</artifactId>
    <version>1.6.0</version>
</dependency>

-->

Hi @Dino,

We tried your code above and still got "No provider for smtp" error on our Apigee setup. We have OPDK 4.17.05. We switched on "mail.debug" and it looks like its trying to locate javamail providers somewhere from the classpath. It is not probably accepting the smtp settings that we have provided in the code.

Here is the debug log:

DEBUG:URLjar:file:/opt/apigee/edge-gateway-4.17.05-0.0.1231/lib/thirdparty/aws-java-sdk-1.4.7.jar!/META-INF/javamail.providers

DEBUG:Badproviderentry:

DEBUG:successfullyloadedresource:jar:file:/opt/apigee/edge-gateway-4.17.05-0.0.1231/lib/thirdparty/aws-java-sdk-1.4.7.jar!/META-INF/javamail.providers

DEBUG:TablesofloadedprovidersDEBUG:ProvidersListedByClassName: {com.amazonaws.services.simpleemail.AWSJavaMailTransport=javax.mail.Provider[TRANSPORT,aws,com.amazonaws.services.simpleemail.AWSJavaMailTransport,AmazonWebServicesLLC]}

DEBUG:ProvidersListedByProtocol: {aws=javax.mail.Provider[TRANSPORT,aws,com.amazonaws.services.simpleemail.AWSJavaMailTransport,AmazonWebServicesLLC]}

DEBUG:failedtoloadaddressmap, usingdefaultsjavax.mail.NoSuchProviderException:Noproviderforsmtp

hi - is your question at all related to the original?

Are you part of the same company or organization, or is your situation totally different?

If you have a different situation, please use the "Ask a Question" button.

5793-ask-a-question.png