Skip to main content

How to Import Templates

Easy Email Pro supports importing email templates from various formats, allowing you to migrate existing templates or load templates from files.

Supported Formats​

You can import templates from the following formats:

  1. MJML XML Format - Standard MJML XML files
  2. MJML JSON Format - MJML data in JSON structure
  3. Easy Email JSON - Templates from the open-source Easy Email project
  4. Easy Email Pro JSON - Native Easy Email Pro template format

Implementation​

For complete implementation examples, check our live demo code.

Import Methods​

Import MJML XML​

Import from MJML XML files:

import { useEditorContext } from "easy-email-pro-theme";
import { mjmlToJson } from "easy-email-pro-theme";
import { Uploader } from "@arco-design/web-react";

const { reset } = useEditorContext();

const onImportMJML = async () => {
const uploader = new Uploader(() => Promise.resolve(""), {
accept: "text/mjml,application/xml",
limit: 1,
});

const [file] = await uploader.chooseFile();
const reader = new FileReader();

const pageData = await new Promise<[string, EmailTemplate["content"]]>(
(resolve, reject) => {
reader.onload = function (evt) {
if (!evt.target) {
reject(new Error("Failed to read file"));
return;
}
try {
// Convert MJML XML to Easy Email Pro format
const pageData = mjmlToJson(evt.target.result as string);
resolve([file.name, pageData]);
} catch (error) {
reject(error);
}
};
reader.readAsText(file);
}
);

// Reset editor with imported template
reset({
subject: pageData[0],
content: pageData[1],
});
};

Import MJML JSON​

Import from MJML JSON format:

const onImportMJMLJSON = async () => {
const uploader = new Uploader(() => Promise.resolve(""), {
accept: "application/json",
limit: 1,
});

const [file] = await uploader.chooseFile();
const reader = new FileReader();

const pageData = await new Promise<[string, EmailTemplate["content"]]>(
(resolve, reject) => {
reader.onload = function (evt) {
if (!evt.target) {
reject(new Error("Failed to read file"));
return;
}
try {
// Parse JSON and convert to Easy Email Pro format
const mjmlJson = JSON.parse(evt.target.result as string);
const pageData = mjmlToJson(mjmlJson);
resolve([file.name, pageData]);
} catch (error) {
reject(error);
}
};
reader.readAsText(file);
}
);

reset({
subject: pageData[0],
content: pageData[1],
});
};

Import Easy Email Pro JSON​

Import native Easy Email Pro template format:

import { EmailTemplate } from "easy-email-pro-editor";

const onImportJSON = async () => {
const uploader = new Uploader(() => Promise.resolve(""), {
accept: "application/json",
limit: 1,
});

const [file] = await uploader.chooseFile();
const reader = new FileReader();

const emailTemplate = await new Promise<EmailTemplate>(
(resolve, reject) => {
reader.onload = function (evt) {
if (!evt.target) {
reject(new Error("Failed to read file"));
return;
}
try {
const template = JSON.parse(
evt.target.result as string
) as EmailTemplate;

// Validate template structure
if (!template.content || !template.subject) {
throw new Error("Invalid template format");
}

resolve(template);
} catch (error) {
reject(error);
}
};
reader.readAsText(file);
}
);

reset({
subject: emailTemplate.subject,
content: emailTemplate.content,
});
};

Import Easy Email (Legacy)​

Import templates from the open-source Easy Email project:

import { easyEmailToEasyEmailPro } from "easy-email-pro-core";
import { Message } from "@arco-design/web-react";

const onImportEasyEmailJSON = async () => {
const uploader = new Uploader(() => Promise.resolve(""), {
accept: "application/json",
limit: 1,
});

const [file] = await uploader.chooseFile();
const reader = new FileReader();

const emailTemplate = await new Promise<EmailTemplate>(
(resolve, reject) => {
reader.onload = function (evt) {
if (!evt.target) {
reject(new Error("Failed to read file"));
return;
}
try {
const template = JSON.parse(evt.target.result as string);

if (!template.content) {
Message.error("Invalid template: content parameter is required");
reject(new Error("Invalid template"));
return;
}

// Convert Easy Email format to Easy Email Pro format
const content = easyEmailToEasyEmailPro(template.content);

resolve({
subject: template.subject || "",
content: content,
});
} catch (error) {
console.error("Import error:", error);
Message.error("Failed to import template");
reject(error);
}
};
reader.readAsText(file);
}
);

reset({
subject: emailTemplate.subject,
content: emailTemplate.content,
});
};

Complete Example​

Here's a complete example with error handling:

import { useEditorContext } from "easy-email-pro-theme";
import { mjmlToJson } from "easy-email-pro-theme";
import { easyEmailToEasyEmailPro } from "easy-email-pro-core";
import { Uploader, Message } from "@arco-design/web-react";
import { EmailTemplate } from "easy-email-pro-editor";

