Unable to use Azure Communication Service API in Salesforce

Supneet Singh 25 Reputation points
2024-02-05T04:57:19.0566667+00:00

Hi,

I am trying to use Azure Communication Services (Email Send) REST API in Salesforce. Goal is to send Emails(including attachments) from salesforce through Azure Communication Services.

  For authentication I am following the Access Key Authentication as mentioned here, and request body as mentioned here Azure Subscription : Free Trial

I have tried multiple different combination of ‘host’, ’endpoint’, ‘authorization’ headers. But always getting one of these two errors:

  1. The request hostname is invalid.
  2. Status=Unauthorized

I will appreciate if someone can review and suggest what I am doing wrong.

My salesforce Apex code is below:

public class AzureEmailService {

               private string AzureEndPoint = 'https://mycommunicationservice.location.communication.azure.com/emails:send?api-version=2021-10-01-preview';
               private string AzureHOST = 'mycommunicationservice.location.communication.azure.com';
               private string AzurePATH = 'emails:send';
               private string AzureQUERY = 'api-version=2021-10-01-preview';
               private string VERB = 'POST';
               
               private string AzureContentHash;
               private string URIPathAndQuery;
               private String formattedDate;
               private string MessageBody;
               
               private string AzureAccessKey = 'primary-key-from-communication-services-settings';
               
               
               public AzureEmailService(){
                              generateMessageBody();
               }
               
               public String generateSignature() {
               Datetime currentDateTime = Datetime.now();
               formattedDate = currentDateTime.formatGMT('EEE, dd MMM yyyy HH:mm:ss z');
                              
               URIPathAndQuery = AzurePATH + '?' + AzureQUERY; 
               AzureContentHash=EncodingUtil.Base64Encode(Crypto.generateDigest('SHA-256', Blob.valueOf(MessageBody)));
               String stringToSign = VERB+'\n'+URIPathAndQuery+'\n'+formattedDate+ ';' + AzureHOST + ';' + AzureContentHash;
               //String stringToSign = VERB+'\n emails:send \n'+formattedDate+ ';mycommunicationservice.location.communication.azure.com;' + AzureContentHash;

               Blob decodedAzureAccessKey = EncodingUtil.base64Decode(AzureAccessKey);
               Blob macStringToSign = Crypto.generateMac('HMACSHA256', Blob.valueOf(stringToSign), decodedAzureAccessKey);
               String signature = EncodingUtil.base64Encode(macStringToSign);

               return signature;
    }
               
