Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
cwise committed Feb 19, 2019
0 parents commit 284a38d
Show file tree
Hide file tree
Showing 12 changed files with 520 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
source 'https://rubygems.org'

group :test do
gem 'rspec'
gem 'faastruby-rpc'
gem 'faastruby'
end
21 changes: 21 additions & 0 deletions LICENCE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2019 FaaStRuby

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# faastruby-sendgrid-ruby-template
Use this template to handle SendGrid inbound parse webhooks
https://sendgrid.com/docs/ui/account-and-settings/inbound-parse/

## Getting started
### Prerequisites
* [FaaStRuby](https://faastruby.io) version 0.4.16 or higher.
```
# To install
~$ gem install faastruby
# To update
~$ gem update faastruby
```
### How to deploy this function
```
~$ cd FUNCTION_FOLDER
~/FUNCTION_FOLDER$ faastruby deploy-to WORKSPACE_NAME
```
### How to use this function as a template
```
~$ faastruby new FUNCTION_NAME --template github:cwise/faastruby-sendgrid-ruby-template
```
## SendGridInbound
The message is parsed for processing including extraction of mail headers and body.
7 changes: 7 additions & 0 deletions faastruby.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
cli_version: 0.4.16
name: sendgrid-ruby-template
runtime: ruby:2.5.3
test_command: rspec
abort_build_when_tests_fail: true
abort_deploy_when_tests_fail: true
32 changes: 32 additions & 0 deletions handler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require 'send_grid_inbound'

# To deploy this function, cd into its folder and run:
# faastruby deploy-to WORKSPACE_NAME
def handler event
# The 'event' argument has the following attributes
# event.body - The request body
# event.context - The execution context
# event.headers - The request headers
# event.query_params - The query params

# FUNCTION RESPONSE
#
# You can render text, json, yaml, html or js. Example:
# render html: '<p>Hello World!</p>'
# render yaml: {hello: 'world!'}
#
# Status:
# The default status is 200. You can set a custom status like this:
# render json: {error: 'Could not perform the action'}, status: 422
#
# Headers:
# The 'Content-Type' header is automatically set when you use 'render'.
# You can set custom headers using a hash with string keys. Example:
# render text: 'It Works!', headers: {'TransactionId' => 23928}

# parse the payload from SendGrid and handle the message
inbound = SendGridInbound.new(event)


render text: "Hello, World!\n"
end
99 changes: 99 additions & 0 deletions send_grid_inbound.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
class SendGridInbound
attr_reader :content_type
attr_reader :content_length
attr_reader :boundary
attr_reader :parts
attr_reader :raw_headers
attr_reader :sendgrid_headers
attr_reader :mail_headers

MSG_ID_REGEX = /<([a-z\-\d_]+)@[a-z\d.]+>/i

def initialize event
@content_type = event.headers['Content-Type']
@content_length = event.headers['Content-Length']

# ensure this is multi-part/form-data from Sendgrid
@boundary = ""
matches = /%r|\A(multipart\/.*)boundary=\"?([^\";,]+)\"?|ni/.match(content_type)
if matches
@content_type_detail = matches[1].strip
@boundary = matches[2]
end

body = event.body

# parse SendGrid headers
@parts = body.split("--"+@boundary)
@sendgrid_headers = {}
@parts.each do |part|
matches = /Content-Disposition: form-data; name="([a-zA-z]+)"\r\n\r\n(.+)/m.match(part)
if matches
key = matches[1]
value = matches[2].strip
@sendgrid_headers[key] = value
end
end

# parse mail_headers
@raw_headers = @sendgrid_headers['headers']
@mail_headers = {}
unless @raw_headers.nil?
@raw_headers.split("\n").each do |header|
matches = /([a-zA-Z-]+):\s(.+)/.match(header)

unless matches.nil?
key = matches[1]
value = matches[2].strip

# see if there is a value otherwise add
unless @mail_headers.keys.include?(key)
@mail_headers[key] = value
else
current = @mail_headers[key]
if current.is_a?(String)
# convert to an array
@mail_headers[key] = [] << current << value
else
@mail_headers[key] << value
end
end
end
end
end
end

def sender
@sendgrid_headers['from']
end

def sender_ip
@sendgrid_headers['sender_ip']
end

def receiver
@sendgrid_headers['to']
end

def subject
@sendgrid_headers['subject']
end

def attachments
@sendgrid_headers['attachments']
end

def body
@sendgrid_headers['text']
end

def message_id
matches = MSG_ID_REGEX.match(@mail_headers['Message-Id'])
matches ? matches[1] : ""
end

def in_reply_to
matches = MSG_ID_REGEX.match(@mail_headers['In-Reply-To'])
matches ? matches[1] : ""
end
end
87 changes: 87 additions & 0 deletions spec/fixtures/body.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
--xYzZY
Content-Disposition: form-data; name="headers"

Received: by mx0059p1mdw1.sendgrid.net with SMTP id UIfaEDCHj4 Fri, 15 Feb 2019 13:16:34 +0000 (UTC)
Received: from mail-qt1-f174.google.com (mail-qt1-f174.google.com [209.85.160.174]) by mx0059p1mdw1.sendgrid.net (Postfix) with ESMTPS id 4BD8686310C for <test@hutzbot-development.rangefindr.ca>; Fri, 15 Feb 2019 13:16:34 +0000 (UTC)
Received: by mail-qt1-f174.google.com with SMTP id 2so10778950qtb.5 for <test@hutzbot-development.rangefindr.ca>; Fri, 15 Feb 2019 05:16:34 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:content-transfer-encoding:mime-version:subject:message-id:date :to; bh=Bwn44D/maw3RSV4WjQHpxXjJZsIVUliJdYQdQJN8X60=; b=eNaU2pey/Uc0e4o6LCdLspwEoLjYx2n/810aavs8IZOA82Edmc57tW2jnIwrf/nq1u 04Mt4R+163KlpX5vfJmRbVgrix4qXu7GR0Q8J844/0eQwlffApdrZb5GfGSK4LRMhz18 iI+QejsUjedRDrQEfGqS/BbkkSo2EXuoGrnEE+RFeG1MTMBlhCAuiHBi1UvSNywQ6ii+ 1ZX8H6lYXjtaaB4XOiGd/OYo23dPy04nn+Yagdt9a2/jHlywGSFnsCFreQeRKXIIqDAN pHpejlh/N54vmTnPzaZniff0qYOniTI/4u2nP/EemkoE4raN/wGBaHCPrMqtinb9iIxn 9xiQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:content-transfer-encoding:mime-version :subject:message-id:date:to; bh=Bwn44D/maw3RSV4WjQHpxXjJZsIVUliJdYQdQJN8X60=; b=n+rlQ+kt/uCp8ON0n6/+YlnaePSmwvrv9vkyA/zhwZLYriFGXbdSQfZ5e2s0r3mOKO Dgv3resp2KYzFqKYBKYQ4Riyavau+HI5e8xm/Rg7bBk7zVyR6SVS0n2zhGLTeRyceD2P 4sgHKmd5k/brwucnpO6aY677EBsK4ibxg26IScTFXVkit5q6+35nCg7OztQ0i2RTorBW TU+N+bwv4gPrTgEOZ1fc2Rh7jpcFtaAhw8vJf6Mllc3Wum7oo8bYoqNIw5Fvoajv+qtb NsbaroZ8WC8YMptgGJhGdWYZP5P1EOuwDk/ltAz+nzMgo6H6KQlHK8mdcIPCizOMZ9G+ P5nw==
X-Gm-Message-State: AHQUAubjCeyV0lzWs2JZda6g0GhHGqJfiSHErWRJzKTYuJK0YDZqh5Kr 5ssIGcEWA6XxELfLi12pl09s2CLQ
X-Google-Smtp-Source: AHgI3IZwOpARfLvQofx6LgpFbN7F8bgT9Goggd5XR4kiFZLgKNDXreZtIcqyNfzWLNwRSLD62raYqg==
X-Received: by 2002:a0c:c60c:: with SMTP id v12mr7016091qvi.29.1550236593744; Fri, 15 Feb 2019 05:16:33 -0800 (PST)
Received: from [10.10.11.26] ([206.47.149.34]) by smtp.gmail.com with ESMTPSA id a15sm2880511qtj.96.2019.02.15.05.16.33 for <test@hutzbot-development.rangefindr.ca> (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 15 Feb 2019 05:16:33 -0800 (PST)
From: Chris Wise <chriswise71@gmail.com>
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Mime-Version: 1.0 (Mac OS X Mail 12.2 \(3445.102.3\))
Subject: This is a the subject line
Message-Id: <3B0F3105-1E39-4C70-B185-8571D6790BE8@gmail.com>
Date: Fri, 15 Feb 2019 08:16:32 -0500
To: test@hutzbot-development.rangefindr.ca
X-Mailer: Apple Mail (2.3445.102.3)

--xYzZY
Content-Disposition: form-data; name="dkim"

{@gmail.com : pass}
--xYzZY
Content-Disposition: form-data; name="to"

test@hutzbot-development.rangefindr.ca
--xYzZY
Content-Disposition: form-data; name="from"

Chris Wise <chriswise71@gmail.com>
--xYzZY
Content-Disposition: form-data; name="text"

This is the body

--xYzZY
Content-Disposition: form-data; name="sender_ip"

209.85.160.174
--xYzZY
Content-Disposition: form-data; name="spam_report"

Spam detection software, running on the system "mx0059p1mdw1.sendgrid.net", has
identified this incoming email as possible spam. The original message
has been attached to this so you can view it (if it isn't spam) or label
similar future email. If you have any questions, see
@@CONTACT_ADDRESS@@ for details.

Content preview: This is the body [...]

Content analysis details: (0.0 points, 5.0 required)

pts rule name description
---- ---------------------- --------------------------------------------------
0.0 FREEMAIL_FROM Sender email is freemail (chriswise71[at]gmail.com)
0.0 T_TO_NO_BRKTS_FREEMAIL T_TO_NO_BRKTS_FREEMAIL


--xYzZY
Content-Disposition: form-data; name="envelope"

{"to":["test@hutzbot-development.rangefindr.ca"],"from":"chriswise71@gmail.com"}
--xYzZY
Content-Disposition: form-data; name="attachments"

0
--xYzZY
Content-Disposition: form-data; name="subject"

This is a the subject line
--xYzZY
Content-Disposition: form-data; name="spam_score"

0.011
--xYzZY
Content-Disposition: form-data; name="charsets"

{"to":"UTF-8","subject":"UTF-8","from":"UTF-8","text":"us-ascii"}
--xYzZY
Content-Disposition: form-data; name="SPF"

pass
--xYzZY--
18 changes: 18 additions & 0 deletions spec/fixtures/headers.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Received: by mx0059p1mdw1.sendgrid.net with SMTP id UIfaEDCHj4 Fri, 15 Feb 2019 13:16:34 +0000 (UTC)
Received: from mail-qt1-f174.google.com (mail-qt1-f174.google.com [209.85.160.174]) by mx0059p1mdw1.sendgrid.net (Postfix) with ESMTPS id 4BD8686310C for <test@hutzbot-development.rangefindr.ca>; Fri, 15 Feb 2019 13:16:34 +0000 (UTC)
Received: by mail-qt1-f174.google.com with SMTP id 2so10778950qtb.5 for <test@hutzbot-development.rangefindr.ca>; Fri, 15 Feb 2019 05:16:34 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:content-transfer-encoding:mime-version:subject:message-id:date :to; bh=Bwn44D/maw3RSV4WjQHpxXjJZsIVUliJdYQdQJN8X60=; b=eNaU2pey/Uc0e4o6LCdLspwEoLjYx2n/810aavs8IZOA82Edmc57tW2jnIwrf/nq1u 04Mt4R+163KlpX5vfJmRbVgrix4qXu7GR0Q8J844/0eQwlffApdrZb5GfGSK4LRMhz18 iI+QejsUjedRDrQEfGqS/BbkkSo2EXuoGrnEE+RFeG1MTMBlhCAuiHBi1UvSNywQ6ii+ 1ZX8H6lYXjtaaB4XOiGd/OYo23dPy04nn+Yagdt9a2/jHlywGSFnsCFreQeRKXIIqDAN pHpejlh/N54vmTnPzaZniff0qYOniTI/4u2nP/EemkoE4raN/wGBaHCPrMqtinb9iIxn 9xiQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:content-transfer-encoding:mime-version :subject:message-id:date:to; bh=Bwn44D/maw3RSV4WjQHpxXjJZsIVUliJdYQdQJN8X60=; b=n+rlQ+kt/uCp8ON0n6/+YlnaePSmwvrv9vkyA/zhwZLYriFGXbdSQfZ5e2s0r3mOKO Dgv3resp2KYzFqKYBKYQ4Riyavau+HI5e8xm/Rg7bBk7zVyR6SVS0n2zhGLTeRyceD2P 4sgHKmd5k/brwucnpO6aY677EBsK4ibxg26IScTFXVkit5q6+35nCg7OztQ0i2RTorBW TU+N+bwv4gPrTgEOZ1fc2Rh7jpcFtaAhw8vJf6Mllc3Wum7oo8bYoqNIw5Fvoajv+qtb NsbaroZ8WC8YMptgGJhGdWYZP5P1EOuwDk/ltAz+nzMgo6H6KQlHK8mdcIPCizOMZ9G+ P5nw==
X-Gm-Message-State: AHQUAubjCeyV0lzWs2JZda6g0GhHGqJfiSHErWRJzKTYuJK0YDZqh5Kr 5ssIGcEWA6XxELfLi12pl09s2CLQ
X-Google-Smtp-Source: AHgI3IZwOpARfLvQofx6LgpFbN7F8bgT9Goggd5XR4kiFZLgKNDXreZtIcqyNfzWLNwRSLD62raYqg==
X-Received: by 2002:a0c:c60c:: with SMTP id v12mr7016091qvi.29.1550236593744; Fri, 15 Feb 2019 05:16:33 -0800 (PST)
Received: from [10.10.11.26] ([206.47.149.34]) by smtp.gmail.com with ESMTPSA id a15sm2880511qtj.96.2019.02.15.05.16.33 for <test@hutzbot-development.rangefindr.ca> (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 15 Feb 2019 05:16:33 -0800 (PST)
From: Chris Wise <chriswise71@gmail.com>
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Mime-Version: 1.0 (Mac OS X Mail 12.2 \(3445.102.3\))
Subject: This is a the subject line
Message-Id: <3B0F3105-1E39-4C70-B185-8571D6790BE8@gmail.com>
Date: Fri, 15 Feb 2019 08:16:32 -0500
To: test@hutzbot-development.rangefindr.ca
X-Mailer: Apple Mail (2.3445.102.3)
Loading

0 comments on commit 284a38d

Please sign in to comment.