Files
contact/Pages/Contact.cshtml.cs

99 lines
3.3 KiB
C#

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using contact.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace contact.Pages
{
[BindProperties(SupportsGet = true)]
public class ContactFormModel
{
public ContactFormModel()
{
DbId = "n/a v7";
}
[Required]
public string Name { get; set; }
[Required]
public string Company { get; set; }
//Optional; AyaNova clients deep-link to this page with their database ID.
//Binding attributes left exactly as they were so that link keeps working.
[BindProperty(SupportsGet = true)]
public string DbId { get; set; }
[Required, EmailAddress]
public string Email { get; set; }
[Required]
public string Message { get; set; }
}
public class ContactModel : PageModel
{
private const string ConfirmedUrl = "https://ayanova.com/confirmed.htm";
//2022-05-06 Company names containing any of these are dropped silently but still get the
//success redirect, so the spammer gets no signal and has to pay someone to enter them by hand
public static readonly string[] SpamBlocks = { "google", "jumboleadmagnet", "boostleadgeneration" };
[BindProperty(SupportsGet = true)]
public ContactFormModel Contact { get; set; }
//Set when the send fails, so the page can tell the visitor instead of claiming success
public bool SendFailed { get; set; }
private readonly MailSender _mail;
private readonly ILogger<ContactModel> _logger;
public ContactModel(MailSender mail, ILogger<ContactModel> logger)
{
_mail = mail;
_logger = logger;
}
public void OnGet()
{
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
//2025-11-01 reCAPTCHA removed (Google service change). Replacement deferred, see runbook Phase 6.
if (IsBlocked(Contact.Company))
{
return Redirect(ConfirmedUrl);
}
//Email is in the body as well as Reply-To, so it survives even if Reply-To can't be set
var body = $"Name:\r\n{Contact.Name}\r\n\r\nCompany:\r\n{Contact.Company}\r\n\r\nEmail:\r\n{Contact.Email}\r\n\r\nDatabase Id:\r\n{Contact.DbId}\r\n\r\nMessage:\r\n{Contact.Message}";
try
{
await _mail.SendToSupportAsync($"Question about AyaNova from {Contact.Company}", body, Contact.Name, Contact.Email);
}
catch (Exception ex)
{
//Log the whole submission so it can be recovered from the journal, not lost
_logger.LogError(ex, "Contact form send failed. Submission:\r\n{Body}", body);
SendFailed = true;
return Page();
}
return Redirect(ConfirmedUrl);
}
public static bool IsBlocked(string company)
{
var c = company.ToLowerInvariant();
return SpamBlocks.Any(s => c.Contains(s));
}
}
}