diff --git a/.gitignore b/.gitignore
index 0127b16..521d3c8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,6 +56,7 @@ fastlane/screenshots
jest_*
dist
+.env
.envrc
.graphcoolrc
diff --git a/messaging/ses/README.md b/messaging/ses/README.md
new file mode 100644
index 0000000..c8f08c5
--- /dev/null
+++ b/messaging/ses/README.md
@@ -0,0 +1,93 @@
+# ses
+
+Send emails with AWS SES in your Graphcool project 🎁
+
+## Getting Started
+
+### 1. Add the template to your Graphcool service
+
+```sh
+graphcool add-template graphcool/templates/messaging/ses
+```
+
+### 2. Uncomment lines in `graphcool.yml` and `types.graphql`
+
+The [`add-template`](https://docs-next.graph.cool/reference/graphcool-cli/commands-aiteerae6l#graphcool-add-template) command is performing three major steps:
+
+1. Download the source files from the [`src`](./src) directory and put them into your service's `src` directory (into a subdirectory called `ses`).
+2. Download the contents from [`graphcool.yml`](./graphcool.yml) and append them as comments to your service's `graphcool.yml`.
+3. Download the contents from [`types.graphql`](./types.graphql) and append them as comments to your service's `types.graphql`.
+
+In order for the changes to take effect, you need to manually uncomment all the lines that have been added by the `add-template` command.
+
+### 3. Setup AWS SES credentials
+
+You need to configure these credentials as environment variables:
+
+In your base project, you need to configure the following **environment variables**.
+
+- `ACCESS_KEY_ID`: AWS Access Key ID
+- `SECRET_ACCESS_KEY`: AWS Secret Access Key
+- `REGION`: AWS Region (example: us-west-2)
+
+You can read more about managing your Access Keys [in the AWS docs](https://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html). Note: You'll need to create an account.
+
+An easy way to setup environment variables is using [direnv](https://direnv.net/).
+To use `direnv`, put the following into `.envrc` in you project root:
+
+```sh
+export ACCESS_KEY_ID=xxx
+export SECRET_ACCESS_KEY=xxx
+export REGION=xxx
+```
+
+### 4. Deploy the service
+
+Finally, you need to install the [node dependencies](./package.json#L2) and apply all the changes you just made by deploying the service:
+
+```sh
+npm install
+graphcool deploy
+```
+
+## Test the Code
+
+Use the `sendSesEmail` mutation to send emails according to its parameters:
+
+* `from: String!`: sender email
+* `to: [String!]!`: a list of recipient emails
+* `subject: String!`: the email subject
+* `text: String!`: the text body of the email
+* `html: String!`: the html body of the email
+
+**Important Note:** You can only use verified emails to send and receive. You can learn more [from the AWS docs](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-email-addresses.html)
+
+Go to the Graphcool Playground:
+
+```sh
+graphcool playground
+```
+
+Hook into the function logs:
+
+```sh
+graphcool logs -f sendEmail --tail
+```
+
+Run this mutation to send a new email:
+
+```graphql
+mutation {
+ sendSesEmail(
+ from: "__SENDER_EMAIL__"
+ to: "__RECIPIENT_EMAIL__"
+ subject: "A new email from the Graphcool SES template!"
+ html: "This is your first email from the Graphcool SES template!"
+ text: "This is your first email from the Graphcool SES template!"
+ ) {
+ success
+ }
+}
+```
+
+
diff --git a/messaging/ses/graphcool.yml b/messaging/ses/graphcool.yml
new file mode 100644
index 0000000..7eb2080
--- /dev/null
+++ b/messaging/ses/graphcool.yml
@@ -0,0 +1,13 @@
+types: ./types.graphql
+
+functions:
+ sendEmail:
+ handler:
+ code:
+ src: src/sendEmail.ts
+ environment:
+ ACCESS_KEY_ID: ${env:ACCESS_KEY_ID}
+ SECRET_ACCESS_KEY: ${env:SECRET_ACCESS_KEY}
+ REGION: ${env:REGION}
+ type: resolver
+ schema: src/sendEmail.graphql
diff --git a/messaging/ses/package.json b/messaging/ses/package.json
new file mode 100644
index 0000000..f23bc34
--- /dev/null
+++ b/messaging/ses/package.json
@@ -0,0 +1,9 @@
+{
+ "dependencies": {
+ "aws-sdk": "^2.135.0",
+ "graphcool-lib": "^0.1.3"
+ },
+ "devDependencies": {
+ "@types/node": "^8.0.45"
+ }
+}
diff --git a/messaging/ses/src/sendEmail.graphql b/messaging/ses/src/sendEmail.graphql
new file mode 100644
index 0000000..add4e29
--- /dev/null
+++ b/messaging/ses/src/sendEmail.graphql
@@ -0,0 +1,13 @@
+type SesEmailPayload {
+ success: Boolean!
+}
+
+extend type Mutation {
+ sendSesEmail(
+ from: String!
+ to: [String!]!
+ subject: String!
+ text: String!
+ html: String!
+ ): SesEmailPayload!
+}
\ No newline at end of file
diff --git a/messaging/ses/src/sendEmail.ts b/messaging/ses/src/sendEmail.ts
new file mode 100644
index 0000000..e37432f
--- /dev/null
+++ b/messaging/ses/src/sendEmail.ts
@@ -0,0 +1,83 @@
+import * as aws from 'aws-sdk'
+import { FunctionEvent } from 'graphcool-lib'
+
+const ses = new aws.SES({
+ region: process.env.REGION,
+ accessKeyId: process.env.ACCESS_KEY_ID,
+ secretAccessKey: process.env.SECRET_ACCESS_KEY,
+})
+
+
+interface EventData {
+ from: string
+ to: [string]
+ subject: string
+ text: string
+ html: string
+}
+
+export default async (event: FunctionEvent) => {
+ console.log(event)
+
+ console.log(process.env)
+
+ if (!process.env['ACCESS_KEY_ID']) {
+ console.log('Please provide a valid AWS Access Key ID!')
+ return { error: 'Module not configured correctly.' }
+ }
+
+ if (!process.env['SECRET_ACCESS_KEY']) {
+ console.log('Please provide a valid AWS Secret Access Key!')
+ return { error: 'Module not configured correctly.' }
+ }
+
+ if (!process.env['REGION']) {
+ console.log(`Please provide a valid AWS region, for example 'us-east-2'!`)
+ return { error: 'Module not configured correctly.' }
+ }
+
+ try {
+
+ const { to, from, subject, text, html } = event.data
+
+ const params = {
+ Destination: {
+ ToAddresses: to
+ },
+ Message: {
+ Body: {
+ Html: {
+ Charset: 'UTF-8',
+ Data: html
+ },
+ Text: {
+ Charset: 'UTF-8',
+ Data: text
+ },
+ },
+ Subject: {
+ Charset: 'UTF-8',
+ Data: subject
+ }
+ },
+ ReturnPath: from,
+ Source: from
+ }
+
+ await new Promise((resolve, reject) => {
+ ses.sendEmail(params, (err) => {
+ if (err) {
+ throw new Error(JSON.stringify(err))
+ } else {
+ resolve({})
+ }
+ })
+ })
+
+ return { data: { success: true } }
+ } catch(e) {
+ console.log(`Email could not be sent because an error occured:`)
+ console.log(e)
+ return { error: 'An unexpected error occured while sending email.' }
+ }
+}
diff --git a/messaging/ses/types.graphql b/messaging/ses/types.graphql
new file mode 100644
index 0000000..e69de29