1 | import { getResumeUrls } from "https://deno.land/x/windmill@v1.85.0/mod.ts"; |
2 | import { encode as base64UrlEncode } from "https://deno.land/std@0.82.0/encoding/base64url.ts"; |
3 |
|
4 | type Gmail = { |
5 | token: string; |
6 | }; |
7 | export async function main( |
8 | gmail_auth: Gmail, |
9 | approver_emails: string[], |
10 | subject = "Resume Windmill flow", |
11 | ) { |
12 | throwOnInvalidApprovers(approver_emails); |
13 |
|
14 | const token = gmail_auth["token"]; |
15 | const email_promises = approver_emails.map((to_email) => |
16 | sendEmail(token, to_email, subject), |
17 | ); |
18 | const results = await Promise.all(email_promises); |
19 |
|
20 | return results; |
21 | } |
22 |
|
23 | async function sendEmail( |
24 | gmail_token: string, |
25 | to_email: string, |
26 | subject: string, |
27 | ): Promise<object> { |
28 | const email = await getEmailBody(to_email, subject); |
29 | const SEND_EMAIL_URL = `https://gmail.googleapis.com/gmail/v1/users/me/messages/send`; |
30 | const body = { |
31 | raw: email, |
32 | }; |
33 | const response = await fetch(SEND_EMAIL_URL, { |
34 | method: "POST", |
35 | body: JSON.stringify(body), |
36 | headers: { |
37 | Authorization: `Bearer ${gmail_token}`, |
38 | }, |
39 | }); |
40 | const response_json = await response.json(); |
41 |
|
42 | return handleSendEmailResult(response_json, to_email); |
43 | } |
44 |
|
45 | async function getEmailBody(to_email: string, subject: string) { |
46 | const { approvalPage } = await getResumeUrls(to_email); |
47 | const message = `There is a Windmill flow at ${Deno.env.get( |
48 | "WM_FLOW_PATH", |
49 | )} run by ${Deno.env.get("WM_USERNAME")} waiting for your approval to resume. |
50 |
|
51 | In order to resume or cancel the flow go to ${approvalPage}`; |
52 | const email_body = `From: <me>\nTo: <${to_email}>\nSubject: ${subject}\n\r ${message}`; |
53 |
|
54 | return base64UrlEncode(email_body); |
55 | } |
56 |
|
57 | function throwOnInvalidApprovers(approvers: string[]) { |
58 | if (!Array.isArray(approvers) || approvers.length === 0) { |
59 | throw new Error("Expected at least one approver email"); |
60 | } |
61 | } |
62 |
|
63 | async function handleSendEmailResult(result: object, to_email: string) { |
64 | if (Object.keys(result).includes("error")) { |
65 | return Promise.reject({ wm_to_email: to_email, ...result }); |
66 | } |
67 |
|
68 | return result; |
69 | } |
70 |
|