@liara/cli
Version:
The command line interface for Liara
233 lines (232 loc) • 8.49 kB
JavaScript
import fs from 'fs';
import path from 'path';
import mime from 'mime';
import inquirer from 'inquirer';
import ora from 'ora';
import { Flags } from '@oclif/core';
import Command from '../../base.js';
import { createDebugLogger } from '../../utils/output.js';
import { MAIL_SERVICE_URL, DEV_MODE, MAIL_SERVICE_URL_DEV, } from '../../constants.js';
class SendMail extends Command {
async setGotConfig(config) {
await super.setGotConfig(config);
this.got = this.got.extend({
prefixUrl: DEV_MODE ? MAIL_SERVICE_URL_DEV : MAIL_SERVICE_URL,
});
}
async run() {
var _a, _b, _c, _d, _e;
this.spinner = ora();
const { flags } = await this.parse(SendMail);
const debug = createDebugLogger(flags.debug);
await this.setGotConfig(flags);
const { data } = await this.got('api/v1/mails').json();
const mailDomain = await this.promptMails();
const mailId = flags.mail ||
((_a = data.mailServers.find((mail) => mail.domain === mailDomain)) === null || _a === void 0 ? void 0 : _a.id) ||
'';
const from = flags.from || (await this.promptFrom(mailId));
const to = flags.to || (await this.promptTo());
const mailRegex = new RegExp(/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/g);
const isValidDestination = mailRegex.test(to);
if (!isValidDestination) {
this.error(`Invalid destination email address.`);
}
const subject = flags.subject || (await this.promptSubject());
const text = flags.text || (await this.promptText());
const flagAttachments = flags.attachments
? this.getFlagFiles(flags.attachments)
: undefined;
const attachments = flagAttachments || (await this.promptFiles());
try {
if (await this.confirm(to)) {
await this.got.post(`api/v1/mails/${mailId}/messages`, {
json: { from, to, subject, text, attachments },
});
this.log(`Mail has been sent to ${to}.`);
}
}
catch (error) {
debug(error.message);
if (error.response && error.response.body) {
debug(JSON.stringify(error.response.body));
}
if (error.response && error.response.statusCode === 401) {
this.error(`Missing authentication.`);
}
if (((_b = error.response) === null || _b === void 0 ? void 0 : _b.statusCode) === 404 &&
((_c = error.response) === null || _c === void 0 ? void 0 : _c.body.message) === 'Account not found.') {
this.error(`Account not found.`);
}
if (((_d = error.response) === null || _d === void 0 ? void 0 : _d.statusCode) === 404 &&
((_e = error.response) === null || _e === void 0 ? void 0 : _e.body.message) === 'Mail Server not found.') {
this.error(`Mail server not found.`);
}
this.log(error.response.body);
this.error(`Could not send the email. Please try again.`);
}
}
async promptMails() {
this.spinner = ora();
this.spinner.start('Loading...');
try {
const { data } = await this.got('api/v1/mails').json();
this.spinner.stop();
if (!data.mailServers.length) {
this.warn('Please go to https://console.liara.ir/mail and create a mail server, first.');
this.exit(1);
}
const { mailDomain } = (await inquirer.prompt({
name: 'mailDomain',
type: 'list',
message: 'Please select a mail:',
choices: [...data.mailServers.map((mail) => mail.domain)],
validate: (input) => input.length > 2,
}));
return mailDomain;
}
catch (error) {
this.spinner.stop();
throw error;
}
}
async promptFrom(mailId) {
this.spinner = ora();
this.spinner.start('Loading...');
try {
const { data } = await this.got(`api/v1/mails/${mailId}/accounts`).json();
this.spinner.stop();
if (!data.accounts.length) {
this.warn('Please go to https://console.liara.ir/mail and create a mail server account, first.');
this.exit(1);
}
const { from } = (await inquirer.prompt({
name: 'from',
type: 'list',
message: 'What address should it be sent from:',
choices: [
...data.accounts.map((account) => `${account.name}@${data.domain}`),
],
validate: (input) => input.length > 2,
}));
return from;
}
catch (error) {
this.spinner.stop();
throw error;
}
}
async promptTo() {
const { to } = (await inquirer.prompt({
name: 'to',
type: 'input',
message: 'Enter the destination address:',
validate: (input) => input.length > 2,
}));
return to;
}
async promptSubject() {
const { subject } = (await inquirer.prompt({
name: 'subject',
type: 'input',
message: 'The subject of your mail:',
validate: (input) => input.length > 2,
}));
return subject;
}
async promptText() {
const { text } = (await inquirer.prompt({
name: 'text',
type: 'editor',
message: 'The text of your mail:',
validate: (input) => input.length > 2,
}));
return text;
}
getFlagFiles(flagFiles) {
const files = [];
for (const flagFile of flagFiles) {
const file = path.join(process.cwd(), flagFile);
if (!fs.statSync(file).isDirectory()) {
const resultFile = {
content_type: mime.getType(file) || '',
data: `data:${mime.getType(file)};base64,${fs.readFileSync(file, {
encoding: 'base64',
})}`,
name: file.split('/').pop() || '',
};
files.push(resultFile);
}
}
return files;
}
getFiles() {
const files = [];
const filesInCurrentDirectory = fs.readdirSync('./');
for (const file of filesInCurrentDirectory) {
if (!fs.statSync(file).isDirectory()) {
const resultFile = {
content_type: mime.getType(file) || '',
data: `data:${mime.getType(file)};base64,${fs.readFileSync(file, {
encoding: 'base64',
})}`,
name: file || '',
};
files.push(resultFile);
}
}
return files;
}
async promptFiles() {
const files = this.getFiles();
const { attachments } = (await inquirer.prompt({
name: 'attachments',
type: 'checkbox',
message: 'Select your attachments:',
choices: files.map((file) => file.name),
}));
const filesResult = [];
for (const attachment of attachments) {
for (const file of files) {
if (attachment === file.name) {
filesResult.push(file);
}
}
}
return filesResult;
}
async confirm(dest) {
const { confirmation } = (await inquirer.prompt({
name: 'confirmation',
type: 'confirm',
message: `Are you sure to send an e-mail to "${dest}"?`,
default: false,
}));
return confirmation;
}
}
SendMail.description = 'send an email';
SendMail.flags = {
...Command.flags,
mail: Flags.string({
description: 'mail server id',
}),
from: Flags.string({
description: 'from',
}),
to: Flags.string({
description: 'to',
}),
subject: Flags.string({
description: 'subject',
}),
text: Flags.string({
description: 'text',
}),
attachments: Flags.string({
multiple: true,
description: 'path of your attachments',
}),
};
SendMail.aliases = ['mail:send'];
export default SendMail;