We have released fixes for both ColdFusion (2021 release) and ColdFusion (2018 release) that help authenticate IMAP, POP, SMTP, and Exchange connections using OAuth.
How to apply the update
Before applying the updates, ensure that ColdFusion is on the latest update for both versions:
If you have multiple ColdFusion instances, you must apply the updates for each instance.
ColdFusion (2021 release)
- Unzip the file patch zip.
- Stop the ColdFusion server.
- Replace <cf_home>/cfusion/bundles/mail-2021.0.05.330109.jar with the file mail-2021.0.05.330109.jar.
- Replace <cf_home>/cfusion/lib/mail.jar with mail.jar.
- Clear the folder <cf_home>/cfusion/bin/felix-cache.
- In jvm.config, add the flag -Dcoldfusion.mail.oauth2=true.
- Start the ColdFusion server.
ColdFusion (2018 release)
- Stop the ColdFusion server.
- Copy the file hf201800-4212004.jar in C:\ColdFusion2018\cfusion\lib\updates.
- Replace <cf_home>/cfusion/lib/ with the file mail.jar.
- In jvm.config, add the flag -Dcoldfusion.mail.oauth2=true.
- Start the ColdFusion server.
Get the authorization code.
Register your application
To use OAuth, register an application in Azure Active Directory. For more information, see Register an application. clientid, secretkey, authendpoint will be obtained after registering the application.
<cfoauth clientid = "client-id" secretkey = "secret-key" scope="https://outlook.office.com/SMTP.Send" authendpoint="auth-end-point" accesstokenendpoint = "access-token-endpoint" result = "res" redirecturi = "http://localhost:8500/oauth/response.cfm">
Get the access token.
<cfhttp result="res" url="https://login.microsoftonline.com/<auth-code>/oauth2/v2.0/token" method="post"> <cfhttpparam name="grant_type" type="formfield" value="authorization_code"> <cfhttpparam name="code" type="formfield" value="#code#"> <cfhttpparam name="client_id" type="formfield" value="client-id"> <cfhttpparam name="scope" type="formfield" value="https://outlook.office.com/SMTP.Send"> <cfhttpparam name="client_secret" type="formfield" value="secret-key"> <cfhttpparam name="redirect_uri" type="formfield" value="http://localhost:8500/oauth/response.cfm"> </cfhttp> <cfset record=deserializeJSON(res.Filecontent)/> <cfset token=#record.access_token#/>
Pass the access token to the password field of cfmail.
<cfmail server="smtp.office365.com" to="username@example.com" from="username@example.com" subject="#emailid#" port="587" username="#username#" password="#token#" spoolenable=false useTLS=true timeout=120> Hello, World! </cfmail>
<cfoauth clientid = "client-id" secretkey = "secret-key" scope="https://outlook.office.com/POP.AccessAsUser.All" authendpoint="auth-end-point" accesstokenendpoint = "access-token-endpoint" result = "res" redirecturi = http://localhost:8500/oauth/response.cfm>
Get the access token.
<cfhttp result="res" url="https://login.microsoftonline.com/<auth-code>/oauth2/v2.0/token" method="post"> <cfhttpparam name="grant_type" type="formfield" value="authorization_code"> <cfhttpparam name="code" type="formfield" value="#code#"> <cfhttpparam name="client_id" type="formfield" value="client-id"> <cfhttpparam name="scope" type="formfield" value="https://outlook.office.com/POP.Send"> <cfhttpparam name="client_secret" type="formfield" value="secret-key"> <cfhttpparam name="redirect_uri" type="formfield" value="http://localhost:8500/oauth/response.cfm"> </cfhttp> <cfset record=deserializeJSON(res.Filecontent)/> <cfset token=#record.access_token#/>
Pass the access token to the password field of cfpop, as shown below.
<cfpop server = "outlook.office365.com" username = "#username#" password="#token#" port="995" action="GETALL" name="msg" secure="true">
<cfoauth clientid = "client-id" secretkey = "secret-key" scope="https://outlook.office.com/IMAP.AccessAsUser.All" authendpoint="auth-end-point" accesstokenendpoint = "access-token-endpoint" result = "res" redirecturi = http://localhost:8500/oauth/response.cfm>
Get the access token.
<cfhttp result="res" url="https://login.microsoftonline.com/<auth-code>/oauth2/v2.0/token" method="post"> <cfhttpparam name="grant_type" type="formfield" value="authorization_code"> <cfhttpparam name="code" type="formfield" value="#code#"> <cfhttpparam name="client_id" type="formfield" value="client-id"> <cfhttpparam name="scope" type="formfield" value="https://outlook.office.com/IMAP.Send"> <cfhttpparam name="client_secret" type="formfield" value="secret-key"> <cfhttpparam name="redirect_uri" type="formfield" value="http://localhost:8500/oauth/response.cfm"> </cfhttp> <cfset record=deserializeJSON(res.Filecontent)/> <cfset token=#record.access_token#/>
Pass the access token to the password field of cfimap, as shown below.
<cfimap action="OPEN" connection="IMAPCONNECTION" server="outlook.office365.com" username="#username#" password="#token#" secure="true" stoponerror="false"/> <cfimap action="LISTALLFOLDERS" connection="IMAPCONNECTION" name="queryname" recurse=true stoponerror="false"/>
Here's how you'll apply the update.
ColdFusion (2021 release)
- Download the exchange package jar file, jar.
- Stop the ColdFusion server.
- Replace <cf_home>/cfusion/bundles/exchange-2021.0.05.330109.jar with the file exchange-2021.0.05.330109.jar.
- Clear the folder C:\ColdFusion2021\cfusion\bin\felix-cache.
- Set the following jvm args in the jvm.config file (the default is false) "-Dcoldfusion.exchange.useOauth2=true".
- Start the ColdFusion server.
ColdFusion (2018 release)
- Stop the ColdFusion server.
- Copy the file hf201800-4212511.jar in <cf_home>/cfusion/lib/updates.
- Set the following jvm args in the jvm.config file (the default is false) "-Dcoldfusion.exchange.useOauth2=true".
- Start the ColdFusion server.
The following workflow generates an access token that can then be passed to the cfexchangeconnection to get an authenticated exchange connection:
<cfoauth clientid = "your clientid" secretkey = "secret created in Azure portal when registering the application" scope = "https://outlook.office365.com/EWS.AccessAsUser.All" authendpoint = "https://login.microsoftonline.com/<tenant-ID>/oauth2/v2.0/authorize" accesstokenendpoint = "https://login.microsoftonline.com/<tenant-ID>/v2.0/token" result = "oresult" redirecturi = "http://localhost:8500/oauth/response.cfm">
Response.cfm
<cfhttp result="httpresult" url="https://login.microsoftonline.com/<tenant-ID>/oauth2/v2.0/token" method="post"> <cfhttpparam name="grant_type" type="formfield" value="authorization_code"> <cfhttpparam name="scope" type="formfield" value="https://outlook.office365.com/EWS.AccessAsUser.All"> <cfhttpparam name="code" type="formfield" value="#url.code#"> <cfhttpparam name="client_id" type="formfield" value="your clientid"> <cfhttpparam name="redirect_uri" type="formfield" value="http://localhost:8500/oauth/response.cfm"> </cfhttp> <cfdump var=#res.Filecontent#> // the access_token in the response here contains the access_token passed in the cfexchange tag <cfexchangeconnection action="open" username="username@domain.com" password="#auth-token#" server="outlook.office365.com" protocol="https" serverversion="2010_SP2" connection="exchangeconn">
When impersonating a user, set the following flag to true (the default is false), -Dcoldfusion.exchange.setImpersonatedUser=true