Bucket Place/Ruby on Rails

[Rails] ActionMailer & Mail 서비스를 시작하자!

Cloud Travel 2014. 8. 7. 14:19


  들어가며... 


안녕하세요. Bucket Place에서 개발자를 맡고 있는 Cloud Travel이라고 합니다. 정말로 오랜만에 글을 쓰네요. 개발일정에 이리처이고 저리치이며... ㅠ_ㅠ 눈물이 앞을 가리는 하루하루를 살았답니다. 아직도 바쁘지만, 그래도 언젠가 들어올 후임을 위해서 그리고 저를 위해서 간단하게 Mailer에 대해서 정리해보고 넘아가려고 합니다.


 Mailer는 한글로 번역하면 우체부(?) 정도로 해석하면 좋을 것 같습니다. Rails에는 기본으로 제공해주는 ActionMailer를 포함해서 다양한 Mailer가 존재합니다. 오늘 제가 Mailer를 이용해서 해볼 일은 2가지가 있습니다.


 1) 사용자에게 간단한 이메일 문의 받기

 2) 사용자에게 이메일 보내기


 설명에 앞서서 기본적으로 제가 작업한 환경을 말씀드리자면...

 1) Rails 4.0 이상의 버전을 이용할 것!

 2) ruby 버전을 1.9.3 이상을 이용할 것!

 3) 사용해본 운영체제로는 윈도우와 맥이있습니다. 



  사용자에게 간단한 이메일 문의 받기(Contact Form 만들기) 



1. 사전 준비사항

 - Rails 4.0.0 이상 / Simple_form 3.0 이상 / mail_form 1.5 이상

 - mail_form과 simple_form은 Gemfile에 추가하여 installing을 하자.


<Gemfile>

gem 'mail_form'
gem 'simple_form'


2. Contact Form을 위한 모델/컨트롤러 생성과 라우트 설정 및 뷰제적

 - MailForm을 상속받는 Contact 모델을 생성하여 아래와 같이 작성해줍니다.

 - Model에서는 미리 Email Header를 작성하는데 중간에 to에 자신의 이메일 주소를 작성해 줍시다. 

 - attribute는 자신이 필요한 것을 기준으로 더 추가해주시면 됩니다.

 - 여기서 생성한 attributes는 view에서 전달받은 값이라고 생각하면 됩니다. 

 - 저는 추가적인 기능으로 보내는 사람의 이메일 검정을 하였습니다.


<app/models/contact.rb>

class Contact < MailForm::Base
	attribute :type
	attribute :name,      :validate => true
	attribute :email,     :validate => /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
	attribute :message

	# Declare the e-mail headers. It accepts anything the mail method
	# in ActionMailer accepts.
	def headers
		{
				:subject => "#{type}",
				:to => "[put your email]",
				:from => %("#{name}" <#{email}>)
		}
	end
end




 - ApplicationController를 상속받아서 ContactsController를 생성하여 아래와 같이 작성해 줍니다.


<app/controllers/contacts_controller.rb>

class ContactsController < ApplicationController
  def new
    @contact = Contact.new
  end

  def create
    @contact = Contact.new(params[:contact])
    @contact.request = request
    if @contact.deliver
      flash.now[:notice] = 'Thank you for your message. We will contact you soon!'
    else
      flash.now[:error] = 'Cannot send message.'
      render :new
    end
  end
end



 - 이제 form에 접근할 route를 설정해줍니다.


 <routes.rb>

match 'feedback', to: 'contacts#new', via: 'get'
resources "contacts", only: [:new, :create]


 - 마지막으로는 이메일을 받을 view를 간단하게 작성해줍니다.


<app/views/contacts/new.html.erb>

<div id="form">
  <div class="introduction">
    <div class="title">문의 및 제안</div>
  </div>

  <%= simple_form_for @contact do |f| %>
    <div class="field">
      <%= f.label :type, '유형' %>
      <%= f.select(:type,[['제안', '제안'], ['문의', '문의'], ['신고', '신고'], ['상담', '상담'], ['채용', '채용']] ) %>
    </div>
    <div class="field">
      <%= f.label :name, '이름' %> <%= f.text_field :name, required: true, value: (current_user.nickname unless current_user.nil?) %>
    </div>
    <div class="field">
      <%= f.label :email, '이메일' %> <%= f.text_field :email, required: true, value: (current_user.email unless current_user.nil?) %>
    </div>
    <div class="field">
      <%= f.label :message, '내용' %> <%= f.text_area :message, required: true %>
    </div>

    <div class="buttons">
      <%= f.button :submit, '보내기', :id=> "submit" %>
    </div>
  <% end %>
</div>


 여기에 추가적으로 css만 추가해주면 간단한 메일을 받는 것이 가능할 것입니다.

 잘 보시면 위에서 to에 자신의 이메일을 적지 않고 form을 통해서 받으면 어엿한 email form이 완성이 됩니다.

 여기서는 거기까진 다루진 않을 겁니다만 ' ' 쉽게 응요잉 가능한 부분이랍니다.





  ActionMailer를 이용하여 사용자에게 이메일 알림을 하자! 



 Simple Form과 Mail Form을 이용한 경우에는 간단하게 즉각적으로 보내는 이메일 서비스에 유용합니다. 하지만, 사용자 전체에게 수시로 메일이 가는 경우에는 어떻게 해야 할까요? 예를 들어 Facebook에서 여러분에게 알림메세지를 어떻게 전달해 줄가요? 


 이것은 Even-driven으로 사용자의 행동에 맞춰서 그때 그때마다 이메일을 보내줘야 합니다. 이와 같은 역할을 하는 메일링 시스템을 구축해보도록 합시다. 


 Rails에서 기본적으로 제공해주는 ActionMailer를 사용하면 됩니다. 자 이제 따라가 봅시다.


1. Mailer를 하나 생성해줍니다.

$ rails g mailer [MailerName]

example) rails g mailer SystemMailer

 - Mailer를 생성한 경우에는 app이하에 mailers라는 폴더가 생성됩니다. 

 - 그 이하에는 생성된 ActionMailer(example> mailers/system_mailer.rb)가 존재할 것입니다.

 

2. app/mailer/[ActionMailer].rb 파일을 수정합시다.

 - 보내는 사람(관리자 메일 또는 운용자 메일)을 설정해줍니다. 

 - 사용자에게 보낼 기본 정보를 가져옵니다.

 - 여기서는 예시로 회원 가입시 알림을 보내주는 화면을 구성해보도록 하겠습니다.


<app/mailers/system_mailer.rb>

class UserMailer < ActionMailer::Base
  default from: '[put your system email]'
 
  def welcome_email(user)
    @user = user
    @url  = 'http://example.com/'
    mail(to: @user.email, subject: '저희 홈페이지에 가입하신 것을 환영합니다.')
  end
end


 - 실질적으로 메일이 보내지는 것은 mail()함수를 통해서 보내지게 됩니다.

 - 여기서 간단하게 ActionMailer가 행해지는 행동을 도식화 하면 다음과 같습니다.

  - 다시 순서로 돌아와서 다음과정으로 갑시다.


3. app/vies/system_mailer/welcome_email.html.erb를 생성하여 view를 제작합시다.

 - 여기서 사용하는 각 변수들은 controller에서 다 불러오시는게 편합니다.(eg. DB data)

<!DOCTYPE html>
<html>
  <head>
    <meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
  </head>
  <body>
    <h1><%= @user.name %>님! 회원 가입을 축하합니다.</h1>
    <p>
      계정명 : <%= @user.login %>.<br>
    </p>
    <p>
      저희 사이트를 다시 방문해주세요! : <%= @url %>.
    </p>
  </body>
</html>


4. 메일을 보내야 할 시점을 생각하여서 메일을 보내는 명령문을 추가시켜줍니다.


 [Mailer Name].welcome_email(user data)



 비동기식으로 보내기


 

 위 과정까지 잘따라 오셨다면 마지막 관문이 있습니다. 이메일을 보내는데에는 서버에서 많은 양의 데이터를 소화해야 합니다. 이에 따라서 사용자 입장에서는 쓸데 없이 기다려야 하는 경우가 발생하죠. 이를 대비해서 나온 것이 비동기식 이메일 전송입니다. 이메일 전송을 관리할 시스템 부분을 따라 켜놓고, 이메일 전송 내역은 큐에다가 저장시키는 방식입니다. 이는 매우 필요하고 중요한 기능입니다.


 Rails에서는 비동기식 이메일 전송을 위해서 다양한 Gem이 존재합니다. 여러가지의 Gem중에서 제가 사용할 Gem은 'delayed_job_active_record' 입니다.


 이것에 대해서는 git에 설명이 잘되어 있기 때문에 이를 링크 시켜드리겠습니다.

 - https://github.com/collectiveidea/delayed_job

 

 중간에 작성되있지만 4.0 이상버전에서 생기는 에러에 대해서는 잘 대처해주시기 바랍니다.


 그리고 이 세팅이 끝난다면 메일을 가져다 보내주는 것을 하나 실행시켜줘야 합니다.

 rake jobs:work !