I’m working on developing my first Add-In for Outlook 365/Windows 10. In theory, it’s quite simple—it’s a drop-down menu with two options. Each option opens a new email and loads a different template, depending on the selection.
So far, the menu is functioning smoothly. Selecting option A displays the corresponding template, and the same goes for option B.
However, I’m facing a problem: I can’t get the user’s signature to load automatically as expected, even though the signature is properly configured and set as the default for new emails.
Attached you will find my manifest.xml and commands.ts
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0" xmlns:mailappor="http://schemas.microsoft.com/office/mailappversionoverrides/1.0" xsi:type="MailApp">
<Id>2eb95a7a-bc4a-4f53-bc6f-ba64b72d8663</Id>
<Version>1.0.0.0</Version>
<ProviderName>Contoso</ProviderName>
<DefaultLocale>en-US</DefaultLocale>
<DisplayName DefaultValue="NewClientMatter"/>
<Description DefaultValue="A template to get started."/>
<IconUrl DefaultValue="https://localhost:3000/assets/icon-64.png"/>
<HighResolutionIconUrl DefaultValue="https://localhost:3000/assets/icon-128.png"/>
<SupportUrl DefaultValue="https://www.contoso.com/help"/>
<AppDomains>
<AppDomain>https://www.contoso.com</AppDomain>
</AppDomains>
<Hosts>
<Host Name="Mailbox"/>
</Hosts>
<Requirements>
<Sets>
<Set Name="Mailbox" MinVersion="1.5"/>
</Sets>
</Requirements>
<FormSettings>
<Form xsi:type="ItemRead">
<DesktopSettings>
<SourceLocation DefaultValue="https://localhost:3000/taskpane.html"/>
<RequestedHeight>250</RequestedHeight>
</DesktopSettings>
</Form>
</FormSettings>
<Permissions>ReadWriteItem</Permissions>
<Rule xsi:type="RuleCollection" Mode="Or">
<Rule xsi:type="ItemIs" ItemType="Message" FormType="Read"/>
<Rule xsi:type="ItemIs" ItemType="Message" FormType="Edit"/>
</Rule>
<DisableEntityHighlighting>false</DisableEntityHighlighting>
<VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides" xsi:type="VersionOverridesV1_0">
<Requirements>
<bt:Sets DefaultMinVersion="1.5">
<bt:Set Name="Mailbox"/>
</bt:Sets>
</Requirements>
<Hosts>
<Host xsi:type="MailHost">
<DesktopFormFactor>
<FunctionFile resid="Commands.Url"/>
<ExtensionPoint xsi:type="MessageReadCommandSurface">
<OfficeTab id="TabDefault">
<Group id="msgReadGroup">
<Label resid="GroupLabel"/>
<Control xsi:type="Menu" id="DropdownMenu">
<Label resid="DropdownMenu.Label"/>
<Supertip>
<Title resid="DropdownMenu.Label"/>
<Description resid="DropdownMenu.Tooltip"/>
</Supertip>
<Icon>
<bt:Image size="16" resid="MenuIcon.16x16"/>
<bt:Image size="32" resid="MenuIcon.32x32"/>
<bt:Image size="80" resid="MenuIcon.80x80"/>
</Icon>
<Items>
<Item id="InternalAction">
<Label resid="InternalAction.Label"/>
<Supertip>
<Title resid="InternalAction.Label"/>
<Description resid="InternalAction.Tooltip"/>
</Supertip>
<Icon>
<bt:Image size="16" resid="InternalIcon.16x16"/>
<bt:Image size="32" resid="InternalIcon.32x32"/>
<bt:Image size="80" resid="InternalIcon.80x80"/>
</Icon>
<Action xsi:type="ExecuteFunction">
<FunctionName>handleInternalAction</FunctionName>
</Action>
</Item>
<Item id="ExternalAction">
<Label resid="ExternalAction.Label"/>
<Supertip>
<Title resid="ExternalAction.Label"/>
<Description resid="ExternalAction.Tooltip"/>
</Supertip>
<Icon>
<bt:Image size="16" resid="ExternalIcon.16x16"/>
<bt:Image size="32" resid="ExternalIcon.32x32"/>
<bt:Image size="80" resid="ExternalIcon.80x80"/>
</Icon>
<Action xsi:type="ExecuteFunction">
<FunctionName>handleExternalAction</FunctionName>
</Action>
</Item>
</Items>
</Control>
</Group>
</OfficeTab>
</ExtensionPoint>
</DesktopFormFactor>
</Host>
</Hosts>
<Resources>
<bt:Images>
<bt:Image id="MenuIcon.16x16" DefaultValue="https://localhost:3000/assets/menu-icon-16.png"/>
<bt:Image id="MenuIcon.32x32" DefaultValue="https://localhost:3000/assets/menu-icon-32.png"/>
<bt:Image id="MenuIcon.80x80" DefaultValue="https://localhost:3000/assets/menu-icon-80.png"/>
<bt:Image id="InternalIcon.16x16" DefaultValue="https://localhost:3000/assets/int-16.png"/>
<bt:Image id="InternalIcon.32x32" DefaultValue="https://localhost:3000/assets/int-32.png"/>
<bt:Image id="InternalIcon.80x80" DefaultValue="https://localhost:3000/assets/int-80.png"/>
<bt:Image id="ExternalIcon.16x16" DefaultValue="https://localhost:3000/assets/ext-16.png"/>
<bt:Image id="ExternalIcon.32x32" DefaultValue="https://localhost:3000/assets/ext-32.png"/>
<bt:Image id="ExternalIcon.80x80" DefaultValue="https://localhost:3000/assets/ext-80.png"/>
</bt:Images>
<bt:Urls>
<bt:Url id="Commands.Url" DefaultValue="https://localhost:3000/commands.html"/>
<bt:Url id="Taskpane.Url" DefaultValue="https://localhost:3000/taskpane.html"/>
<bt:Url id="CommandsJs.Url" DefaultValue="https://localhost:3000/commands/commands.js"/>
</bt:Urls>
<bt:ShortStrings>
<bt:String id="GroupLabel" DefaultValue="New Client/Matter"/>
<bt:String id="DropdownMenu.Label" DefaultValue="Choose Action"/>
<bt:String id="InternalAction.Label" DefaultValue="Internal"/>
<bt:String id="ExternalAction.Label" DefaultValue="External"/>
</bt:ShortStrings>
<bt:LongStrings>
<bt:String id="DropdownMenu.Tooltip" DefaultValue="Select an action to perform."/>
<bt:String id="InternalAction.Tooltip" DefaultValue="Opens an internal email template."/>
<bt:String id="ExternalAction.Tooltip" DefaultValue="Opens an external email template."/>
</bt:LongStrings>
</Resources>
</VersionOverrides>
</OfficeApp>
commands.ts
/* global Office */
Office.onReady(function (info) {
if (info.host === Office.HostType.Outlook) {
Office.actions.associate("handleInternalAction", handleInternalAction);
Office.actions.associate("handleExternalAction", handleExternalAction);
}
});
/**
* Handles the "Internal" action.
* @param event The Office Add-in event.
*/
function handleInternalAction(event: Office.AddinCommands.Event): void {
openEmailTemplate("internal", event);
}
/**
* Handles the "External" action.
* @param event The Office Add-in event.
*/
function handleExternalAction(event: Office.AddinCommands.Event): void {
openEmailTemplate("external", event);
}
/**
* Opens an email template with the user's signature.
* @param templateType The type of template ("internal" or "external").
* @param event The Office Add-in event.
*/
function openEmailTemplate(templateType: string, event: Office.AddinCommands.Event): void {
let templateBody: string;
let subject: string;
if (templateType === "internal") {
templateBody = `
My fields<br/><br/>
`;
subject = "(Internal)";
} else if (templateType === "external") {
templateBody = `
My fields<br/><br/>
`;
subject = "(External)";
} else {
console.error("Invalid template type specified:", templateType);
event.completed();
return;
}
// Open a new email draft
Office.context.mailbox.displayNewMessageForm({
subject,
htmlBody: templateBody,
});
// Function to check draft readiness and insert the signature
const checkDraftReady = () => {
Office.context.mailbox.item.body.getAsync(Office.CoercionType.Html, (result) => {
if (result.status === Office.AsyncResultStatus.Succeeded) {
const userSignature = result.value || "";
if (userSignature) {
const combinedBody = `
<html>
<head>
<meta charset="utf-8">
</head>
<body>
${templateBody} <!-- Template Body -->
<br/><br/>
${userSignature} <!-- User Signature -->
</body>
</html>
`;
Office.context.mailbox.item.body.setAsync(
combinedBody,
{ coercionType: Office.CoercionType.Html },
(setResult) => {
if (setResult.status !== Office.AsyncResultStatus.Succeeded) {
console.error("Failed to set email body:", setResult.error);
}
event.completed(); // Ensure event is completed after the set operation
}
);
} else {
console.warn("User's signature not available.");
event.completed();
}
} else {
console.error("Failed to get user's signature. Retrying...", result.error);
setTimeout(checkDraftReady, 500); // Retry after a short delay
}
});
};
setTimeout(checkDraftReady, 500); // Initial retry delay
}
Thank you so much for your support!
userSignaturecomes up empty?<body>tag (or</body>depending on where you are inserting) in one HTML string, then insert the value between the<body>and</body>tags of the second HTML string. You'll lose the styles defined in the header, but you can deal with that too.