1+ import nodemailer from 'nodemailer' ;
2+
3+ import { catchErrors , reportError } from '../errors' ;
4+ import { delay } from '@httptoolkit/util' ;
5+ import { getCorsResponseHeaders } from '../cors' ;
6+
7+ const {
8+ CONTACT_FORM_DESTINATION ,
9+ SMTP_HOST ,
10+ SMTP_PORT ,
11+ SMTP_USERNAME ,
12+ SMTP_PASSWORD
13+ } = process . env ;
14+
15+ if ( ! CONTACT_FORM_DESTINATION ) throw new Error ( 'No contact form destination configured' ) ;
16+
17+ if ( ! SMTP_HOST ) throw new Error ( 'No SMTP host configured' ) ;
18+ if ( ! SMTP_PORT ) throw new Error ( 'No SMTP port configured' ) ;
19+ if ( ! SMTP_USERNAME ) throw new Error ( 'No SMTP user configured' ) ;
20+ if ( ! SMTP_PASSWORD ) throw new Error ( 'No SMTP password configured' ) ;
21+
22+ const mailer = nodemailer . createTransport ( {
23+ host : SMTP_HOST ,
24+ port : Number ( SMTP_PORT ) ,
25+ secure : true ,
26+ auth : {
27+ user : SMTP_USERNAME ,
28+ pass : SMTP_PASSWORD
29+ }
30+ } ) ;
31+
32+ const THANK_YOU_PAGE = 'https://httptoolkit.com/contact-thank-you/'
33+
34+ export const handler = catchErrors ( async ( event ) => {
35+ let headers = getCorsResponseHeaders ( event ) ;
36+
37+ if ( event . httpMethod === 'OPTIONS' ) {
38+ return { statusCode : 200 , headers, body : '' } ;
39+ } else if ( event . httpMethod !== 'POST' ) {
40+ return { statusCode : 405 , headers, body : '' } ;
41+ }
42+
43+ const formData = new URLSearchParams ( event . body || '' ) ;
44+ const {
45+ name,
46+ email,
47+ message,
48+ phone : honeypot
49+ } = Object . fromEntries ( formData ) ;
50+
51+ if ( honeypot ) {
52+ // We can remove this later - just reporting each hit for now to check if it's working
53+ reportError ( 'Contact form honeypot triggered' , {
54+ extraMetadata : { name, email, message, honeypot }
55+ } ) ;
56+
57+ // Pretend it did actually work so they don't try again:
58+ await delay ( 1000 ) ;
59+ return {
60+ statusCode : 302 ,
61+ headers : {
62+ Location : THANK_YOU_PAGE
63+ } ,
64+ body : ''
65+ } ;
66+ }
67+
68+ const fields = [
69+ [ 'Name' , name ] ,
70+ [ 'Email' , email ] ,
71+ [ 'Message' , message ]
72+ ]
73+
74+ fields . forEach ( ( [ field , value ] ) => {
75+ if ( ! value ) {
76+ return {
77+ statusCode : 400 ,
78+ headers,
79+ body : `${ field } is required`
80+ } ;
81+ }
82+ } ) ;
83+
84+ await mailer . sendMail ( {
85+ from :
'Contact form <[email protected] >' , 86+ to : CONTACT_FORM_DESTINATION ,
87+ replyTo : email ,
88+ subject : 'HTTP Toolkit contact form message' ,
89+ html : `<html><style>p { margin-bottom: 10px; }</style><body>
90+ ${
91+ fields . map ( ( [ field , value ] ) => {
92+ return `<p><strong>${ field } </strong>:<br/>${ value } </p>` ;
93+ } ) . join ( '' )
94+ } </body></html>`
95+ } ) ;
96+
97+ return {
98+ statusCode : 302 ,
99+ headers : {
100+ Location : THANK_YOU_PAGE
101+ } ,
102+ body : ''
103+ } ;
104+ } ) ;
0 commit comments