I'll assign the email address I obtained to the contact form.
Contact Form.
When building a website on a CMS like Drupal or WordPress, it's standard practice to set up a contact form for receiving inquiries from visitors by email, and I use one myself. Listing an email address directly on the website with mailto: exposes it to malicious bots that harvest addresses and flood you with spam — and in some cases the security implications go beyond that.
Beyond that, presenting inquiry content in a template format makes it easier for visitors to reach out, and makes it easier for the recipient to receive messages in an organized form. This makes it easier to respond in turn. The contact form serves both to protect against malicious bots and to make it easier for visitors to get in touch.
In WordPress, plugins like Contact Form 7 and WPForms are available and can be added to a website very easily, making them a popular choice for contact mail. Drupal includes Contact Form functionality as standard.
Here I configure the Contact Form and run a test using the email account on the domain I registered with AWS. When I run the test, a send error appears and mail won't go through, so I trace the cause and work through the following process to get the contact form working.
1. Testing with Drupal Defaults
- Configure the Contact Form
- Assign the email on the AWS domain
- Configure reCAPTCHA
- Test the contact form
- Mail send error
- Trace the cause
2. Testing with SES SMTP
- Configure SMTP
- Configure SES SMTP
- Test the contact form
- Mail send error
- Trace the cause
3. Resolving the Address Mismatch
- Error caused by mismatch between registered user email and contact form email
- Update the user email address
- Test the contact form
- Problem resolved
The cause has been identified and the form is now working. The cause was simple — a mistake on my part. The email used when registering the user and the email assigned as the contact form recipient were different, which prevented mail from sending.
Without realizing this, I ended up not using Drupal's default mail sending and instead configuring AWS SES and SMTP. You could call it a blessing in disguise — at this point the contact form sends through SES SMTP, which gives better response times than a standard mail assignment.
This article covers everything from the initial contact form test through the SMTP module and SES configuration, to fixing the address mismatch and resolving the send error.
1. Configuring the Contact Form.
I've registered a domain through AWS and configured an email account on that domain. I'll now configure the Contact Form to receive inquiries using that email account.
- Log in to the Drupal admin
- Home > Administration > Structure > Contact forms { / / Select Contact forms }
- The screen below appears — click 'Edit' for the Inquiry form.
Home > Administration > Structure > Contact forms
1-1. Contact form.
Home > Administration > Structure > Contact forms | |||
+ Add contact form | |||
Form | Recipients | Selected | Operations |
Inquiry | info@my-domain.com | Yes | Edit |
Website feedback | user@example.com | No | Edit |
Personal contact form | Selected users | No | Manage fields |
Select 'Edit' for the Inquiry form. The screen below appears — fill in the required fields.
Home > Administration > Structure > Contact forms > Manage > Edit contact form
1-2. Editing the Contact Form.
Home > Administration > Structure > Contact forms > Manage > Edit contact form | ||||
View | Edit | Manage fields | Manage form display | Manage display |
Label | ||||
Inquiry { // Contact form name } | Machine name: { contact } | |||
Enter a descriptive category name for users. e.g. 'Site feedback', 'Product information request' | ||||
Recipients | ||||
info@my-domain.com { // Email account obtained through AWS } | ||||
e.g. 'webmaster@example.com' or 'sales@example.com,support@example.com'. For multiple recipients, separate addresses with commas. | ||||
Message | ||||
{ Leave blank — not used } | ||||
The message to display to users after the form is submitted. Leave blank to display no message. | ||||
Redirect path | ||||
/ { Specify '/' to redirect to the top page after sending } | ||||
The path users are redirected to after submitting the form. For example, entering '/about' will redirect to that page. Use a relative path starting with a slash. | ||||
Auto-reply | ||||
{ Leave blank — not used } | ||||
If you would like to auto-reply to the user, enter the message here. Leave blank if you do not want to send an auto-reply. | ||||
Weight | ||||
0∨ { Can be set from negative to positive, but select 0 } | ||||
Forms are sorted from the lightest (smallest) weight to the heaviest (largest). Forms with the same weight are sorted alphabetically. | ||||
✓ Make this the default form { // Check to enable. } | ||||
Save / Delete { Select Save } | ||||
Once the required fields are filled in and saved:
- Manage fields // Configure additional fields.
- Manage form display // Manage the form's display settings.
- Manage display // Customize which field items are displayed.
These can be configured, but since this is a test I'll skip them for now.
1-3. Setup Complete.
Once these settings are complete,
the contact form is accessible at https://my-domain.com/contact.
2. Configuring reCAPTCHA.
When building a website on a CMS like Drupal or WordPress, the fixed site structure means that once the site is published, there's a real risk of attacks and malicious intrusion. Spam attacks via bots on the contact form, and in some cases attempts to hack the admin login, are real concerns that require security measures.
Google reCAPTCHA, provided by Google, is well known and capable as a tool for detecting and blocking repeated submissions, suspicious submissions, and suspicious login attempts, so I'll use it.
In WordPress, well-known contact form plugins like Contact Form 7 and WPForms include built-in reCAPTCHA configuration. In Drupal, I use modules to configure Google reCAPTCHA.
2-1. Configuring the CAPTCHA Module.
To use Google reCAPTCHA in Drupal, two modules are needed.
Additionally, since I'm using v2 as the challenge type within v3, I also install reCAPTCHA.
Log in to Bitnami via SSH and install each with Composer.
Install CAPTCHA
$ sudo composer require 'drupal/captcha:^2.0'Install reCAPTCHA v3
$ sudo composer require 'drupal/recaptcha_v3:^2.0'Install reCAPTCHA
$ sudo composer require 'drupal/recaptcha:^3.4'
2-2. Configuring Google reCAPTCHA.
To use Google reCAPTCHA,
https://www.google.com/recaptcha/about/
log in and proceed through the following:
- Register the domain for reCAPTCHA v3
- Select v2 / v3
- Obtain the v3 site key and secret key
- Register the domain for reCAPTCHA
- Select v2 / v3
- Obtain the v2 site key and secret key
These are the steps I go through.
I select both v2 and v3, but I default to v3. The difference is that v2 always requires verification (the familiar image selection), while v3 allows whitelisted users to proceed without any check.
Drupal's default CAPTCHA challenge uses image-based number verification and simple math problems. Since I want to use the reCAPTCHA v2 form as the challenge type, I register both v3 and v2 separately and obtain keys for each.
For admin logins, if the same IP, user agent, and cookies are present as a previous session, the user is recognized and no challenge is required on subsequent visits. A change of IP or device will trigger a verification.
A Google account is required. If you don't have one, you'll need to create one.
2-3. Configuring the CAPTCHA Module.
reCAPTCHA v3 is an extension of the CAPTCHA module. The base configuration is done in CAPTCHA, reCAPTCHA v3 settings are handled within CAPTCHA, and the challenge method uses reCAPTCHA v2 image verification.
2-3-1. Configuring CAPTCHA.
The CAPTCHA settings configure the basic behavior on the Drupal pages where reCAPTCHA is placed.
Home > Administration > Configuration > People > CAPTCHA settings
- Default challenge type // reCAPTCHA v3 (provided by the reCAPTCHA v3 module)
- Challenge title // reCAPTCHA
- Challenge description // This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
- Wrong CAPTCHA response error message // The answer you entered for the CAPTCHA was not correct.
- Default CAPTCHA validation // Select case insensitive validation
- Persistence // Omit challenges in a multi-step/preview workflow once the user successfully responds to a challenge.
- Save configuration
2-3-2. Configuring the reCAPTCHA v3 Module.
This configures the reCAPTCHA v3 loaded by CAPTCHA. Enter the site key and secret key issued by Google. Since reCAPTCHA v2 is used as the fallback, specify reCAPTCHA, check the error message, and save the configuration.
Home > Administration > Configuration > People > CAPTCHA settings > ReCAPTCHA V3 Settings
- Site key // Enter the site key issued by Google reCAPTCHA [40-character alphanumeric string}
- Secret key // Enter the secret key issued by Google reCAPTCHA [40-character alphanumeric string}
- Local domain name validation // Check to enable
- Default fallback challenge type // reCAPTCHA (provided by the reCAPTCHA module)
Options are None, Math, Image, and reCAPTCHA — select reCAPTCHA - Error message // To prevent unauthorized access, reCAPTCHA is configured with a higher threshold. We apologize for the inconvenience, but please follow the reCAPTCHA instructions to submit your message.
- Save configuration
2-3-3. reCAPTCHA v3 Action Settings.
This configures the behavior of reCAPTCHA v3 — specifically the threshold for distinguishing humans from bots, and what challenge to present when a bot is suspected. Lowering the threshold relaxes the judgment. While 1 is the strictest setting, it can be a bit harsh, so setting a value between 0.5 and 1 is recommended.
Home > Administration > Configuration > People > CAPTCHA settings > ReCAPTCHA V3 Actions
+Add reCAPTCHA v3 action
Label-//-Action-//-Threshold-//-Fail challenge-//-Operations
reCAPTCHA v3 action-//-recaptcha_v3_action-//-0.8-//-reCAPTCHA (provided by the reCAPTCHA module)-//-Edit
- Label // reCAPTCHA v3 action
- Threshold // 0.8
- Fallback challenge // reCAPTCHA (provided by the reCAPTCHA module)
- Save configuration
2-3-4. Configuring the reCAPTCHA Module.
Since I'm using reCAPTCHA v2 as the challenge within reCAPTCHA v3, I configure the reCAPTCHA module. Enter the v2 site key and secret key issued by Google, select the display style for the image challenge, and save the configuration.
Home > Administration > Configuration > People > CAPTCHA settings > ReCAPTCHA
- Site key // Enter the site key issued by Google reCAPTCHA [40-character alphanumeric string}
- Secret key // Enter the secret key issued by Google reCAPTCHA [40-character alphanumeric string}
- Local domain name validation // Check to enable
- Widget settings
- Theme // Light (default)
- Type // Image (default)
- Size // Normal (default)
- Save configuration
2-3-5. Configuring CAPTCHA Points.
In the CAPTCHA Points settings, I specify the page (in practice, the form ID) where reCAPTCHA v3 authentication is applied and enable it. Here I specify the contact form. It's not registered by default, so I use Add CAPTCHA Point to add the form ID and enable it.
Home > Administration > Configuration > People > CAPTCHA settings > CAPTCHA Configuration
+Add CAPTCHA Point
Captcha Point form ID-//-Captcha Point challenge type-//-Status-//-Operations
contact_form_001-//-recaptcha_v3/recaptcha_v3_action-//-Enabled-//-Edit
Click Add CAPTCHA Point to add the contact form and enable CAPTCHA.
When adding, enter the Form ID and specify the challenge type (ReCAPTCHA v3).
contact_form_001 // The form ID of the contact form created with WebForm
// The easiest way to find the form ID is to look near the submit button in the HTML source of the contact form page. Look for: name="form_id" value= // The value that follows is the form ID for this page.
type="hidden" name="form_id" value=contact_form_001
2-4. Setup Complete.
This completes the reCAPTCHA configuration.
With this configuration in place, the reCAPTCHA icon appears on the specified contact form.
3. Verifying the Contact Form.
With the contact form and reCAPTCHA configured, I test whether both are working. I open the contact form page.
- The contact form opens at /contact.
- The reCAPTCHA icon is showing.
- Fill in the required fields and click the send button.
- The Google reCAPTCHA v2 image verification screen appears — I follow the instructions, select the specified images, and click submit.
- I'm redirected to the top page, where a send error appears at the top.
To trace the cause of the error, I temporarily clear the reCAPTCHA settings and try sending again without reCAPTCHA.
- Even with reCAPTCHA disabled, the same error appears, so I suspect the mail server.
- To narrow down whether the issue is with Drupal Core's mail sending or with AWS mail, I send a test email from the MacBook mail client to the AWS mail account rather than using the contact form, confirm receipt, then confirm a reply.
- In this test, there's no problem with the AWS mail account.
At this point, the most likely explanation is that the SMTP for the email address registered in Drupal isn't working. Since the same setup works fine on my Drupal running on Xserver, it seems Drupal Core can't drive AWS SMTP. I look for a way to use an external SMTP in Drupal.
4. SMTP Authentication Support.
I look for a Drupal module that allows use of an external SMTP.
This module handles it, so I install it right away.
Installing SMTP Authentication Support
$ sudo composer require 'drupal/smtp:^1.4'This is the module for using an external SMTP in Drupal. The configuration is straightforward, so I set it up right away.
Home > Administration > Configuration > System > SMTP Authentication Support
4-1. Configuring SMTP Authentication Support.
Install options
- Set SMTP as the default mailsystem // On
SMTP server settings
- SMTP server // email-smtp.ap-xxxxxx-1.amazonaws.com
- SMTP backup server // Leave blank
- SMTP port // 25, 587, etc.
- Use encrypted protocol // Use TLS
- Enable TLS encryption automatically // On
- Timeout // 30
- Username // SMTP username specified by SES
- Password // SMTP password specified by SES
E-mail options
- Hostname // Leave blank
- HELO // Leave blank
Send test e-mail
- E-mail address to send a test e-mail to // Leave blank
- E-mail address to reroute all emails to // Leave blank
Save configuration
With SMTP Authentication Support configured, Drupal can now use an external SMTP. I set up SMTP authentication on the AWS side to allow access from Drupal. Once the SMTP credentials are registered in SMTP Authentication Support, Drupal can send mail through AWS SMTP.
I configure the external SMTP connection in AWS SES (Simple Email Service).
5. SES (Simple Email Service).
I configure the SMTP authentication that Drupal uses to connect, in AWS SES (Simple Email Service).
Opening the SES Console
- Log in to the AWS Management Console
- Enter "SES" or "Simple Email" in the search bar to find SES
- Select SES from the search results
- Amazon Simple Email Service — Get started // Click Get started
- The Amazon Simple Email Service console opens.
The Amazon SES console is displayed.
Click "SMTP settings" in the left-hand menu.
The Simple Mail Transfer Protocol (SMTP) settings appear.
5-1. Simple Mail Transfer Protocol (SMTP) Settings.
- SMTP endpoint // email-smtp.region.amazonaws.com
- Transport Layer Security (TLS) // Required
- STARTTLS port // 25, 587, or 2587
- Custom SSL client support -
- TLS wrapper port // 465 or 2465
Click "Create SMTP credentials."
AWS manages the credentials that allow external SMTP access through IAM. This means SMTP credentials are configured and managed in IAM, not in SES. Clicking the button takes you from the SES console to the IAM console.
In the IAM console that opens, I create the SMTP credentials.
5-2. Creating SMTP Credentials.
IAM / Users / Create user
Create an IAM user with SMTP credentials for SMTP authentication with Amazon SES.
- Specify user details // A name like ses-smtp-user.YYYY-date-xxxxxx is auto-generated. Leave as-is if no changes are needed.
- Permissions // The group the SES-created user belongs to is displayed. Leave as-is if no changes are needed.
- Tags // Create if needed; fine to leave blank.
- Click Create user.
Proceed to obtaining the SMTP credentials.
- Note down the ID and password displayed. (Can be copied)
- A CSV file can be downloaded — save it to your computer.
This completes the setup, allowing Drupal to access AWS SMTP.
Return to the Drupal admin and register the obtained SMTP credentials in SMTP Authentication Support.
5-3. Registering Credentials in SMTP Authentication Support.
SMTP server settings
- SMTP server // email-smtp.ap-xxxxxx-1.amazonaws.com
- SMTP backup server // Leave blank
- SMTP port // 25, 587, etc.
- Use encrypted protocol // Use TLS
- Enable TLS encryption automatically // On
- Timeout // 30
- Username // SMTP username specified by SES
- Password // SMTP password specified by SES
For 7., enter the ID just issued.
For 8., enter the password just issued and save the configuration. Drupal will then connect to SES SMTP and mail sending becomes available.
If there are any configuration issues, an error appears when saving SMTP Authentication Support. If no error appears, the settings are valid and mail can be sent through SES SMTP.
5-4. Setup Complete.
Drupal is now configured to use AWS SMTP, and is ready to receive messages from the contact form at the email address on the registered domain.
I verify whether using an external SMTP has resolved the mail send error.
6. Verifying the Contact Form.
I run the same verification as in Section 3 — but the error hasn't been resolved...
Looking at the error, it's different from the one in Section 3. The answer is right there in the error displayed on the top page I was redirected to. The cause turns out to be simple.
The error message reads "Please check your iCloud SMTP." iCloud??? — but the cause becomes clear immediately. When I first installed Drupal on Lightsail, the email address used for the initial user registration was my personal iCloud address, since I hadn't registered a domain yet. I'd forgotten to update that placeholder address.
I immediately change the user email from the personal iCloud address to the email address on the AWS domain. After the change, sending a message from the contact form goes through without any issues.
The reason this article turned out so long was simply that I'd forgotten to update the placeholder email address.
- Incorrect: User registration email -- user@icloud.com / Contact form email -- info@my-domain.com
- Corrected: User registration email -- info@my-domain.com / Contact form email -- info@my-domain.com
When attempting to send from the contact form, Drupal calls the SMTP of the registered user email — iCloud — which differs from the AWS email address assigned to the contact form. That mismatch was the cause of the error.
The article goes on at length about the process of resolving the mail send error, but the root cause was an extremely simple mistake. With the cause identified and addressed, the goal of using the AWS domain email in Drupal as the contact form recipient has been achieved. The contact form has worked without issue ever since.
This article covers the contact form testing process. When actually using the contact form in practice, I've added fields and descriptive text. I hope to cover that kind of content in a future article on building pages in Drupal.
What the error helped me understand:
- The SMTP used by Drupal is the default SMTP of the registered user email.
- Drupal doesn't have its own built-in capability to send mail via SMTP.
- Simply put, it works in a similar way to a mailto: link in HTML.
- Contact form mail is sent using the SMTP of the registered user email address.
- In this case, a send request for the AWS domain address registered in the contact form was going to the iCloud SMTP of the registered user email — that mismatch was the cause of the error.
At the scale of this website, with hardly any mail volume, an external SMTP isn't actually needed. Simply using the registered domain email address for both the user registration and the contact form would have been fine.
That's what I came to understand.
A blessing in disguise — if this error hadn't occurred, I'd never have thought to use a dedicated, high-performance external SMTP for Drupal's mail function. The effect is noticeable: using a dedicated SMTP speeds up both sending and receiving.
Since I've gone to the trouble of setting it up, I'll keep running with the external SMTP for a while — even though it's overkill for this site's contact form usage. AWS offers a free tier for SES when the volume of mail sent isn't that large.
SES's mail delivery service is designed as a high-performance system for enterprises sending large volumes of customer communications. It's built to handle large-scale delivery to many recipients, and is used by major companies worldwide.
7. Summary.
A summary of this article.
Contact Form Setup and Error Resolution.
- Use the email on the AWS domain as Drupal's default mail
- Use it as the recipient for the contact form
- Use Google reCAPTCHA since the contact form is in use
- Use the CAPTCHA, reCAPTCHA v3, and reCAPTCHA modules; manage authentication with reCAPTCHA v3, using reCAPTCHA v2 as the challenge
- An error prevents mail from sending, so I enable an external SMTP
- Use SMTP Authentication Support as the module for enabling external SMTP
- Since AWS is the external SMTP, manage SMTP through SES and configure authentication for access from Drupal
- Authentication management is handled through IAM, not SES
- The cause of the error turns out to be not a system issue but a mistake in the registered email; the registered email is corrected
- Correcting the registered email resolves the error and fixes the mail send problem
- Gained an understanding of Drupal's mail processing
- Keep the configured external SMTP in place; the effect is improved mail response times
The error that arose from a mistake in the contact form setup led me through various tests and into installing modules I hadn't originally planned to use. Through that process, I gained a better understanding of both Drupal and AWS — and I consider that the real takeaway from this article.
Summary of the Lightsail Setup Articles.
After five articles covering Amazon Lightsail, the long-form content has piled up and the overall picture has become hard to follow. The next article provides a summary. From there, the series moves on to Drupal-related content.