1 | import * as wmill from "windmill-client" |
2 | import { S3Object } from "windmill-client" |
3 |
|
4 | |
5 | * Send Email |
6 | * Send an email from the connected mailbox, with optional cc/bcc, reply-to and file attachments from object storage (about 3 MB in total). Requires Mail.Send (a connection default); a shared mailbox also needs Mail.Send.Shared, not a default. |
7 | */ |
8 | export async function main( |
9 | auth: RT.Outlook, |
10 | to: string[], |
11 | subject: string, |
12 | body: string, |
13 | content_type: "HTML" | "Text" = "HTML", |
14 | cc: string[] | undefined, |
15 | bcc: string[] | undefined, |
16 | reply_to: string[] | undefined, |
17 | attachments: S3Object[] | undefined, |
18 | save_to_sent_items: boolean = true, |
19 | mailbox: string | undefined |
20 | ) { |
21 | const base = `https://graph.microsoft.com/v1.0/${ |
22 | mailbox != null && mailbox !== "" |
23 | ? `users/${encodeURIComponent(mailbox)}` |
24 | : "me" |
25 | }` |
26 | const recipients = (addresses: string[] | undefined) => |
27 | (addresses ?? []) |
28 | .filter((a) => a != null && a.trim() !== "") |
29 | .map((address) => ({ emailAddress: { address } })) |
30 |
|
31 | const files = [] |
32 | for (const file of attachments ?? []) { |
33 | const bytes = await wmill.loadS3File(file) |
34 | if (!bytes) throw new Error(`Could not load ${file.s3}`) |
35 | files.push({ |
36 | "@odata.type": "#microsoft.graph.fileAttachment", |
37 | name: file.s3.split("/").pop(), |
38 | contentBytes: Buffer.from(bytes).toString("base64"), |
39 | }) |
40 | } |
41 |
|
42 | const response = await fetch(`${base}/sendMail`, { |
43 | method: "POST", |
44 | headers: { |
45 | Authorization: `Bearer ${auth.token}`, |
46 | "Content-Type": "application/json", |
47 | Accept: "application/json", |
48 | }, |
49 | body: JSON.stringify({ |
50 | message: { |
51 | subject, |
52 | body: { contentType: content_type, content: body }, |
53 | toRecipients: recipients(to), |
54 | ccRecipients: recipients(cc), |
55 | bccRecipients: recipients(bcc), |
56 | replyTo: recipients(reply_to), |
57 | attachments: files, |
58 | }, |
59 | saveToSentItems: save_to_sent_items, |
60 | }), |
61 | }) |
62 |
|
63 | if (!response.ok) { |
64 | throw new Error(`${response.status} ${await response.text()}`) |
65 | } |
66 |
|
67 | |
68 | return { success: true } |
69 | } |
70 |
|