Pull to refresh

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

Reading time3 min
Views26K
Часто в приложениях возникает необходимость отправлять письма пользователям. Сегодня я покажу как с помощью 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" })

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


Получаем вот такую форму:

Теперь создадим контроллер, который непосредственно будет отправлять наши письма. Назовем его 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/
Tags:
Hubs:
+2
Comments15

Articles