diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..ca3d04b
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,18 @@
+; This file is for unifying the coding style for different editors and IDEs.
+; More information at http://editorconfig.org
+
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.yml]
+indent_size = 2
+
+[*.json]
+charset = utf-8
+indent_size = 2
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..e16b4b4
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,42 @@
+# Define the line ending behavior of the different file extensions
+# Set default behaviour, in case users don't have core.autocrlf set.
+* text=auto
+* text eol=lf
+
+# Explicitly declare text files we want to always be normalized and converted
+# to native line endings on checkout.
+*.php text
+*.default text
+*.ctp text
+*.sql text
+*.md text
+*.po text
+*.js text
+*.css text
+*.ini text
+*.properties text
+*.txt text
+*.xml text
+*.svg text
+*.yml text
+.htaccess text
+
+# Declare files that will always have CRLF line endings on checkout.
+*.bat eol=crlf
+
+# Declare files that will always have LF line endings on checkout.
+*.pem eol=lf
+
+# Denote all files that are truly binary and should not be modified.
+*.png binary
+*.jpg binary
+*.gif binary
+*.ico binary
+*.mo binary
+*.pdf binary
+*.phar binary
+*.woff binary
+*.woff2 binary
+*.ttf binary
+*.otf binary
+*.eot binary
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a3e9703
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,33 @@
+/config/app.php
+
+/.htpasswd
+/vendor/*
+.DS_Store
+.DS_Store?
+._*
+.Spotlight-V100
+.Trashes
+Icon?
+ehthumbs.db
+ehthumbs_vista.db
+Thumbs.db
+Desktop.ini
+$RECYCLE.BIN/
+*.stackdump
+/.well-known/*
+*~
+*.swp
+*.swo
+*.sublime-*
+*.stTheme.cache
+*.tmlanguage.cache
+*.tmPreferences.cache
+.settings/*
+.idea/*
+nbproject/*
+.vscode
+.sass-cache/
+*.php_cs.cache
+/.scannerwork/*
+/.settings/*
+/.tests/*
\ No newline at end of file
diff --git a/.htaccess b/.htaccess
new file mode 100644
index 0000000..325546b
--- /dev/null
+++ b/.htaccess
@@ -0,0 +1,24 @@
+
+ RequestHeader unset Proxy
+
+
+ RewriteEngine on
+ RewriteBase /
+
+ RewriteCond %{REQUEST_URI} !^/webroot/
+ RewriteCond %{REQUEST_URI} !^(\.well-known/.*)$
+ RewriteRule ^(.*)$ /webroot/$1 [QSA,L]
+
+ RewriteRule ^(\.well-known/.*)$ $1 [L]
+
+ RewriteCond %{HTTP:Authorization} ^(.*)
+ RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
+
+
+SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
+
+
+ Header set Access-Control-Allow-Origin: "*"
+ Header set Access-Control-Allow-Methods: "POST"
+ Header set Access-Control-Allow-Headers: "Authorization, Access-Control-Allow-Origin, Content-Type"
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..41bf941
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Pittica S.r.l.s.
+
+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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6b4fb60
--- /dev/null
+++ b/README.md
@@ -0,0 +1,56 @@
+# Post SendGrid
+
+[![LICENSE](https://img.shields.io/github/license/pittica/post-sendgrid.svg)](LICENSE)
+[![packagist](https://img.shields.io/badge/packagist-pittica%2Fpost--sendgrid-brightgreen.svg)](https://packagist.org/packages/pittica/post-sendgrid)
+![PHP from Packagist](https://img.shields.io/packagist/php-v/pittica/post-sendgrid)
+
+This project uses SendGrid to send data from contact forms.
+
+## Installation
+
+You can install _post-sendgrid_ using [Composer](https://getcomposer.org).
+
+``` bash
+composer create-project --prefer-dist pittica/post-sendgrid
+```
+
+## Configuration
+
+Create and edit a **config/app.php** file.
+
+### Example
+
+``` php
+ [
+ 'whitelisted' => [
+ 'message'
+ ],
+ 'email' => 'email',
+ 'subject' => 'subject',
+ 'name' => 'name',
+ 'labels' => [
+ 'message' => 'Message',
+ 'email' => 'E-Mail',
+ 'subject' => 'Subject'
+ ]
+ ],
+ 'sender' => [
+ 'address' => 'YOUR@EMAIL.ADDRESS',
+ 'name' => 'YOUR NAME'
+ ],
+ 'api' => [
+ 'key' => 'SendGrid API KEY'
+ ],
+ 'recaptcha' => [
+ 'key' => 'RECAPTCHA KEY',
+ 'field' => 'g-recaptcha'
+ ]
+];
+```
+
+## Copyright
+
+© 2020 [Pittica S.r.l.s.](https://pittica.com)
\ No newline at end of file
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..af133eb
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,38 @@
+{
+ "name": "pittica/post-sendgrid",
+ "homepage": "https://github.com/pittica/post-sendgrid",
+ "description": "Send e-mails using SendGrid from HTTP POST",
+ "type": "project",
+ "license": "MIT",
+ "keywords": [
+ "email",
+ "sendgrid",
+ "post"
+ ],
+ "authors": [
+ {
+ "name": "Lucio Benini",
+ "email": "info@pittica.com",
+ "homepage": "https://pittica.com",
+ "role": "Web Developer"
+ }
+ ],
+ "autoload": {
+ "psr-4": {
+ "Pittica\\PostSendGrid\\": "src"
+ }
+ },
+ "minimum-stability": "stable",
+ "require": {
+ "ext-curl": "*",
+ "ext-json": "*",
+ "php": "^7.1",
+ "sendgrid/sendgrid": "^7.0",
+ "guzzlehttp/guzzle": "^6.5.2",
+ "google/recaptcha": "^1.2"
+ },
+ "prefer-stable": true,
+ "config": {
+ "sort-packages": true
+ }
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..93fb948
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,457 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "a98692bcf162b8ed1acff17d7eeb4ba5",
+ "packages": [
+ {
+ "name": "google/recaptcha",
+ "version": "1.2.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/google/recaptcha.git",
+ "reference": "98c4a6573b27e8b0990ea8789c74ea378795134c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/google/recaptcha/zipball/98c4a6573b27e8b0990ea8789c74ea378795134c",
+ "reference": "98c4a6573b27e8b0990ea8789c74ea378795134c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^2.2.20|^2.15",
+ "php-coveralls/php-coveralls": "^2.1",
+ "phpunit/phpunit": "^4.8.36|^5.7.27|^6.59|^7.5.11"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "ReCaptcha\\": "src/ReCaptcha"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "Client library for reCAPTCHA, a free service that protects websites from spam and abuse.",
+ "homepage": "https://www.google.com/recaptcha/",
+ "keywords": [
+ "Abuse",
+ "captcha",
+ "recaptcha",
+ "spam"
+ ],
+ "time": "2019-08-16T15:48:25+00:00"
+ },
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "6.5.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "43ece0e75098b7ecd8d13918293029e555a50f82"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/43ece0e75098b7ecd8d13918293029e555a50f82",
+ "reference": "43ece0e75098b7ecd8d13918293029e555a50f82",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "guzzlehttp/promises": "^1.0",
+ "guzzlehttp/psr7": "^1.6.1",
+ "php": ">=5.5"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
+ "psr/log": "^1.1"
+ },
+ "suggest": {
+ "ext-intl": "Required for Internationalized Domain Name (IDN) support",
+ "psr/log": "Required for using the Log middleware"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "6.5-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "rest",
+ "web service"
+ ],
+ "time": "2019-12-23T11:57:10+00:00"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "v1.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
+ "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "time": "2016-12-20T10:07:11+00:00"
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "1.6.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "239400de7a173fe9901b9ac7c06497751f00727a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a",
+ "reference": "239400de7a173fe9901b9ac7c06497751f00727a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0",
+ "psr/http-message": "~1.0",
+ "ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
+ },
+ "provide": {
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "ext-zlib": "*",
+ "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
+ },
+ "suggest": {
+ "zendframework/zend-httphandlerrunner": "Emit PSR-7 responses"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Schultze",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "PSR-7 message implementation that also provides common utility methods",
+ "keywords": [
+ "http",
+ "message",
+ "psr-7",
+ "request",
+ "response",
+ "stream",
+ "uri",
+ "url"
+ ],
+ "time": "2019-07-01T23:21:34+00:00"
+ },
+ {
+ "name": "psr/http-message",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "time": "2016-08-06T14:39:51+00:00"
+ },
+ {
+ "name": "ralouphie/getallheaders",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ralouphie/getallheaders.git",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.1",
+ "phpunit/phpunit": "^5 || ^6.5"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/getallheaders.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ralph Khattar",
+ "email": "ralph.khattar@gmail.com"
+ }
+ ],
+ "description": "A polyfill for getallheaders.",
+ "time": "2019-03-08T08:55:37+00:00"
+ },
+ {
+ "name": "sendgrid/php-http-client",
+ "version": "3.10.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sendgrid/php-http-client.git",
+ "reference": "a3891dfe1130014e46b59e3c76be0c1c9d4fd540"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sendgrid/php-http-client/zipball/a3891dfe1130014e46b59e3c76be0c1c9d4fd540",
+ "reference": "a3891dfe1130014e46b59e3c76be0c1c9d4fd540",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.4",
+ "squizlabs/php_codesniffer": "~2.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "SendGrid\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Matt Bernier",
+ "email": "dx@sendgrid.com"
+ },
+ {
+ "name": "Elmer Thomas",
+ "email": "ethomas@twilio.com"
+ }
+ ],
+ "description": "HTTP REST client, simplified for PHP",
+ "homepage": "http://github.com/sendgrid/php-http-client",
+ "keywords": [
+ "api",
+ "fluent",
+ "http",
+ "rest",
+ "sendgrid"
+ ],
+ "time": "2020-01-22T20:51:56+00:00"
+ },
+ {
+ "name": "sendgrid/sendgrid",
+ "version": "7.4.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sendgrid/sendgrid-php.git",
+ "reference": "d697c9e1677516314c28d2b946cc3062ee9537ff"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sendgrid/sendgrid-php/zipball/d697c9e1677516314c28d2b946cc3062ee9537ff",
+ "reference": "d697c9e1677516314c28d2b946cc3062ee9537ff",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "ext-json": "*",
+ "ext-mbstring": "*",
+ "ext-openssl": "*",
+ "php": ">=5.6",
+ "sendgrid/php-http-client": "~3.10"
+ },
+ "replace": {
+ "sendgrid/sendgrid-php": "*"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.7.9 || ^6.4.3",
+ "squizlabs/php_codesniffer": "3.*",
+ "swaggest/json-diff": "^3.4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "SendGrid\\": "lib/",
+ "SendGrid\\Mail\\": "lib/mail/",
+ "SendGrid\\Contacts\\": "lib/contacts/",
+ "SendGrid\\Stats\\": "lib/stats/"
+ },
+ "files": [
+ "lib/SendGrid.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "This library allows you to quickly and easily send emails through Twilio SendGrid using PHP.",
+ "homepage": "http://github.com/sendgrid/sendgrid-php",
+ "keywords": [
+ "email",
+ "grid",
+ "send",
+ "sendgrid",
+ "twilio sendgrid"
+ ],
+ "time": "2020-01-22T20:59:57+00:00"
+ }
+ ],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": true,
+ "prefer-lowest": false,
+ "platform": {
+ "ext-curl": "*",
+ "ext-json": "*",
+ "php": "^7.1"
+ },
+ "platform-dev": []
+}
diff --git a/config/empty b/config/empty
new file mode 100644
index 0000000..e69de29
diff --git a/sonar-project.properties b/sonar-project.properties
new file mode 100644
index 0000000..406bec0
--- /dev/null
+++ b/sonar-project.properties
@@ -0,0 +1,12 @@
+sonar.projectKey=post-sendgrid
+sonar.projectName=Post SendGrid
+sonar.projectVersion=1.0
+sonar.sources=src
+sonar.language=php
+sonar.sourceEncoding=UTF-8
+sonar.issue.ignore.multicriteria=e1
+sonar.issue.ignore.multicriteria.e1.ruleKey=php:S1192
+sonar.issue.ignore.multicriteria.e1.resourceKey=**/*.php
+#sonar.tests=tests
+sonar.php.tests.reportPath=.tests/junit.xml
+sonar.php.coverage.reportPath=.tests/coverage-clover.xml
\ No newline at end of file
diff --git a/src/Application.php b/src/Application.php
new file mode 100644
index 0000000..04fd96a
--- /dev/null
+++ b/src/Application.php
@@ -0,0 +1,117 @@
+
+ * @copyright 2020 Pittica S.r.l.s. (https://pittica.com)
+ * @license https://opensource.org/licenses/mit-license.php MIT License
+ * @link https://pittica.com Pittica S.r.l.s.
+ * @since 1.0.0
+ */
+
+namespace Pittica\PostSendGrid;
+
+use SendGrid\Mail\Mail;
+
+/**
+ * Application main class.
+ * @package Pittica\PostSendGrid
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+class Application
+{
+ /**
+ * The configuration.
+ * @var array
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ private $_config = [];
+
+ /**
+ * Application constructor.
+ * @throws \Exception Method is not POST.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function __construct()
+ {
+ $server = new Server;
+
+ if (!$server->isPost()) {
+ http_response_code(200);
+
+ header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
+ header('Access-Control-Allow-Headers: Authorization, Content-Type, Accept, Origin');
+
+ exit(0);
+ }
+
+ $config = new Configuration;
+ $this->_config = $config->get();
+ }
+
+ /**
+ * Runs the application.
+ * @return void
+ * @throws \SendGrid\Mail\TypeException
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function run(): void
+ {
+ $recaptha = new ReCaptcha;
+
+ if ($recaptha->validate()) {
+ $vars = new BodyParts();
+ $message = new Mail();
+ $email = $vars->getAddress();
+ $subject = $vars->getSubject();
+ $name = $vars->getName();
+
+ if (!$name) {
+ $name = $email;
+ }
+
+ $message->setFrom($email, $name);
+ $message->setSubject($subject ? $subject : ('Message from: ' . $name));
+ $message->addTo($this->_config['sender']['address'], $this->_config['sender']['name']);
+ $message->addContent("text/plain", $vars->toString());
+ $message->addContent("text/html", $vars->toHTML());
+ $client = new \SendGrid($this->_config['api']['key']);
+
+ header('Content-type:application/json;charset=utf-8');
+
+ try {
+ $this->_respond($client->send($message)->statusCode());
+ } catch (\Exception $e) {
+ $this->_respond(500);
+ }
+ }
+
+ $this->_respond(403);
+ }
+
+ /**
+ * Prepares and output the JSON response.
+ * @param int $code HTTP code.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ protected function _respond(int $code): void
+ {
+ http_response_code($code);
+
+ die(json_encode([
+ 'error' => $code < 200 || $code >= 300
+ ]));
+ }
+}
diff --git a/src/BodyParts.php b/src/BodyParts.php
new file mode 100644
index 0000000..502e05c
--- /dev/null
+++ b/src/BodyParts.php
@@ -0,0 +1,203 @@
+
+ * @copyright 2020 Pittica S.r.l.s. (https://pittica.com)
+ * @license https://opensource.org/licenses/mit-license.php MIT License
+ * @link https://pittica.com Pittica S.r.l.s.
+ * @since 1.0.0
+ */
+
+namespace Pittica\PostSendGrid;
+
+/**
+ * Represents the form variables and message body parts.
+ * @package Pittica\PostSendGrid
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+class BodyParts
+{
+ /**
+ * The configuration.
+ * @var array
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ private $_config = [];
+
+ /**
+ * The variables.
+ * @var array
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ private $_vars = [];
+
+ /**
+ * The formatted variables.
+ * @var array
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ private $_parts = [];
+
+ /**
+ * BodyParts constructor.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function __construct()
+ {
+ $config = new Configuration;
+
+ $this->_config = $config->get('fields');
+ $this->_vars = $this->_processFields();
+ $this->_parts = $this->_formatFields();
+ }
+
+ /**
+ * Gets the e-mail address.
+ * @return string The e-mail address.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function getAddress(): string
+ {
+ return $this->_getValue('email');
+ }
+
+ /**
+ * Gets the sender's name.
+ * @return string The sender's name.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function getName(): string
+ {
+ return $this->_getValue('name');
+ }
+
+ /**
+ * Gets the subject.
+ * @return string The subject.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function getSubject(): string
+ {
+ return $this->_getValue('subject');
+ }
+
+ /**
+ * Gets a value from the raw variables.
+ * @param string $key The key of the associated value.
+ * @return string A value from the raw variables.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ protected function _getValue(string $key): string
+ {
+ return !empty($this->_vars[$this->_config[$key]]) ? $this->_vars[$this->_config[$key]] : '';
+ }
+
+ /**
+ * Returns an HTML representation of the current object.
+ * @return string An HTML representation of the current object.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function toHTML(): string
+ {
+ $out = '';
+
+ foreach ($this->_vars as $label => $var) {
+ $out .= '' . $label . '
' . $var . '';
+ }
+
+ return $out;
+ }
+
+ /**
+ * Returns a string representation of the current object.
+ * @return string A string representation of the current object.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function toString(): string
+ {
+ $out = '';
+
+ foreach ($this->_vars as $label => $var) {
+ $out .= $label . ':' . PHP_EOL . $var . PHP_EOL . PHP_EOL;
+ }
+
+ return $out;
+ }
+
+ /**
+ * Returns a string representation of the current object.
+ * @return string A string representation of the current object.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function __toString(): string
+ {
+ return $this->toString();
+ }
+
+ /**
+ * Formats an array of form variables in an array of label/value.
+ * @return array An array of label/value.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ protected function _formatFields(): array
+ {
+ if (!empty($this->_config['labels'])) {
+ $res = [];
+
+ foreach ($this->_vars as $key => $value) {
+ if (!empty($this->_config['labels'][$key])) {
+ $res[$this->_config['labels'][$key]] = $value;
+ }
+ }
+
+ return $res;
+ }
+
+ return $this->_vars;
+ }
+
+ /**
+ * Processes an array of form variables.
+ * @return array An array of variables.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ protected function _processFields(): array
+ {
+ $res = [];
+ $fields = array_merge([$this->_config['email'], $this->_config['subject'], $this->_config['name']], $this->_config['whitelisted']);
+
+ if (!empty($fields)) {
+ $server = new Server;
+
+ foreach ($server->getFields() as $key => $var) {
+ if (in_array($key, $fields)) {
+ $res[$key] = $var;
+ }
+ }
+ }
+
+ return $res;
+ }
+}
diff --git a/src/Configuration.php b/src/Configuration.php
new file mode 100644
index 0000000..140ff71
--- /dev/null
+++ b/src/Configuration.php
@@ -0,0 +1,62 @@
+
+ * @copyright 2020 Pittica S.r.l.s. (https://pittica.com)
+ * @license https://opensource.org/licenses/mit-license.php MIT License
+ * @link https://pittica.com Pittica S.r.l.s.
+ * @since 1.0.0
+ */
+
+namespace Pittica\PostSendGrid;
+
+/**
+ * Configuration reader.
+ * @package Pittica\PostSendGrid
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+class Configuration
+{
+ /**
+ * The configuration data.
+ * @var array
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ private $_data = [];
+
+ /**
+ * Configuration constructor.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function __construct()
+ {
+ $this->_data = include '..' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'app.php';
+ }
+
+ /**
+ * Gets configuration data.
+ * @param $key string Configuration key.
+ * @return array|string|null The configuration data.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function get(string $key = '')
+ {
+ if (empty($key)) {
+ return $this->_data;
+ }
+
+ return !empty($this->_data[$key]) ? $this->_data[$key] : null;
+ }
+}
\ No newline at end of file
diff --git a/src/ReCaptcha.php b/src/ReCaptcha.php
new file mode 100644
index 0000000..5bf0689
--- /dev/null
+++ b/src/ReCaptcha.php
@@ -0,0 +1,71 @@
+
+ * @copyright 2020 Pittica S.r.l.s. (https://pittica.com)
+ * @license https://opensource.org/licenses/mit-license.php MIT License
+ * @link https://pittica.com Pittica S.r.l.s.
+ * @since 1.0.0
+ */
+
+namespace Pittica\PostSendGrid;
+
+/**
+ * ReCaptcha client.
+ * @package Pittica\PostSendGrid
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+class ReCaptcha
+{
+ /**
+ * The configuration.
+ * @var array
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ private $_config = [];
+
+ /**
+ * Application constructor.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function __construct()
+ {
+ $config = new Configuration;
+ $this->_config = $config->get('recaptcha');
+ }
+
+ /**
+ * Validates the captcha input.
+ * @return bool A value indicating whether the request has been validated.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function validate(): bool
+ {
+ if (!empty($this->_config)) {
+ $server = new Server;
+ $response = $server->getField($this->_config['field']);
+
+ if ($response) {
+ $recaptcha = new \ReCaptcha\ReCaptcha($this->_config['key']);
+
+ return $recaptcha->verify($response, $server->getRemoteAddress())->isSuccess();
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/Server.php b/src/Server.php
new file mode 100644
index 0000000..2cf9f0a
--- /dev/null
+++ b/src/Server.php
@@ -0,0 +1,94 @@
+
+ * @copyright 2020 Pittica S.r.l.s. (https://pittica.com)
+ * @license https://opensource.org/licenses/mit-license.php MIT License
+ * @link https://pittica.com Pittica S.r.l.s.
+ * @since 1.0.0
+ */
+
+namespace Pittica\PostSendGrid;
+
+use GuzzleHttp\Psr7\ServerRequest;
+
+/**
+ * Server.
+ * @package Pittica\PostSendGrid
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+class Server
+{
+ /**
+ * Gets the address of the request.
+ * @return string The address of the request.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function getRemoteAddress(): string
+ {
+ $request = ServerRequest::fromGlobals();
+ $params = $request->getServerParams();
+
+ return $params['REMOTE_ADDR'];
+ }
+
+ /**
+ * Determines whether the request is POST.
+ * @return bool A value indicating whether the request is POST.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function isPost(): bool
+ {
+ $request = ServerRequest::fromGlobals();
+ $params = $request->getServerParams();
+
+ return $params['REQUEST_METHOD'] === 'POST';
+ }
+
+ /**
+ * Gets fields from request.
+ * @return array The fields from the current request.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function getFields(): array
+ {
+ $request = ServerRequest::fromGlobals();
+ $body = $request->getParsedBody();
+
+ if (is_array($body)) {
+ return $body;
+ }
+
+ return [];
+ }
+
+ /**
+ * Gets a field from request.
+ * @param $key string The key of the field.
+ * @return string A field from the current request.
+ * @author Lucio Benini
+ * @since 1.0.0
+ */
+ public function getField(string $key): string
+ {
+ $body = $this->getFields();
+
+ if (!empty($body[$key])) {
+ return $body[$key];
+ }
+
+ return '';
+ }
+}
diff --git a/web.config b/web.config
new file mode 100644
index 0000000..398285c
--- /dev/null
+++ b/web.config
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/webroot/index.php b/webroot/index.php
new file mode 100644
index 0000000..629e819
--- /dev/null
+++ b/webroot/index.php
@@ -0,0 +1,24 @@
+
+ * @copyright 2020 Pittica S.r.l.s. (https://pittica.com)
+ * @license https://opensource.org/licenses/mit-license.php MIT License
+ * @link https://pittica.com Pittica S.r.l.s.
+ * @since 1.0.0
+ */
+
+require dirname(__DIR__) . '/vendor/autoload.php';
+
+use Pittica\PostSendGrid\Application;
+
+$application = new Application();
+$application->run();
\ No newline at end of file