Skip to content

Commit

Permalink
Add SES to templates/messaging (#118)
Browse files Browse the repository at this point in the history
* Add AWS SES to templates/messaging

* Clean up some code

* Remove some deps and general clean up

* Add Promise, remove a couple imports, and cleanup

* Refactor Promise to be correct syntax

* Remove name, version, & description from package.json

* Add readme to SES template

* Update readme for SES template

* Update readme for SES template

* clean up graphcool.yml

* clean up types, payload and fields

* clean up env vars

* clean up promise

* code style

* rehaul README
  • Loading branch information
Nilan Marktanner authored Nov 1, 2017
1 parent dfa6f1b commit 1f7588f
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ fastlane/screenshots
jest_*
dist

.env
.envrc
.graphcoolrc

Expand Down
93 changes: 93 additions & 0 deletions messaging/ses/README.md
Original file line number Diff line number Diff line change
@@ -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: "<b>This is your first email from the Graphcool SES template!</b>"
text: "This is your first email from the Graphcool SES template!"
) {
success
}
}
```

![](http://i.imgur.com/5RHR6Ku.png)
13 changes: 13 additions & 0 deletions messaging/ses/graphcool.yml
Original file line number Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions messaging/ses/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"dependencies": {
"aws-sdk": "^2.135.0",
"graphcool-lib": "^0.1.3"
},
"devDependencies": {
"@types/node": "^8.0.45"
}
}
13 changes: 13 additions & 0 deletions messaging/ses/src/sendEmail.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type SesEmailPayload {
success: Boolean!
}

extend type Mutation {
sendSesEmail(
from: String!
to: [String!]!
subject: String!
text: String!
html: String!
): SesEmailPayload!
}
83 changes: 83 additions & 0 deletions messaging/ses/src/sendEmail.ts
Original file line number Diff line number Diff line change
@@ -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<EventData>) => {
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.' }
}
}
Empty file added messaging/ses/types.graphql
Empty file.

0 comments on commit 1f7588f

Please sign in to comment.