Form with attachments upload and email sending

I need to make form with a textarea and an image upload field. When somebody submit it I want it to send email (with text from textarea) with attachements (from input file upload field) to me.

My simple form looks like that:

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>        
            @Html.TextArea("Question");      
            <input type="file"/> 
            <input type="submit" value="Send" />

    </fieldset>

}

I found PHP scripts that are doing something like that, but how could I do it in ASP.NET MVC (could be with JavaScript)?

Answers


Here's an example using gmail's SMTP but if you have your own SMTP server you could easily adapt the code.

As always I would start with a view model:

public class QuestionViewModel
{
    [Required]
    public string Question { get; set; }

    public HttpPostedFileBase Attachment { get; set; }
}

then a controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new QuestionViewModel());
    }

    [HttpPost]
    public ActionResult Index(QuestionViewModel model)
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }

        using (var client = new SmtpClient("smtp.gmail.com", 587))
        {
            client.EnableSsl = true;
            client.Credentials = new NetworkCredential("someaccount@gmail.com", "secret");
            var mail = new MailMessage();
            mail.From = new MailAddress("fromaddress@gmail.com");
            mail.To.Add("toaddress@gmail.com");
            mail.Subject = "Test mail";
            mail.Body = model.Question;
            if (model.Attachment != null && model.Attachment.ContentLength > 0)
            {
                var attachment = new Attachment(model.Attachment.InputStream, model.Attachment.FileName);
                mail.Attachments.Add(attachment);
            }
            client.Send(mail);
        }
        return Content("email sent", "text/plain");
    }
}

and finally a view:

@model QuestionViewModel

@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.ValidationSummary(true)
    <fieldset>        
        <div>
            @Html.LabelFor(x => x.Question)
            @Html.TextAreaFor(x => x.Question)
        </div>
        <div>
            <label for="attachment">Attachment</label>
            <input type="file" name="attachment" id="attachment"/> 
        </div>
        <input type="submit" value="Send" />
    </fieldset>
}

A further improvement to this code would be to externalize the actual sending of the mail into a repository implementing some interface and using DI in order to weaken the coupling between the controller logic and the mail sending logic.

Note that you can also configure your SMTP settings in web.config:

<system.net>
    <mailSettings>
      <smtp from="fromaddress@gmail.com" deliveryMethod="Network">
        <network 
          enableSsl="true" 
          host="smtp.gmail.com" 
          port="587" 
          userName="someaccount@gmail.com" 
          password="secret" 
        />
      </smtp>
    </mailSettings>
</system.net>

and then simply:

using (var client = new SmtpClient())
{
    var mail = new MailMessage();
    mail.To.Add("toaddress@gmail.com");
    mail.Subject = "Test mail";
    mail.Body = model.Question;
    if (model.Attachment != null && model.Attachment.ContentLength > 0)
    {
        var attachment = new Attachment(model.Attachment.InputStream, model.Attachment.FileName);
        mail.Attachments.Add(attachment);
    }
    client.Send(mail);
}

MailMessage class in .NET should be able to handle that for you:

http://msdn.microsoft.com/en-us/library/system.net.mail.mailmessage.attachments.aspx

Or are you looking for something more specific to your actual code? (e.g. how to read the file and add it to the attachment)?


  if (model.Attachment != null && model.Attachment.ContentLength > 0)
    {
    foreach (HttpPostedFileBase item in fileUploader)
      {

        var attachment = new Attachment(model.Attachment.InputStream,   model.Attachment.FileName);
        mail.Attachments.Add(attachment);
      }
    }

In addition to Daren's answer, you don't have to hardcode the input and label for your file upload in your view. Just slap this in there :)

@Html.TextBoxFor(model => model.Attachment, new { type = "file" })
@Html.LabelFor(model => model.Attachment)

Need Your Help

How do I add an "Add to Favorites" button or link on my website?

javascript jquery html bookmarks

I'm building a website using Drupal. On the header of each page I want to have a single image (custom designed by me) which would act as a custom "Add to Favorites" button. Clicking on the image sh...

How to determine if you have an internet connection in R

r

Sometimes I need to download data from the internet. On occasions this has failed either because the website is down or because my computer has lost its internet connection.