form-to-mail 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of form-to-mail might be problematic. Click here for more details.
- package/.env.sample +24 -0
- package/.env.test +18 -0
- package/.github/workflows/npm-publish.yml +33 -0
- package/README.md +131 -0
- package/app.js +20 -0
- package/images/form-submission.jpeg +0 -0
- package/modules/mailer.js +140 -0
- package/package.json +42 -0
- package/test/devtest.js +26 -0
- package/test/mailer.test.js +12 -0
- package/test/pages/contact-form.html +129 -0
- package/test/pages/thank-you.html +123 -0
- package/test/prodTest.js +26 -0
package/.env.sample
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# This is a sample .env file for use in local development.
|
|
2
|
+
# Duplicate this file as .env in the root of the project
|
|
3
|
+
# and update the environment variables to match your
|
|
4
|
+
# desired config
|
|
5
|
+
#
|
|
6
|
+
# See the README for full descriptions of each of the
|
|
7
|
+
# available configurations.
|
|
8
|
+
|
|
9
|
+
#Node
|
|
10
|
+
NODE_ENV=
|
|
11
|
+
|
|
12
|
+
# SMTP
|
|
13
|
+
SMTP_HOST=
|
|
14
|
+
SMTP_PORT=
|
|
15
|
+
SMTP_USER=
|
|
16
|
+
SMTP_PASSWORD=
|
|
17
|
+
|
|
18
|
+
#Mail Options
|
|
19
|
+
MAIL_FROM_NAME=
|
|
20
|
+
MAIL_FROM_EMAIL=
|
|
21
|
+
MAIL_TO_NAME=
|
|
22
|
+
MAIL_TO_EMAIL=
|
|
23
|
+
MAIL_CC_EMAIL=
|
|
24
|
+
MAIL_BCC_EMAIL=
|
package/.env.test
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# This is a test .env file for use in Jest.
|
|
2
|
+
|
|
3
|
+
#Node
|
|
4
|
+
NODE_ENV=development
|
|
5
|
+
|
|
6
|
+
# SMTP
|
|
7
|
+
SMTP_HOST=smtp.domain.com
|
|
8
|
+
SMTP_PORT=587
|
|
9
|
+
SMTP_USER=Username
|
|
10
|
+
SMTP_PASSWORD=password
|
|
11
|
+
|
|
12
|
+
#Mail Options
|
|
13
|
+
MAIL_FROM_NAME=Mailer
|
|
14
|
+
MAIL_FROM_EMAIL=mailer@example.com
|
|
15
|
+
MAIL_TO_NAME=
|
|
16
|
+
MAIL_TO_EMAIL=to@example.com
|
|
17
|
+
MAIL_CC_EMAIL= 'cc@example.com',"foo" <bar@example.com>,'Name' <baz@example.com>
|
|
18
|
+
MAIL_BCC_EMAIL= 'BCC@example.com',"Ноде Майлер" <foobar@example.com>,"Майлер, Ноде" <foobar@example.com>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
|
2
|
+
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
|
|
3
|
+
|
|
4
|
+
name: Publish Package to NPM
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
release:
|
|
8
|
+
types: [created]
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v3
|
|
15
|
+
- uses: actions/setup-node@v3
|
|
16
|
+
with:
|
|
17
|
+
node-version: 16
|
|
18
|
+
- run: npm ci
|
|
19
|
+
- run: npm test
|
|
20
|
+
|
|
21
|
+
publish-npm:
|
|
22
|
+
needs: build
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v3
|
|
26
|
+
- uses: actions/setup-node@v3
|
|
27
|
+
with:
|
|
28
|
+
node-version: 16
|
|
29
|
+
registry-url: https://registry.npmjs.org/
|
|
30
|
+
- run: npm ci
|
|
31
|
+
- run: npm publish
|
|
32
|
+
env:
|
|
33
|
+
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
package/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Form To Mail
|
|
2
|
+
|
|
3
|
+
Form To mail is a simple way to receive emails ✉ from contact forms on your website. Which handles files uploads on the fly for you Out of the box itself.
|
|
4
|
+
Just Plugin the formToMail middleware and setup the .env variable's. You are good to go.
|
|
5
|
+
|
|
6
|
+
In development test SMTP service account from ethereal.email are generated and Preview URL's are logged. you can visit them to view the emails.
|
|
7
|
+
|
|
8
|
+
## Getting Started
|
|
9
|
+
|
|
10
|
+
## 1. Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install form-to-mail
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## 2. Setup SMTP and Mail Options
|
|
17
|
+
|
|
18
|
+
Create a `.env` file in the root of your project with below environmental variables and fill them with your credentials.
|
|
19
|
+
|
|
20
|
+
```dosini
|
|
21
|
+
# SMTP
|
|
22
|
+
SMTP_HOST=
|
|
23
|
+
SMTP_PORT=
|
|
24
|
+
SMTP_USER=
|
|
25
|
+
SMTP_PASSWORD=
|
|
26
|
+
|
|
27
|
+
#Mail Options
|
|
28
|
+
MAIL_FROM_NAME=
|
|
29
|
+
MAIL_FROM_EMAIL=
|
|
30
|
+
MAIL_TO_NAME=
|
|
31
|
+
MAIL_TO_EMAIL=
|
|
32
|
+
MAIL_CC_EMAIL=
|
|
33
|
+
MAIL_BCC_EMAIL=
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
All email addresses can be plain email addresses ```'foobar@example.com'``` or with formatted name (includes unicode support) ```'Ноде Майлер <foobar@example.com>'``` <br>
|
|
37
|
+
```dosini
|
|
38
|
+
#Mail Options
|
|
39
|
+
MAIL_FROM_NAME= Sender Name
|
|
40
|
+
MAIL_FROM_EMAIL= Sender@example.com
|
|
41
|
+
MAIL_TO_EMAIL= to@example.com, "receiver" <receiver@example.com>
|
|
42
|
+
MAIL_CC_EMAIL= 'cc@example.com',"foo" <bar@example.com>,'Name' <baz@example.com>
|
|
43
|
+
MAIL_BCC_EMAIL= 'BCC@example.com',"Ноде Майлер" <foobar@example.com>,"Майлер, Ноде" <foobar@example.com>
|
|
44
|
+
```
|
|
45
|
+
Notice that all address fields are comma separated lists, so if you want to use a comma ( or any other special symbol ) in the name part, make sure you enclose the name in double quotes like this: `' "Майлер, Ноде" '`
|
|
46
|
+
|
|
47
|
+
## Example
|
|
48
|
+
|
|
49
|
+
Suppose you have this HTML from in your contact page.Set the form action URL to your Custom endpoint.
|
|
50
|
+
|
|
51
|
+
contact-form.html
|
|
52
|
+
```html
|
|
53
|
+
<form action="/" method="POST">
|
|
54
|
+
|
|
55
|
+
<div>
|
|
56
|
+
<label for="name" class="form-label"> Full Name </label>
|
|
57
|
+
<input type="text" name="name" id="name" placeholder="Full Name" class="form-input" />
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div>
|
|
61
|
+
<label for="email" class="form-label"> Email Address </label>
|
|
62
|
+
<input type="email" name="email" id="email" placeholder="Enter your email" class="form-input"/>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div>
|
|
66
|
+
<label for="subject" class="form-label"> Subject </label>
|
|
67
|
+
<input type="text" name="subject" id="subject" placeholder="Enter your subject" class="form-input"/>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div class="mb-5">
|
|
71
|
+
<label for="message" class="form-label"> Message </label>
|
|
72
|
+
<textarea rows="6" name="message" id="message" placeholder="Type your message" class="form-input"></textarea>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div>
|
|
76
|
+
<button class="form-btn">Submit</button>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
</form>
|
|
80
|
+
```
|
|
81
|
+
## 3. Create a express app
|
|
82
|
+
creates the routes for the POST endpoint. and add formToMail middleware which will handle the form submission for you.
|
|
83
|
+
After that you can redirect the users to a confirmation / thank you page or you cloud send a custom response.
|
|
84
|
+
You can access fields and files with the request Object.
|
|
85
|
+
```js
|
|
86
|
+
app.post('/',formToMail, (req, res) => {
|
|
87
|
+
const fields = req.fields
|
|
88
|
+
const files = req.files
|
|
89
|
+
console.log('fields: ', fields)
|
|
90
|
+
console.log('files: ', files)
|
|
91
|
+
res.redirect(303, '/thank-you')
|
|
92
|
+
})
|
|
93
|
+
```
|
|
94
|
+
app.js
|
|
95
|
+
```js
|
|
96
|
+
const express = require('express')
|
|
97
|
+
const app = express()
|
|
98
|
+
const port = 3000
|
|
99
|
+
const formToMail = require('form-to-mail')
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
app.get('/', (req, res) => res.sendFile('contact-form.html'))
|
|
103
|
+
app.get('/thank-you', (req, res) => res.sendFile('thank-you.html'))
|
|
104
|
+
|
|
105
|
+
// POST endpoint
|
|
106
|
+
app.post('/',formToMail, (req, res) => {
|
|
107
|
+
res.redirect(303, '/thank-you');
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
app.listen(port, () => console.log(`listening on port ${port}!`))
|
|
111
|
+
```
|
|
112
|
+
Sample Form Submission
|
|
113
|
+
|
|
114
|
+

|
|
115
|
+
|
|
116
|
+
You can find the sample Contact and Thank you pages inside the test folder.
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
<!-- CONTRIBUTING -->
|
|
120
|
+
## Contributing
|
|
121
|
+
|
|
122
|
+
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
|
|
123
|
+
|
|
124
|
+
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".
|
|
125
|
+
Don't forget to give the project a star! Thanks again!
|
|
126
|
+
|
|
127
|
+
1. Fork the Project
|
|
128
|
+
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
|
|
129
|
+
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
|
|
130
|
+
4. Push to the Branch (`git push origin feature/AmazingFeature`)
|
|
131
|
+
5. Open a Pull Request
|
package/app.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const formidable = require('formidable')
|
|
2
|
+
const { mailer } = require('./modules/mailer.js')
|
|
3
|
+
|
|
4
|
+
const formMailer = (req, res, next) => {
|
|
5
|
+
|
|
6
|
+
const form = formidable({ multiples: true });
|
|
7
|
+
|
|
8
|
+
form.parse(req, async(err, fields, files) => {
|
|
9
|
+
if (err) {
|
|
10
|
+
next(err);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
await mailer(fields,files)
|
|
14
|
+
req.fields = fields;
|
|
15
|
+
req.files = files;
|
|
16
|
+
next();
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
module.exports = formMailer
|
|
Binary file
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const nodemailer = require('nodemailer')
|
|
3
|
+
const dotenv = require('dotenv');
|
|
4
|
+
|
|
5
|
+
// Set .env.test for Jest
|
|
6
|
+
const isTest = process.env.NODE_ENV === 'test'
|
|
7
|
+
isTest ? dotenv.config({ path: '.env.test' }) : dotenv.config()
|
|
8
|
+
|
|
9
|
+
const isProduction = process.env.NODE_ENV === 'production'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
const getSMTPCredentials = () => {
|
|
13
|
+
|
|
14
|
+
const SMTP = {
|
|
15
|
+
host: process.env.SMTP_HOST,
|
|
16
|
+
port: process.env.SMTP_PORT,
|
|
17
|
+
user: process.env.SMTP_USER,
|
|
18
|
+
password: process.env.SMTP_PASSWORD
|
|
19
|
+
}
|
|
20
|
+
return SMTP
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const createTestTransport = (testAccount) => {
|
|
24
|
+
|
|
25
|
+
// create reusable transporter object using the default SMTP transport
|
|
26
|
+
const transporter = nodemailer.createTransport({
|
|
27
|
+
host: "smtp.ethereal.email",
|
|
28
|
+
port: 587,
|
|
29
|
+
secure: false, // true for 465, false for other ports
|
|
30
|
+
auth: {
|
|
31
|
+
user: testAccount.user, // generated ethereal user
|
|
32
|
+
pass: testAccount.pass, // generated ethereal password
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
return transporter
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const createTransport = () => {
|
|
39
|
+
|
|
40
|
+
const SMTP = getSMTPCredentials()
|
|
41
|
+
const transporter = nodemailer.createTransport({
|
|
42
|
+
host: SMTP.host,
|
|
43
|
+
port: SMTP.port || 587,
|
|
44
|
+
secure: SMTP.port === 465, // true for 465, false for other ports
|
|
45
|
+
auth: {
|
|
46
|
+
user: SMTP.user,
|
|
47
|
+
pass: SMTP.password,
|
|
48
|
+
},
|
|
49
|
+
})
|
|
50
|
+
return transporter
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const getTransporter = (testAccount) => {
|
|
54
|
+
if(isProduction) return createTransport()
|
|
55
|
+
return createTestTransport(testAccount)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const getTestAccount = async() => {
|
|
59
|
+
// Generate test SMTP service account from ethereal.email
|
|
60
|
+
// Only needed if you don't have a real mail account for testing
|
|
61
|
+
const testAccount = await nodemailer.createTestAccount()
|
|
62
|
+
console.log('testAccount: ', testAccount)
|
|
63
|
+
return testAccount
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const getFields = fields => {
|
|
67
|
+
let submissionFields=''
|
|
68
|
+
Object.entries(fields).forEach(([field, value]) => {
|
|
69
|
+
let capitalization = field.charAt(0).toUpperCase()+ field.slice(1)
|
|
70
|
+
submissionFields+=`<p><b>${capitalization}:</b> ${value}</p>`
|
|
71
|
+
})
|
|
72
|
+
return submissionFields
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const getAttachments = files => {
|
|
76
|
+
let attachments = []
|
|
77
|
+
Object.entries(files).forEach(([file, fileData]) => {
|
|
78
|
+
attachments.push({
|
|
79
|
+
filename:fileData.originalFilename,
|
|
80
|
+
path:fileData.filepath
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
return attachments
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const mailer = async (fields,files) => {
|
|
87
|
+
|
|
88
|
+
// Generate test SMTP service account from ethereal.email
|
|
89
|
+
// Only needed if you don't have a real mail account for testing
|
|
90
|
+
let testAccount
|
|
91
|
+
if(!isProduction) testAccount = await getTestAccount()
|
|
92
|
+
|
|
93
|
+
let transporter = getTransporter(testAccount)
|
|
94
|
+
|
|
95
|
+
const mailFromName = process.env.MAIL_FROM_NAME
|
|
96
|
+
const mailFrom = process.env.MAIL_FROM_EMAIL
|
|
97
|
+
const mailToName = process.env.MAIL_TO_NAME
|
|
98
|
+
const mailTo = process.env.MAIL_TO_EMAIL
|
|
99
|
+
const mailCC = process.env.MAIL_CC_EMAIL
|
|
100
|
+
const mailBCC = process.env.MAIL_BCC_EMAIL
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
let submissionFields=getFields(fields)
|
|
104
|
+
let attachments = getAttachments(files)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
const mailSubject = fields.subject ? fields.subject : "New submission"
|
|
108
|
+
|
|
109
|
+
// send mail with defined transport object
|
|
110
|
+
let email = await transporter.sendMail({
|
|
111
|
+
from: `${mailFromName} <${mailFrom}>`, // sender address
|
|
112
|
+
to: mailTo, // list of receivers
|
|
113
|
+
cc: mailCC,
|
|
114
|
+
bcc: mailBCC,
|
|
115
|
+
subject: mailSubject, // Subject line
|
|
116
|
+
html:`<p>Hola ${mailToName}, </p>
|
|
117
|
+
<p>You have a new submission on from Contact form.</p>
|
|
118
|
+
<p style="color: #999999;"><strong>SUBMISSION<strong></p>
|
|
119
|
+
${submissionFields}
|
|
120
|
+
`, // html body
|
|
121
|
+
attachments:attachments
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
console.log("Message sent: %s", email.messageId);
|
|
125
|
+
// Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>
|
|
126
|
+
|
|
127
|
+
// Preview only available when sending through an Ethereal account
|
|
128
|
+
console.log("Preview URL: %s", nodemailer.getTestMessageUrl(email))
|
|
129
|
+
// Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
|
|
130
|
+
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
module.exports={
|
|
134
|
+
mailer: mailer,
|
|
135
|
+
getSMTPCredentials: getSMTPCredentials,
|
|
136
|
+
getTestAccount: getTestAccount,
|
|
137
|
+
createTestTransport: createTestTransport,
|
|
138
|
+
createTransport: createTransport,
|
|
139
|
+
getTransporter: getTransporter
|
|
140
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "form-to-mail",
|
|
3
|
+
"version": "1.3.1",
|
|
4
|
+
"description": "A Simple Form Mailer. ✉",
|
|
5
|
+
"main": "app.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "jest",
|
|
8
|
+
"devtest": "node test/devtest.js",
|
|
9
|
+
"devtest:prod": "node test/prodTest.js"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/LazyFolks/form-to-mail.git"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"email",
|
|
17
|
+
"email-sender",
|
|
18
|
+
"form-to-mail",
|
|
19
|
+
"form-mail",
|
|
20
|
+
"form-mailer",
|
|
21
|
+
"formtoemail"
|
|
22
|
+
],
|
|
23
|
+
"author": "Karthik",
|
|
24
|
+
"license": "ISC",
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/LazyFolks/form-to-mail/issues"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/LazyFolks/form-to-mail#readme",
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"dotenv": "^16.0.3",
|
|
31
|
+
"formidable": "^2.0.1",
|
|
32
|
+
"nodemailer": "^6.8.0"
|
|
33
|
+
},
|
|
34
|
+
"directories": {
|
|
35
|
+
"test": "test"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"express": "^4.18.2",
|
|
39
|
+
"form-to-mail": "^1.3.0",
|
|
40
|
+
"jest": "^29.2.2"
|
|
41
|
+
}
|
|
42
|
+
}
|
package/test/devtest.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const express = require('express')
|
|
2
|
+
const app = express()
|
|
3
|
+
const port = 3000
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const formToMail = require(path.join(__dirname,'../','app.js'))
|
|
6
|
+
|
|
7
|
+
const pages = '/pages'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
app.get('/', (req, res) => res.sendFile(path.join(__dirname, pages, 'contact-form.html')))
|
|
11
|
+
app.get('/thank-you', (req, res) => res.sendFile(path.join(__dirname,pages, 'thank-you.html')))
|
|
12
|
+
|
|
13
|
+
app.post('/',formToMail, (req, res) => {
|
|
14
|
+
const fields = req.fields
|
|
15
|
+
const files = req.files
|
|
16
|
+
console.log('fields: ', fields)
|
|
17
|
+
console.log('files: ', files)
|
|
18
|
+
res.redirect(303, '/thank-you')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
app.listen(port, () => {
|
|
23
|
+
console.log(`listening on port ${port}!`)
|
|
24
|
+
console.log(`Contact Form: http://localhost:${port}`)
|
|
25
|
+
console.log(`Thank You: http://localhost:${port}/thank-you`)
|
|
26
|
+
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const { getSMTPCredentials, getTestAccount, getTransporter } = require('../modules/mailer')
|
|
2
|
+
|
|
3
|
+
test('Get SMTP Credentials', () => {
|
|
4
|
+
const SMTPCredentials = getSMTPCredentials();
|
|
5
|
+
expect(SMTPCredentials).toEqual({
|
|
6
|
+
host: "smtp.domain.com",
|
|
7
|
+
port: "587",
|
|
8
|
+
user: "Username",
|
|
9
|
+
password: "password"
|
|
10
|
+
});
|
|
11
|
+
})
|
|
12
|
+
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>Contact Form</title>
|
|
8
|
+
<style>
|
|
9
|
+
* {
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 0;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
}
|
|
14
|
+
body {
|
|
15
|
+
font-family: 'Source Sans Pro', sans-serif;
|
|
16
|
+
}
|
|
17
|
+
.mb-5 {
|
|
18
|
+
margin-bottom: 20px;
|
|
19
|
+
}
|
|
20
|
+
.form-main-wrapper {
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
padding: 48px;
|
|
25
|
+
}
|
|
26
|
+
.form-wrapper {
|
|
27
|
+
margin: 0 auto;
|
|
28
|
+
max-width: 550px;
|
|
29
|
+
width: 100%;
|
|
30
|
+
background: white;
|
|
31
|
+
}
|
|
32
|
+
.form-label {
|
|
33
|
+
display: block;
|
|
34
|
+
font-weight: 500;
|
|
35
|
+
font-size: 16px;
|
|
36
|
+
color: #07074d;
|
|
37
|
+
margin-bottom: 12px;
|
|
38
|
+
}
|
|
39
|
+
.form-input {
|
|
40
|
+
width: 100%;
|
|
41
|
+
padding: 12px 24px;
|
|
42
|
+
border-radius: 6px;
|
|
43
|
+
border: 1px solid #e0e0e0;
|
|
44
|
+
background: white;
|
|
45
|
+
font-weight: 500;
|
|
46
|
+
font-size: 16px;
|
|
47
|
+
color: #6b7280;
|
|
48
|
+
outline: none;
|
|
49
|
+
resize: none;
|
|
50
|
+
}
|
|
51
|
+
.form-input:focus {
|
|
52
|
+
border-color: #5892FF;
|
|
53
|
+
box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.05);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.form-btn {
|
|
57
|
+
text-align: center;
|
|
58
|
+
font-size: 16px;
|
|
59
|
+
border-radius: 6px;
|
|
60
|
+
padding: 14px 32px;
|
|
61
|
+
border: none;
|
|
62
|
+
font-weight: 600;
|
|
63
|
+
background-color: #5892FF;
|
|
64
|
+
color: white;
|
|
65
|
+
cursor: pointer;
|
|
66
|
+
}
|
|
67
|
+
.form-btn:hover {
|
|
68
|
+
box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.05);
|
|
69
|
+
}
|
|
70
|
+
</style>
|
|
71
|
+
</head>
|
|
72
|
+
<body>
|
|
73
|
+
<main>
|
|
74
|
+
<div class="form-main-wrapper">
|
|
75
|
+
<div class="form-wrapper">
|
|
76
|
+
<form action="/" method="POST">
|
|
77
|
+
<div class="mb-5">
|
|
78
|
+
<label for="name" class="form-label"> Full Name </label>
|
|
79
|
+
<input
|
|
80
|
+
type="text"
|
|
81
|
+
name="name"
|
|
82
|
+
id="name"
|
|
83
|
+
placeholder="Full Name"
|
|
84
|
+
class="form-input"
|
|
85
|
+
/>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<div class="mb-5">
|
|
89
|
+
<label for="email" class="form-label"> Email Address </label>
|
|
90
|
+
<input
|
|
91
|
+
type="email"
|
|
92
|
+
name="email"
|
|
93
|
+
id="email"
|
|
94
|
+
placeholder="Enter your email"
|
|
95
|
+
class="form-input"
|
|
96
|
+
/>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<div class="mb-5">
|
|
100
|
+
<label for="subject" class="form-label"> Subject </label>
|
|
101
|
+
<input
|
|
102
|
+
type="text"
|
|
103
|
+
name="subject"
|
|
104
|
+
id="subject"
|
|
105
|
+
placeholder="Enter your subject"
|
|
106
|
+
class="form-input"
|
|
107
|
+
/>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<div class="mb-5">
|
|
111
|
+
<label for="message" class="form-label"> Message </label>
|
|
112
|
+
<textarea
|
|
113
|
+
rows="6"
|
|
114
|
+
name="message"
|
|
115
|
+
id="message"
|
|
116
|
+
placeholder="Type your message"
|
|
117
|
+
class="form-input"
|
|
118
|
+
></textarea>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<div>
|
|
122
|
+
<button class="form-btn">Submit</button>
|
|
123
|
+
</div>
|
|
124
|
+
</form>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</main>
|
|
128
|
+
</body>
|
|
129
|
+
</html>
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>Thank you !</title>
|
|
8
|
+
<style>
|
|
9
|
+
*{
|
|
10
|
+
box-sizing:border-box;
|
|
11
|
+
}
|
|
12
|
+
body{
|
|
13
|
+
background: #ffffff;
|
|
14
|
+
background: linear-gradient(to bottom, #ffffff 0%,#e1e8ed 100%);
|
|
15
|
+
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#e1e8ed',GradientType=0 );
|
|
16
|
+
height: 100%;
|
|
17
|
+
margin: 0;
|
|
18
|
+
background-repeat: no-repeat;
|
|
19
|
+
background-attachment: fixed;
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
.parent-wrapper{
|
|
23
|
+
width:100%;
|
|
24
|
+
height:100vh;
|
|
25
|
+
display: flex;
|
|
26
|
+
flex-direction: column;
|
|
27
|
+
}
|
|
28
|
+
.child-wrapper{
|
|
29
|
+
padding :30px;
|
|
30
|
+
text-align:center;
|
|
31
|
+
}
|
|
32
|
+
h1{
|
|
33
|
+
font-family: 'Kaushan Script', cursive;
|
|
34
|
+
font-size:4em;
|
|
35
|
+
letter-spacing:3px;
|
|
36
|
+
color:#5892FF ;
|
|
37
|
+
margin:0;
|
|
38
|
+
margin-bottom:20px;
|
|
39
|
+
}
|
|
40
|
+
.child-wrapper p{
|
|
41
|
+
margin:0;
|
|
42
|
+
font-size:1.3em;
|
|
43
|
+
color:#aaa;
|
|
44
|
+
font-family: 'Source Sans Pro', sans-serif;
|
|
45
|
+
letter-spacing:1px;
|
|
46
|
+
}
|
|
47
|
+
.go-home{
|
|
48
|
+
color:#fff;
|
|
49
|
+
background:#5892FF;
|
|
50
|
+
border:none;
|
|
51
|
+
padding:10px 50px;
|
|
52
|
+
margin:30px 0;
|
|
53
|
+
border-radius:30px;
|
|
54
|
+
text-transform:capitalize;
|
|
55
|
+
box-shadow: 0 10px 16px 1px rgba(174, 199, 251, 1);
|
|
56
|
+
cursor:pointer;
|
|
57
|
+
}
|
|
58
|
+
.footer-wrapper{
|
|
59
|
+
margin-top: auto;
|
|
60
|
+
background:#D7E6FE;
|
|
61
|
+
padding:6px;
|
|
62
|
+
text-align:center;
|
|
63
|
+
}
|
|
64
|
+
.footer-wrapper p{
|
|
65
|
+
margin:0;
|
|
66
|
+
padding:4px;
|
|
67
|
+
color:#5892FF;
|
|
68
|
+
font-family: 'Source Sans Pro', sans-serif;
|
|
69
|
+
letter-spacing:1px;
|
|
70
|
+
}
|
|
71
|
+
.footer-wrapper p a{
|
|
72
|
+
text-decoration:none;
|
|
73
|
+
color:#5892FF;
|
|
74
|
+
font-weight:600;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@media (min-width:360px){
|
|
78
|
+
h1{
|
|
79
|
+
font-size:4.5em;
|
|
80
|
+
}
|
|
81
|
+
.go-home{
|
|
82
|
+
margin-bottom:20px;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@media (min-width:600px){
|
|
87
|
+
.content{
|
|
88
|
+
max-width:1000px;
|
|
89
|
+
margin:0 auto;
|
|
90
|
+
}
|
|
91
|
+
.parent-wrapper{
|
|
92
|
+
height: initial;
|
|
93
|
+
max-width:620px;
|
|
94
|
+
margin:0 auto;
|
|
95
|
+
margin-top:50px;
|
|
96
|
+
box-shadow: 4px 8px 40px 8px rgba(88, 146, 255, 0.2);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
</style>
|
|
100
|
+
</head>
|
|
101
|
+
<body>
|
|
102
|
+
<main>
|
|
103
|
+
<div class=content>
|
|
104
|
+
<div class="parent-wrapper">
|
|
105
|
+
<div class="child-wrapper">
|
|
106
|
+
<h1>Thank you !</h1>
|
|
107
|
+
<p>we will get in touch with you as soon as possible and</p>
|
|
108
|
+
<p>you should receive a confirmation email soon.</p>
|
|
109
|
+
<button class="go-home" onclick="history.back()">
|
|
110
|
+
go back
|
|
111
|
+
</button>
|
|
112
|
+
</div>
|
|
113
|
+
<div class="footer-wrapper">
|
|
114
|
+
<p>Email not received?
|
|
115
|
+
<a href="#" onclick="history.back()">Click here to send again</a>
|
|
116
|
+
</p>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
</main>
|
|
122
|
+
</body>
|
|
123
|
+
</html>
|
package/test/prodTest.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const express = require('express')
|
|
2
|
+
const app = express()
|
|
3
|
+
const port = 3000
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const formToMail = require('form-to-mail')
|
|
6
|
+
|
|
7
|
+
const pages = '/pages'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
app.get('/', (req, res) => res.sendFile(path.join(__dirname, pages, 'contact-form.html')))
|
|
11
|
+
app.get('/thank-you', (req, res) => res.sendFile(path.join(__dirname,pages, 'thank-you.html')))
|
|
12
|
+
|
|
13
|
+
app.post('/',formToMail, (req, res) => {
|
|
14
|
+
const fields = req.fields
|
|
15
|
+
const files = req.files
|
|
16
|
+
console.log('fields: ', fields)
|
|
17
|
+
console.log('files: ', files)
|
|
18
|
+
res.redirect(303, '/thank-you')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
app.listen(port, () => {
|
|
23
|
+
console.log(`listening on port ${port}!`)
|
|
24
|
+
console.log(`Contact Form: http://localhost:${port}`)
|
|
25
|
+
console.log(`Thank You: http://localhost:${port}/thank-you`)
|
|
26
|
+
})
|