               // method responsible to send email
               public void sendAzureEmail() {
                              String signature = generateSignature();
                              HttpRequest req = new HttpRequest();
                              req.setMethod(VERB);
                              req.setEndpoint(AzureEndPoint);
                              req.setBody(MessageBody);

                              //HEADERS
                              req.setHeader('x-ms-date', formattedDate);
                              req.setHeader('x-ms-content-sha256', AzureContentHash);
                              req.setHeader('Content-type', 'application/json');
                              
                              /*I have tried two different values for 'Authorization' and 'host' header. All 4 combinations are not working*/
                              
                              
                              /* //#1
                              String azureAuth = 'HMACSHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature='+signature;
                              req.setHeader('Authorization', azureAuth);
                              
                              //This throws error : HTTP Error 400. The request hostname is invalid.
                              req.setHeader('host', URIPathAndQuery); // 'emails:send?api-version=2021-10-01-preview'
                              */
                              
                              /* //#2
                              String azureAuth = 'HMACSHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature='+signature;
                              req.setHeader('Authorization', azureAuth);

                              //This throws error : Status=Unauthorized
                              req.setHeader('host', AzureHOST); // 'mycommunicationservice.location.communication.azure.com'
                              */
                              
                              /* //#3
                              req.setHeader('Authorization', signature);
                              
                              //This throws error : HTTP Error 400. The request hostname is invalid.
                              req.setHeader('host', URIPathAndQuery); // 'emails:send?api-version=2021-10-01-preview'
                              */
                              
                              /* //#4
                              req.setHeader('Authorization', signature);

                              //This throws error : Status=Unauthorized
                              req.setHeader('host', AzureHOST); // 'mycommunicationservice.location.communication.azure.com'
                              */
                              
                              Http http = new Http();
                              HTTPResponse res = http.send(req);
                              System.debug('##Response Body--->'+res.getBody());
               }
   
   
               /* Method and inner classes to generate email content*/
               public void generateMessageBody() {
                              AzureContent aContent = new AzureContent('Test Email from Azure!','Email sent from Azure','<html><head><title>Hello!</title></head><body><h1>Email sent from Azure</h1></body></html>');
                              
                              AzureRecipient aRecepient = new AzureRecipient('recepient@test.com','My Name');
                              list<AzureRecipient> recepientList = new list<AzureRecipient>();
                              recepientList.add(aRecepient);
                              AzureRecipients aRecepients = new AzureRecipients(recepientList);
                              
                              AzureAttachment aAttachment = new AzureAttachment('Attachment.pdf','application/pdf','AttachmentBlob');
                              list<AzureAttachment> attachmentList = new list<AzureAttachment>();
                              attachmentList.add(aAttachment);
                              
                              AzureRecipient aReplyTo = new AzureRecipient('replyTo@test.com','Customer Support');
                              list<AzureRecipient> replyToList = new list<AzureRecipient>();
                              replyToList.add(aReplyTo);
                              
                              AzureEmailBody emailBody = new AzureEmailBody();
                              emailBody.senderAddress = 'Email Communication Services Domain >> MailFrom Address';
                              emailBody.content = aContent;
                              emailBody.recipients = aRecepients;
                              emailBody.attachments = attachmentList;
                              emailBody.replyTo = replyToList;
                              MessageBody = JSON.serialize(emailBody);
               }

               public class AzureContent {
                              public String subject;
                              public String plainText;
                              public String html;
                              
                              public AzureContent(String sub,String pText,String hText) {
                                             subject = sub;
                                             plainText = pText;
                                             html = hText;
                              }
               }

               public class AzureRecipient {
                              public String address;
                              public String displayName;
                              
                              public AzureRecipient(String strAddress,String strName) {
                                             address = strAddress;
                                             displayName = strName;
                              }
               }

               public class AzureRecipients {
                              public List<AzureRecipient> to;

                              public AzureRecipients(List<AzureRecipient> resTo) {
                                             to = resTo;
                              }
               }

               public class AzureAttachment {
                              public String name;
                              public String contentType;
                              public String contentInBase64;
                              
                              public AzureAttachment(String strName,String strContentType,String strContentInBase64) {
                                             name = strName;
                                             contentType = strContentType;
                                             contentInBase64 = strContentInBase64;
                              }
               }

               public class AzureEmailBody {
                              public String senderAddress;
                              public AzureContent content;
                              public AzureRecipients recipients;
                              public List<AzureAttachment> attachments;
                              public List<AzureRecipient> replyTo;
               }
}


Azure Communication Services
Azure Communication Services
An Azure communication platform for deploying applications across devices and platforms.
933 questions
{count} vote

Accepted answer
  1. VenkateshDodda-MSFT 22,716 Reputation points Microsoft Employee
    2024-02-06T08:25:45.06+00:00

    @Supneet Singh Thanks for reaching out to Microsoft Q&A, apologize for any inconvenience caused on this.

    Based on above information, I understand that you are using an authentication string containing a signature that is generated using HMAC-SHA256 scheme authentication, and it is failing with either request hostname invalid or Unauthorized.

    • Can you please try creating the HMAC signature by following the documented steps here.

    If you application doesn't have any dependency on which authentication method to use, then try using the Azure AD authentication by following the below steps,

    1. Create a new application registration choose either single tenant or multitenant based on usage who need to access this API.
    2. Once the app registration is completed, create secrets and scope to make your app work.
    3. Assign contributor permission to above created app registration using Access Control (IAM) of communication service.
    4. Generate an access token of Type oAuth 2.0 and pass the audience scope as https://communication.azure.com.
    5. And use the above generated access token in authorization to send the email using the REST API.

    Hope this helps, Let me know if you have any further questions on this.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.