1 | |
2 |
|
3 | |
4 | * Create Draft |
5 | * Save an unsent draft in the connected Gmail account. Set `is_html` to send `body` as HTML. To draft a reply, pass the original's `thread_id` and its `Message-ID` header as `in_reply_to` and keep the same subject. |
6 | */ |
7 | export async function main( |
8 | auth: RT.Gmail, |
9 | to: string, |
10 | subject: string, |
11 | body: string, |
12 | cc: string | undefined, |
13 | bcc: string | undefined, |
14 | is_html: boolean = false, |
15 | thread_id: string | undefined, |
16 | in_reply_to: string | undefined |
17 | ) { |
18 | const headers = [ |
19 | `To: ${to}`, |
20 | cc ? `Cc: ${cc}` : undefined, |
21 | bcc ? `Bcc: ${bcc}` : undefined, |
22 | `Subject: =?UTF-8?B?${base64(subject)}?=`, |
23 | in_reply_to ? `In-Reply-To: ${in_reply_to}` : undefined, |
24 | in_reply_to ? `References: ${in_reply_to}` : undefined, |
25 | "MIME-Version: 1.0", |
26 | `Content-Type: text/${is_html ? "html" : "plain"}; charset="UTF-8"`, |
27 | "Content-Transfer-Encoding: base64", |
28 | ].filter((h) => h !== undefined) |
29 | const mime = `${headers.join("\r\n")}\r\n\r\n${base64(body)}` |
30 | const raw = base64(mime).replace(/\+/g, "-").replace(/\//g, "_") |
31 |
|
32 | const response = await fetch( |
33 | "https://gmail.googleapis.com/gmail/v1/users/me/drafts", |
34 | { |
35 | method: "POST", |
36 | headers: { |
37 | Authorization: `Bearer ${auth.token}`, |
38 | "Content-Type": "application/json", |
39 | Accept: "application/json", |
40 | }, |
41 | body: JSON.stringify({ |
42 | message: { raw, threadId: thread_id || undefined }, |
43 | }), |
44 | } |
45 | ) |
46 | if (!response.ok) { |
47 | throw new Error(`${response.status} ${await response.text()}`) |
48 | } |
49 |
|
50 | return await response.json() |
51 | } |
52 |
|
53 | function base64(s: string) { |
54 | const bytes = new TextEncoder().encode(s) |
55 | let binary = "" |
56 | for (const b of bytes) binary += String.fromCharCode(b) |
57 | return btoa(binary) |
58 | } |
59 |
|