diff --git a/src/common/email-templates/job-template-simplified.html b/src/common/email-templates/job-template-simplified.html
new file mode 100644
index 000000000..b80251ab5
--- /dev/null
+++ b/src/common/email-templates/job-template-simplified.html
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+ Your {{type}} job has been submitted and will be processed as soon as possible.
+ You will be notified by email as soon as the job is completed.
+
+
+ Job id: {{id}}
+
+ {{#if jobParams.datasetIds}}
+
Job will be perfomed on the following dataset(s):
+
+ {{#each jobParams.datasetIds}}
+
+
+ {{this}}
+ |
+
+ {{/each}}
+
+ {{/if}}
+
+
+
+
+
diff --git a/src/jobs/actions/emailaction.ts b/src/jobs/actions/emailaction.ts
index f7c242ff9..6ac6fa8f7 100644
--- a/src/jobs/actions/emailaction.ts
+++ b/src/jobs/actions/emailaction.ts
@@ -3,11 +3,27 @@
* This is intended as an example of the JobAction interface
*
*/
+import { readFileSync } from "fs";
+import { compile, TemplateDelegate } from "handlebars";
+import { createTransport, Transporter } from "nodemailer";
import { Logger, NotFoundException } from "@nestjs/common";
import { JobAction } from "../config/jobconfig";
import { JobClass } from "../schemas/job.schema";
-import { createTransport, Transporter } from "nodemailer";
-import { compile, TemplateDelegate } from "handlebars";
+import configuration from "src/config/configuration";
+
+// Handlebar options for JobClass templates
+const jobTemplateOptions = {
+ allowedProtoProperties: {
+ id: true,
+ type: true,
+ statusCode: true,
+ statusMessage: true,
+ createdBy: true,
+ jobParams: true,
+ contactEmail: true,
+ },
+ allowProtoPropertiesByDefault: false, // limit accessible fields for security
+};
type MailOptions = {
to: string;
@@ -16,17 +32,23 @@ type MailOptions = {
text?: string;
};
+type Auth = {
+ user: string;
+ password: string;
+};
+
/**
* Send an email following a job
*/
export class EmailJobAction implements JobAction {
+ public static readonly actionType = "email";
+
private mailService: Transporter;
private toTemplate: TemplateDelegate;
private from: string;
+ private auth: Auth | object = {};
private subjectTemplate: TemplateDelegate;
- private bodyTemplate?: TemplateDelegate;
-
- public static readonly actionType = "email";
+ private bodyTemplate: TemplateDelegate;
getActionType(): string {
return EmailJobAction.actionType;
@@ -38,8 +60,20 @@ export class EmailJobAction implements JobAction {
"EmailJobAction",
);
- if (!data["mailer"]) {
- throw new NotFoundException("Param 'mailer' is undefined");
+ if (data["auth"]) {
+ // check optional auth field
+ function CheckAuthDefinition(obj: object): obj is Auth {
+ return (
+ Object.keys(obj).length == 2 && "user" in obj && "password" in obj
+ );
+ }
+
+ if (!CheckAuthDefinition(data["auth"])) {
+ throw new NotFoundException(
+ "Param 'auth' should contain fields 'user' and 'password' only.",
+ );
+ }
+ this.auth = data["auth"] as Auth;
}
if (!data["to"]) {
throw new NotFoundException("Param 'to' is undefined");
@@ -47,22 +81,31 @@ export class EmailJobAction implements JobAction {
if (!data["from"]) {
throw new NotFoundException("Param 'from' is undefined");
}
- if (typeof data["from"] !== "string") {
- throw new TypeError("from should be a string");
- }
if (!data["subject"]) {
throw new NotFoundException("Param 'subject' is undefined");
}
- if (!data["body"]) {
- throw new NotFoundException("Param 'body' is undefined");
+ if (!data["bodyTemplateFile"]) {
+ throw new NotFoundException("Param 'bodyTemplateFile' is undefined");
}
Logger.log("EmailJobAction parameters are valid.", "EmailJobAction");
- this.mailService = createTransport(data["mailer"]);
+ // const mailerConfig = configuration().smtp;
+ // this.mailService = createTransport({
+ // host: mailerConfig.host,
+ // port: mailerConfig.port,
+ // secure: mailerConfig.secure,
+ // auth: this.auth
+ // } as any);
+
+ this.from = data["from"] as string;
this.toTemplate = compile(data["to"]);
- this.from = data["from"];
this.subjectTemplate = compile(data["subject"]);
- this.bodyTemplate = compile(data["body"]);
+
+ const templateFile = readFileSync(
+ data["bodyTemplateFile"] as string,
+ "utf8",
+ );
+ this.bodyTemplate = compile(templateFile);
}
async performJob(job: JobClass) {
@@ -73,13 +116,14 @@ export class EmailJobAction implements JobAction {
// Fill templates
const mail: MailOptions = {
- to: this.toTemplate(job),
+ to: this.toTemplate(job, jobTemplateOptions),
from: this.from,
- subject: this.subjectTemplate(job),
+ subject: this.subjectTemplate(job, jobTemplateOptions),
};
- if (this.bodyTemplate) {
- mail.text = this.bodyTemplate(job);
- }
- await this.mailService.sendMail(mail);
+ mail.text = this.bodyTemplate(job, jobTemplateOptions);
+ Logger.log(mail);
+
+ // Send the email
+ // await this.mailService.sendMail(mail);
}
}
diff --git a/src/jobs/config/jobConfig.example.json b/src/jobs/config/jobConfig.example.json
index 21eb29903..fae19537e 100644
--- a/src/jobs/config/jobConfig.example.json
+++ b/src/jobs/config/jobConfig.example.json
@@ -25,6 +25,17 @@
"exchange": "jobs.write",
"queue": "client.jobs.write",
"key": "jobqueue"
+ },
+ {
+ "actionType": "email",
+ "auth": {
+ "user": "user",
+ "password": "password"
+ },
+ "to": "{{contactEmail}}",
+ "from": "from",
+ "subject": "[SciCat] Your {{type}} job was submitted successfully",
+ "bodyTemplateFile": "src/common/email-templates/job-template-simplified.html"
}
]
},
diff --git a/src/jobs/jobs.controller.ts b/src/jobs/jobs.controller.ts
index fb97fbca3..471d8ec94 100644
--- a/src/jobs/jobs.controller.ts
+++ b/src/jobs/jobs.controller.ts
@@ -401,6 +401,10 @@ export class JobsController {
let datasetIds: string[] = [];
if (JobsConfigSchema.DatasetIds in jobCreateDto.jobParams) {
datasetIds = await this.checkDatasetIds(jobCreateDto.jobParams);
+ jobInstance.jobParams = {
+ ...jobInstance.jobParams,
+ [JobsConfigSchema.DatasetIds]: datasetIds,
+ };
}
if (user) {
// the request comes from a user who is logged in.