Supabase Edge function to send an email from the Gmail server using Deno runtime

/blog/avatar-andrii-minchekov.png

April 28, 2024, written by

Andrii Minchekov

[object Object]

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.

Prerequisites

  1. Gmail Account: You'll need a Gmail account to send emails.
  2. Supabase Account: You can sign up here.
  3. Deno Environment: In case you would like to run Deno function locally without local installation of Supabase. You can download Deno from Deno's official website.

Step 1: Set Up Your Gmail Account

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:

  1. Sign in to your Gmail account and go to your Google Account settings.
  2. Navigate to the "Security" tab.
  3. Scroll down to the "Less secure app access" section.
  4. Click on "Turn on access".
  5. Toggle the switch to "ON" to allow less secure apps to access your Gmail account.

send email

Step 2: Create Supabase edge function

  1. Install supabase-cli locally.

  2. Create a new Supabase integration in a project folder on your local machine.

    supabase init
  3. Create a new Edge Function called "send-email-from-gmail" inside your project.

    supabase functions new send-email-from-gmail
  4. 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.

  5. Add following env variables with your own values which are used by Deno runtime in the code above

  6. Running Edge Functions

    • Locally from IDE

      • Follow this setup guide to integrate the Deno language server with your editor and run deno function from IDE.
    • Locally with supabase docker-compose

      • supabase starts //start the supabase stack
      • supabase functions serve // start the Functions watcher
      • invoke local function using curl
      curl --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)

      • deploy supabase function supabase functions deploy send-email-from-gmail
      • invoking remote functions
      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

Supabase Edge function
send email using Deno
send email from the Gmail
send email using denomailer