Skip to content

Commit

Permalink
Merge pull request #3 from sinch/feat/eu-region-support
Browse files Browse the repository at this point in the history
feat: Add support for sending emails using EU region
  • Loading branch information
sinchflows authored Apr 25, 2024
2 parents a240f9a + 384bb5e commit ca70653
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 75 deletions.
6 changes: 4 additions & 2 deletions src/api/mailgun-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@ const registerCallback = (RED) => {
const registerTemplates = (RED) => {
RED.httpNode.post("/external/mailgun/templates", async (req, res) => {
const mailgun = new Mailgun(formData);
const { baseUrl, apiKey } = req.body;
const { baseUrl, apiKey, region } = req.body;
if (!baseUrl || !apiKey) {
return res.sendStatus(400);
}

const mg = mailgun.client({ username: "api", key: apiKey });
const url = region === 'EU' ? 'https://api.eu.mailgun.net' : undefined;

const mg = mailgun.client({ username: "api", key: apiKey, url });
try {
const response = await mg.domains.domainTemplates.list(baseUrl);
if (response && response.items) {
Expand Down
3 changes: 2 additions & 1 deletion src/nodes/send-email/locales/en-US/send-email.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
"clicked": "Link clicked",
"complained": "Spam complaints",
"responses": "Responses",
"outputs": "Outputs"
"outputs": "Outputs",
"region": "Region"
}
166 changes: 95 additions & 71 deletions src/nodes/send-email/send-email.html
Original file line number Diff line number Diff line change
@@ -1,48 +1,51 @@
<script type="text/javascript">
const events = {
default: 'Default',
delivered: 'Delivered',
failed: 'Failed',
unsubscribed: 'Unsubscribed',
opened: 'Opened',
clicked: 'Link clicked',
complained: 'Spam complaints',
responses: 'Responses',
default: "Default",
delivered: "Delivered",
failed: "Failed",
unsubscribed: "Unsubscribed",
opened: "Opened",
clicked: "Link clicked",
complained: "Spam complaints",
responses: "Responses",
};

RED.nodes.registerType('sinch-send-email', {
category: 'Mailgun',
color: '#F3B2BA',
RED.nodes.registerType("sinch-send-email", {
category: "Mailgun",
color: "#F3B2BA",
defaults: {
name: {
value: "" ,
name: {
value: "",
},
baseUrl: {
value: '',
value: "",
required: true,
},
apiKey: {
value: '',
value: "",
required: true,
},
sender: {
value: '',
value: "",
},
recipient: {
value: '',
value: "",
},
subject: {
value: '',
value: "",
required: true,
},
body: {
value: '',
value: "",
},
template: {
value: '',
value: "",
},
region: {
value: "US",
},
variables: {
value: [{ key: '', value: '' }],
value: [{ key: "", value: "" }],
},
tags: {
value: [],
Expand Down Expand Up @@ -78,15 +81,15 @@
if (this.outputMap) {
const outputFor = JSON.parse(this.outputMap);
for (const [key, value] of Object.entries(outputFor)) {
if (key == '') return '[error]';
if (key == "") return "[error]";
if (value === index) {
return this._(events[key]) || events[key];
}
}
}
return this._('output');
return this._("output");
},
icon: 'font-awesome/fa-envelope-o',
icon: "font-awesome/fa-envelope-o",
paletteLabel: function() {
return this.name || this._("node-label") || "Send Email";
},
Expand All @@ -97,77 +100,93 @@
oneditsave,
});
function oneditprepare() {
const nodeInputTemplate = $('#node-input-template');
const nodeInputBaseUrl = $('#node-input-baseUrl');
const nodeInputApiKey = $('#node-input-apiKey');
const syncTemplateButton = $('#send-email-sync-template-button');
const nodeInputTemplate = $("#node-input-template");
const nodeInputRegion = $("#node-input-region");
const nodeInputBaseUrl = $("#node-input-baseUrl");
const nodeInputApiKey = $("#node-input-apiKey");
const syncTemplateButton = $("#send-email-sync-template-button");

nodeInputRegion.typedInput({
types: [
{
value: "region",
options: [{ value: "US", label: "US" }, { value: "EU", label: "EU" }],
},
],
});

const loadTemplates = (calledFromSyncButton = false) => {
const loadTemplates = (region) => {
$.ajax({
// eslint-disable-next-line no-undef
url: location.pathname + 'external/mailgun/templates',
method: 'POST',
url: location.pathname + "external/mailgun/templates",
method: "POST",
data: {
baseUrl: nodeInputBaseUrl.val(),
apiKey: nodeInputApiKey.val(),
region: region ? region : nodeInputRegion.val(),
},
success: (res) => {
if (res && res.length) {
nodeInputTemplate.empty();
res.forEach(({ name }) => {
nodeInputTemplate.append(
$('<option></option>')
.attr('value', name)
.attr('selected', this.template === name)
$("<option></option>")
.attr("value", name)
.attr("selected", this.template === name)
.text(name)
);
});
nodeInputTemplate.prop('disabled', false);
nodeInputTemplate.off('change');
nodeInputTemplate.prop("disabled", false);
nodeInputTemplate.off("change");
nodeInputTemplate.append(
$('<option></option>')
.attr('value', '')
.text(this._('no-template-selected'))
.attr('selected', this.template === '')
$("<option></option>")
.attr("value", "")
.text(this._("no-template-selected"))
.attr("selected", this.template === "")
);
} else {
nodeInputTemplate.append(
$('<option></option>')
.attr('value', '')
.text(this._('no-templates-available'))
.attr('selected', this.template === '')
$("<option></option>")
.attr("value", "")
.text(this._("no-templates-available"))
.attr("selected", this.template === "")
);
}
},
error: () => {
if (!calledFromSyncButton) {
nodeInputTemplate.empty();
nodeInputTemplate.append(
$('<option></option>')
.attr('value', '')
.text(this._('authentication-error'))
$("<option></option>")
.attr("value", "")
.text(this._("authentication-error"))
);
}
},
});
};
syncTemplateButton.click(() => {
loadTemplates(true);
loadTemplates();
});
loadTemplates();
$('#node-config-input-variables-container')
.css('min-height', '200px')
.css('min-width', '250px')

nodeInputRegion.change((evt) => {
loadTemplates(evt.target.value);

});

$("#node-config-input-variables-container")
.css("min-height", "200px")
.css("min-width", "250px")
.editableList({
addButton: false,
addItem: (container, i, { key, value }) => {
const initialInputWidth = (container.width() - 45) / 2;
container.css({
overflow: 'hidden',
whiteSpace: 'nowrap',
overflow: "hidden",
whiteSpace: "nowrap",
});

key = typeof key === 'string' ? key : '';
value = typeof value === 'string' ? value : '';
key = typeof key === "string" ? key : "";
value = typeof value === "string" ? value : "";

$(`
<div class="form-row">
Expand All @@ -189,19 +208,19 @@
removable: true,
buttons: [
{
label: 'Add Variable',
icon: 'fa fa-plus',
label: "Add Variable",
icon: "fa fa-plus",
click: function() {
$('#node-config-input-variables-container').editableList(
'addItem',
{ key: '', value: '' }
$("#node-config-input-variables-container").editableList(
"addItem",
{ key: "", value: "" }
);
},
},
],
});
this.variables.forEach(({ key, value }) => {
$('#node-config-input-variables-container').editableList('addItem', {
$("#node-config-input-variables-container").editableList("addItem", {
key,
value,
});
Expand All @@ -211,29 +230,29 @@
function oneditsave() {
const node = this;
node.variables = [];
let variable = { key: '', value: '' };
let variable = { key: "", value: "" };
let isKey = true;
$('#node-config-input-variables-container input').each(function(_, input) {
$("#node-config-input-variables-container input").each(function(_, input) {
if (isKey) {
variable.key = input.value || '';
variable.key = input.value || "";
isKey = false;
} else {
variable.value = input.value || '';
variable.value = input.value || "";
isKey = true;
node.variables.push(variable);
variable = { key: '', value: '' };
variable = { key: "", value: "" };
}
});

let counter = 1;
const outputMapping = { default: 0 };
Object.keys(events).forEach((key) => {
if ($(`#node-input-${key}`).prop('checked')) {
if ($(`#node-input-${key}`).prop("checked")) {
outputMapping[key] = counter++;
}
});
$('#node-input-outputs').val(counter);
$('#node-input-outputMap').val(JSON.stringify(outputMapping));
$("#node-input-outputs").val(counter);
$("#node-input-outputMap").val(JSON.stringify(outputMapping));
node.outputs = counter;
node.outputMap = JSON.stringify(outputMapping);
}
Expand Down Expand Up @@ -286,6 +305,11 @@
<input type="text" id="node-input-body" data-i18n="[placeholder]body-input">
</div>

<div class="form-row">
<label for="node-input-region"><span data-i18n="region"></span></label>
<input type="text" id="node-input-region">
</div>

<div class="form-row">
<label for="node-input-template"><span data-i18n="template"></span></label>
<select id="node-input-template" style="width: 60%" disabled></select>
Expand Down
5 changes: 4 additions & 1 deletion src/nodes/send-email/send-email.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module.exports = function(RED) {
outputMap,
outputs,
variables,
region,
} = this.config;

this.onCallback = (msg) => {
Expand Down Expand Up @@ -65,7 +66,9 @@ module.exports = function(RED) {
};
}

const mg = mailgun.client({ username: 'api', key: apiKey });
const url = region === 'EU' ? 'https://api.eu.mailgun.net' : undefined;

const mg = mailgun.client({ username: 'api', key: apiKey, url });
mg.messages
.create(baseUrl, data)
.then((res) => {
Expand Down

0 comments on commit ca70653

Please sign in to comment.