Skip to content

Issue 53534: Support Microsoft's Graph Protocol API for authentication via OAuth2 token#7381

Merged
labkey-bpatel merged 38 commits intodevelopfrom
fb_mail_transport_via_graph
Mar 5, 2026
Merged

Issue 53534: Support Microsoft's Graph Protocol API for authentication via OAuth2 token#7381
labkey-bpatel merged 38 commits intodevelopfrom
fb_mail_transport_via_graph

Conversation

@labkey-bpatel
Copy link
Contributor

@labkey-bpatel labkey-bpatel commented Feb 3, 2026

Rationale

Microsoft plans to retire SMTP Basic Authentication in March 2026. In response, one of our clients’ IT department has requested a shift to OAuth-based authentication

Since SMTP Oauth 2.0 client credential flow with non-interactive sign-in (for email notifications) is not supported we’ll need to use Microsoft’s Graph API instead of SMTP protocol

This PR adds a Graph transport method as an alternative to SMTP, which enables mail delivery via OAuth2 authentication method.

Spec

Related Pull Requests

Changes

  • Add EmailTransportProvider interface.
  • Extract SMTP logic from MailHelper to its own provider class.
  • Update MailHelper to manage multiple transport providers and detect configuration conflict (if both SMTP and Graph are configured)
  • Add EmailTestWithAttachmentAction in AdminController to test Graph API with HTML content, large attachments and data URI images.
  • Update emailTest.jsp to display success feedback after email send attempts and add Graph-specific test button for HTML and attachment workflow (button only visible when Graph is the active provider).

Tasks 📍

  • Manual Testing
  • Unit test
  • Verify Fix

@github-actions
Copy link

github-actions bot commented Feb 3, 2026

WARNING: This PR appears to have the default title generated by GitHub. Please use something more descriptive.

@labkey-bpatel labkey-bpatel changed the title Fb mail transport via graph Issue 53534: Support Microsoft's Graph Protocol API for authentication via OAuth2 token Feb 3, 2026
@labkey-bpatel labkey-bpatel marked this pull request as ready for review February 5, 2026 00:46
Copy link
Contributor

@labkey-adam labkey-adam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good, generally speaking. No required changes, but please review my questions & comments.

My biggest concern is the fact that this adds 70MB of JAR files to API. This is an extraordinary amount of new code for a single feature that will be used rarely. Were there any other options that would reduce the dependencies? Can any dependencies be excluded? If we can't slim it down, we may need to consider pushing the Graph API transport and dependencies into a separate module.

@labkey-bpatel
Copy link
Contributor Author

labkey-bpatel commented Feb 24, 2026

Code looks good, generally speaking. No required changes, but please review my questions & comments.

My biggest concern is the fact that this adds 70MB of JAR files to API. This is an extraordinary amount of new code for a single feature that will be used rarely. Were there any other options that would reduce the dependencies? Can any dependencies be excluded? If we can't slim it down, we may need to consider pushing the Graph API transport and dependencies into a separate module.

We could trim ~10MB by cutting azure-identity, but that would require us to handle token management - not a significant saving. I am leaning toward pushing these changes to a standalone module for now, then we can revisit moving it into premiumModules down the road. Thoughts?

…er class to a new module in premiumModules. Rename test action to 'GraphEmailTestWithAttachmentAction'. Remove setting activeProvider in setSession. Use StringUtilsLabKey.joinWithConjunction()
Copy link
Contributor

@labkey-adam labkey-adam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see a few suggestions and questions. I'm approving and no further review is needed at this stage.

I do think we should consider some refactoring to make key classes less tied to SMTP and Jakarta Mail. MailHelper special cases SMTP in a few places, making some of the methods applicable to SMTP only. It's now odd that ViewMessage and MultipartMessage extend Jakarta Mail classes and hold an SMTP session, even when used with Graph. Ideally, MailHelper and the message classes would be completely generic to the provider. Dumbster could construct & configure an SmtpTransportProvider, and set that as MailHelper's active provider. However, I don't think any of this is required right now. I'd prefer to get this tested and merged, and get the client to test it. Then circle back with some improvements as a follow-on.

return session;
public static void setSession(Session session)
{
_smtpProvider.setSession(session);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this throw if called when Graph transport is active?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method (now renamed to setSmtpSession()) is already SMTP scoped, so caller invoking it presumably knows they are configuring SMTP.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the caller wants to configure SMTP, but if Graph is the active transport then the caller's SMTP configuration will silently fail. This will be addressed by the follow-on refactor issue, so I don't really care.

@labkey-bpatel
Copy link
Contributor Author

Please see a few suggestions and questions. I'm approving and no further review is needed at this stage.

I do think we should consider some refactoring to make key classes less tied to SMTP and Jakarta Mail. MailHelper special cases SMTP in a few places, making some of the methods applicable to SMTP only. It's now odd that ViewMessage and MultipartMessage extend Jakarta Mail classes and hold an SMTP session, even when used with Graph. Ideally, MailHelper and the message classes would be completely generic to the provider. Dumbster could construct & configure an SmtpTransportProvider, and set that as MailHelper's active provider. However, I don't think any of this is required right now. I'd prefer to get this tested and merged, and get the client to test it. Then circle back with some improvements as a follow-on.

Yup, that makes sense! I thought about decoupling SMTP specific things out MailHelper and Dumbster; however the scope kept increasing so left it as-is, but a follow up improvements sounds like a fine plan!

@labkey-bpatel
Copy link
Contributor Author

@labkey-adam I've added an issue for the follow up work: https://github.com/LabKey/kanban/issues/1714

@labkey-bpatel labkey-bpatel merged commit e046e9f into develop Mar 5, 2026
10 checks passed
@labkey-bpatel labkey-bpatel deleted the fb_mail_transport_via_graph branch March 5, 2026 00:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants