Hi ilan,
You could do it with javascript, the whole process is:
1. Create a custom button and add it to ribbon with Ribbon Workbench, then bind custom javascript(2 & 3) command to the button.
2. Create an email record based on an appointment record by Web API.
3. Send new created email with Web API action: Microsoft.Dynamics.CRM.SendEmail
Here is a tutorial about step 1, there are also many other tutorials about the topic.
https://dynamicscrmtips.com/button-dynamics-crm-ribbon-workbench/
I've tested following code which has integrated step 2 & 3 and it works well, you can create a HTML web resource for quick test:
createNow();
function createNow() {
var fromUser = Xrm.Page.context.getUserId().replace(/[{}]/g, "");
var toPerson = Xrm.Page.getAttribute("requiredattendees").getValue()[0].id.replace(/[{}]/g, "");
var subjectText = "Your appointment is coming";
var descriptionText = "";
descriptionText = "Subject: " Xrm.Page.getAttribute("subject").getValue() "
";
descriptionText = "Start Time: " Xrm.Page.getAttribute("scheduledstart").getValue() "
";
descriptionText = "End Time: " Xrm.Page.getAttribute("scheduledend").getValue() "
";
var entity = {
"subject": subjectText,
"description": descriptionText,
"regardingobjectid_contact@odata.bind": "/contacts(" toPerson ")",
"email_activity_parties": [
{
"partyid_systemuser@odata.bind": "/systemusers(" fromUser ")",
"participationtypemask": 1
},
{
"partyid_contact@odata.bind": "/contacts(" toPerson ")",
"participationtypemask": 2
}
]
}
var req = new XMLHttpRequest();
req.open("POST", Xrm.Page.context.getClientUrl() "/api/data/v9.0/emails", true);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function () {
if (this.readyState === 4) {
req.onreadystatechange = null;
if (this.status === 204) {
var uri = this.getResponseHeader("OData-EntityId");
var regExp = /\(([^)] )\)/;
var matches = regExp.exec(uri);
var newEntityId = matches[1];
SendEmail(newEntityId);
} else {
Xrm.Utility.alertDialog(this.responseText);
}
}
};
req.send(JSON.stringify(entity));
}
function SendEmail(emailGblId) {
var parameters = {};
parameters.IssueSend = true;
var req = new XMLHttpRequest();
req.open("POST", Xrm.Page.context.getClientUrl() "/api/data/v9.0/emails(" emailGblId ")/Microsoft.Dynamics.CRM.SendEmail", true);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function () {
if (this.readyState === 4) {
req.onreadystatechange = null;
if (this.status === 200) {
var results = JSON.parse(this.response);
var confirmStrings = { text: "Email has been sent. \n Would you like to open it immediately?", title: "Confirmation" };
var confirmOptions = { height: 150, width: 250 };
Xrm.Navigation.openConfirmDialog(confirmStrings, confirmOptions).then(
function (success) {
if (success.confirmed) {
openEntityForm(emailGblId, "email");
console.log("Dialog closed using OK button.");
}
else {
console.log("Dialog closed using Cancel button or X.");
}
});
} else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send(JSON.stringify(parameters));
}
function openEntityForm(id, entityName) {
var entityFormOptions = {};
entityFormOptions["entityName"] = entityName;
entityFormOptions["entityId"] = id;
// Open the form.
Xrm.Navigation.openForm(entityFormOptions).then(
function (success) {
console.log(success);
},
function (error) {
console.log(error);
});
}
Result 1: User will receive a confirmation dialog about the email has been sent successfully,
if he clicks Ok, then he'll be navigated to new email record.

Result 2: The delivered test email

My code is very basic, you could extend it with more necessary features,
such as validation for fields, add more information from appointment record into description,
better format for schedule time and email content etc.
Regards,
Clofly