Отправляем письма из ASP .NET MVC

в 12:45, , рубрики: .net, ASP, email, письма, метки: ,

Часто в приложениях возникает необходимость отправлять письма пользователям. Сегодня я покажу как с помощью ActionMailer .Net эта задача легко решается. Основной его плюс в представлении отправляемых писем в виде действий контроллера, само тело письма представлено отображением, а также то, что в режиме отладки он позволяет сохранять письма напрямую на жесткий диск, без использования почтового сервера.

Создадим пустой проект. С помощью NuGet'a добавим ActionMailer:

PM> Install-Package ActionMailer

Для демонстрации создадим один контроллер Home, и добавим в него четыре действия: для главной странички, отправки, странички в случае успешной отправки и в случае не успешной отправки:

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

    [HttpPost]
    public ActionResult Index(EmailModel model)
    {
        throw new NotImplementedException();
    }

    public ActionResult Success()
    {
        return View();
    }

    public ActionResult Error()
    {
        return View();
    }

}

Добавим теперь модель для письма:

public class EmailModel
{
    public string Subject { get; set; }

    public string From { get; set; }

    public string To { get; set; }

    public string Body { get; set; }
}

Создадим отображение для действия Index. У нас это будет простенькая формочка с необходимыми полями:

@model TestSendEmail.Models.EmailModel
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "Index";
}
@using(Html.BeginForm("Index", "Home", FormMethod.Post, new { @class = "well"}))
{
    @Html.ValidationSummary()

    <label>Subject</label>
    @Html.TextBoxFor(m => m.Subject, new { @class = "input-xxlarge" })

    <label>To</label>
    @Html.TextBoxFor(m => m.To, new { @class = "input-xxlarge" })

    <label>From</label>
    @Html.TextBoxFor(m => m.From, new { @class = "input-xxlarge" })

    <label>Body</label>
    @Html.TextAreaFor(m => m.Body, new { @class = "input-xxlarge" })

    
    <input type="submit" class="btn" value="Send"/>
}

Получаем вот такую форму:
Отправляем письма из ASP .NET MVC
Теперь создадим контроллер, который непосредственно будет отправлять наши письма. Назовем его EmailController и унаследуем от MailerBase. Также добавим и реализуем действие отправки письма:

public class EmailController : MailerBase
{
    public EmailResult SendEmail(EmailModel model)
    {
        To.Add(model.To);

        From    = model.From;

        Subject = model.Subject;

        return Email("SendEmail", model);
    }
}

To, From, Subject — являются внутренними свойствами контроллера, и значения из них будут использованы при отправки письма. Стоит заметить, что To является списком, таким образом возможны массовые рассылки. Спамеры возрадуются.
Теперь добавим к нашему действию вид. В данном случае вид будет играть роль тела отправляемого письма, т.е. можно добавлять html-разметку:

@model TestSendEmail.Models.EmailModel
@{
    Layout = null;
}
<html>
    <body>
        <h1>@Model.Subject</h1>
        <p>@Model.Body</p>
    </body>
</html>

Замечу еще насчет именования файлов вида. В дефолтном варианте он будет иметь имя: ResetPassword.cshtml. Для корректной работы ActionMailer'a необходимо добавить .html, чтобы имя приняло следующий вид: ResetPassword.html.cshtml.
Также для корректной работы необходимо добавить параметры как отправлять почту. Первый вариант для сохранения отправляемой почти на локальный диск:

<mailSettings>
      <smtp deliveryMethod="SpecifiedPickupDirectory">
        <specifiedPickupDirectory pickupDirectoryLocation="C:" />
        <network host="localhost" />
      </smtp>
</mailSettings>

И второй вариант при использовании почтового сервера:

<mailSettings>
      <smtp deliveryMethod="Network">
        <network host="smtp.gmail.com" userName="myemail@gmail.com" password="mypassword"  enableSsl="true"/>
      </smtp>
</mailSettings>

Эти строки необходимо добавить в Web.config, в секцию <system.net>.
Ну и теперь добавим логику отправления письма в действие Index нашего Home контроллера:

[HttpPost]
public ActionResult Index(EmailModel model)
{
    if (ModelState.IsValid)
    {
        try
        {
            new EmailController().SendEmail(model).Deliver();

            return RedirectToAction("Success");
        }
        catch (Exception)
        {
            return RedirectToAction("Error");
        }
    }
    return View(model);
}

Теперь при нажатии на кнопку наше письмо будет отправлено (или сохранено на диск).

Дополнительные материалы:
http://geeksharp.com/2011/01/26/actionmailer-net-email-templates-for-the-mvc-crowd/

Автор: vyacheslav_ka

* - обязательные к заполнению поля