Skip to content

Commit 81241ab

Browse files
authored
feat(functions): add tem example (#87)
* feat(functions): add tem example * fix: review changes * fix: review changes
1 parent e293672 commit 81241ab

File tree

4 files changed

+163
-1
lines changed

4 files changed

+163
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Table of Contents:
3030
<!-- markdownlint-disable MD033 -->
3131

3232
| Example | Runtime | Deployment |
33-
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ---------------------- |
33+
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| --------- | ---------------------- |
3434
| **[Badge PHP](functions/badge-php/README.md)** <br/> A PHP function to generate repository badges. | php82 | [Serverless Framework] |
3535
| **[CORS Go](functions/cors-go/README.md)** <br/> A Go function which allows CORS requests. | go119 | [Serverless Framework] |
3636
| **[CORS Node](functions/cors-node/README.md)** <br/> A Node function which allows CORS requests. | node18 | [Serverless Framework] |
@@ -49,6 +49,7 @@ Table of Contents:
4949
| **[Python MultiPart Upload to S3](functions/python-upload-file-s3-multipart/README.md)** <br/> A function to upload file from form-data to S3. | python311 | [Python API Framework] |
5050
| **[Python SQS Trigger Hello World](functions/python-sqs-trigger-hello-world/README.md)** <br/> Trigger a function by sending a message to a SQS queue. | python311 | [Terraform] |
5151
| **[Python SQS Trigger Async Worker](functions/python-sqs-trigger-async-worker/README.md)** <br/> Use SQS queues and function triggers to scheule an async task from another function. | python311 | [Terraform] |
52+
| **[Python TEM SMTP Server](functions/python-tem-smtp-server/README.md)** <br/> Send Transactional Emails from a serverless function. | python311 | [Terraform] |
5253
| **[Redis TLS](functions/redis-tls/README.md)** <br/> How to connect a function to a Scaleway Redis cluster with TLS enabled. | python310 | [Terraform] |
5354
| **[Rust MNIST](functions/rust-mnist/README.md)** <br/> A Rust function to recognize hand-written digits with a simple neural network. | rust165 | [Serverless Framework] |
5455
| **[PostgreSQL Python](functions/postgre-sql-python/README.md)** <br/> A Python function to perform a query on a PostgreSQL managed database. | python310 | [Serverless Framework] |
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Send Transactional Emails from a Serverless Function
2+
3+
This example demonstrates how to send TEM with an SMTP server from Python functions.
4+
5+
It assumes that you are familiar with how Serverless Functions and Scaleway Transactional Email work.
6+
If needed, you can check the Scaleway official documentation for serverless functions [here](https://www.scaleway.com/en/docs/serverless/functions/quickstart/)
7+
and for TEM [here](https://www.scaleway.com/en/docs/managed-services/transactional-email/quickstart/).
8+
9+
## Requirements
10+
11+
* You have generated an API key with the permission `TransactionalEmailFullAccess`
12+
* You have [Python](https://www.python.org/) installed on your machine
13+
* You have [Terraform](https://registry.terraform.io/providers/scaleway/scaleway/latest/docs) installed on your machine
14+
15+
## Setup
16+
17+
You have to configure your domain with Transactional Email (tutorial available [here](https://www.scaleway.com/en/docs/managed-services/transactional-email/quickstart/))
18+
19+
Then, edit the file `handler.py` to set the sender and the recipient of the email.
20+
21+
Also, depending on your SMTP server, you might also need to change the value of the variables `host` and `port`.
22+
23+
## Testing with serverless offline for Python
24+
25+
In order to test your function locally before the deployment, you can install our offline testing library with:
26+
27+
```bash
28+
pip install scaleway_functions_python==0.2.0
29+
```
30+
31+
Export your environment variables and then launch your function locally:
32+
```bash
33+
export TEM_PROJECT_ID=<the Project ID of the Project in which the TEM domain was created>
34+
export SECRET_KEY=<the secret key of the API key of the project used to manage your TEM domain>
35+
36+
python handler.py
37+
```
38+
39+
Test your local function using `curl`:
40+
41+
```bash
42+
curl http://localhost:8080
43+
```
44+
45+
This should email the recipient defined in `handler.py`.
46+
47+
## Deploy
48+
49+
Use the Terraform configuration to deploy the function.
50+
51+
```shell
52+
terraform init
53+
terraform apply -var "scw_project_id=$TEM_PROJECT_ID" -var "scw_secret_key=$SECRET_KEY"
54+
```
55+
56+
## Call the function
57+
58+
When the deployment is complete, you can check the deployment succeeded either by:
59+
60+
i) curl the container's endpoint with:
61+
```sh
62+
curl $(terraform output -raw endpoint)
63+
```
64+
ii) hit it from a browser.
65+
66+
Doing so will send an e-mail to the recipient defined in the file `handler.py`.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import os
2+
import logging
3+
import smtplib
4+
from email.mime.text import MIMEText
5+
6+
7+
def handle(event, context):
8+
9+
# SMTP configuration, see https://www.scaleway.com/en/docs/managed-services/transactional-email/reference-content/smtp-configuration/ for more info
10+
11+
host = "smtp.tem.scw.cloud" # The domain name or IP address of the SMTP server. If you are using Scaleway TEM, the domain to use is smtp.tem.scw.cloud
12+
port = 465
13+
14+
# Your Scaleway SMTP username is the Project ID of the Project in which the TEM domain was created
15+
login = os.environ.get("TEM_PROJECT_ID")
16+
# Your password is the secret key of the API key of the project used to manage your TEM domain
17+
password = os.environ.get("SECRET_KEY")
18+
19+
# the email address that will appear as the sender
20+
sender_email = "[email protected]"
21+
# the email address to send the email to
22+
receiver_email = "[email protected]"
23+
24+
message = MIMEText(
25+
"You've successfully sent an email from Serverless Functions!", "plain"
26+
)
27+
message["Subject"] = "Congratulations"
28+
message["From"] = sender_email
29+
message["To"] = receiver_email
30+
31+
try:
32+
with smtplib.SMTP_SSL(host, port) as server:
33+
server.login(login, password)
34+
server.sendmail(sender_email, receiver_email, message.as_string())
35+
except Exception as e:
36+
logging.error("Failed to send email: %s", e)
37+
38+
39+
if __name__ == "__main__":
40+
from scaleway_functions_python import local
41+
42+
local.serve_handler(handle)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
terraform {
2+
required_providers {
3+
scaleway = {
4+
source = "scaleway/scaleway"
5+
version = ">= 2.40"
6+
}
7+
archive = {
8+
source = "hashicorp/archive"
9+
version = ">= 2.4"
10+
}
11+
}
12+
required_version = ">= 1.0"
13+
}
14+
15+
variable "scw_project_id" {
16+
type = string
17+
}
18+
19+
variable "scw_secret_key" {
20+
type = string
21+
sensitive = true
22+
}
23+
24+
data "archive_file" "function" {
25+
type = "zip"
26+
source_file = "${path.module}/handler.py"
27+
output_path = "${path.module}/function.zip"
28+
}
29+
30+
resource "scaleway_function_namespace" "main" {
31+
name = "serverless-with-tem-example"
32+
description = "Serverless with TEM example"
33+
}
34+
35+
resource "scaleway_function" "main" {
36+
namespace_id = scaleway_function_namespace.main.id
37+
name = "python-tem-smtp-server"
38+
runtime = "python311"
39+
handler = "handler.handle"
40+
privacy = "public"
41+
zip_file = data.archive_file.function.output_path
42+
zip_hash = data.archive_file.function.output_sha256
43+
deploy = true
44+
45+
secret_environment_variables = {
46+
TEM_PROJECT_ID = var.scw_project_id
47+
SECRET_KEY = var.scw_secret_key
48+
}
49+
}
50+
51+
output "endpoint" {
52+
value = scaleway_function.main.domain_name
53+
}

0 commit comments

Comments
 (0)