Skip to content

Commit

Permalink
refactor(email): sender definitions in templates & requests (#914)
Browse files Browse the repository at this point in the history
  • Loading branch information
kkopanidis authored Jan 23, 2024
1 parent dda35ba commit f12bf62
Show file tree
Hide file tree
Showing 14 changed files with 63 additions and 31 deletions.
4 changes: 2 additions & 2 deletions libraries/grpc-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,14 +439,14 @@ export default class ConduitGrpcSdk {
? `${this.urlRemap['*']}:${moduleUrl.split(':')[1]}`
: moduleUrl);
if (this._availableModules[moduleName]) {
// ConduitGrpcSdk.Logger.log(`Creating gRPC client for ${moduleName}`);
ConduitGrpcSdk.Logger.info(`Creating gRPC client for ${moduleName}`);
this._modules[moduleName] = new this._availableModules[moduleName](
this.name,
moduleUrl,
this._grpcToken,
);
} else if (this._dynamicModules[moduleName]) {
// ConduitGrpcSdk.Logger.log(`Creating gRPC client for ${moduleName}`);
ConduitGrpcSdk.Logger.info(`Creating gRPC client for ${moduleName}`);
this._modules[moduleName] = new ConduitModule(
this.name,
moduleName,
Expand Down
10 changes: 8 additions & 2 deletions libraries/grpc-sdk/src/modules/email/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { ConduitModule } from '../../classes/ConduitModule';
import { EmailDefinition } from '../../protoUtils/email';

export class Email extends ConduitModule<typeof EmailDefinition> {
constructor(private readonly moduleName: string, url: string, grpcToken?: string) {
constructor(
private readonly moduleName: string,
url: string,
grpcToken?: string,
) {
super(moduleName, 'email', url, grpcToken);
this.initializeClient(EmailDefinition);
}
Expand All @@ -12,12 +16,14 @@ export class Email extends ConduitModule<typeof EmailDefinition> {
subject: string;
body: string;
variables: string[];
sender?: string;
}) {
return this.client!.registerTemplate({
name: template.name,
subject: template.subject,
body: template.body,
variables: template.variables,
sender: template.sender,
}).then(res => {
return JSON.parse(res.template);
});
Expand All @@ -28,7 +34,7 @@ export class Email extends ConduitModule<typeof EmailDefinition> {
params: {
email: string;
variables: any;
sender: string;
sender?: string;
replyTo?: string;
cc?: string[];
attachments?: string[];
Expand Down
1 change: 0 additions & 1 deletion modules/authentication/src/Authentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,6 @@ export default class Authentication extends ManagedModule<Config> {
const link = `${result.hostUrl}/hook/authentication/verify-email/${result.verificationToken.token}`;
await this.grpcSdk.emailProvider!.sendEmail('EmailVerification', {
email: user.email,
sender: 'no-reply',
variables: {
link,
},
Expand Down
4 changes: 0 additions & 4 deletions modules/authentication/src/handlers/local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,6 @@ export class LocalHandlers implements IAuthenticationStrategy {
await this.emailModule
.sendEmail('EmailVerification', {
email: user.email,
sender: 'no-reply',
variables: {
link,
},
Expand Down Expand Up @@ -333,7 +332,6 @@ export class LocalHandlers implements IAuthenticationStrategy {
if (config.local.verification.send_email && this.grpcSdk.isAvailable('email')) {
await this.emailModule.sendEmail('ForgotPassword', {
email: user.email,
sender: 'no-reply',
variables: {
link,
},
Expand Down Expand Up @@ -451,7 +449,6 @@ export class LocalHandlers implements IAuthenticationStrategy {
await this.emailModule
.sendEmail('ChangeEmailVerification', {
email: newEmail,
sender: 'no-reply',
variables: {
link,
},
Expand Down Expand Up @@ -583,7 +580,6 @@ export class LocalHandlers implements IAuthenticationStrategy {
const link = `${result.hostUrl}/hook/authentication/verify-email/${result.token}`;
await this.emailModule.sendEmail('EmailVerification', {
email,
sender: 'no-reply',
variables: {
link,
},
Expand Down
1 change: 0 additions & 1 deletion modules/authentication/src/handlers/magicLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ export class MagicLinkHandlers implements IAuthenticationStrategy {
const link = `${baseUrl}/${token.token}`;
await this.emailModule.sendEmail('MagicLink', {
email: user.email,
sender: 'no-reply',
variables: {
user,
link,
Expand Down
1 change: 0 additions & 1 deletion modules/authentication/src/handlers/team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,6 @@ export class TeamsHandler implements IAuthenticationStrategy {
await this.grpcSdk
.emailProvider!.sendEmail('TeamInvite', {
email: email,
sender: 'no-reply',
variables: {
link,
teamName: team.name,
Expand Down
1 change: 0 additions & 1 deletion modules/chat/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ export async function sendInvitations(
await grpcSdk
.emailProvider!.sendEmail('ChatRoomInvitation', {
email: invitedUser.email,
sender: 'no-reply',
variables: {
acceptLink,
declineLink,
Expand Down
16 changes: 10 additions & 6 deletions modules/email/src/Email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
} from './protoTypes/email';
import metricsSchema from './metrics';
import { ConfigController, ManagedModule } from '@conduitplatform/module-tools';
import { ISendEmailParams } from './interfaces';

export default class Email extends ManagedModule<Config> {
configSchema = AppConfigSchema;
Expand Down Expand Up @@ -95,6 +96,7 @@ export default class Email extends ManagedModule<Config> {
subject: call.request.subject,
body: call.request.body,
variables: call.request.variables,
sender: call.request.sender,
};
let errorMessage: string | null = null;
const template = await this.emailService
Expand All @@ -110,19 +112,21 @@ export default class Email extends ManagedModule<Config> {
callback: GrpcCallback<SendEmailResponse>,
) {
const template = call.request.templateName;
const params = {
const emailConfig: Config = await this.grpcSdk.config
.get('email')
.catch(() => ConduitGrpcSdk.Logger.error('Failed to get sending domain'));
const params: ISendEmailParams = {
email: call.request.params!.email,
variables: JSON.parse(call.request.params!.variables),
sender: call.request.params!.sender,
sender: call.request.params!.sender ?? '',
cc: call.request.params!.cc,
replyTo: call.request.params!.replyTo,
attachments: call.request.params!.attachments,
sendingDomain: emailConfig?.sendingDomain ?? '',
};
const emailConfig: Config = await this.grpcSdk.config
.get('email')
.catch(() => ConduitGrpcSdk.Logger.error('Failed to get sending domain'));
params.sender = params.sender + `@${emailConfig?.sendingDomain ?? 'conduit.com'}`;

let errorMessage: string | null = null;

const sentMessageInfo = await this.emailService
.sendEmail(template, params)
.catch((e: Error) => (errorMessage = e.message));
Expand Down
2 changes: 1 addition & 1 deletion modules/email/src/admin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export class AdminHandlers {
throw new GrpcError(status.NOT_FOUND, 'Template does not exist');
}

['name', 'subject', 'body'].forEach(key => {
['name', 'subject', 'body', 'sender'].forEach(key => {
if (call.request.params[key]) {
// @ts-ignore
templateDocument[key] = call.request.params[key];
Expand Down
3 changes: 2 additions & 1 deletion modules/email/src/email.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ message RegisterTemplateRequest {
string subject = 2;
string body = 3;
repeated string variables = 4;
optional string sender = 5;
}

message RegisterTemplateResponse {
Expand All @@ -18,7 +19,7 @@ message SendEmailRequest {
message SendEmailParams {
string email = 1;
string variables = 2;
string sender = 3;
optional string sender = 3;
repeated string cc = 4;
optional string replyTo = 5;
repeated string attachments = 6;
Expand Down
1 change: 1 addition & 0 deletions modules/email/src/interfaces/RegisterTemplateParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export interface IRegisterTemplateParams {
name: string;
subject: string;
body: string;
sender?: string;
variables: string[];
}
1 change: 1 addition & 0 deletions modules/email/src/interfaces/SendEmailParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ export interface ISendEmailParams {
sender: string;
cc?: string[];
replyTo?: string;
sendingDomain?: string;
attachments?: string[];
}
43 changes: 34 additions & 9 deletions modules/email/src/services/email.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isNil } from 'lodash';
import { isEmpty, isNil } from 'lodash';
import { EmailTemplate } from '../models';
import { IRegisterTemplateParams, ISendEmailParams } from '../interfaces';
import handlebars from 'handlebars';
Expand All @@ -7,6 +7,7 @@ import { CreateEmailTemplate } from '../email-provider/interfaces/CreateEmailTem
import { UpdateEmailTemplate } from '../email-provider/interfaces/UpdateEmailTemplate';
import { Attachment } from 'nodemailer/lib/mailer';
import { Template } from '../email-provider/interfaces/Template';
import ConduitGrpcSdk from '@conduitplatform/grpc-sdk';

export class EmailService {
constructor(private emailer: EmailProvider) {}
Expand Down Expand Up @@ -39,7 +40,7 @@ export class EmailService {
}

async registerTemplate(params: IRegisterTemplateParams) {
const { name, body, subject, variables } = params;
const { name, body, subject, variables, sender } = params;

const existing = await EmailTemplate.getInstance().findOne({ name });
if (!isNil(existing)) return existing;
Expand All @@ -48,6 +49,7 @@ export class EmailService {
name,
subject,
body,
sender,
variables,
});
}
Expand All @@ -63,7 +65,7 @@ export class EmailService {
let subjectString = subject!;
let bodyString = body!;
let templateFound: EmailTemplate | null;

let senderAddress: string | undefined;
if (template) {
templateFound = await EmailTemplate.getInstance().findOne({ name: template });
if (isNil(templateFound)) {
Expand All @@ -80,15 +82,38 @@ export class EmailService {
if (!isNil(templateFound.subject) && isNil(subject)) {
subjectString = handlebars.compile(templateFound.subject)(variables);
}
if (!isEmpty(templateFound.sender)) {
senderAddress = templateFound.sender;
}
}

if (!isNil(sender)) {
builder.setSender(sender);
} else if (!isNil(templateFound!.sender)) {
builder.setSender(templateFound!.sender);
} else {
throw new Error(`Sender must be provided!`);
if (isNil(senderAddress) || isEmpty(senderAddress)) {
if (!isEmpty(sender)) {
senderAddress = sender;
} else {
senderAddress = 'no-reply';
}
}
if (isNil(params.sendingDomain) || isEmpty(params.sendingDomain)) {
if (senderAddress.includes('@')) {
ConduitGrpcSdk.Logger.warn(
`Sending domain is not set, attempting to send email with provided address: ${senderAddress}`,
);
} else {
throw new Error(
`Sending domain is not set, and sender address is not valid: ${senderAddress}`,
);
}
} else if (!senderAddress.includes(params.sendingDomain)) {
if (senderAddress.includes('@')) {
ConduitGrpcSdk.Logger.warn(
`You are trying to send email from ${senderAddress} but it does not match sending domain ${params.sendingDomain}`,
);
} else {
senderAddress = `${senderAddress}@${params.sendingDomain}`;
}
}
builder.setSender(senderAddress!);

builder.setContent(bodyString);
builder.setReceiver(email);
Expand Down
6 changes: 4 additions & 2 deletions modules/forms/src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ export class FormsRoutes {
public readonly _routingManager: RoutingManager;
private forms: UntypedArray = [];

constructor(readonly server: GrpcServer, private readonly grpcSdk: ConduitGrpcSdk) {
constructor(
readonly server: GrpcServer,
private readonly grpcSdk: ConduitGrpcSdk,
) {
this._routingManager = new RoutingManager(this.grpcSdk.router!, server);
}

Expand Down Expand Up @@ -93,7 +96,6 @@ export class FormsRoutes {
await this.grpcSdk
.emailProvider!.sendEmail('FormSubmission', {
email: form.forwardTo,
sender: 'forms',
replyTo: form.emailField ? data[form.emailField] : null,
variables: {
data: text,
Expand Down

0 comments on commit f12bf62

Please sign in to comment.