Skip to content

Commit

Permalink
updated urls (#725)
Browse files Browse the repository at this point in the history
  • Loading branch information
deepakprabhakara authored Jan 20, 2023
1 parent 4396bc9 commit 975f037
Show file tree
Hide file tree
Showing 11 changed files with 247 additions and 228 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Retraced Documentation
url: https://www.retraced.io/documentation/overview/introduction-to-retraced/
url: https://boxyhq.com/docs/retraced/overview
about: Learn more about Retraced
222 changes: 118 additions & 104 deletions src/_processor/services/Emailer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,33 @@ import { logger } from "../logger";
import config from "../../config";

export interface Email {
to: string | string[];
subject: string;
template: string;
context: any;
to: string | string[];
subject: string;
template: string;
context: any;
}

interface MandrillResult {
_id: string;
email: string;
status: "sent" | "queued" | "rejected" | "invalid";
reject_reason?: "hard-bounce" | "soft-bounce" | "spam" | "unsub" | "custom" | "invalid-sender" | "invalid" | "test-mode-limit" | "unsigned" | "rule";
_id: string;
email: string;
status: "sent" | "queued" | "rejected" | "invalid";
reject_reason?:
| "hard-bounce"
| "soft-bounce"
| "spam"
| "unsub"
| "custom"
| "invalid-sender"
| "invalid"
| "test-mode-limit"
| "unsigned"
| "rule";
}

// Returns the no-send-list.
export type RecipientFilter = (recipients: string[]) => Promise<string[]>;

export class Emailer {

public static getDefault(): Emailer {
if (!Emailer.instance) {
let transport = Emailer.smtpFromEnv();
Expand All @@ -59,124 +68,129 @@ export class Emailer {
Emailer.instance = new Emailer(
transport,
Emailer.defaultTemplates(),
config.EMAIL_FROM || "Retraced <contact@retraced.io>",
handleRejects,
config.EMAIL_FROM || "Retraced <retraced@boxyhq.com>",
handleRejects
);
}

return Emailer.instance;
}

public static defaultTemplates(): Map<string, (context: any) => string> {
const templates = new Map();
public static defaultTemplates(): Map<string, (context: any) => string> {
const templates = new Map();

templates.set("retraced/invite-to-team", inviteTmpl);
templates.set("retraced/report-day", reportTmpl);
templates.set("retraced/deletion-request", deletionRequestTmpl);

templates.set("retraced/invite-to-team", inviteTmpl);
templates.set("retraced/report-day", reportTmpl);
templates.set("retraced/deletion-request", deletionRequestTmpl);
return templates;
}

return templates;
public static smtpFromEnv(): nodemailer.Transporter | null {
if (!config.SMTP_CONNECTION_URL) {
return null;
}

public static smtpFromEnv(): nodemailer.Transporter | null {
if (!config.SMTP_CONNECTION_URL) {
return null;
}
logger.info("Configured SMTP for sending emails");

logger.info("Configured SMTP for sending emails");
return nodemailer.createTransport(config.SMTP_CONNECTION_URL);
}

return nodemailer.createTransport(config.SMTP_CONNECTION_URL);
public static mandrillFromEnv(): nodemailer.Transporter | null {
if (!config.MANDRILL_KEY) {
return null;
}

public static mandrillFromEnv(): nodemailer.Transporter | null {
if (!config.MANDRILL_KEY) {
return null;
}

logger.info("Configured Mandrill for sending emails");
logger.info("Configured Mandrill for sending emails");

return nodemailer.createTransport(mandrillTransport({
auth: {
apiKey: config.MANDRILL_KEY,
},
}));
}
return nodemailer.createTransport(
mandrillTransport({
auth: {
apiKey: config.MANDRILL_KEY,
},
})
);
}

public static mandrillRejectHandler(pgPool: pg.Pool, registry: Registry) {
return (results: MandrillResult[]) => {
// the list of email addresses that cannot ever receive or do not want more emails
const rejections = results.filter((result: MandrillResult): boolean => {
if (result.status === "invalid") {
logger.error(`Mandrill send to ${result.email} invalid`);
return false;
}

registry.meter(`Emailer.mandrillRejectHandler.${result.reject_reason}`).mark();
logger.warn(`Mandrill send to ${result.email} rejected: ${result.reject_reason}`);

switch (result.reject_reason) {
case "hard-bounce":
case "spam":
case "unsub":
return true;
default:
return false;
}
})
.map(({ email }) => email);

pgPool.query(`
public static mandrillRejectHandler(pgPool: pg.Pool, registry: Registry) {
return (results: MandrillResult[]) => {
// the list of email addresses that cannot ever receive or do not want more emails
const rejections = results
.filter((result: MandrillResult): boolean => {
if (result.status === "invalid") {
logger.error(`Mandrill send to ${result.email} invalid`);
return false;
}

registry.meter(`Emailer.mandrillRejectHandler.${result.reject_reason}`).mark();
logger.warn(`Mandrill send to ${result.email} rejected: ${result.reject_reason}`);

switch (result.reject_reason) {
case "hard-bounce":
case "spam":
case "unsub":
return true;
default:
return false;
}
})
.map(({ email }) => email);

pgPool
.query(
`
update retraceduser
set tx_emails_recipient = false
where email = any($1)`,
[rejections],
)
.catch((err) => {
logger.error(`Failed to turn off tx email receiving for ${rejections}: ${err.message}`);
});
};
}
[rejections]
)
.catch((err) => {
logger.error(`Failed to turn off tx email receiving for ${rejections}: ${err.message}`);
});
};
}

private static instance: Emailer;
private static instance: Emailer;

constructor(
private readonly transport: nodemailer.Transporter,
private readonly templates: Map<string, (context: any) => string>,
private readonly from: string,
private readonly onRejected?: (rejected: any[]) => void,
) { }
constructor(
private readonly transport: nodemailer.Transporter,
private readonly templates: Map<string, (context: any) => string>,
private readonly from: string,
private readonly onRejected?: (rejected: any[]) => void
) {}

@instrumented
public async send(email: Email) {
const tmpl = this.templates.get(email.template);
@instrumented
public async send(email: Email) {
const tmpl = this.templates.get(email.template);

if (!tmpl) {
throw new Error(`Emailer does not have template ${email.template}`);
if (!tmpl) {
throw new Error(`Emailer does not have template ${email.template}`);
}

const recipients = Array.isArray(email.to) ? email.to : [email.to];

return new Promise((resolve, reject) => {
const rendered = {
from: this.from,
to: recipients.join(", "),
subject: email.subject,
html: tmpl(email.context),
};

this.transport.sendMail(rendered, (err, info) => {
if (err) {
logger.error(`Failure sending "${email.template}" email to ${email.to}`);
reject(err);
return;
}
logger.info(`Delivered "${email.template}" email to ${email.to}`);

const recipients = Array.isArray(email.to) ? email.to : [email.to];

return new Promise((resolve, reject) => {
const rendered = {
from: this.from,
to: recipients.join(", "),
subject: email.subject,
html: tmpl(email.context),
};

this.transport.sendMail(rendered, (err, info) => {
if (err) {
logger.error(`Failure sending "${email.template}" email to ${email.to}`);
reject(err);
return;
}
logger.info(`Delivered "${email.template}" email to ${email.to}`);

if (!_.isEmpty(info.rejected) && typeof this.onRejected === "function") {
this.onRejected(info.rejected);
}

resolve(info);
});
});
}
if (!_.isEmpty(info.rejected) && typeof this.onRejected === "function") {
this.onRejected(info.rejected);
}

resolve(info);
});
});
}
}
2 changes: 1 addition & 1 deletion src/_processor/services/templates/deletionRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ a {
<div class="footer">
<table width="100%">
<tr>
<td class="aligncenter content-block">Visit <a href="http://www.retraced.io">retraced.io</a>.</td>
<td class="aligncenter content-block">Visit <a href="https://boxyhq.com/audit-logs">https://boxyhq.com/audit-logs</a>.</td>
</tr>
</table>
</div></div>
Expand Down
2 changes: 1 addition & 1 deletion src/_processor/services/templates/inviteToTeam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ a {
<div class="footer">
<table width="100%">
<tr>
<td class="aligncenter content-block">Visit <a href="http://www.retraced.io">retraced.io</a>.</td>
<td class="aligncenter content-block">Visit <a href="https://boxyhq.com/audit-logs">https://boxyhq.com/audit-logs</a>.</td>
</tr>
</table>
</div></div>
Expand Down
6 changes: 3 additions & 3 deletions src/_processor/services/templates/reportDay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export default Handlebars.compile(`<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
<tbody>
<tr>
<td style="padding-bottom:40px !important;">
<a href="https://preview.retraced.io/" target="_blank">
<img alt="Retraced" src="https://preview.retraced.io/images/logo.png" style="width:140px !important;height:26px !important;display:block"/>
<a href="https://boxyhq.com/audit-logs" target="_blank">
<img alt="Retraced" src="https://boxyhq.com/img/products/audit-logs/logo.svg" style="width:40px !important;height:40px !important;display:block"/>
</a>
</td>
</tr>
Expand Down Expand Up @@ -363,7 +363,7 @@ export default Handlebars.compile(`<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
<tr>
<td style="text-align:left;">
<p style="text-align:left;font-size:12px !important;font-weight:400 !important;line-height:12px !important;color:#9B9B9B;">Coded by
<img alt="Retraced" src="https://preview.retraced.io/images/logo.png" style="width:70px !important;height:13px !important;display:inline-block;margin-left:3px;vertical-align:top;"/>
<img alt="Retraced" src="https://boxyhq.com/img/products/audit-logs/logo.svg" style="width:13px !important;height:13px !important;display:inline-block;margin-left:3px;vertical-align:top;"/>
</p>
</td>
<td style="text-align:right;">
Expand Down
21 changes: 17 additions & 4 deletions src/controllers/AdminController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
import { Get, Post, Delete, Route, Body, Query, Header, Path, SuccessResponse, Controller, Put, Request } from "tsoa";
import {
Get,
Post,
Delete,
Route,
Body,
Query,
Header,
Path,
SuccessResponse,
Controller,
Put,
Request,
} from "tsoa";
import express from "express";
import * as uuid from "uuid";

Expand Down Expand Up @@ -120,7 +133,7 @@ export class AdminAPI extends Controller {
/**
* Create a template. An overview of Template usage in Retraced can be found at
*
* https://preview.retraced.io/documentation/advanced-retraced/display-templates/
* https://boxyhq.com/docs/retraced/advanced/display-templates
*
* @param auth Base64 encoded JWT
* @param projectId The project id
Expand Down Expand Up @@ -157,7 +170,7 @@ export class AdminAPI extends Controller {
/**
* Search templates. An overview of Template usage in Retraced can be found at
*
* https://preview.retraced.io/documentation/advanced-retraced/display-templates/
* https://boxyhq.com/docs/retraced/advanced/display-templates
*
* @param auth Base64 encoded JWT
* @param projectId The project id
Expand Down Expand Up @@ -186,7 +199,7 @@ export class AdminAPI extends Controller {
/**
* Delete a template. An overview of Template usage in Retraced can be found at
*
* https://preview.retraced.io/documentation/advanced-retraced/display-templates/
* https://boxyhq.com/docs/retraced/advanced/display-templates
*
*
* @param auth Base64 encoded JWT authentication
Expand Down
Loading

0 comments on commit 975f037

Please sign in to comment.