Skip to content

Commit

Permalink
New Components - elastic_email (#15692)
Browse files Browse the repository at this point in the history
* elastic_email init

* [Components] elasticemail #15687
Sources
 - New Email Open
 - New Email Click
 - New Contact Added

Actions
 - Send Email
 - Add Contact
 - Unsubscribe Contact

* pnpm update

* some adjusts

* some adjusts

* fix template prop
  • Loading branch information
luancazarine authored Feb 28, 2025
1 parent 2db43fd commit 335ff74
Show file tree
Hide file tree
Showing 17 changed files with 702 additions and 20 deletions.
3 changes: 0 additions & 3 deletions components/elastic_email/.gitignore

This file was deleted.

104 changes: 104 additions & 0 deletions components/elastic_email/actions/add-contact/add-contact.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { ConfigurationError } from "@pipedream/platform";
import {
CONSENT_TRACKING_OPTIONS,
STATUS_OPTIONS,
} from "../../common/constants.mjs";
import { parseObject } from "../../common/utils.mjs";
import app from "../../elastic_email.app.mjs";

export default {
key: "elastic_email-add-contact",
name: "Add Contact to Mailing List",
description: "Adds a new contact to a mailing list. [See the documentation](https://elasticemail.com/developers/api-documentation/rest-api#operation/contactsPost)",
version: "0.0.1",
type: "action",
props: {
app,
email: {
propDefinition: [
app,
"email",
],
},
listNames: {
propDefinition: [
app,
"listNames",
],
optional: true,
},
status: {
type: "string",
label: "Status",
description: "The initial status of the contact.",
options: STATUS_OPTIONS,
optional: true,
},
firstName: {
type: "string",
label: "First Name",
description: "The contact's first name.",
optional: true,
},
lastName: {
type: "string",
label: "Last Name",
description: "The contact's last name.",
optional: true,
},
customFields: {
type: "object",
label: "Custom Fields",
description: "A key-value collection of custom contact fields which can be used in the system. Only already existing custom fields will be saved.",
optional: true,
},
consentIP: {
type: "string",
label: "Consent IP",
description: "IP address of consent to send this contact(s) your email. If not provided your current public IP address is used for consent.",
optional: true,
},
consentDate: {
type: "string",
label: "Consent Date",
description: "Date of consent to send this contact(s) your email. If not provided current date is used for consent.",
optional: true,
},
consentTracking: {
type: "string",
label: "Consent Tracking",
description: "Tracking of consent to send this contact(s) your email. Defaults to \"Unknown\".",
options: CONSENT_TRACKING_OPTIONS,
optional: true,
},
},
async run({ $ }) {
const response = await this.app.addContact({
$,
params: {
listnames: parseObject(this.listNames),
},
data: [
{
Email: this.email,
Status: this.status,
FirstName: this.firstName,
LastName: this.lastName,
CustomFields: parseObject(this.customFields),
Consent: {
ConsentIP: this.consentIP,
ConsentDate: this.consentDate,
ConsentTracking: this.consentTracking,
},
},
],
});

if (("success" in response) && response.success === "false") {
throw new ConfigurationError(response.error);
}

$.export("$summary", `Successfully added contact ${this.email} to the mailing list`);
return response;
},
};
135 changes: 135 additions & 0 deletions components/elastic_email/actions/send-email/send-email.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import {
BODY_CONTENT_TYPE_OPTIONS,
ENCODING_OPTIONS,
} from "../../common/constants.mjs";
import { parseObject } from "../../common/utils.mjs";
import app from "../../elastic_email.app.mjs";

export default {
key: "elastic_email-send-email",
name: "Send Email",
description: "Sends an email to one or more recipients. [See the documentation](https://elasticemail.com/developers/api-documentation/rest-api#operation/emailsPost)",
version: "0.0.1",
type: "action",
props: {
app,
recipients: {
type: "string[]",
label: "Recipients",
description: "List of recipients",
},
from: {
type: "string",
label: "From",
description: "Your e-mail with an optional name (e.g.: [email protected])",
},
bodyContentType: {
type: "string",
label: "Body Content Type",
description: "Type of body part",
options: BODY_CONTENT_TYPE_OPTIONS,
optional: true,
},
bodyContent: {
type: "string",
label: "Body Content",
description: "Actual content of the body part",
optional: true,
},
merge: {
type: "object",
label: "Merge",
description: "A key-value collection of custom merge fields, shared between recipients. Should be used in e-mail body like so: {firstname}, {lastname} etc.",
optional: true,
},
replyTo: {
type: "string",
label: "Reply To",
description: "To what address should the recipients reply to (e.g. [email protected])",
optional: true,
},
subject: {
type: "string",
label: "Subject",
description: "Default subject of email.",
optional: true,
},
templateName: {
propDefinition: [
app,
"templateName",
],
optional: true,
},
timeOffset: {
type: "integer",
label: "Time Offset",
description: "By how long should an e-mail be delayed (in minutes). Maximum is 35 days.",
optional: true,
},
poolName: {
type: "string",
label: "Pool Name",
description: "Name of your custom IP Pool to be used in the sending process",
optional: true,
},
channelName: {
type: "string",
label: "Channel Name",
description: "Name of selected channel.",
optional: true,
},
encoding: {
type: "string",
label: "Encoding",
description: "Encoding type for the email headers",
options: ENCODING_OPTIONS,
optional: true,
},
trackOpens: {
type: "boolean",
label: "Track Opens",
description: "Should the opens be tracked? If no value has been provided, Account's default setting will be used.",
optional: true,
},
trackClicks: {
type: "boolean",
label: "Track Clicks",
description: "Should the clicks be tracked? If no value has been provided, Account's default setting will be used.",
optional: true,
},
},
async run({ $ }) {
const response = await this.app.sendBulkEmails({
$,
data: {
Recipients: parseObject(this.recipients)?.map((item) => ({
Email: item,
})),
Content: {
From: this.from,
Body: [
{
ContentType: this.bodyContentType,
Body: this.bodyContent,
},
],
Merge: parseObject(this.merge),
ReplyTo: this.replyTo,
Subject: this.subject,
TemplateName: this.templateName,
},
Options: {
TimeOffset: this.timeOffset,
PoolName: this.poolName,
ChannelName: this.channelName,
Encoding: this.encoding,
TrackOpens: this.trackOpens,
TrackClicks: this.trackClicks,
},
},
});
$.export("$summary", `Emails sent successfully to ${this.recipients.join(", ")}`);
return response;
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { parseObject } from "../../common/utils.mjs";
import app from "../../elastic_email.app.mjs";

export default {
key: "elastic_email-unsubscribe-contact",
name: "Unsubscribe Contact",
description: "Unsubscribes a contact from future emails. [See the documentation](https://elasticemail.com/developers/api-documentation/rest-api#operation/suppressionsUnsubscribesPost)",
version: "0.0.1",
type: "action",
props: {
app,
unsubscribeEmails: {
propDefinition: [
app,
"unsubscribeEmails",
],
},
},
async run({ $ }) {
const parsedEmails = parseObject(this.unsubscribeEmails);
const response = await this.app.unsubscribeContact({
$,
data: parsedEmails,
});
$.export("$summary", `Unsubscribed ${parsedEmails.length} contact(s) successfully`);
return response;
},
};
13 changes: 0 additions & 13 deletions components/elastic_email/app/elastic_email.app.ts

This file was deleted.

36 changes: 36 additions & 0 deletions components/elastic_email/common/constants.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export const LIMIT = 100;

export const STATUS_OPTIONS = [
"Transactional",
"Engaged",
"Active",
"Bounced",
"Unsubscribed",
"Abuse",
"Inactive",
"Stale",
"NotConfirmed",
];

export const ENCODING_OPTIONS = [
"UserProvided",
"None",
"Raw7bit",
"Raw8bit",
"QuotedPrintable",
"Base64",
"Uue",
];

export const CONSENT_TRACKING_OPTIONS = [
"Unknown",
"Allow",
"Deny",
];

export const BODY_CONTENT_TYPE_OPTIONS = [
"HTML",
"PlainText",
"AMP",
"CSS",
];
24 changes: 24 additions & 0 deletions components/elastic_email/common/utils.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export const parseObject = (obj) => {
if (!obj) return undefined;

if (Array.isArray(obj)) {
return obj.map((item) => {
if (typeof item === "string") {
try {
return JSON.parse(item);
} catch (e) {
return item;
}
}
return item;
});
}
if (typeof obj === "string") {
try {
return JSON.parse(obj);
} catch (e) {
return obj;
}
}
return obj;
};
Loading

0 comments on commit 335ff74

Please sign in to comment.