April 28, 2024, written by
Andrii Minchekov
In today's programming world, sending emails through your applications is a common task. For Deno developers, integrating Gmail for email functionality offers reliability and ease of use. In this blog post, we'll walk through the process of sending an email from the Gmail server using Supabase Edge function which are developed using Deno environment.
Before proceeding, make sure your Gmail account is configured correctly: enable Less Secure Apps or Use App Password (for security, it's recommended to use an application-specific password). To enable "Less Secure App Access" in your Gmail account, follow these steps:
Install supabase-cli locally.
Create a new Supabase integration in a project folder on your local machine.
supabase init
Create a new Edge Function called "send-email-from-gmail" inside your project.
supabase functions new send-email-from-gmail
Copy next code to the index.ts file inside supabase function folder "send-email-from-gmail"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import {SMTPClient} from 'https://deno.land/x/denomailer@1.6.0/mod.ts'
console.log(`Function "send-email-smtp" up and running!`)
const {SMTP_HOSTNAME, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD} = Deno.env.toObject();
export type LeadRow = {
created_at: string
email: string
firstName: string
howHeardAboutUs: string
id: number
isNdaRequired: boolean
isProcessed: boolean
isTacAgree: boolean
lastName: string
projectDetails: string
projectServices: string[]
}
type DbEventType = "INSERT" | "UPDATE" | "DELETE"
interface DbEventLead {
type: DbEventType
table: string
record: LeadRow
schema: string
old_record: {} | null
}
Deno.serve(async (req) => {
const leadInJson: DbEventLead = await req.json();
console.log(`Arrived request with body=${JSON.stringify(leadInJson)}`)
const client = new SMTPClient({
connection: {
hostname: SMTP_HOSTNAME, // Replace with your SMTP server host
port: +SMTP_PORT,
tls: true,
auth: {
username: SMTP_USERNAME, // Replace with your SMTP username
password: SMTP_PASSWORD, // Replace with your SMTP password
},
},
});
try {
await client.send({
from: `"site.com" <${SMTP_USERNAME}>`, // Replace with your email
to: SMTP_USERNAME, // Replace with recipient email
subject: "New Lead came from site.com",
content: `Hi, Sales team. Please check new Lead from marketing site https://site.com.
Find all Lead data by lead email ${leadInJson.record.email} here
https://supabase.com/dashboard/project/your_project_id/editor/your_table_id`,
})
console.log(`Email about new lead ${leadInJson.record.email} sent successfully to Sales team`)
} catch (error) {
console.error(`Couldn't sent email because of error=${error.message}`)
return new Response(error.message, {status: 500})
}
await client.close()
return new Response(
JSON.stringify({
success: true,
body: leadInJson.record
}),
{
headers: {'Content-Type': 'application/json'},
}
)
})
This Deno function is configured to be listening to database table changes thus a request contains an Insert Event from the database with payload of inserted table record.
Add following env variables with your own values which are used by Deno runtime in the code above
Running Edge Functions
Locally from IDE
Locally with supabase docker-compose
supabase starts
//start the supabase stacksupabase functions serve
// start the Functions watchercurl --request POST 'http://localhost:54321/functions/v1/send-email-from-gmail' \
--header 'Authorization: Bearer SUPABASE_ANON_KEY' \
--header 'Content-Type: application/json' \
--data "{\"type\":\"INSERT\",\"table\":\"leads\",\"record\":{\"id\":19,\"email\":\"a@i.ua\",\"lastName\":\"New LastName\",\"firstName\":\"NewName\",\"created_at\":\"2023-12-05T20:34:05.515238+00:00\",\"isTacAgree\":true,\"isProcessed\":false,\"isNdaRequired\":true,\"projectDetails\":\"ppp\",\"howHeardAboutUs\":\"social\",\"projectServices\":[\"audit\"]},\"schema\":\"public\",\"old_record\":null}"
Remotely (on the Supabase SaaS)
supabase functions deploy send-email-from-gmail
curl --request POST 'https://<project_id>.supabase.co/functions/v1/send-email-from-gmail' \
--header 'Authorization: Bearer ANON_KEY' \
--header 'Content-Type: application/json' \
--data "{\"type\":\"INSERT\",\"table\":\"leads\",\"record\":{\"id\":19,\"email\":\"a@i.ua\",\"lastName\":\"New LastName\",\"firstName\":\"NewName\",\"created_at\":\"2023-12-05T20:34:05.515238+00:00\",\"isTacAgree\":true,\"isProcessed\":false,\"isNdaRequired\":true,\"projectDetails\":\"ppp\",\"howHeardAboutUs\":\"social\",\"projectServices\":[\"audit\"]},\"schema\":\"public\",\"old_record\":null}"
If as a result of function invocation you see this error in a response
535: 5.7.8 Username and Password not accepted. For more information, go to,5.7.8 https://support.google.com/mail/?p=BadCredentials k12-20020a056402048c00b00554a56ee252sm5777602edv.91 - gsmtp
that means you have misconfigured Security Settings in your Google account and have to go back to Step 1