How to trigger an email on database update in Flutter with SendGrid

Demola Malomo - Nov 24 '22 - - Dev Community

Email is a medium of communication used to send and receive electronic-based files like text documents, photos, videos, etc. Beyond the traditional use case, it has become an essential tool used by developers to monitor and communicate their applications' status.

In this post, we will learn how to use Appwrite Function and SendGrid to trigger an email when a database is updated in Flutter.

Technology overview

Appwrite Function is a service that lets us use Appwrite server functionality by executing a custom code using a language of choice like Node.js, Python, PHP, Dart, or Java.

SendGrid is a cloud-based email marketing tool developers and marketers use to manage mailing lists, A/B testing, predefined templates, and image libraries used in campaign management and audience engagement.

GitHub links

The project source codes are below:

Prerequisites

To follow along in this tutorial, the following requirements apply:

Set up SendGrid as an email provider

To get started, we need to log into our Sendgrid account and create a sender identity for sending emails. To do this, click the Create a Single Sender button and fill in the required details.

Click on single sender
Fill details

We will also be required to verify the email filled in as the sender's identity.

Next, we need to create an API Key to securely access our SendGrid account and send emails from a client. To do this, navigate to the API Key tab under the Settings menu and click the Create API Key button.

Create API Key

Input appwrite_sendgrid as the API Key Name and click the Create & View button.

Input detail and create

SendGrid will generate an API Key. We need to copy and keep the generated key, as it will come in handy when setting up our Appwrite function.

Integrate Appwrite Function with SendGrid

Enabling Dart runtime in Appwrite
By default, Dart is not included as part of the Appwrite runtime. To enable Dart as a supported runtime, we first need to navigate to the directory created when we installed Appwrite and edit the .env file by adding dart-2.17 as shown below:

Appwrite folder with .env file

//remaining env variable goes here

_APP_FUNCTIONS_RUNTIMES=node-16.0,php-8.0,python-3.9,ruby-3.0,dart-2.17
Enter fullscreen mode Exit fullscreen mode

Updated runtime with Dart support

Lastly, we need to sync the changes we made on the .env file with our Appwrite server. To do this, we must run the command below inside the appwrite directory.

docker compose up -d --force-recreate
Enter fullscreen mode Exit fullscreen mode

Create Appwrite project
With our Appwrite instance up and running, we can now create a project that our function will use to integrate SendGrid to send emails. To do this, we first need to navigate to the desired directory and run the command below:

mkdir appwrite_sendgrid && cd appwrite_sendgrid
Enter fullscreen mode Exit fullscreen mode

The command creates a project folder called appwrite_sendgrid and navigates into the folder.

Secondly, we need to log into the Appwrite server using the CLI.

appwrite login
Enter fullscreen mode Exit fullscreen mode

We will be prompted to input our email and password. We need to use the credentials we used to sign up to the Appwrite console.

Lastly, we need to create a new Appwrite project using the command below:

appwrite init project
Enter fullscreen mode Exit fullscreen mode

We will be prompted with some questions on how to set up our project, and we can answer as shown below:

How would you like to start? <select "Create a new project">
What would you like to name your project? <input "appwrite_sendgrid">
What ID would you like to have for your project? (unique()) <press enter>
Enter fullscreen mode Exit fullscreen mode

Create Appwrite Function inside the project
With our project setup, we can proceed to create a function by running the command below:

appwrite init function
Enter fullscreen mode Exit fullscreen mode

We will also be prompted with some questions about how to set up our function; we can answer as shown below:

What would you like to name your function? <input "appwrite_sendgrid">
What ID would you like to have for your function? (unique()) <press enter>
What runtime would you like to use? <scroll to dart-2.17 and press enter>
Enter fullscreen mode Exit fullscreen mode

The command will create a starter Dart project.

Starter project

Secondly, we need to install the required dependency by navigating to pubspec.yaml file and add SendGrid SDK to the dependencies section.

sendgrid_mailer: ^0.1.3
Enter fullscreen mode Exit fullscreen mode

Install dependency

We also need to install the specified dependency by running the command below:

cd functions/appwrite_sendgrid/
dart pub get
Enter fullscreen mode Exit fullscreen mode

Thirdly, we need to modify the main.dart file inside the lib folder as shown below:

import 'package:dart_appwrite/dart_appwrite.dart';
import 'package:sendgrid_mailer/sendgrid_mailer.dart';

Future<void> start(final req, final res) async {
  Client client = Client();

  final mailer = Mailer('SENDGRID API KEY');
  final toAddress = Address('SEND TO EMAIL');
  final fromAddress = Address('SENDER EMAIL CREATED ON SENDGRID');
  final content =
      Content('text/plain', 'Appwrite Database successfully updated');
  final subject = 'Database Update Alert!';
  final personalization = Personalization([toAddress]);

  final email =
      Email([personalization], fromAddress, subject, content: [content]);
  mailer.send(email).then((result) {
    print(result);
  }).catchError((onError) {
    print('error');
  });

  res.json({
    'data': "testing emails",
  });
}
Enter fullscreen mode Exit fullscreen mode

