mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-18 15:42:54 +00:00
feat: mail
This commit is contained in:
@@ -7,58 +7,65 @@ config({path: '.env.local'});
|
||||
const app = express();
|
||||
const port = process.env.PORT || 4000;
|
||||
|
||||
if (!process.env.IMAP_USER || !process.env.IMAP_PASSWORD) {
|
||||
throw new Error('Provide IMAP user');
|
||||
}
|
||||
app.use(async (request, response, next) => {
|
||||
try {
|
||||
const [user, pass] = Buffer.from(request.headers['authorization']!.replace(/^Basic /, ''), 'base64')
|
||||
.toString('utf8')
|
||||
.split(':');
|
||||
|
||||
app.use((_request, response, next) => {
|
||||
const client = new ImapFlow({
|
||||
host: 'imap.server.uni-frankfurt.de',
|
||||
port: 993,
|
||||
secure: true,
|
||||
emitLogs: false,
|
||||
auth: {
|
||||
user: process.env.IMAP_USER!,
|
||||
pass: process.env.IMAP_PASSWORD!,
|
||||
},
|
||||
});
|
||||
response.locals.client = client;
|
||||
next();
|
||||
const client = new ImapFlow({
|
||||
host: 'imap.server.uni-frankfurt.de',
|
||||
port: 993,
|
||||
secure: true,
|
||||
emitLogs: false,
|
||||
auth: {user, pass},
|
||||
});
|
||||
response.locals.client = client;
|
||||
|
||||
await client.connect();
|
||||
response.on('finish', async () => {
|
||||
await client.logout();
|
||||
});
|
||||
|
||||
next();
|
||||
} catch {
|
||||
response.status(401).send();
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/', async (request, response) => {
|
||||
const client = response.locals.client as ImapFlow;
|
||||
await client.connect();
|
||||
const lock = await client.getMailboxLock('INBOX');
|
||||
app.get('/', async (_request, response) => {
|
||||
const result = await response.locals.client.listTree();
|
||||
response.json(result);
|
||||
});
|
||||
|
||||
app.get('/:mailbox', async (request, response) => {
|
||||
try {
|
||||
await response.locals.client.mailboxOpen(request.params.mailbox);
|
||||
const since = Number(request.query.since) || undefined;
|
||||
const data = response.locals.client.fetch(
|
||||
'1:*',
|
||||
{},
|
||||
{
|
||||
// caution, BigInt can throw
|
||||
changedSince: typeof since === 'string' ? BigInt(since) : undefined,
|
||||
},
|
||||
);
|
||||
|
||||
const messages = [];
|
||||
for await (const message of client.fetch('1:*', {
|
||||
envelope: true,
|
||||
labels: true,
|
||||
bodyStructure: true,
|
||||
flags: true,
|
||||
})) {
|
||||
messages.push({
|
||||
bodyStructure: message.bodyStructure,
|
||||
labels: [...(message.labels ?? [])],
|
||||
flags: [...(message.flags ?? [])],
|
||||
envelope: message.envelope,
|
||||
seq: message.seq,
|
||||
});
|
||||
for await (const message of data) {
|
||||
messages.push(message.seq);
|
||||
}
|
||||
response.json(messages);
|
||||
} finally {
|
||||
lock.release();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
response.status(404).send();
|
||||
}
|
||||
await client.logout();
|
||||
});
|
||||
|
||||
app.get('/:id', async (request, response) => {
|
||||
const client = response.locals.client as ImapFlow;
|
||||
await client.connect();
|
||||
const lock = await client.getMailboxLock('INBOX');
|
||||
app.get('/:mailbox/:id', async (request, response) => {
|
||||
try {
|
||||
const message = await client.fetchOne(request.params.id, {
|
||||
await response.locals.client.mailboxOpen(request.params.mailbox);
|
||||
const message = await response.locals.client.fetchOne(request.params.id, {
|
||||
envelope: true,
|
||||
labels: true,
|
||||
flags: true,
|
||||
@@ -71,49 +78,39 @@ app.get('/:id', async (request, response) => {
|
||||
envelope: message.envelope,
|
||||
seq: message.seq,
|
||||
});
|
||||
} finally {
|
||||
lock.release();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
response.status(404).send();
|
||||
}
|
||||
await client.logout();
|
||||
});
|
||||
|
||||
app.get('/:id/attachment/:attachment?', async (request, response) => {
|
||||
const client = response.locals.client as ImapFlow;
|
||||
await client.connect();
|
||||
const lock = await client.getMailboxLock('INBOX');
|
||||
app.get('/:mailbox/:id/:part', async (request, response) => {
|
||||
try {
|
||||
const message = await client.download(request.params.id, request.params.attachment);
|
||||
message.content.on('data', chunk => {
|
||||
response.write(chunk);
|
||||
});
|
||||
message.content.on('end', () => {
|
||||
await response.locals.client.mailboxOpen(request.params.mailbox, {readOnly: true});
|
||||
if (request.query.raw) {
|
||||
const message = await response.locals.client.fetchOne(request.params.id, {
|
||||
bodyParts: [`${request.params.part}.mime`, request.params.part],
|
||||
});
|
||||
|
||||
response.write(message.bodyParts.get(`${request.params.part}.mime`));
|
||||
response.write(message.bodyParts.get(request.params.part));
|
||||
|
||||
response.end();
|
||||
});
|
||||
} finally {
|
||||
lock.release();
|
||||
} else {
|
||||
const message = await response.locals.client.download(request.params.id, request.params.part);
|
||||
message.content.on('data', chunk => {
|
||||
response.write(chunk);
|
||||
});
|
||||
message.content.on('end', () => {
|
||||
response.end();
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
response.status(404).send();
|
||||
}
|
||||
await client.logout();
|
||||
});
|
||||
|
||||
app.get('/:id/raw/:part', async (request, response) => {
|
||||
const client = response.locals.client as ImapFlow;
|
||||
await client.connect();
|
||||
const lock = await client.getMailboxLock('INBOX');
|
||||
try {
|
||||
const message = await client.fetchOne(request.params.id, {
|
||||
bodyParts: [`${request.params.part}.mime`, request.params.part],
|
||||
});
|
||||
|
||||
response.write(message.bodyParts.get(`${request.params.part}.mime`));
|
||||
response.write(message.bodyParts.get(request.params.part));
|
||||
|
||||
response.end();
|
||||
} finally {
|
||||
lock.release();
|
||||
}
|
||||
await client.logout();
|
||||
});
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Server is running on http://localhost:${port}`);
|
||||
console.log(`Server listening on port ${port}`);
|
||||
});
|
||||
|
||||
9
backend/mail-plugin/src/types.d.ts
vendored
Normal file
9
backend/mail-plugin/src/types.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import {ImapFlow} from 'imapflow';
|
||||
|
||||
declare global {
|
||||
namespace Express {
|
||||
interface Locals {
|
||||
client: ImapFlow;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user