skip to Main Content

I am attempting to create an API in my Azure Static Web App which sends an email when a form submission occurs in my app.

I was able to get this working by passing a connection string to the EmailClient, but I would prefer to authenticate my EmailClient using Azure’s Service Principals as recommended in the email quickstart and briefly explained in the SMS quickstart.

I have tried passing an DefaultAzureCredential() as in the SMS quickstart

email_client = EmailClient(endpoint=endpoint, credential=DefaultAzureCredential())

But I get an error saying expected bytes or ASCII in the credential parameter.

I then attempted to generate a token from the credential using the Client ID of the Email Communication Services object, so I could pass this as the credential per the identity docs, but I get an error saying that the scope has not been provided:

credential=DefaultAzureCredential()
token=credential.get_token(scopes="bbjkl-xyz-abc/.default").token
email_client = EmailClient(endpoint=endpoint, credential=token)

DefaultAzureCredential failed to retrieve a token from the included credentials. 
Attempted credentials:
    EnvironmentCredential: "get_token" requires at least one scope

How do I authenticate the EmailClient using service principals? Or is this – as I suspect – a bug?

2

Answers


  1. I tried in my environment and got below results:

    Initially, I tried the EmailClient with Defaultcredentials and got same error:

    enter image description here

    TypeError: argument should be a bytes-like object or ASCII string, not ‘DefaultAzureCredential’

    As a workaround for authentication to send an email using EmailClient I tried to use Azurekeycredential method to send an email to the recipient.

    Code:

    from azure.communication.email import EmailClient,EmailAddress,EmailContent,EmailRecipients,EmailMessage
    from azure.core.credentials import AzureKeyCredential
    
    end="< your communication endpoint >"
    cred=AzureKeyCredential(key="< key of azure communication service >")
    email=EmailClient(endpoint=end,credential=cred)
    content = EmailContent(
        subject="Welcome to Azure Communication Services Email",
        plain_text="This email message is sent from Azure Communication Services Email using the Python SDK.",
    )
    
    address = EmailAddress(email="demomail.com")
    recipient = EmailRecipients(to=[address])
    
    message = EmailMessage(
                sender="[email protected]",
                content=content,
                recipients=recipient
            )
    
    response = email.send(message)
    

    Console:

    enter image description here

    Mail:
    The above code executed successfully by send mail to recipient with Azurekeycredential method.

    enter image description here

    Reference:

    Azure.communication.email.EmailClient class | Microsoft Learn

    Login or Signup to reply.
  2. This is still in preview, so it’s not well documented. I can’t answer how to use the provided library, but here’s an example using the REST API with service principal authentication.

    Note your principal needs the Contributor role on the Azure Communication Service as well

    import msal
    import requests
    import uuid
    from wsgiref.handlers import format_date_time
    from datetime import datetime
    from time import mktime
    
    def get_token_with_client_secret(client_id, client_secret, tenant_id):
        app = msal.ConfidentialClientApplication(
            client_id         = client_id,
            client_credential = client_secret,
            authority         = f"https://login.microsoftonline.com/{tenant_id}")
    
        scopes = ["https://communication.azure.com/.default"]
    
        token = app.acquire_token_for_client(scopes = scopes)
    
        return(token)
    
    def main():
        tenant_id = ""
        client_id = ""
        client_secret = ""
        endpoint = "https://endpoint.communication.azure.com/"
        sender = "[email protected]"
        
        # Obtain a token using the application credentials
        cred = get_token_with_client_secret(client_id, client_secret, tenant_id)
        
        # Generate timestamp to use in the repeatability-first-sent header    
        now = datetime.now()
        stamp = mktime(now.timetuple())
        time = format_date_time(stamp)
    
        request_url = f"{endpoint}emails:send?api-version=2021-10-01-preview"
    
        request_headers = {
            "Authorization": "Bearer " + cred["access_token"],
            "Content-Type": "application/json",
            "repeatability-request-id": str(uuid.uuid4()),
            "repeatability-first-sent": time
        }
    
        request_body = {
            "Sender": sender,
            "Content": {
                "Subject": "Email Subject",
                "PlainText": "This is the email body"
            },
            "Importance": "Normal",
            "Recipients": {
                "To": [
                    {
                        "Email": "[email protected]",
                        "DisplayName": "User"
                    }
                ]
            }
        }
    
        response = requests.post(url = request_url, headers = request_headers, json = request_body)
    
    main()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search