Pete Helgren
Pete Helgren

Reputation: 448

Use Microsoft Graph to send email in Liferay 7.3 cannot resolve dependency

I originally sent emails from a Liferay 7.3 application from JavaMail (SMTP). SMTP was used to relay through our Exchange 365 instance. I had to change to a different method so I decided to use Graph to get to Exchange 365 because it looked simple....

The issue is that I get "org.osgi.framework.BundleException: Could not resolve module: org.bsfinternational.dashboard [1147]_ Unresolved requirement: Import-Package: com.azure.core.credential_ [Sanitized]"

Normally I have been able to resolve these by double-checking the build.gradle entries to make sure I have accounted for the dependencies. Here is what I have:

// Azure core

implementation 'com.azure:azure-core:1.43.0'

implementation 'com.azure:azure-core-http-netty:1.15.0'

// Include the sdk as a dependency

implemenation 'com.microsoft.graph:microsoft-graph:5.57.0'

implemenation 'com.microsoft.graph:microsoft-graph-auth:0.3.0'

// Include Azure identity for authentication

implementation 'com.azure:azure-identity:1.9.0'

I could post the code but this doesn't seem to be a code issue because the code compiles. The build is successful in gradle. It's when I deploy to OSGI that the dependency failure error is thrown. I double checked the dependencies multiple times. I have tried omitting certain packages in the bnd.bnd file in the project. Nothing seems to work. My assumption is that there is some transitive dependency that I am missing but I can find no documentation that indicates that another library is needed. I have tried different versions of the libraries, included and omitted them. I can compile the code, just can't deploy it. I am new to the Graph API but the API looks pretty simple.

The GoGo shell in Liferay isn't helpful. It tells me exactly what the deployment tells me "Unresolved requirement". I tried to find out a better way to understand the dependency tree but based on what I have read, there aren't any required dependencies that I am missing. I have run into this issue before with other Liferay projects but have always been able, through trial and error, to figure out what is missing. This time, no luck.

Any ideas at this point would be helpful. Thanks.

Code sample is here:

public static int sendExchangeEmail(String fromName, String fromAddress, String toAddress, String toName, String subject, String emailbody, String replyT, boolean htmlFormat)
 throws SystemException
{                            
int messageID = 0;
                    
String clientId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
String clientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
String tenantId ="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

 // Create credentials
ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder().clientId(clientId).clientSecret(clientSecret).tenantId(tenantId).build();

 // Initialize authentication provider and Graph client
final TokenCredentialAuthProvider authProvider = new TokenCredentialAuthProvider(clientSecretCredential);
final GraphServiceClient<okhttp3.Request> graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();

// Construct the email message
com.microsoft.graph.models.Message message = new com.microsoft.graph.models.Message();

message.subject = subject;
ItemBody body = new ItemBody();
body.contentType = BodyType.TEXT;
body.content = emailbody;
message.body = body;
LinkedList<Recipient> toRecipients = new LinkedList<>();
 Recipient recipient = new Recipient();
EmailAddress emailAddress = new EmailAddress();
emailAddress.address = "[email protected]";
emailAddress.name = toName;
recipient.emailAddress = emailAddress;
toRecipients.add(recipient);
message.toRecipients = toRecipients;
Recipient from = new Recipient();
from.emailAddress = new EmailAddress();
from.emailAddress.address = fromAddress;
from.emailAddress.name = fromName;
message.from = from;
LinkedList<Recipient> replyToRecipients = new LinkedList<>();
Recipient replyTo = new Recipient();
replyTo.emailAddress = new EmailAddress();
replyTo.emailAddress.address = replyT;
replyToRecipients.add(replyTo);
message.replyTo = replyToRecipients;
// Create the parameter set
UserSendMailParameterSet parameterSet = new UserSendMailParameterSet().newBuilder().withMessage(message).withSaveToSentItems(false).build();
// Don't save to Sent Items folder
// Send the email
try {
    graphClient.me().sendMail(parameterSet).buildRequest().post();

    System.out.println("Email sent successfully!");

     } catch (Exception e) {

         e.printStackTrace();

         System.err.println("Error sending email: " + e.getMessage());

}
 return messageID; 

 }

