NoSpam - a General Spam Protection Control
Overview
NoSpam is a user control (.ascx) for the n-gen.net CMS that provides comprehensive spam protection for web forms. It implements multiple layers of defence including honeypot fields, time-based validation, user interaction tracking, rate limiting, and content filtering - all without requiring CAPTCHA.
The control is designed to be easily integrated into any ASP.NET WebForms page and is fully configurable through public properties.
Features
a. Multi-Layer Protection
Honeypot Field - A hidden field that is invisible to humans but visible to bots. When filled, the submission is blocked.
Time Validation - Requires a minimum time (default 3 seconds) between page load and form submission, preventing automated rapid submissions.
Interaction Tracking - Monitors mouse movement, keyboard input, and touch events to verify human interaction.
Rate Limiting - Prevents flooding with per-minute (default 3) and per-hour (default 20) limits.
Duplicate Detection - Identifies and blocks identical messages sent within 5 minutes.
Referrer Validation - Ensures submissions originate from the same domain.
Content Filtering - Scans for suspicious patterns, spam keywords, and common XSS vectors.
b. User Experience
Clear Error Messages - Users receive specific feedback about why their submission was blocked.
Configurable Limits - All protection parameters can be adjusted per form.
Logging - All security events are logged for monitoring and debugging.
Transparent Operation - Legitimate users rarely notice the protection is active.
Usage
Basic Integration
<%@ Register Src="~/nospam.ascx" TagName="NoSpam" TagPrefix="uc" %>
<uc:NoSpam ID="NoSpam1" runat="server" />
Required Validation in Code-Behind
protected void btnSend_Click(object sender, EventArgs e)
{
// Validate the nospam control
NoSpam1.Validate();
if (!NoSpam1.IsValid)
{
string errorMessage = NoSpam1.ErrorMessage;
if (string.IsNullOrEmpty(errorMessage))
{
errorMessage = "Spam protection triggered. Please try again.";
}
ShowError(errorMessage);
return;
}
// Proceed with form processing...
}
Technical Details
Control Properties
|
Property
|
Type |
Default |
Description |
| MinTimeSeconds |
int |
3 |
Minimum seconds required between page load and form submission |
| HoneypotFieldName |
string |
"middleName" |
Name of the hidden honeypot field |
| EnableAdvancedChecks |
bool |
true |
Enable/disable content filtering |
| MaxMessagesPerHour |
int |
20 |
Maximum messages allowed per hour per IP |
| MaxMessagesPerMinute |
int |
3 |
Maximum messages allowed per minute per IP |
| LogSuccess |
bool |
false |
Enable logging of successful submissions |
| ErrorMessage |
string |
"Are you human?" |
Custom error message |
| EnableDebugLogging |
bool |
false |
Enable/disable detailed logging for debug |
Parameter Recommendations
| Form Type |
MinTimeSeconds |
MaxMessagesPerHour |
MaxMessagesPerMinute |
EnableAdvancedChecks |
| Contact Form |
3-5 |
5-10 |
2-3 |
true |
| Registration/Signup |
5-10 |
3-5 |
1-2 |
true |
| Support/Feedback |
2-3 |
20-30 |
5-10 |
false |
| Newsletter Signup |
2 |
10-20 |
3-5 |
false |
| Comment Form |
3 |
10-15 |
3-5 |
true |
| Iframe Embedded |
1-2 |
10-20 |
3-5 |
false |
Validation Order
- Rate Limit (per-minute and per-hour)
- Honeypot Field
- User Interaction
- Time Validation
- Referrer Validation
- Advanced Content Checks
Important:
Rate limiting applies to all users, including logged-in users. Other checks may be skipped for authenticated users to prevent false positives.
Logging
The control logs to multiple locations:
Primary Log: /App_Data/pro_mail.log
- All security events are logged here
- Includes timestamp, user, IP, and specific reason
Debug Log: /App_Data/nospam_debug.log
- Detailed step-by-step validation logs
- Useful for troubleshooting
Log Entry Format:
Example
2026-07-08 12:34:56.789 -- NoSpam -- [SECURITY] -- IP: 85.191.109.xxx -- RateLimit: Duplicate message detected within 5 minutes
When LogSuccess="true":
2026-07-13 14:23:45.123 -- NoSpam -- [SUCCESS ] -- User: Level 2 -- IP: 85.191.109.xxx -- SUCCESS
When EnableDebugLogging="true":
2026-07-13 14:23:45.123 -- NoSpam -- [DEBUG ] -- User: Level 2 -- IP: 85.191.109.xxx -- [VALIDATION START] Beginning spam validation
2026-07-13 14:23:45.124 -- NoSpam -- [DEBUG ] -- User: Level 2 -- IP: 85.191.109.xxx -- [RATE LIMIT PASSED] OK
2026-07-13 14:23:45.124 -- NoSpam -- [DEBUG ] -- User: Level 2 -- IP: 85.191.109.xxx -- [HONEYPOT PASSED] Field is empty
2026-07-13 14:23:45.124 -- NoSpam -- [DEBUG ] -- User: Level 2 -- IP: 85.191.109.xxx -- [INTERACTION PASSED] User interacted with page
When Spam is Blocked:
2026-07-13 14:23:45.123 -- NoSpam -- [SECURITY] -- User: Level 1 -- IP: 85.191.109.xxx -- NoSpam: Duplicate message detected within 5 minutes -- UA: Mozilla/5.0...
Security Considerations
Access Control
- The control does not require specific user levels
- It works for both anonymous and authenticated users
- Authenticated users receive fewer restrictions
Data Protection
- Honeypot field is hidden using CSS positioning
- Form field names are configurable to avoid detection
- All user input is validated server-side
- No sensitive data is stored in client-side code
Rate Limiting Data
- Stored in Application cache (in-memory)
- Tracks per IP address
- Automatically expires after 1 hour
- Dedicated storage for duplicate content detection
Integration Examples
Example 1: Contact Form
html
<%@ Register Src="~/nospam.ascx" TagName="NoSpam" TagPrefix="uc" %>
<div class="form-group">
<label for="txtMessage">Your Message</label>
<asp:TextBox ID="txtMessage" runat="server" TextMode="MultiLine" />
</div>
<div class="form-group">
<uc:NoSpam ID="NoSpam1" runat="server" MinTimeSeconds="3" />
</div>
<asp:Button ID="btnSend" runat="server" Text="Send" OnClick="btnSend_Click" />
Code-Behind:
protected void btnSend_Click(object sender, EventArgs e)
{
NoSpam1.Validate();
if (!NoSpam1.IsValid)
{
ShowError(NoSpam1.ErrorMessage);
return;
}
// Process message...
}
Example 2: Signup Form (Stricter)
<uc:NoSpam ID="NoSpam1" runat="server"
MinTimeSeconds="5"
MaxMessagesPerHour="3"
MaxMessagesPerMinute="1"
EnableAdvancedChecks="true" />
Example 3: Newsletter Signup (Less Strict)
<uc:NoSpam ID="NoSpam1" runat="server"
MinTimeSeconds="2"
MaxMessagesPerHour="10"
MaxMessagesPerMinute="2"
EnableAdvancedChecks="false" />
For iframe Compatibility (I.e. contactSimple.aspx)
When using the control in an iframe, use the wrapper approach:
private bool ValidateNoSpam()
{
try
{
var noSpam = pnlNoSpam.FindControl("NoSpam1") as UserControl;
if (noSpam == null)
{
LogToFile("WARNING", "ContactSimple", "NoSpam1 control not found - skipping validation");
return true;
}
var validateMethod = noSpam.GetType().GetMethod("Validate");
if (validateMethod != null)
{
validateMethod.Invoke(noSpam, null);
}
var isValidProperty = noSpam.GetType().GetProperty("IsValid");
if (isValidProperty != null)
{
bool isValid = (bool)isValidProperty.GetValue(noSpam, null);
if (!isValid)
{
var errorProp = noSpam.GetType().GetProperty("ErrorMessage");
if (errorProp != null)
{
string errorMsg = (string)errorProp.GetValue(noSpam, null);
if (!string.IsNullOrEmpty(errorMsg))
{
ShowError(errorMsg);
}
else
{
ShowError("Spam protection triggered. Please try again.");
}
}
else
{
ShowError("Spam protection triggered. Please try again.");
}
return false;
}
}
return true;
}
catch (Exception ex)
{
LogToFile("ERROR", "ContactSimple", "NoSpam validation error: " + ex.Message);
return true;
}
}
Troubleshooting
Error:
"Spam protection triggered"
Possible Causes:
- Form submitted too quickly (less than MinTimeSeconds)
- User didn't interact with the page
- Honeypot field was filled (often by browser autofill)
Solutions:
- Wait at least 3 seconds before submitting
- Click or type in the form before submitting
- Disable browser autofill or test in incognito mode
Error:
"You are sending messages too quickly"
Possible Causes:
- More than MaxMessagesPerMinute submissions
- More than MaxMessagesPerHour submissions
Solutions:
- Wait a minute before trying again
- The limit resets automatically after 1 hour
Error:
"It looks like you're sending the same message again"
Possible Causes:
- Sending identical message content within 5 minutes
Solutions:
- Change the message slightly
- Wait 5 minutes before sending the same message
Error:
"Invalid characters detected"
Possible Causes:
- The message contains characters not allowed by the whitelist
- HTML tags or script injections are blocked
- Solutions:
- Use only letters, numbers, spaces, and common punctuation
- Avoid using <, >, ", ' or script tags
Error:
"Your message contains suspicious content"
Possible Causes:
- Message contains spam keywords (viagra, casino, loans, etc.)
- Message consists of random letters with no spaces
Solutions:
- Write a proper message with real words and punctuation
- Avoid spammy keywords
Debugging
Enable detailed logging:
<uc:NoSpam ID="NoSpam1" runat="server" LogSuccess="true" />
Check log files:
- /App_Data/pro_mail.log - Main security log
- /App_Data/nospam_debug.log - Detailed validation steps
View validation results:
NoSpam1.Validate();
bool isValid = NoSpam1.IsValid;
string errorMessage = NoSpam1.ErrorMessage;
Best Practices
- Set appropriate limits - Adjust MaxMessagesPerHour and MaxMessagesPerMinute based on expected usage
- Test with real users - Ensure the protection doesn't block legitimate users
- Monitor logs - Regularly review /App_Data/pro_mail.log for security events
- Keep defaults unless needed - The default settings work well for most forms
- Use with other protections - Combine with server-side validation and email filtering
- Educate users - Consider adding help text explaining the spam protection
- Update the control - Keep the control updated with the latest security patches