120 lines
3.3 KiB
TypeScript
120 lines
3.3 KiB
TypeScript
import EmailRepository from "@Repositories/EmailRepository";
|
|
import BaseService from "@Services/BaseService";
|
|
import { Emails, Prisma } from "@prisma/client";
|
|
import { Service } from "typedi";
|
|
import MailchimpClient from "@mailchimp/mailchimp_transactional";
|
|
import { BackendVariables } from "@Common/config/variables/Variables";
|
|
|
|
@Service()
|
|
export default class MailchimpService extends BaseService {
|
|
private static readonly from = "no-reply@smart-chain.fr";
|
|
|
|
constructor(
|
|
private emailRepository: EmailRepository,
|
|
protected variables: BackendVariables,
|
|
) {
|
|
super();
|
|
}
|
|
|
|
/**
|
|
* @description : Get all emails
|
|
* @throws {Error} If emails cannot be get
|
|
*/
|
|
public async get(query: Prisma.EmailsFindManyArgs): Promise<Emails[]> {
|
|
return this.emailRepository.findMany(query);
|
|
}
|
|
|
|
/**
|
|
* @description : Create a new email
|
|
* @throws {Error} If email cannot be created
|
|
*/
|
|
public async create(emailEntity: Emails): Promise<Emails> {
|
|
emailEntity.from = MailchimpService.from;
|
|
return this.emailRepository.create(emailEntity);
|
|
}
|
|
|
|
/**
|
|
* @description : Modify an email
|
|
* @throws {Error} If email cannot be modified
|
|
*/
|
|
public async update(uid: string, emailEntity: Emails): Promise<Emails> {
|
|
return this.emailRepository.update(uid, emailEntity);
|
|
}
|
|
|
|
/**
|
|
* @description : Get a email by uid
|
|
* @throws {Error} If email cannot be get
|
|
*/
|
|
public async getByUid(uid: string, query?: any): Promise<Emails | null> {
|
|
return this.emailRepository.findOneByUid(uid);
|
|
}
|
|
|
|
/**
|
|
* @description : Function called by cron to send emails
|
|
* @throws {Error} If email cannot be sent
|
|
*/
|
|
public async sendEmails() {
|
|
const emailsToSend = await this.get({ where: { sentAt: null } });
|
|
const currentDate = new Date();
|
|
let nextTrySendDate = null;
|
|
|
|
for (const email of emailsToSend) {
|
|
//If tries exceed 10, we stop trying to send the email
|
|
if (email.nbTrySend && email.nbTrySend > 9) continue;
|
|
|
|
//If email has never been sent, we send it
|
|
if (email.nbTrySend == 0) {
|
|
nextTrySendDate = currentDate;
|
|
}
|
|
//If email has already been sent, we send it again every nbTrySend^2 minutes
|
|
else {
|
|
nextTrySendDate = new Date(email.lastTrySendDate!);
|
|
nextTrySendDate.setMinutes(nextTrySendDate.getMinutes() + Math.pow(email.nbTrySend!, 2));
|
|
}
|
|
|
|
//If the next try send date is passed, we send the email
|
|
if (currentDate >= nextTrySendDate) {
|
|
try {
|
|
await this.sendEmail(email);
|
|
email.sentAt = currentDate;
|
|
} catch (error) {
|
|
email.lastTrySendDate = currentDate;
|
|
email.nbTrySend = email.nbTrySend! + 1;
|
|
}
|
|
await this.update(email.uid, email);
|
|
}
|
|
}
|
|
}
|
|
|
|
private async sendEmail(email: Emails) {
|
|
const apiKey = this.variables.MAILCHIMP_API_KEY;
|
|
const mailchimpApiClient = MailchimpClient(apiKey!);
|
|
|
|
await mailchimpApiClient.messages.sendTemplate({
|
|
template_name: email.templateName,
|
|
template_content: [],
|
|
message: {
|
|
global_merge_vars: this.buildVariables(email.templateVariables),
|
|
from_email: email.from!,
|
|
from_name: "LeCoffre.io",
|
|
subject: email.subject,
|
|
to: [
|
|
{
|
|
email: email.to,
|
|
type: "to",
|
|
},
|
|
],
|
|
},
|
|
});
|
|
}
|
|
|
|
private buildVariables(templateVariables: any) {
|
|
return Object.keys(templateVariables).map((key) => {
|
|
return {
|
|
name: key,
|
|
content: templateVariables[key],
|
|
};
|
|
});
|
|
}
|
|
}
|