Search code examples
asp.netformsasp.net-mvc-5smtpclient

MVC Contact Form with Email


I wonder if someone can please help with a MVC Contact Form which send an Email on submission? I think I have most elements setup, but for some reason the form appear to be sending (takes ages) then just returns back to the form and no email is received.

MailModels.cs:

namespace WebApplication1.Models
{
    public class MailModels
    {
       public string Name { get; set; }
       public string Email { get; set; }
       public string Telephone { get; set; }
       public string Message { get; set; }
    }
}

Contact.cshtml:

@using (Html.BeginForm("Contact", "Home", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @id = "contact-form", role = "form" }))
{
    @Html.ValidationSummary()
    <fieldset>
        <div class="form-div-1">
            <label class="name">
                @Html.TextBoxFor(m => m.Name, new { @placeholder = "Name *", @type = "text" })
            </label>
        </div>
        <div class="form-div-2">
            <label class="email">
                @Html.TextBoxFor(m => m.Email, new { @placeholder = "Email Address *", @type = "email" })
            </label>
        </div>
        <div class="form-div-3">
            <label class="phone notRequired">
                @Html.TextBoxFor(m => m.Telephone, new { @placeholder = "Telephone Number", @type = "text" })
            </label>
        </div>
        <div>
            <label class="message">
                @Html.TextAreaFor(m => m.Message, new { @placeholder = "Message *" })
            </label>
        </div>
        <div class="button-wrapper">
            <input type="submit" value="Send" name="submit" class="button"> <input type="reset" value="Reset" name="MFReset" class="button"><span>* Required Fields</span>
        </div>
    </fieldset>
}

HomeController.cs:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net.Mail;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using WebApplication1.Models;
using System.Text;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
    public ActionResult Contact()
    {
        ViewBag.Message = "Test Form";

        return View();
    }

    [HttpPost]
    public ActionResult Contact(MailModels e)
    {
        if (ModelState.IsValid)
        {

            StringBuilder message = new StringBuilder();
            MailAddress from = new MailAddress(e.Email.ToString());
            message.Append("Name: " + e.Name + "\n");
            message.Append("Email: " + e.Email + "\n");
            message.Append("Telephone: " + e.Telephone + "\n\n");
            message.Append(e.Message);

            MailMessage mail = new MailMessage();

            SmtpClient smtp = new SmtpClient();

            smtp.Host = "smtp.mail.yahoo.com";
            smtp.Port = 465;

            System.Net.NetworkCredential credentials = new System.Net.NetworkCredential("yahooaccount", "yahoopassword");

            smtp.Credentials = credentials;
            smtp.EnableSsl = true;

            mail.From = from;
            mail.To.Add("yahooemailaddress");
            mail.Subject = "Test enquiry from "+e.Name;
            mail.Body = message.ToString();

            smtp.Send(mail);
        }
        return View();
    }

Banging my head against a brickwall with this one, any help would be much appreciated :-)


Solution

  • Sending an email will take time. It should be a thread. Put your code in a function. And make the following changes:

    public void SendEmail(string toAddress, string fromAddress, 
                          string subject, string message)
    {
        try
        {
            using (var mail = new MailMessage())
            {
                const string email = "[email protected]";
                const string password = "password!";
    
                var loginInfo = new NetworkCredential(email, password);
    
    
                mail.From = new MailAddress(fromAddress);
                mail.To.Add(new MailAddress(toAddress));
                mail.Subject = subject;
                mail.Body = message;
                mail.IsBodyHtml = true;
    
                try
                {
                    using (var smtpClient = new SmtpClient(
                                                     "smtp.mail.yahoo.com", 465))
                    {
                        smtpClient.EnableSsl = true;
                        smtpClient.UseDefaultCredentials = false;
                        smtpClient.Credentials = loginInfo;
                        smtpClient.Send(mail);
                    }
    
                }
    
                finally
                {
                    //dispose the client
                    mail.Dispose();
                }
    
            }
        }
        catch (SmtpFailedRecipientsException ex)
        {
            foreach (SmtpFailedRecipientException t in ex.InnerExceptions)
            {
                var status = t.StatusCode;
                if (status == SmtpStatusCode.MailboxBusy ||
                    status == SmtpStatusCode.MailboxUnavailable)
                {
                    Response.Write("Delivery failed - retrying in 5 seconds.");
                    System.Threading.Thread.Sleep(5000);
                    //resend
                    //smtpClient.Send(message);
                }
                else
                {
                    Response.Write("Failed to deliver message to {0}",
                                      t.FailedRecipient);
                }
            }
        }
        catch (SmtpException Se)
        {
            // handle exception here
            Response.Write(Se.ToString());
        }
    
        catch (Exception ex)
        {
            Response.Write(ex.ToString());
        }
    
    }
    

    Call that function in your controller:

    [HttpPost]
    public ActionResult Contact(MailModels e)
    {
        if (ModelState.IsValid)
        {
    
            //prepare email
            var toAddress = "[email protected]";
            var fromAddress = e.Email.ToString();
            var subject = "Test enquiry from "+ e.Name;
            var message = new StringBuilder();
            message.Append("Name: " + e.Name + "\n");
            message.Append("Email: " + e.Email + "\n");
            message.Append("Telephone: " + e.Telephone + "\n\n");
            message.Append(e.Message);
    
            //start email Thread
            var tEmail = new Thread(() => 
           SendEmail(toAddress, fromAddress, subject, message));
            tEmail.Start();
        }
        return View();
    }
    

    If you dont get email, check your spam folder