Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,30 @@ NOTE: You will NOT receive an email if you(the author that registered their emai
"urlToPads": "http://beta.etherpad.org/p/", // urlToPads = The URL to your pads note the trailing /
"emailServer": { // See https://github.com/eleith/emailjs for settings
"host": "127.0.0.1"
},
"messages": { // All fields are optional; omit any to use the built-in default
"footer": "\nYou can unsubscribe from these emails in the pad's Settings window.\n",
"beginSubject": "Someone started editing {padId}",
"beginBody": "This pad is now being edited:\n <{padUrl}>\n{footer}",
"endSubject": "Someone finished editing {padId}",
"endBody": "This pad is done being edited:\n <{padUrl}>\n{footer}",
"subscribeSubject": "Email subscription confirmation for pad {padId}",
"subscribeBody": "Please click on this link in order to validate your subscription to the pad {padId}\n{confirmLink}",
"unsubscribeSubject": "Email unsubscription confirmation for pad {padId}",
"unsubscribeBody": "Please click on this link in order to validate your unsubscription to the pad {padId}\n{confirmLink}"
}
}
```

Supported placeholders in `messages` templates:

| Placeholder | Available in | Description |
|---|---|---|
| `{padId}` | all | The pad's identifier |
| `{padUrl}` | all | Full URL to the pad |
| `{footer}` | `beginBody`, `endBody` | The configured (or default) footer text |
| `{confirmLink}` | `subscribeBody`, `unsubscribeBody` | The one-click confirmation URL |

# Translation
This plugin has for now translations for english, french and german.
In case you would like to have it in another language, you can easily translate the few sentences and then contact us on irc (#etherpad-lite-dev on irc.freenode.net) or create a Pull-Request on the GitHub repository.
Expand Down
36 changes: 30 additions & 6 deletions handleMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const urlToPads = (pluginSettings && pluginSettings.urlToPads)
? pluginSettings.urlToPads : 'http://beta.etherpad.org/p/';
const emailServer = (pluginSettings && pluginSettings.emailServer)
? pluginSettings.emailServer : {host: '127.0.0.1'};
const messageSettings = (pluginSettings && pluginSettings.messages) || {};
const {renderTemplate} = require('./messageUtils');

if (!pluginSettings) {
console.warn('Settings for ep_email_notifications plugin are missing in settings.json file');
Expand Down Expand Up @@ -159,14 +161,25 @@ const subscriptionEmail = async (context, email, emailFound, userInfo, padId) =>
});

// Send mail to user with the link for validation
const confirmLink = `${padUrl(padId)}/subscribe=${subscribeId}`;
const vars = {padId, padUrl: padUrl(padId), confirmLink};
const subject = renderTemplate(
messageSettings.subscribeSubject != null
? messageSettings.subscribeSubject
: 'Email subscription confirmation for pad {padId}',
vars);
const text = renderTemplate(
messageSettings.subscribeBody != null
? messageSettings.subscribeBody
: 'Please click on this link in order to validate your subscription to the pad {padId}\n{confirmLink}',
vars);
let message;
try {
message = await util.promisify(server.send.bind(server))({
text: 'Please click on this link in order to validate your subscription to the pad ' +
`${padId}\n${padUrl(padId)}/subscribe=${subscribeId}`,
text,
from: `${fromName} <${fromEmail}>`,
to: userInfo.email,
subject: `Email subscription confirmation for pad ${padId}`,
subject,
});
} catch (err) {
console.error(err);
Expand Down Expand Up @@ -231,14 +244,25 @@ const unsubscriptionEmail = async (context, emailFound, userInfo, padId) => {
});

// Send mail to user with the link for validation
const confirmLink = `${padUrl(padId)}/unsubscribe=${unsubscribeId}`;
const vars = {padId, padUrl: padUrl(padId), confirmLink};
const subject = renderTemplate(
messageSettings.unsubscribeSubject != null
? messageSettings.unsubscribeSubject
: 'Email unsubscription confirmation for pad {padId}',
vars);
const text = renderTemplate(
messageSettings.unsubscribeBody != null
? messageSettings.unsubscribeBody
: 'Please click on this link in order to validate your unsubscription to the pad {padId}\n{confirmLink}',
vars);
let message;
try {
message = await util.promisify(server.send.bind(server))({
text: 'Please click on this link in order to validate your unsubscription to the pad ' +
`${padId}\n${padUrl(padId)}/unsubscribe=${unsubscribeId}`,
text,
from: `${fromName} <${fromEmail}>`,
to: userInfo.email,
subject: `Email unsubscription confirmation for pad ${padId}`,
subject,
});
} catch (err) {
console.error(err);
Expand Down
14 changes: 14 additions & 0 deletions messageUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict';

/**
* Expand template placeholders of the form {key} using the provided vars map.
* Unknown placeholders are left unchanged.
*
* @param {string} template - The template string containing {key} placeholders.
* @param {Object} vars - Map of placeholder names to replacement values.
* @returns {string} The rendered string.
*/
const renderTemplate = (template, vars) =>
template.replace(/\{(\w+)\}/g, (_, key) => (key in vars ? vars[key] : `{${key}}`));

module.exports = {renderTemplate};
36 changes: 31 additions & 5 deletions update.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ const urlToPads = (pluginSettings && pluginSettings.urlToPads)
? pluginSettings.urlToPads : 'http://beta.etherpad.org/p/';
const emailServer = (pluginSettings && pluginSettings.emailServer)
? pluginSettings.emailServer : {host: '127.0.0.1'};
const messageSettings = (pluginSettings && pluginSettings.messages) || {};
const {renderTemplate} = require('./messageUtils');

// A timer object we maintain to control how we send emails
const timers = {};
Expand All @@ -33,7 +35,9 @@ const timers = {};

const server = new SMTPClient(emailServer);

const emailFooter = "\nYou can unsubscribe from these emails in the pad's Settings window.\n";
const emailFooter = messageSettings.footer != null
? messageSettings.footer
: "\nYou can unsubscribe from these emails in the pad's Settings window.\n";

exports.padUpdate = (hookName, _pad) => {
if (!pluginSettings) return false;
Expand Down Expand Up @@ -70,13 +74,24 @@ const notifyBegin = async (padId) => {
return;
}
console.debug(`Emailing ${recipient} about a new begin update`);
const vars = {padId, padUrl: padUrl(padId), footer: emailFooter};
const subject = renderTemplate(
messageSettings.beginSubject != null
? messageSettings.beginSubject
: 'Someone started editing {padId}',
vars);
const text = renderTemplate(
messageSettings.beginBody != null
? messageSettings.beginBody
: 'This pad is now being edited:\n <{padUrl}>\n{footer}',
vars);
let message;
try {
message = await util.promisify(server.send.bind(server))({
text: `This pad is now being edited:\n <${padUrl(padId)}>\n${emailFooter}`,
text,
from: `${fromName} <${fromEmail}>`,
to: recipient,
subject: `Someone started editing ${padId}`,
subject,
});
} catch (err) {
console.error(err);
Expand Down Expand Up @@ -104,13 +119,24 @@ const notifyEnd = async (padId) => {
return;
}
console.debug(`Emailing ${recipient} about a pad finished being updated`);
const vars = {padId, padUrl: padUrl(padId), footer: emailFooter};
const subject = renderTemplate(
messageSettings.endSubject != null
? messageSettings.endSubject
: 'Someone finished editing {padId}',
vars);
const text = renderTemplate(
messageSettings.endBody != null
? messageSettings.endBody
: 'This pad is done being edited:\n <{padUrl}>\n{footer}',
vars);
let message;
try {
message = await util.promisify(server.send.bind(server))({
text: `This pad is done being edited:\n <${padUrl(padId)}>\n${emailFooter}`,
text,
from: `${fromName} <${fromEmail}>`,
to: recipient,
subject: `Someone finished editing ${padId}`,
subject,
});
} catch (err) {
console.error(err);
Expand Down
Loading