function ImportButtons() {
const { reset } = useEditorContext();

const handleFileUpload = async (
accept: string,
processor: (content: string) => EmailTemplate["content"]
) => {
try {
const uploader = new Uploader(() => Promise.resolve(""), {
accept,
limit: 1,
});

const [file] = await uploader.chooseFile();
const reader = new FileReader();

const result = await new Promise<EmailTemplate["content"]>(
(resolve, reject) => {
reader.onload = (evt) => {
if (!evt.target) {
reject(new Error("Failed to read file"));
return;
}
try {
const content = processor(evt.target.result as string);
resolve(content);
} catch (error) {
reject(error);
}
};
reader.onerror = () => reject(new Error("File read error"));
reader.readAsText(file);
}
);

reset({
subject: file.name,
content: result,
});

Message.success("Template imported successfully");
} catch (error) {
Message.error(`Import failed: ${error.message}`);
}
};

return (
<div>
<Button onClick={() => handleFileUpload(
"text/mjml,application/xml",
(content) => mjmlToJson(content)
)}>
Import MJML XML
</Button>

<Button onClick={() => handleFileUpload(
"application/json",
(content) => {
const json = JSON.parse(content);
return mjmlToJson(json);
}
)}>
Import MJML JSON
</Button>

<Button onClick={() => handleFileUpload(
"application/json",
(content) => {
const template = JSON.parse(content);
return easyEmailToEasyEmailPro(template.content);
}
)}>
Import Easy Email JSON
</Button>
</div>
);
}

Notes​

  • Always validate imported templates before resetting the editor
  • Handle errors gracefully with user feedback
  • The reset function will replace the entire template, so ensure the imported data is valid
  • MJML imports may require additional validation depending on MJML version compatibility
EditorHeader.tsx
const { values, submit, setFieldValue, mergetagsData, reset, dirty } =
useEditorContext();

const onImportMJML = async () => {
const uploader = new Uploader(() => Promise.resolve(""), {
accept: "text/mjml",
limit: 1,
});

const [file] = await uploader.chooseFile();
const reader = new FileReader();
const pageData = await new Promise<[string, EmailTemplate["content"]]>(
(resolve, reject) => {
reader.onload = function (evt) {
if (!evt.target) {
reject();
return;
}
try {
const pageData = mjmlToJson(evt.target.result as any);
resolve([file.name, pageData]);
} catch (error) {
reject();
}
};
reader.readAsText(file);
}
);

reset({
subject: pageData[0],
content: pageData[1],
});
};

const onImportMJMLJSON = async () => {
const uploader = new Uploader(() => Promise.resolve(""), {
accept: "application/json",
limit: 1,
});

const [file] = await uploader.chooseFile();
const reader = new FileReader();
const pageData = await new Promise<[string, EmailTemplate["content"]]>(
(resolve, reject) => {
reader.onload = function (evt) {
if (!evt.target) {
reject();
return;
}
try {
const pageData = mjmlToJson(
JSON.parse(evt.target.result as any) as any
);
resolve([file.name, pageData]);
} catch (error) {
reject();
}
};
reader.readAsText(file);
}
);

reset({
subject: pageData[0],
content: pageData[1],
});
};

const onImportJSON = async () => {
const uploader = new Uploader(() => Promise.resolve(""), {
accept: "application/json",
limit: 1,
});

const [file] = await uploader.chooseFile();
const reader = new FileReader();
const emailTemplate = await new Promise<EmailTemplate>((resolve, reject) => {
reader.onload = function (evt) {
if (!evt.target) {
reject();
return;
}
try {
const template = JSON.parse(evt.target.result as any) as EmailTemplate;
resolve(template);
} catch (error) {
reject();
}
};
reader.readAsText(file);
});

reset({
subject: emailTemplate.subject,
content: emailTemplate.content,
});
};

const onImportEasyEmailJSON = async () => {
const uploader = new Uploader(() => Promise.resolve(""), {
accept: "application/json",
limit: 1,
});

const [file] = await uploader.chooseFile();
const reader = new FileReader();
const emailTemplate = await new Promise<EmailTemplate>((resolve, reject) => {
reader.onload = function (evt) {
if (!evt.target) {
reject();
return;
}
try {
const template = JSON.parse(evt.target.result as any);
const content = easyEmailToEasyEmailPro(template.content);
if (!template.content) {
Message.error(`Invalid template, need content params`);
reject();
return;
}

resolve({
subject: template.subject,
content: content,
});
} catch (error) {
console.log(error);
reject();
}
};
reader.readAsText(file);
});

reset({
subject: emailTemplate.subject,
content: emailTemplate.content,
});
};