mirror of
https://github.com/documenso/documenso.git
synced 2025-11-15 01:01:49 +10:00
feat: add queue for sending emails
This commit is contained in:
@ -1,3 +1,4 @@
|
|||||||
|
import type { SendMailOptions } from 'nodemailer';
|
||||||
import { createTransport } from 'nodemailer';
|
import { createTransport } from 'nodemailer';
|
||||||
|
|
||||||
import { ResendTransport } from '@documenso/nodemailer-resend';
|
import { ResendTransport } from '@documenso/nodemailer-resend';
|
||||||
@ -54,3 +55,4 @@ const getTransport = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const mailer = getTransport();
|
export const mailer = getTransport();
|
||||||
|
export type MailOptions = SendMailOptions;
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import { createElement } from 'react';
|
import { createElement } from 'react';
|
||||||
|
|
||||||
import { mailer } from '@documenso/email/mailer';
|
|
||||||
import { render } from '@documenso/email/render';
|
import { render } from '@documenso/email/render';
|
||||||
import DocumentCancelTemplate from '@documenso/email/templates/document-cancel';
|
import DocumentCancelTemplate from '@documenso/email/templates/document-cancel';
|
||||||
import { prisma } from '@documenso/prisma';
|
import { prisma } from '@documenso/prisma';
|
||||||
@ -92,18 +91,21 @@ export const deleteDocument = async ({
|
|||||||
assetBaseUrl,
|
assetBaseUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
await mailer.sendMail({
|
await queueJob({
|
||||||
to: {
|
job: 'send-mail',
|
||||||
address: recipient.email,
|
args: {
|
||||||
name: recipient.name,
|
to: {
|
||||||
|
address: recipient.email,
|
||||||
|
name: recipient.name,
|
||||||
|
},
|
||||||
|
from: {
|
||||||
|
name: FROM_NAME,
|
||||||
|
address: FROM_ADDRESS,
|
||||||
|
},
|
||||||
|
subject: 'Document Cancelled',
|
||||||
|
html: render(template),
|
||||||
|
text: render(template, { plainText: true }),
|
||||||
},
|
},
|
||||||
from: {
|
|
||||||
name: FROM_NAME,
|
|
||||||
address: FROM_ADDRESS,
|
|
||||||
},
|
|
||||||
subject: 'Document Cancelled',
|
|
||||||
html: render(template),
|
|
||||||
text: render(template, { plainText: true }),
|
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { createElement } from 'react';
|
import { createElement } from 'react';
|
||||||
|
|
||||||
import { mailer } from '@documenso/email/mailer';
|
|
||||||
import { render } from '@documenso/email/render';
|
import { render } from '@documenso/email/render';
|
||||||
import { DocumentInviteEmailTemplate } from '@documenso/email/templates/document-invite';
|
import { DocumentInviteEmailTemplate } from '@documenso/email/templates/document-invite';
|
||||||
import { FROM_ADDRESS, FROM_NAME } from '@documenso/lib/constants/email';
|
import { FROM_ADDRESS, FROM_NAME } from '@documenso/lib/constants/email';
|
||||||
@ -110,45 +109,42 @@ export const resendDocument = async ({
|
|||||||
|
|
||||||
const { actionVerb } = RECIPIENT_ROLES_DESCRIPTION[recipient.role];
|
const { actionVerb } = RECIPIENT_ROLES_DESCRIPTION[recipient.role];
|
||||||
|
|
||||||
await prisma.$transaction(
|
await queueJob({
|
||||||
async (tx) => {
|
job: 'send-mail',
|
||||||
await mailer.sendMail({
|
args: {
|
||||||
to: {
|
to: {
|
||||||
address: email,
|
address: email,
|
||||||
name,
|
name,
|
||||||
},
|
},
|
||||||
from: {
|
from: {
|
||||||
name: FROM_NAME,
|
name: FROM_NAME,
|
||||||
address: FROM_ADDRESS,
|
address: FROM_ADDRESS,
|
||||||
},
|
},
|
||||||
subject: customEmail?.subject
|
subject: customEmail?.subject
|
||||||
? renderCustomEmailTemplate(customEmail.subject, customEmailTemplate)
|
? renderCustomEmailTemplate(customEmail.subject, customEmailTemplate)
|
||||||
: `Please ${actionVerb.toLowerCase()} this document`,
|
: `Please ${actionVerb.toLowerCase()} this document`,
|
||||||
html: render(template),
|
html: render(template),
|
||||||
text: render(template, { plainText: true }),
|
text: render(template, { plainText: true }),
|
||||||
});
|
|
||||||
|
|
||||||
await queueJob({
|
|
||||||
job: 'create-document-audit-log',
|
|
||||||
args: {
|
|
||||||
type: DOCUMENT_AUDIT_LOG_TYPE.EMAIL_SENT,
|
|
||||||
documentId: document.id,
|
|
||||||
user,
|
|
||||||
requestMetadata,
|
|
||||||
data: {
|
|
||||||
emailType: recipientEmailType,
|
|
||||||
recipientEmail: recipient.email,
|
|
||||||
recipientName: recipient.name,
|
|
||||||
recipientRole: recipient.role,
|
|
||||||
recipientId: recipient.id,
|
|
||||||
isResending: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
// Hopefully the queue makes this redundant
|
});
|
||||||
{ timeout: 30_000 },
|
|
||||||
);
|
await queueJob({
|
||||||
|
job: 'create-document-audit-log',
|
||||||
|
args: {
|
||||||
|
type: DOCUMENT_AUDIT_LOG_TYPE.EMAIL_SENT,
|
||||||
|
documentId: document.id,
|
||||||
|
user,
|
||||||
|
requestMetadata,
|
||||||
|
data: {
|
||||||
|
emailType: recipientEmailType,
|
||||||
|
recipientEmail: recipient.email,
|
||||||
|
recipientName: recipient.name,
|
||||||
|
recipientRole: recipient.role,
|
||||||
|
recipientId: recipient.id,
|
||||||
|
isResending: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import { createElement } from 'react';
|
import { createElement } from 'react';
|
||||||
|
|
||||||
import { mailer } from '@documenso/email/mailer';
|
|
||||||
import { render } from '@documenso/email/render';
|
import { render } from '@documenso/email/render';
|
||||||
import DocumentCancelTemplate from '@documenso/email/templates/document-cancel';
|
import DocumentCancelTemplate from '@documenso/email/templates/document-cancel';
|
||||||
import { prisma } from '@documenso/prisma';
|
import { prisma } from '@documenso/prisma';
|
||||||
@ -49,18 +48,21 @@ export const superDeleteDocument = async ({ id, requestMetadata }: SuperDeleteDo
|
|||||||
assetBaseUrl,
|
assetBaseUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
await mailer.sendMail({
|
await queueJob({
|
||||||
to: {
|
job: 'send-mail',
|
||||||
address: recipient.email,
|
args: {
|
||||||
name: recipient.name,
|
to: {
|
||||||
|
address: recipient.email,
|
||||||
|
name: recipient.name,
|
||||||
|
},
|
||||||
|
from: {
|
||||||
|
name: FROM_NAME,
|
||||||
|
address: FROM_ADDRESS,
|
||||||
|
},
|
||||||
|
subject: 'Document Cancelled',
|
||||||
|
html: render(template),
|
||||||
|
text: render(template, { plainText: true }),
|
||||||
},
|
},
|
||||||
from: {
|
|
||||||
name: FROM_NAME,
|
|
||||||
address: FROM_ADDRESS,
|
|
||||||
},
|
|
||||||
subject: 'Document Cancelled',
|
|
||||||
html: render(template),
|
|
||||||
text: render(template, { plainText: true }),
|
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import type { WorkHandler } from 'pg-boss';
|
import type { WorkHandler } from 'pg-boss';
|
||||||
|
|
||||||
|
import type { MailOptions } from '@documenso/email/mailer';
|
||||||
|
import { mailer } from '@documenso/email/mailer';
|
||||||
import { prisma } from '@documenso/prisma';
|
import { prisma } from '@documenso/prisma';
|
||||||
|
|
||||||
import { initQueue } from '.';
|
import { initQueue } from '.';
|
||||||
@ -12,6 +14,7 @@ import {
|
|||||||
import { type SendPendingEmailOptions, sendPendingEmail } from '../document/send-pending-email';
|
import { type SendPendingEmailOptions, sendPendingEmail } from '../document/send-pending-email';
|
||||||
|
|
||||||
type JobOptions = {
|
type JobOptions = {
|
||||||
|
'send-mail': MailOptions;
|
||||||
'send-completed-email': SendCompletedDocumentOptions;
|
'send-completed-email': SendCompletedDocumentOptions;
|
||||||
'send-pending-email': SendPendingEmailOptions;
|
'send-pending-email': SendPendingEmailOptions;
|
||||||
'create-document-audit-log': CreateDocumentAuditLogDataOptions;
|
'create-document-audit-log': CreateDocumentAuditLogDataOptions;
|
||||||
@ -20,25 +23,42 @@ type JobOptions = {
|
|||||||
export const jobHandlers: {
|
export const jobHandlers: {
|
||||||
[K in keyof JobOptions]: WorkHandler<JobOptions[K]>;
|
[K in keyof JobOptions]: WorkHandler<JobOptions[K]>;
|
||||||
} = {
|
} = {
|
||||||
'send-completed-email': async ({ data: { documentId, requestMetadata } }) => {
|
'send-completed-email': async ({ id, name, data: { documentId, requestMetadata } }) => {
|
||||||
|
console.log('Running Queue: ', name, ' ', id);
|
||||||
|
|
||||||
await sendCompletedEmail({
|
await sendCompletedEmail({
|
||||||
documentId,
|
documentId,
|
||||||
requestMetadata,
|
requestMetadata,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
'send-pending-email': async ({ data: { documentId, recipientId } }) => {
|
'send-pending-email': async ({ id, name, data: { documentId, recipientId } }) => {
|
||||||
|
console.log('Running Queue: ', name, ' ', id);
|
||||||
|
|
||||||
await sendPendingEmail({
|
await sendPendingEmail({
|
||||||
documentId,
|
documentId,
|
||||||
recipientId,
|
recipientId,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
'send-mail': async ({ id, name, data: { attachments, to, from, subject, html, text } }) => {
|
||||||
|
console.log('Running Queue: ', name, ' ', id);
|
||||||
|
|
||||||
|
await mailer.sendMail({
|
||||||
|
to,
|
||||||
|
from,
|
||||||
|
subject,
|
||||||
|
html,
|
||||||
|
text,
|
||||||
|
attachments,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
// Audit Logs Queue
|
// Audit Logs Queue
|
||||||
'create-document-audit-log': async ({
|
'create-document-audit-log': async ({
|
||||||
|
name,
|
||||||
data: { documentId, type, requestMetadata, user, data },
|
data: { documentId, type, requestMetadata, user, data },
|
||||||
id,
|
id,
|
||||||
}) => {
|
}) => {
|
||||||
console.log('Running Queue ID', id);
|
console.log('Running Queue: ', name, ' ', id);
|
||||||
|
|
||||||
await prisma.documentAuditLog.create({
|
await prisma.documentAuditLog.create({
|
||||||
data: createDocumentAuditLogData({
|
data: createDocumentAuditLogData({
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { createElement } from 'react';
|
|||||||
|
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { mailer } from '@documenso/email/mailer';
|
|
||||||
import { render } from '@documenso/email/render';
|
import { render } from '@documenso/email/render';
|
||||||
import { ConfirmTeamEmailTemplate } from '@documenso/email/templates/confirm-team-email';
|
import { ConfirmTeamEmailTemplate } from '@documenso/email/templates/confirm-team-email';
|
||||||
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
|
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
|
||||||
@ -13,6 +12,8 @@ import { createTokenVerification } from '@documenso/lib/utils/token-verification
|
|||||||
import { prisma } from '@documenso/prisma';
|
import { prisma } from '@documenso/prisma';
|
||||||
import { Prisma } from '@documenso/prisma/client';
|
import { Prisma } from '@documenso/prisma/client';
|
||||||
|
|
||||||
|
import { queueJob } from '../queue/job';
|
||||||
|
|
||||||
export type CreateTeamEmailVerificationOptions = {
|
export type CreateTeamEmailVerificationOptions = {
|
||||||
userId: number;
|
userId: number;
|
||||||
teamId: number;
|
teamId: number;
|
||||||
@ -122,14 +123,17 @@ export const sendTeamEmailVerificationEmail = async (
|
|||||||
token,
|
token,
|
||||||
});
|
});
|
||||||
|
|
||||||
await mailer.sendMail({
|
await queueJob({
|
||||||
to: email,
|
job: 'send-mail',
|
||||||
from: {
|
args: {
|
||||||
name: FROM_NAME,
|
to: email,
|
||||||
address: FROM_ADDRESS,
|
from: {
|
||||||
|
name: FROM_NAME,
|
||||||
|
address: FROM_ADDRESS,
|
||||||
|
},
|
||||||
|
subject: `A request to use your email has been initiated by ${teamName} on Documenso`,
|
||||||
|
html: render(template),
|
||||||
|
text: render(template, { plainText: true }),
|
||||||
},
|
},
|
||||||
subject: `A request to use your email has been initiated by ${teamName} on Documenso`,
|
|
||||||
html: render(template),
|
|
||||||
text: render(template, { plainText: true }),
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { createElement } from 'react';
|
|||||||
|
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
|
|
||||||
import { mailer } from '@documenso/email/mailer';
|
|
||||||
import { render } from '@documenso/email/render';
|
import { render } from '@documenso/email/render';
|
||||||
import type { TeamInviteEmailProps } from '@documenso/email/templates/team-invite';
|
import type { TeamInviteEmailProps } from '@documenso/email/templates/team-invite';
|
||||||
import { TeamInviteEmailTemplate } from '@documenso/email/templates/team-invite';
|
import { TeamInviteEmailTemplate } from '@documenso/email/templates/team-invite';
|
||||||
@ -15,6 +14,8 @@ import { prisma } from '@documenso/prisma';
|
|||||||
import { TeamMemberInviteStatus } from '@documenso/prisma/client';
|
import { TeamMemberInviteStatus } from '@documenso/prisma/client';
|
||||||
import type { TCreateTeamMemberInvitesMutationSchema } from '@documenso/trpc/server/team-router/schema';
|
import type { TCreateTeamMemberInvitesMutationSchema } from '@documenso/trpc/server/team-router/schema';
|
||||||
|
|
||||||
|
import { queueJob } from '../queue/job';
|
||||||
|
|
||||||
export type CreateTeamMemberInvitesOptions = {
|
export type CreateTeamMemberInvitesOptions = {
|
||||||
userId: number;
|
userId: number;
|
||||||
userName: string;
|
userName: string;
|
||||||
@ -148,14 +149,17 @@ export const sendTeamMemberInviteEmail = async ({
|
|||||||
...emailTemplateOptions,
|
...emailTemplateOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
await mailer.sendMail({
|
await queueJob({
|
||||||
to: email,
|
job: 'send-mail',
|
||||||
from: {
|
args: {
|
||||||
name: FROM_NAME,
|
to: email,
|
||||||
address: FROM_ADDRESS,
|
from: {
|
||||||
|
name: FROM_NAME,
|
||||||
|
address: FROM_ADDRESS,
|
||||||
|
},
|
||||||
|
subject: `You have been invited to join ${emailTemplateOptions.teamName} on Documenso`,
|
||||||
|
html: render(template),
|
||||||
|
text: render(template, { plainText: true }),
|
||||||
},
|
},
|
||||||
subject: `You have been invited to join ${emailTemplateOptions.teamName} on Documenso`,
|
|
||||||
html: render(template),
|
|
||||||
text: render(template, { plainText: true }),
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { createElement } from 'react';
|
import { createElement } from 'react';
|
||||||
|
|
||||||
import { mailer } from '@documenso/email/mailer';
|
|
||||||
import { render } from '@documenso/email/render';
|
import { render } from '@documenso/email/render';
|
||||||
import { TeamEmailRemovedTemplate } from '@documenso/email/templates/team-email-removed';
|
import { TeamEmailRemovedTemplate } from '@documenso/email/templates/team-email-removed';
|
||||||
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
|
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
|
||||||
@ -8,6 +7,8 @@ import { FROM_ADDRESS, FROM_NAME } from '@documenso/lib/constants/email';
|
|||||||
import { TEAM_MEMBER_ROLE_PERMISSIONS_MAP } from '@documenso/lib/constants/teams';
|
import { TEAM_MEMBER_ROLE_PERMISSIONS_MAP } from '@documenso/lib/constants/teams';
|
||||||
import { prisma } from '@documenso/prisma';
|
import { prisma } from '@documenso/prisma';
|
||||||
|
|
||||||
|
import { queueJob } from '../queue/job';
|
||||||
|
|
||||||
export type DeleteTeamEmailOptions = {
|
export type DeleteTeamEmailOptions = {
|
||||||
userId: number;
|
userId: number;
|
||||||
userEmail: string;
|
userEmail: string;
|
||||||
@ -73,18 +74,21 @@ export const deleteTeamEmail = async ({ userId, userEmail, teamId }: DeleteTeamE
|
|||||||
teamUrl: team.url,
|
teamUrl: team.url,
|
||||||
});
|
});
|
||||||
|
|
||||||
await mailer.sendMail({
|
await queueJob({
|
||||||
to: {
|
job: 'create-document-audit-log',
|
||||||
address: team.owner.email,
|
args: {
|
||||||
name: team.owner.name ?? '',
|
to: {
|
||||||
|
address: team.owner.email,
|
||||||
|
name: team.owner.name ?? '',
|
||||||
|
},
|
||||||
|
from: {
|
||||||
|
name: FROM_NAME,
|
||||||
|
address: FROM_ADDRESS,
|
||||||
|
},
|
||||||
|
subject: `Team email has been revoked for ${team.name}`,
|
||||||
|
html: render(template),
|
||||||
|
text: render(template, { plainText: true }),
|
||||||
},
|
},
|
||||||
from: {
|
|
||||||
name: FROM_NAME,
|
|
||||||
address: FROM_ADDRESS,
|
|
||||||
},
|
|
||||||
subject: `Team email has been revoked for ${team.name}`,
|
|
||||||
html: render(template),
|
|
||||||
text: render(template, { plainText: true }),
|
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Todo: Teams - Alert us.
|
// Todo: Teams - Alert us.
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { createElement } from 'react';
|
import { createElement } from 'react';
|
||||||
|
|
||||||
import { mailer } from '@documenso/email/mailer';
|
|
||||||
import { render } from '@documenso/email/render';
|
import { render } from '@documenso/email/render';
|
||||||
import { TeamTransferRequestTemplate } from '@documenso/email/templates/team-transfer-request';
|
import { TeamTransferRequestTemplate } from '@documenso/email/templates/team-transfer-request';
|
||||||
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
|
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
|
||||||
@ -8,6 +7,8 @@ import { FROM_ADDRESS, FROM_NAME } from '@documenso/lib/constants/email';
|
|||||||
import { createTokenVerification } from '@documenso/lib/utils/token-verification';
|
import { createTokenVerification } from '@documenso/lib/utils/token-verification';
|
||||||
import { prisma } from '@documenso/prisma';
|
import { prisma } from '@documenso/prisma';
|
||||||
|
|
||||||
|
import { queueJob } from '../queue/job';
|
||||||
|
|
||||||
export type RequestTeamOwnershipTransferOptions = {
|
export type RequestTeamOwnershipTransferOptions = {
|
||||||
/**
|
/**
|
||||||
* The ID of the user initiating the transfer.
|
* The ID of the user initiating the transfer.
|
||||||
@ -93,15 +94,18 @@ export const requestTeamOwnershipTransfer = async ({
|
|||||||
token,
|
token,
|
||||||
});
|
});
|
||||||
|
|
||||||
await mailer.sendMail({
|
await queueJob({
|
||||||
to: newOwnerUser.email,
|
job: 'create-document-audit-log',
|
||||||
from: {
|
args: {
|
||||||
name: FROM_NAME,
|
to: newOwnerUser.email,
|
||||||
address: FROM_ADDRESS,
|
from: {
|
||||||
|
name: FROM_NAME,
|
||||||
|
address: FROM_ADDRESS,
|
||||||
|
},
|
||||||
|
subject: `You have been requested to take ownership of team ${team.name} on Documenso`,
|
||||||
|
html: render(template),
|
||||||
|
text: render(template, { plainText: true }),
|
||||||
},
|
},
|
||||||
subject: `You have been requested to take ownership of team ${team.name} on Documenso`,
|
|
||||||
html: render(template),
|
|
||||||
text: render(template, { plainText: true }),
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{ timeout: 30_000 },
|
{ timeout: 30_000 },
|
||||||
|
|||||||
@ -2,12 +2,12 @@ import { createElement } from 'react';
|
|||||||
|
|
||||||
import { PDFDocument } from 'pdf-lib';
|
import { PDFDocument } from 'pdf-lib';
|
||||||
|
|
||||||
import { mailer } from '@documenso/email/mailer';
|
|
||||||
import { renderAsync } from '@documenso/email/render';
|
import { renderAsync } from '@documenso/email/render';
|
||||||
import { DocumentSelfSignedEmailTemplate } from '@documenso/email/templates/document-self-signed';
|
import { DocumentSelfSignedEmailTemplate } from '@documenso/email/templates/document-self-signed';
|
||||||
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
|
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
|
||||||
import { FROM_ADDRESS, FROM_NAME, SERVICE_USER_EMAIL } from '@documenso/lib/constants/email';
|
import { FROM_ADDRESS, FROM_NAME, SERVICE_USER_EMAIL } from '@documenso/lib/constants/email';
|
||||||
import { insertFieldInPDF } from '@documenso/lib/server-only/pdf/insert-field-in-pdf';
|
import { insertFieldInPDF } from '@documenso/lib/server-only/pdf/insert-field-in-pdf';
|
||||||
|
import { queueJob } from '@documenso/lib/server-only/queue/job';
|
||||||
import { alphaid } from '@documenso/lib/universal/id';
|
import { alphaid } from '@documenso/lib/universal/id';
|
||||||
import { getFile } from '@documenso/lib/universal/upload/get-file';
|
import { getFile } from '@documenso/lib/universal/upload/get-file';
|
||||||
import { putFile } from '@documenso/lib/universal/upload/put-file';
|
import { putFile } from '@documenso/lib/universal/upload/put-file';
|
||||||
@ -160,19 +160,22 @@ export const singleplayerRouter = router({
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
// Send email to signer.
|
// Send email to signer.
|
||||||
await mailer.sendMail({
|
await queueJob({
|
||||||
to: {
|
job: 'send-mail',
|
||||||
address: signer.email,
|
args: {
|
||||||
name: signer.name,
|
to: {
|
||||||
|
address: signer.email,
|
||||||
|
name: signer.name,
|
||||||
|
},
|
||||||
|
from: {
|
||||||
|
name: FROM_NAME,
|
||||||
|
address: FROM_ADDRESS,
|
||||||
|
},
|
||||||
|
subject: 'Document signed',
|
||||||
|
html,
|
||||||
|
text,
|
||||||
|
attachments: [{ content: signedPdfBuffer, filename: documentName }],
|
||||||
},
|
},
|
||||||
from: {
|
|
||||||
name: FROM_NAME,
|
|
||||||
address: FROM_ADDRESS,
|
|
||||||
},
|
|
||||||
subject: 'Document signed',
|
|
||||||
html,
|
|
||||||
text,
|
|
||||||
attachments: [{ content: signedPdfBuffer, filename: documentName }],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
|
|||||||
Reference in New Issue
Block a user