Files
puter/src/backend/src/modules/mail/UserSendMailService.js
T

116 lines
4.1 KiB
JavaScript

const APIError = require("../../api/APIError");
const { LLRead } = require("../../filesystem/ll_operations/ll_read");
const BaseService = require("../../services/BaseService");
const { Context } = require("../../util/context");
const validator = require('validator')
class UserSendMailService extends BaseService {
async ['__on_driver.register.interfaces'] () {
const svc_registry = this.services.get('registry');
const col_interfaces = svc_registry.get('interfaces');
col_interfaces.set('puter-send-mail', {
description: 'Send an email.',
methods: {
send: {
description: 'Recognize text in an image or document.',
parameters: {
to: {
type: 'string',
},
subject: {
type: 'string',
},
body: {
type: 'string',
},
encoding: {
type: 'string',
},
attachments: {
type: 'json',
}
},
result: { type: 'json' },
},
}
});
}
static IMPLEMENTS = {
'puter-send-mail': {
async send ({
to, subject, body,
encoding,
attachments = [],
}) {
const actor = Context.get('actor');
const svc_email = this.services.get('email');
if ( ! actor.type.user ) {
throw new Error('Only users can send email.');
}
const user = actor.type.user;
encoding = encoding ?? 'html';
if ( ! ['html', 'text'].includes(encoding) ) {
throw APIError.create('field_invalid', null, {
key: 'encoding',
expected: 'html or text',
got: encoding,
});
}
if ( ! validator.isEmail(to) ) {
throw APIError.create('field_invalid', null, {
key: 'to',
expected: 'a valid email address',
got: to,
});
}
// We're going to disallow subject lines over or including 998,
// as nobody would ever do this unless they're trying to
// exploit a faulty email client.
if ( subject.length >= 998 ) {
throw APIError.create('field_too_long', null, {
key: 'subject',
max_length: 997,
});
}
const transporter = svc_email.get_transport_();
const o = {
from: `${user.username}@${this.config.domain}`, // sender address
to,
subject,
[encoding === 'html' ? 'html' : 'text']: body,
};
for ( const attachment of attachments ) {
if ( attachment.path ) {
const svc_fs = this.services.get('filesystem');
const node = await svc_fs.node(attachment.path);
const ll_read = new LLRead();
const stream = await ll_read.run({
actor: Context.get('actor'),
fsNode: node,
});
attachment.content = stream;
delete attachment.path;
}
}
if ( attachments.length > 0 ) {
o.attachments = attachments;
}
await transporter.sendMail(o);
}
}
}
}
module.exports = {
UserSendMailService,
};