The snippet above does the following:

  • Imports the required dependencies
  • Configures SendGrid mail client by specifying the API Key, to emails, from emails, email content, and email subject
  • Sends the email using the configured client

Lastly, we need to navigate back to the project terminal and then deploy our function.

cd ../..
appwrite deploy function
Enter fullscreen mode Exit fullscreen mode

We will also be prompted to the functions to deploy. We can select the appwrite_sendgrid function by pressing the spacebar key to mark and the enter key to select it.

Sample of a deployed function

We can also confirm the deployment by navigating to the Function tab on the Appwrite console,

Deployed function

Add event support to Appwrite Function
Next, we need to add an event (database update) to our Appwrite Function. The event will trigger the function anytime the database is updated. To do this, navigate to the Settings tab, click the Add Event button, and select documents.update option, and click the Add Event. Then finally, click the Update button to save changes.

Click settings
Add Event
Update

Create a Flutter app

With our function deployed and listening for event changes on the database, we can now proceed to set up a Flutter project.

To get started, we need to clone the project by navigating to the desired directory and running the command below:

git clone https://github.com/Mr-Malomz/flutter_sendgrid.git && cd flutter_sendgrid
Enter fullscreen mode Exit fullscreen mode

The project logic to update a database and UI has already been set up. Below are some important files to note in the lib directory:

screens/home.dart: Contains the UI for updating a database.

utils: Contains Appwrite constants and Model. We will update this file shortly.

user_service.dart: Contains application logic for updating the database.

Running the project
First, we need to install the project dependencies by running the command below:

flutter pub get
Enter fullscreen mode Exit fullscreen mode

Then, run the project using the command below:

flutter run
Enter fullscreen mode Exit fullscreen mode

The command above will run the application on the selected device.

Running app

Create a Database and Add Sample Data
Next, we need to create a database with the corresponding collection, document, and add sample data as shown below:

Name
John Travolta

collection

Add Platform support
To add support for our Flutter app, navigate to the Home menu, click on the Add Platform button, and select New Flutter App.

Add platform
Select new Flutter app

Depending on the device on which we are running our Flutter application, we can modify it as shown below.

iOS
To obtain our Bundle ID, we can navigate using the path below:
ios > Runner.xcodeproj > project.pbxproj

Open the project.pbxproj file and search for PRODUCT_BUNDLE_IDENTIFIER.

iOS

Next, open the project directory on Xcode, open the Runner.xcworkspace folder in the app's iOS folder, select the Runner project in the Xcode project navigator, select the Runner target in the main menu sidebar, and then select iOS 11 in the deployment info’s target.

Change deployment target

Android
To get our package name, we can navigate to an XML file using the path below:
android > app > src > debug > AndroidManifest.xml

Open the AndroidManifest.xml file and copy the package value.

Android

Next, we need to modify the AndroidManifext.xml as shown below:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.real_time_comm">
    <uses-permission android:name="android.permission.INTERNET"/>
    <application ...>
    <activity android:name="com.linusu.flutter_web_auth.CallbackActivity" android:exported="true">
      <intent-filter android:label="flutter_web_auth">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="appwrite-callback-[PROJECT_ID]" />
      </intent-filter>
    </activity>
  </application>
</manifest>
Enter fullscreen mode Exit fullscreen mode

We also need to replace the highlighted [PROJECT_ID] with our actual Appwrite project ID.

Putting it all together
With that done, we need to navigate to the utils.dart file to add the required IDs and endpoint.

class AppConstant {
  final String databaseId = "DATABASE ID HERE";
  final String projectId = "PROEJCT ID HERE";
  final String collectionId = "COLLECTION ID";
  final String userId = "USER ID"; //this is the ID of the sample data created
  final String endpoint = "ENDPOINT";
}

class User {
  String name;

  User({required this.name});

  Map<dynamic, dynamic> toJson() {
    return {'name': name};
  }
}
Enter fullscreen mode Exit fullscreen mode

With that done, we restart the application using the code editor or run the command below:

flutter run
Enter fullscreen mode Exit fullscreen mode

https://media.giphy.com/media/e77IjfyDqwLzKbW0rW/giphy.gif

We can validate the sent email by checking Appwrite Function log and SendGrid activity tab

Appwrite log
SendGrid activity

Conclusion

This post discussed how to create and configure Appwrite Function to send emails using SendGrid when a database is updated. Appwrite Function allows developers to write and ship software in their language of choice.

These resources might be helpful:

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .