Мультиблог на Ruby on Rails. Отправка почты. Урок 12.

Курс потихонечку подходит к своему завершению и всё что нам остаётся реализовать в нашем шаблоне, так это последнюю страничку "Contact" - ту самую, на которой находится контактная форма. У нас уже есть контролер Pages; вот там как раз и пропишем action, который будет отвечать за вывод формы:

def contact
end

Не забываем прописать маршрут:

get 'contact', to: 'pages#contact', as: 'contact'

Создание (рендеринг) обычной формы

Нам уже приходилось создавать форму на основе модели, но поскольку сейчас нужно просто получить данные и отправить их на почту, то такой способ нам не подойдёт. Здесь необходима простая форма, отрендерить которую можно так:

<div class="row">
  <div class="col-lg-8 col-md-10 mx-auto">
    <p>Want to get in touch? Fill out the form below to send me a message and I will get back to you as soon as possible!</p>
    <!-- Contact Form - Enter your email address on line 19 of the mail/contact_me.php file to make this form work. -->
    <!-- WARNING: Some web hosts do not allow emails to be sent through forms to common mail hosts like Gmail or Yahoo. It's recommended that you use a private domain email address! -->
    <!-- To use the contact form, your site must be on a live web host with PHP! The form will not work locally! -->
    <%= form_tag route_for(:send_form) do %>
      <div class="control-group">
        <div class="form-group floating-label-form-group controls">
          <label>Name</label>
          <%= text_field_tag :name, '', class: 'form-control', placeholder: 'Name' %>
          <p class="help-block text-danger"></p>
        </div>
      </div>
      <div class="control-group">
        <div class="form-group floating-label-form-group controls">
          <label>Email Address</label>
          <%= text_field_tag :email, '', class: 'form-control', placeholder: 'Email Address' %>
          <p class="help-block text-danger"></p>
        </div>
      </div>
      <div class="control-group">
        <div class="form-group col-xs-12 floating-label-form-group controls">
          <label>Phone Number</label>
          <%= text_field_tag :phone, '', class: 'form-control', placeholder: 'Phone Number' %>
          <p class="help-block text-danger"></p>
        </div>
      </div>
      <div class="control-group">
        <div class="form-group floating-label-form-group controls">
          <label>Message</label>
          <%= text_area_tag :message, '', class: 'form-control', placeholder: 'Message', rows: 5 %>
          <p class="help-block text-danger"></p>
        </div>
      </div>
      <br>
      <%= submit_tag "Send", class: 'btn btn-primary' %>
    <% end %>
  </div>
</div>

Создание почтовой программы

Теперь пришло время заняться непосредственно отправкой самой формы. В RoR для этих целей предназначены почтовые программы - сгенерировать такую можно с помощью консоли:

rails generate mailer Contact

При этом будет создан файл app/mailers/contact_mailer.rb

Поскольку форма будет отправляться с помощью метода POST, нам понадобится маршрут, который будет ссылаться на соответствующий метод:

post 'send_form', to: 'pages#send_form', as: 'send_form'

Данный маршрут я заранее указал в атрибуте action формы, с помощью route_for. Осталось реализовать сам метод:

def send_form
  @email_params = {'email' => params[:email], 'phone' => params[:phone], 'message' => params[:message]}
  flash[:notice] = "Сообщение отправлено"
  ContactMailer.send_email(@email_params).deliver_now
  redirect_to contact_path
end

То, что находится в переменной email_params - это массив данных, которые мы получили из формы посредством метода POST. Далее мы эти данные передаём в метод send_email нашей почтовый программы. Сам метод пока что не реализован, давайте исправим это (делается это в файле app/mailers/contact_mailer.rb)

default from: 'noreply@example.com'

def send_email(email_params)
  @email = email_params['email']
  @message = email_params['message']
  @phone = email_params['phone']
  m = mail(to: 'info@example.com', subject: 'Пришла заявка от пользователя')
  m.transport_encoding = "8bit"
  m.deliver
end

Здесь мы раскладываем данные по переменным, передаём их в шаблон (тело) письма и с помощью функции mail отправляем всё это непосредственно на почту. Тело письма для почтовой программы будет браться из файла app/views/contact_mailer/send_email.html.erb - название формируется из имени почтовой программы и названия метода (соответственно данный файл необходимо будет создать). В нашем случае, содержимое почтового шаблона будет таким:

Пришла заявка от пользователя с email: <%= @email %>
Текст сообщения: <%= @message %>
Телефон: <%= @phone %>

Далее переходим по адресу http://127.0.0.1:3000/contact, заполняем форму и проверяем, всё ли у нас работает (все отправленные письма при этом будут отображаться прямо в консоли)

Настройка почты для работы с SMTP

Что же касается боевого сервера, то здесь потребуется уже реальный SMTP сервер. Настройки для такого прописываются в файле config/environments/development.rb:

config.action_mailer.delivery_method = :smtp

config.action_mailer.smtp_settings = {
  address:              'smtp.gmail.com',
  port:                 587,
  domain:               'example.com',
  user_name:            '<your-email>',
  password:             '<your-password>',
  authentication:       'plain',
  enable_starttls_auto: true
}

Вот мы и реализовали страничку с функционалом отправки данных формы на почту. И в завершении, давайте проставим ссылку на данную страничку в верхнее меню:

<a class="nav-link" href="<%= route_for(:contact) %>">Contact</a>

Все изменения по данному уроку доступны в репозитории.