Joe_Slitzker1 | 2024-04-06 16:34:07 UTC | #1
Continuing the discussion from Configuring OAuth2 Client Credentials Grant for Custom SMTP Server Integration in Genesys Cloud:
vpirat, post:4, topic:22829
regards
I am also interested in setting this up. Could you please share the details on the internal docs that are available. Unfortunately I do not have the ability to easily create a care ticket as requested in the previous thread. I would need to hop through the hoops of a VAR and convince them to enter a care ticket for me which is not really efficient.
vpirat | 2024-04-08 10:43:40 UTC | #2
Hi Joe,
Here's some guidance.
Please not that settings described are for testing purpose only and are not for production, where more restrictions should be applied according to your company policy(ies).
Microsoft supports since July 2023, a new OAuth flow: credentials flow. It does not require anymore a user/password pair and allows to use an application for sending mail on "behalf of". https://techcommunity.microsoft.com/t5/exchange-team-blog/announcing-client-credential-flow-for-smtp-auth-in-exchange/ba-p/3869966
Read this article to get more insights: https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth#use-client-credentials-grant-flow-to-authenticate-smtp-imap-and-pop-connections
Some extra steps are required to allow the application to access user mail boxes. All is described with the above article.
Email configuration
Check Integration configuration
- Enable Custom Smtp Server OAuth in Supportability:
Configure Custom Smtp Integration. Select type Credential Flow
Please note that Integration still requires a user but this requirement is for connecting to SMTP server and check the connection, not to get a token. SMTP protocol requires a user to connect to.
Assign new permissions
At the minimum, allow application to access a mail box:
Open a power shell window in admin mode:
Load modules: Install-Module -Name ExchangeOnlineManagement -allowprerelease Import-module ExchangeOnlineManagement Connect-ExchangeOnline -Organization <orgId>
Then type commands:
New-ServicePrincipal -AppId <appid> -ObjectId <objectId> Get-ServicePrincipal | fl Add-MailboxPermission -Identity "<user name>" -User <ServicePrincipal id> -AccessRights FullAccess
$Mailbox = "user name" Get-MailboxPermission -Identity $Mailbox | Where-Object { ($.AccessRights -eq "FullAccess") -and ($.IsInherited -eq $false) -and -not ($_.User -like "NT AUTHORITY\SELF") } | ft -AutoSize
Example
Assign application access
New-ServicePrincipal -AppId c9fd0428-a094-434d-9dcb-cd86b6838793 -ObjectId 2c85ed7e-ca0f-451a- 9021 -4b49f91be2f1
Get-ServicePrincipal | fl
Add-MailboxPermission -Identity "AdeleV@614ryb.onmicrosoft.com" -User 2c85ed7e-ca0f-451a- 9021 -4b49f91be2f1 -AccessRights FullAccess
$Mailbox = "AdeleV@614ryb.onmicrosoft.com"
Get-MailboxPermission -Identity $Mailbox | Where-Object { ($_.AccessRights -eq "FullAccess" ) -and ($_.IsInherited -eq $ false ) -and -not ($_.User -like "NT AUTHORITY\SELF" ) } | ft -AutoSize
Get a Token
Http request
Pay attention to the scope that needs to be https://outlook.office.com/.default
Example
Response:
credentials flow response
{
"token_type" : "Bearer" ,
"expires_in" : 3599 ,
"ext_expires_in" : 3599 ,
"access_token": "<JWT>"
}
Test script in Python
Change values accordingly to your env.
Credentials flow
import base64
import pprint
import smtplib
import msal
conf = {
"authority": "https://login.microsoftonline.com/d44bf45a-e2fa-45bc-8c65-cc1aa10fd573",
"client_id": "28515eac-a167-4485-85ac-f032492b4e92",
"client_secret": "ZMocbI",
"scope": [ "https://outlook.office.com/.default" ],
"tenant_id": "1cf1f047-bc19-45db-9954-adf81926341b",
"user_name": "AdeleV@614ryb.onmicrosoft.com"
}
MAIL_TO = "<your email address>"
SMTP_PORT = 587
SMTP_HOST = "smtp.office365.com"
def encode_token_as_string(username, token) -> str:
xoauth2_token = encode_auth_token_as_bytes(username, token)
return str(xoauth2_token, "utf-8")
def encode_auth_token_as_bytes(username, token) -> bytes:
just_a_str = f"user={username}\x01auth=Bearer {token}\x01\x01"
xoauth2_token = base64.b64encode(just_a_str.encode('utf-8'))
return xoauth2_token
username = conf['user_name']
if \_\_name__ == "\_\_main__":
app = msal.ConfidentialClientApplication(
conf['client_id'],
authority=conf['authority'],
client_credential=conf['client_secret']
)
result = app.acquire_token_silent(conf['scope'], account=None)
if not result:
print("No suitable token in cache. Getting a new one.")
result = app.acquire_token_for_client(scopes=conf['scope'])
if "access_token" in result:
print(result['token_type'])
pprint.pprint(result)
else:
print(result.get("error"))
print(result.get("error_description"))
print(result.get("correlation_id"))
server = smtplib.SMTP(SMTP_HOST, SMTP_PORT)
server.set_debuglevel(True)
print("Connect")
server.connect(SMTP_HOST, SMTP_PORT)
print("Ehlo")
server.ehlo()
print("StartTLS")
server.starttls()
server.ehlo()
access_token = result['access_token']
print("start XOATUH2")
code, msg = server.docmd("auth", "XOAUTH2 " + encode_token_as_string(username, access_token))
if code != 235:
raise Exception(base64.b64decode(msg.decode()))
print ("Send mail")
message = 'Subject: {}\n\n{}'.format('hello', 'This is a test')
server.sendmail(username, MAIL_TO, message)
print("Done")
server.quit()
Joe_Slitzker1 | 2024-04-08 11:50:43 UTC | #3
Thanks so much, @vpirat I was missing the assignment of the credentials to the mailbox using the exchange online commands. I will give this a shot today. Appreciate the detailed information and the quick reply!
system | 2024-05-09 11:51:27 UTC | #4
This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.
This post was migrated from the old Developer Forum.
ref: 25593