├── db └── .gitkeep ├── .jetskeep ├── Rakefile ├── .ruby-version ├── .rspec ├── app ├── models │ ├── application_item.rb │ └── application_record.rb ├── helpers │ └── application_helper.rb ├── controllers │ ├── application_controller.rb │ └── emails_controller.rb └── jobs │ └── application_job.rb ├── public ├── favicon.ico ├── 500.html ├── 422.html ├── 404.html └── index.html ├── config.ru ├── .gitignore ├── config ├── environments │ ├── development.rb │ ├── test.rb │ └── production.rb ├── routes.rb ├── database.yml ├── dynamodb.yml └── application.rb ├── Procfile ├── spec ├── controllers │ └── posts_controller_spec.rb ├── spec_helper.rb └── fixtures │ └── payloads │ ├── posts-index.json │ └── posts-show.json ├── Gemfile ├── README.md └── Gemfile.lock /db/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.jetskeep: -------------------------------------------------------------------------------- 1 | pack 2 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'jets' 2 | Jets.load_tasks 3 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.5.1@serverless-ruby-simple-email 2 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format documentation 3 | --require spec_helper 4 | -------------------------------------------------------------------------------- /app/models/application_item.rb: -------------------------------------------------------------------------------- 1 | class ApplicationItem < Dynomite::Item 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ApplicationHelper 4 | end 5 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | self.abstract_class = true 3 | end 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SystangoTechnologies/serverless-ruby-simple-email/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationController < Jets::Controller::Base 4 | end 5 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require "jets" 4 | Jets.boot 5 | run Jets.application 6 | -------------------------------------------------------------------------------- /app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < Jets::Job::Base 2 | # Adjust to increase the default timeout for all Job classes 3 | class_timeout 60 4 | end 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .bundle 3 | .byebug_history 4 | .DS_Store 5 | .env* 6 | /node_modules 7 | /public/packs 8 | /public/packs-test 9 | bundled 10 | coverage 11 | pkg 12 | tmp 13 | .rubocop.yml 14 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Jets.application.configure do 2 | # Example: 3 | # config.function.memory_size = 1536 4 | 5 | # config.action_mailer.raise_delivery_errors = false 6 | # Docs: http://rubyonjets.com/docs/email-sending/ 7 | end 8 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | local: dynamodb-local # port 8000 2 | admin: env AWS_ACCESS_KEY_ID=$DYNAMODB_ADMIN_AWS_ACCESS_KEY_ID PORT=8001 dynamodb-admin # port 8001 3 | # web: jets server # port 8888 4 | 5 | # Using Procfile to just start local dynamodb services for now. 6 | # To start jets server for now use: 7 | # jets server 8 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Jets.application.configure do 2 | # Tell Action Mailer not to deliver emails to the real world. 3 | # The :test delivery method accumulates sent emails in the 4 | # ActionMailer::Base.deliveries array. 5 | # Docs: http://rubyonjets.com/docs/email-sending/ 6 | config.action_mailer.delivery_method = :test 7 | end 8 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | Jets.application.configure do 2 | # Example: 3 | # config.function.memory_size = 2048 4 | 5 | # Ignore bad email addresses and do not raise email delivery errors. 6 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 7 | # Docs: http://rubyonjets.com/docs/email-sending/ 8 | # config.action_mailer.raise_delivery_errors = false 9 | end 10 | -------------------------------------------------------------------------------- /spec/controllers/posts_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # Example: 2 | # describe PostsController, type: :controller do 3 | # it "index returns a success response" do 4 | # get '/posts' 5 | # expect(response.status).to eq 200 6 | # pp response.body 7 | # end 8 | # 9 | # it "show returns a success response" do 10 | # Post.create(id: 1) unless Post.find_by(id: 1) # TODO: set up factory_bot 11 | # get '/posts/:id', id: 1 12 | # expect(response.status).to eq 200 13 | # pp response.body 14 | # end 15 | # end 16 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Jets.application.routes.draw do 4 | root 'jets/public#show' 5 | post 'email', to: 'emails#send_email' 6 | # The jets/public#show controller can serve static utf8 content out of the public folder. 7 | # Note, as part of the deploy process Jets uploads files in the public folder to s3 8 | # and serves them out of s3 directly. S3 is well suited to serve static assets. 9 | # More info here: http://rubyonjets.com/docs/assets-serving/ 10 | any '*catchall', to: 'jets/public#show' 11 | end 12 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | gem 'aws-ses' 6 | gem 'dynomite' 7 | gem 'jets' 8 | # Include mysql2 gem if you are using ActiveRecord, remove if you are not 9 | gem 'mysql2', '~> 0.5.2' 10 | 11 | group :development, :test do 12 | gem 'byebug', platforms: %i[mri mingw x64_mingw] 13 | gem 'pry' 14 | gem 'rack' 15 | gem 'rubocop', require: false 16 | gem 'rubocop-performance' 17 | gem 'shotgun' 18 | end 19 | 20 | group :test do 21 | gem 'capybara' 22 | gem 'launchy' 23 | gem 'rspec' 24 | end 25 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | ENV["TEST"] = "1" 2 | ENV["JETS_ENV"] ||= "test" 3 | # Ensures aws api never called. Fixture home folder does not contain ~/.aws/credentails 4 | ENV['HOME'] = "spec/fixtures/home" 5 | 6 | require "byebug" 7 | require "fileutils" 8 | require "jets" 9 | 10 | abort("The Jets environment is running in production mode!") if Jets.env == "production" 11 | Jets.boot 12 | 13 | require "jets/spec_helpers" 14 | 15 | 16 | 17 | module Helpers 18 | def payload(name) 19 | JSON.load(IO.read("spec/fixtures/payloads/#{name}.json")) 20 | end 21 | end 22 | 23 | RSpec.configure do |c| 24 | c.include Helpers 25 | end 26 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | default: &default 2 | adapter: mysql2 3 | encoding: utf8 4 | pool: <%= ENV["DB_POOL"] || 5 %> 5 | database: <%= ENV['DB_NAME'] || 'serverless-ruby-simple-email-service_development' %> 6 | username: <%= ENV['DB_USER'] || 'root' %> 7 | password: <%= ENV['DB_PASS'] %> 8 | host: <%= ENV["DB_HOST"] %> 9 | url: <%= ENV['DATABASE_URL'] %> # takes higher precedence than other settings 10 | 11 | development: 12 | <<: *default 13 | database: <%= ENV['DB_NAME'] || 'serverless-ruby-simple-email-service_development' %> 14 | 15 | test: 16 | <<: *default 17 | database: serverless-ruby-simple-email-service_test 18 | 19 | production: 20 | <<: *default 21 | database: serverless-ruby-simple-email-service_production 22 | url: <%= ENV['DATABASE_URL'] %> 23 | -------------------------------------------------------------------------------- /config/dynamodb.yml: -------------------------------------------------------------------------------- 1 | # Jets::Config.project_namespace is special value results in using the project namespace. Example : 2 | # table_namespace: <%= Jets.config.project_namespace %> 3 | # This is the default value. 4 | 5 | development: 6 | table_namespace: <%= Jets.config.table_namespace %> 7 | # More examples: 8 | # table_namespace: demo-dev 9 | 10 | endpoint: http://localhost:8000 # comment out if want to test with real dynamodb 11 | # on AWS. You can also set the DYNAMODB_ENDPOINT environment variable. 12 | # You can also are actually deploying a development environment is to 13 | # change bin/server and export DYNAMODB_ENDPOINT=http://localhost:8000 at the top 14 | # there. 15 | 16 | test: 17 | # table_namespace: proj # do not include the env 18 | endpoint: http://localhost:8000 19 | table_namespace: <%= Jets.config.table_namespace %> 20 | 21 | production: 22 | table_namespace: <%= Jets.config.table_namespace %> 23 | -------------------------------------------------------------------------------- /app/controllers/emails_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class EmailsController < ApplicationController 4 | before_action :check_from 5 | before_action :check_recipients 6 | before_action :check_subject 7 | before_action :check_body 8 | before_action :initialize_ses 9 | 10 | def send_email 11 | @ses.send_email(email_configurations) 12 | render json: { message: 'Email sent!' }, status: 201 13 | rescue Aws::SES::Errors::ServiceError => e 14 | render json: { message: e }, status: 422 15 | end 16 | 17 | private 18 | 19 | def check_from 20 | return if params[:from].present? 21 | 22 | render json: { message: 'Please pass the from value' }, status: 400 23 | end 24 | 25 | def check_recipients 26 | return if params[:to].present? 27 | 28 | render json: { message: 'Please pass the recipients value' }, status: 400 29 | end 30 | 31 | def check_subject 32 | return if params[:subject].present? 33 | 34 | render json: { message: 'Please pass the subject value' }, status: 400 35 | end 36 | 37 | def check_body 38 | return if params[:textBody].present? || params[:htmlBody].present? 39 | 40 | render json: { message: 'Please pass the body value' }, status: 400 41 | end 42 | 43 | def initialize_ses 44 | @ses = AWS::SES::Base.new(region: ENV['REGION'], 45 | access_key_id: ENV['ACCESS_KEY_ID'], 46 | secret_access_key: ENV['SECRET_ACCESS_KEY']) 47 | end 48 | 49 | def email_configurations 50 | { 51 | from: params[:from], 52 | to: params[:to], 53 | cc: params[:cc], 54 | bcc: params[:bcc], 55 | subject: params[:subject], 56 | text_body: params[:textBody], 57 | html_body: params[:htmlBody] 58 | } 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /spec/fixtures/payloads/posts-index.json: -------------------------------------------------------------------------------- 1 | { 2 | "resource": "/posts", 3 | "path": "/posts", 4 | "httpMethod": "GET", 5 | "headers": { 6 | "Accept": "*/*", 7 | "CloudFront-Forwarded-Proto": "https", 8 | "CloudFront-Is-Desktop-Viewer": "true", 9 | "CloudFront-Is-Mobile-Viewer": "false", 10 | "CloudFront-Is-SmartTV-Viewer": "false", 11 | "CloudFront-Is-Tablet-Viewer": "false", 12 | "CloudFront-Viewer-Country": "US", 13 | "Host": "qg45s7uvg2.execute-api.us-east-1.amazonaws.com", 14 | "User-Agent": "curl/7.54.0", 15 | "Via": "1.1 3d3d633d266d05d90a4eea7a6a59b514.cloudfront.net (CloudFront)", 16 | "X-Amz-Cf-Id": "4mAgowukJJbA7lgTWITzgOPmdiDsXPCwy6vonS8VKPXCdEsmldVgdg==", 17 | "X-Amzn-Trace-Id": "Root=1-59fb8ea5-38c5ad176dac130f3eb9ce97", 18 | "X-Forwarded-For": "69.42.1.180, 54.239.203.118", 19 | "X-Forwarded-Port": "443", 20 | "X-Forwarded-Proto": "https" 21 | }, 22 | "queryStringParameters": null, 23 | "pathParameters": null, 24 | "stageVariables": null, 25 | "requestContext": { 26 | "path": "/prod/posts", 27 | "accountId": "123456789012", 28 | "resourceId": "ery965", 29 | "stage": "prod", 30 | "requestId": "292fbcc8-c015-11e7-94fa-cd109b693f3c", 31 | "identity": { 32 | "cognitoIdentityPoolId": null, 33 | "accountId": null, 34 | "cognitoIdentityId": null, 35 | "caller": null, 36 | "apiKey": "", 37 | "sourceIp": "69.42.1.180", 38 | "accessKey": null, 39 | "cognitoAuthenticationType": null, 40 | "cognitoAuthenticationProvider": null, 41 | "userArn": null, 42 | "userAgent": "curl/7.54.0", 43 | "user": null 44 | }, 45 | "resourcePath": "/posts", 46 | "httpMethod": "GET", 47 | "apiId": "qg45s7uvg2" 48 | }, 49 | "body": null, 50 | "isBase64Encoded": false 51 | } 52 | -------------------------------------------------------------------------------- /spec/fixtures/payloads/posts-show.json: -------------------------------------------------------------------------------- 1 | { 2 | "resource": "/posts/{id}", 3 | "path": "/posts/tung", 4 | "httpMethod": "GET", 5 | "headers": { 6 | "Accept": "*/*", 7 | "CloudFront-Forwarded-Proto": "https", 8 | "CloudFront-Is-Desktop-Viewer": "true", 9 | "CloudFront-Is-Mobile-Viewer": "false", 10 | "CloudFront-Is-SmartTV-Viewer": "false", 11 | "CloudFront-Is-Tablet-Viewer": "false", 12 | "CloudFront-Viewer-Country": "US", 13 | "Host": "qg45s7uvg2.execute-api.us-east-1.amazonaws.com", 14 | "User-Agent": "curl/7.54.0", 15 | "Via": "1.1 dc553909528b8b63475c922dc07d8ba6.cloudfront.net (CloudFront)", 16 | "X-Amz-Cf-Id": "s9NB2f_Z1scd6ksA4fcXA2r4QhpSKQ6QcTLQHGfxDPfI-X7sXM3YLg==", 17 | "X-Amzn-Trace-Id": "Root=1-59fb8ecb-586ab81d73e36910793d767c", 18 | "X-Forwarded-For": "69.42.1.180, 54.239.203.97", 19 | "X-Forwarded-Port": "443", 20 | "X-Forwarded-Proto": "https" 21 | }, 22 | "queryStringParameters": null, 23 | "pathParameters": { 24 | "id": "tung" 25 | }, 26 | "stageVariables": null, 27 | "requestContext": { 28 | "path": "/prod/posts/tung", 29 | "accountId": "123456789012", 30 | "resourceId": "wf2gvu", 31 | "stage": "prod", 32 | "requestId": "3feafb4e-c015-11e7-85c9-194f38f4c414", 33 | "identity": { 34 | "cognitoIdentityPoolId": null, 35 | "accountId": null, 36 | "cognitoIdentityId": null, 37 | "caller": null, 38 | "apiKey": "", 39 | "sourceIp": "69.42.1.180", 40 | "accessKey": null, 41 | "cognitoAuthenticationType": null, 42 | "cognitoAuthenticationProvider": null, 43 | "userArn": null, 44 | "userAgent": "curl/7.54.0", 45 | "user": null 46 | }, 47 | "resourcePath": "/posts/{id}", 48 | "httpMethod": "GET", 49 | "apiId": "qg45s7uvg2" 50 | }, 51 | "body": null, 52 | "isBase64Encoded": false 53 | } 54 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |If you are the application owner check the logs for more information.
64 |Maybe you tried to change something you didn't have access to.
63 |If you are the application owner check the logs for more information.
65 |You may have mistyped the address or the page may have moved.
63 |If you are the application owner check the logs for more information.
65 |
69 | 73 | To get started: 74 |
75 |
76 | $ jets generate scaffold Post title:string
77 | $ jets db:create db:migrate
78 | $ jets server
79 | $ open http://localhost:8888/posts
80 | $ jets help
81 | More on info: rubyonjets.com
83 |Also check out the Jets CLI reference.
84 |
86 | Jets version: 1.8.9
87 | Ruby version: 2.5.3
88 |