This is not a standalone program. It is one method among many in this particular source file. The relevant imports added so the program would compile are:

import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;

import com.microsoft.graph.models.*;
import com.microsoft.graph.models.UserSendMailParameterSet;
import com.microsoft.graph.models.BodyType;
import com.microsoft.graph.models.ItemBody;
import com.microsoft.graph.requests.GraphServiceClient;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider;

And again, this isn't a code issue, it's an issue with deployment. There is something missing as it is deployed in the OSGI stack that causes the program to not deploy.

Upvotes: 0

Views: 99

Answers (1)

Dasari Kamali
Dasari Kamali

Reputation: 3553

I used the Mail.Send scope in the code to send email in Java using Gradle. I added the Mail.Send scope in the API permissions and granted admin consent as shown below.

enter image description here

I used the below dependencies in build.gradle.kts.

implementation("com.azure:azure-identity:1.9.0")
implementation("com.microsoft.graph:microsoft-graph:5.13.0")
implementation("com.sun.mail:javax.mail:1.6.2")
implementation("org.slf4j:slf4j-api:2.0.0-alpha1")
implementation("org.slf4j:slf4j-simple:2.0.0-alpha1")

build.gradle.kts :

plugins {
    id("java")
}

group = "org.example"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation("com.azure:azure-identity:1.9.0")
    implementation("com.microsoft.graph:microsoft-graph:5.13.0")
    implementation("com.sun.mail:javax.mail:1.6.2")
    implementation("org.slf4j:slf4j-api:2.0.0-alpha1")
    implementation("org.slf4j:slf4j-simple:2.0.0-alpha1")
    testImplementation(platform("org.junit:junit-bom:5.10.0"))
    testImplementation("org.junit.jupiter:junit-jupiter")
}

tasks.test {
    useJUnitPlatform()
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21) 
    }
}

KamEmail.java :

import com.azure.identity.InteractiveBrowserCredential;
import com.azure.identity.InteractiveBrowserCredentialBuilder;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider;
import com.microsoft.graph.models.*;
import com.microsoft.graph.requests.GraphServiceClient;

import java.util.Arrays;

public class KamEmail {
    private static final String App_ID = "<appID>";
    private static final String Tenant_ID = "common";
    private static final String[] Scope = {"Mail.Send"};

    public static void main(String[] args) {
        try {
            InteractiveBrowserCredential credential = new InteractiveBrowserCredentialBuilder()
                    .clientId(App_ID)
                    .tenantId(Tenant_ID)
                    .build();

            TokenCredentialAuthProvider authProvider = new TokenCredentialAuthProvider(Arrays.asList(Scope), credential);
            GraphServiceClient<?> graphClient = GraphServiceClient
                    .builder()
                    .authenticationProvider(authProvider)
                    .buildClient();

            Message sendmessage = new Message();
            sendmessage.subject = "Meeting";
            ItemBody body = new ItemBody();
            body.contentType = BodyType.TEXT;
            body.content = "We have a meeting at 2:00 PM. Make sure not to miss it.";
            sendmessage.body = body;

            Recipient FROM = new Recipient();
            FROM.emailAddress = new EmailAddress();
            FROM.emailAddress.address = "[email protected]";
            Recipient TO = new Recipient();
            TO.emailAddress = new EmailAddress();
            TO.emailAddress.address = "[email protected]";

            sendmessage.toRecipients = Arrays.asList(FROM);
            sendmessage.ccRecipients = Arrays.asList(TO);
            UserSendMailParameterSet mailParams = new UserSendMailParameterSet();
            mailParams.message = sendmessage;
            mailParams.saveToSentItems = Boolean.FALSE;
            graphClient.me().sendMail(mailParams).buildRequest().post();
            System.out.println("Meeting mail sent successfully!");
        } catch (Exception e) {
            System.err.println("Error sending email: " + e.getMessage());
        }
    }
}

I added the below URL under Mobile and desktop applications and allow the public client flow as shown below.

http://localhost

enter image description here

enter image description here

I got the below redirect sign-in page for Outlook when I ran the code.

enter image description here

enter image description here

The email was sent successfully in Java using Gradle, as shown below.

enter image description here

Outlook :

enter image description here

Upvotes: 1

Related Questions