@kohanajs/mod-mail-adapter-aws
Version:
KohanaJS Mail Module Adpater - AWS
148 lines (127 loc) • 4.18 kB
JavaScript
const path = require('path');
const { KohanaJS } = require('kohanajs');
const { MailAdapter } = require('@kohanajs/mod-mail');
const MailComposer = require("nodemailer/lib/mail-composer");
class MailAdapterAWSSES extends MailAdapter {
/**
*
* @param opts
* @param opts.host
* @param opts.apiKey
* @param opts.domain
*/
constructor(opts) {
super();
this.service = 'AWS';
const { SES } = require('@aws-sdk/client-ses');
const { fromIni } = require('@aws-sdk/credential-provider-ini');
MailAdapterAWSSES.credentials = MailAdapterAWSSES.credentials || fromIni({
profile: KohanaJS.config.mail.aws.profile,
filepath: path.normalize(KohanaJS.config.mail.aws.credentialsPath),
});
MailAdapterAWSSES.client = MailAdapterAWSSES.client || new SES({
region: KohanaJS.config.mail.aws.region,
credentials: MailAdapterAWSSES.credentials,
});
}
/**
*
* @param {string} subject
* @param {string} text
* @param {string} sender
* @param {string} recipient
* @param opts
* @param {string} opts.cc
* @param {string} opts.bcc
* @param {string} opts.html
* @param {object[]} opts.attachments ['filename', 'data-path']
* @param {string[]} opts.metadata ['user', '12345']
* @returns {Promise<unknown>}
*/
// eslint-disable-next-line class-methods-use-this
async send(subject, text, sender, recipient, opts = {}) {
const {
cc = '',
bcc = '',
html = '',
attachments = [],
// metadata = [],
project = KohanaJS.config.mail.aws.project,
dynamoDB = KohanaJS.config.mail.aws.dynamoDB,
configurationSetName = KohanaJS.config.mail.aws.configurationSetName,
} = opts;
const mail = {
from: sender,
to: recipient,
subject: subject,
text : text,
};
if (cc) mail.cc = cc;
if (bcc) mail.bcc = bcc;
if (html) mail.html = html
if(attachments.length > 0) mail.attachments = attachments;
const Data = await new Promise((resolve, reject) => {
const mc = new MailComposer(mail).compile();
mc.keepBcc = true;
mc.build((err, msg) => {
if(err)reject(err);
resolve(msg);
})
});
const result = await MailAdapterAWSSES.client.sendRawEmail({
ConfigurationSetName: configurationSetName,
Tags: [
{ Name: 'project', Value: project },
{ Name: 'dynamoDB', Value: dynamoDB },
],
Destination: {
ToAddresses: recipient.split(',').map(name => name.trim()),
},
Source: sender,
RawMessage: { Data }
});
return {
id: result.MessageId,
};
}
async readLog(email) {
const { DynamoDBClient, ScanCommand } = require('@aws-sdk/client-dynamodb');
MailAdapterAWSSES.ddb = MailAdapterAWSSES.ddb || new DynamoDBClient({
region: KohanaJS.config.mail.aws.region,
credentials: MailAdapterAWSSES.credentials,
});
// fetch from dynamoDB
const results = await MailAdapterAWSSES.ddb.send(
new ScanCommand({
TableName: KohanaJS.config.mail.aws.dynamoDB,
FilterExpression: '#c = :username and #p = :project',
ProjectionExpression: 'mailMessageID, #c, event, #t',
ExpressionAttributeNames: {
'#c': 'to',
'#t': 'timestamp',
'#p': 'project',
},
ExpressionAttributeValues: {
':username': { S: email },
':project': { S: KohanaJS.config.mail.aws.project },
},
}),
);
const mailLogs = new Map([['service', this.service]]);
results.Items.forEach(item => {
const mailId = item.mailMessageID.S;
if (!mailLogs.has(mailId))mailLogs.set(mailId, { open: 0, click: 0 });
const counts = mailLogs.get(mailId);
switch (item.event.S.toLowerCase()) {
case 'open':
counts.open += 1;
break;
case 'click':
counts.click += 1;
break;
default:
}
});
}
}
module.exports = MailAdapterAWSSES;