├── .gitignore ├── CHANGELOG.md ├── README.md ├── config.json ├── handler.js ├── package.json └── serverless.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # package directories 2 | node_modules 3 | jspm_packages 4 | 5 | # Serverless directories 6 | .serverless -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | ## [Unreleased] 6 | ### Added 7 | - This changelog 8 | - Deployment script for lamdbda function 9 | - automatically generate a config.json file 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lambda-Contact 2 | 3 | A simple aws-lambda function that allows you to have a contact form on your static website. (hosted on S3/Cloudfront) 4 | Currently, emails are sent via SES. 5 | 6 | I made this aws-lambda function in August 2015 for a startup I joined and in 2017 I modified it to use serverless. 7 | 8 | # Instructions 9 | 10 | 1. Install [serverless](https://serverless.com/) 11 | 2. Run `npm install` 12 | 3. Change the config.json file to match your 'from' to 'to'. 13 | 4. Run `serverless deploy` 14 | 5. Copy the URL from the output of the previous command and use it in your contact form. 15 | 16 | ## Exmaple Form 17 | ``` 18 |
25 | ``` 26 | 27 | # TODO 28 | 1. Add more robust spam protection 29 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | {"to":"to@yourdomain.com","from":"from@yourdomain.com","website":"https://www.cowholio5.com/"} 2 | -------------------------------------------------------------------------------- /handler.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var config = require('./config.json'), 3 | qs = require('qs'), 4 | nodemailer = require('nodemailer'), 5 | AWS = require('aws-sdk'), 6 | sesTransport = require('nodemailer-ses-transport'); 7 | var ses = new AWS.SES(); 8 | var transporter = nodemailer.createTransport(sesTransport({ ses: ses })); 9 | 10 | module.exports.contact = function(e, context, callback) { 11 | var referrer = config.website; 12 | 13 | const error_response = { 14 | statusCode: 500, 15 | body: 'Could not send message' 16 | }; 17 | const response = { 18 | statusCode: 301, 19 | headers: { 20 | 'Location': referrer + "?sent=true" 21 | }, 22 | body: 'Redirecting you back to ' + referrer 23 | } 24 | 25 | 26 | var body = qs.parse(e.body), 27 | required = [ "name", "message", "email" ], 28 | options = {}, 29 | i = null, 30 | r = null, 31 | text = null, 32 | on_done = null; 33 | // make sure we have all the needed fields 34 | for (i = 0; i < required.length; i += 1) { 35 | r = required[i]; 36 | if (!body.hasOwnProperty(r)) { 37 | console.log("missing data for " + r) 38 | return callback(null, error_response); 39 | } 40 | } 41 | 42 | text = "Name: " + body.name + "\n"; 43 | if (body.hasOwnProperty("affiliation") && body.affiliation.length > 0) { 44 | text += "Affiliation: " + body.affiliation + "\n"; 45 | } 46 | text += "Email: " + body.email + "\n"; 47 | text += "Source IP: " + e.requestContext.identity.sourceIp + "\n"; 48 | text += "User Agent: " + e.requestContext.identity.userAgent + "\n"; 49 | text += "\n\n\n"; 50 | text += body.message; 51 | 52 | options = { 53 | from: config.from, 54 | to: config.to, 55 | replyTo: body.email, 56 | subject: 'Contact Form [' + body.name + ']', 57 | text: text 58 | }; 59 | on_done = function (error, info) { 60 | if (error) { 61 | console.log(error) 62 | return callback(null, error_response); 63 | } 64 | console.log(info); 65 | callback(null, response); 66 | }; 67 | r = transporter.sendMail(options, on_done); 68 | }; 69 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lamdba-contact-form", 3 | "repository": { 4 | "type": "git", 5 | "url": "git://github.com/cowholio4/lambda-contact-form.git" 6 | }, 7 | "dependencies": { 8 | "aws-sdk" : "^2.60.0", 9 | "nodemailer": "^4.0.1", 10 | "nodemailer-ses-transport": "^1.5.1", 11 | "qs" : "^6.4.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /serverless.yml: -------------------------------------------------------------------------------- 1 | # Welcome to serverless. Read the docs 2 | # https://serverless.com/framework/docs/ 3 | 4 | # Serverless.yml is the configuration the CLI 5 | # uses to deploy your code to your provider of choice 6 | 7 | # The `service` block is the name of the service 8 | service: serverless-contact-form 9 | 10 | # The `provider` block defines where your service will be deployed 11 | provider: 12 | name: aws 13 | region: us-west-2 14 | runtime: nodejs6.10 15 | iamRoleStatements: 16 | - Effect: "Allow" 17 | Action: 18 | - "ses:SendEmail" 19 | - "ses:SendRawEmail" 20 | Resource: "*" 21 | 22 | # The `functions` block defines what code to deploy 23 | functions: 24 | contact: 25 | handler: handler.contact 26 | # The `events` block defines how to trigger the handler.helloWorld code 27 | events: 28 | - http: 29 | path: contact 30 | method: post 31 | cors: true 32 | --------------------------------------------------------------------------------