MVC Contact Form with Email

iggyweb picture iggyweb · May 6, 2014 · Viewed 25.5k times · Source

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 :-)

Answer

meda picture meda · May 6, 2014

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