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:
- The request hostname is invalid.
- 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;
}
}