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:
- Basic understanding of Dart and Flutter
- Flutter SDK installed
- Appwrite CLI installed
- Xcode with a developer account (for Mac users)
- Either IOS Simulator, Android Studio, or Chrome web browser to run our application
- An Appwrite instance; check out this article on how to set up an instance locally or one-click install on DigitalOcean or Gitpod
- A SendGrid account; signup for a trial account is completely free
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.
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.
Input appwrite_sendgrid
as the API Key Name and click the Create & View button.
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:
//remaining env variable goes here
_APP_FUNCTIONS_RUNTIMES=node-16.0,php-8.0,python-3.9,ruby-3.0,dart-2.17
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
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
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
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
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>
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
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>
The command will create a starter Dart 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
We also need to install the specified dependency by running the command below:
cd functions/appwrite_sendgrid/
dart pub get
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",
});
}
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
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.
We can also confirm the deployment by navigating to the Function tab on the Appwrite console,
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.
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
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
Then, run the project using the command below:
flutter run
The command above will run the application on the selected device.
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 |
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.
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
.
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.
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.
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>
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};
}
}
With that done, we restart the application using the code editor or run the command below:
flutter run
https://media.giphy.com/media/e77IjfyDqwLzKbW0rW/giphy.gif
We can validate the sent email by checking Appwrite Function log and SendGrid activity tab
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: