-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaction_mailer_basics.html
868 lines (793 loc) · 46.8 KB
/
action_mailer_basics.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Action Mailer 基礎 — Ruby on Rails 指南</title>
<meta name="description" content="Ruby on Rails 指南:系統學習 Rails(Rails 4.2 版本)" >
<meta name="keywords" content="Ruby on Rails Guides 指南 中文 學習 免費 網路 Web 開發" >
<meta name="author" content="http://git.io/G_R1sA">
<meta property="fb:admins" content="1340181291">
<meta property="og:title" content="Action Mailer 基礎 — Ruby on Rails 指南" >
<meta property="og:site_name" content="Ruby on Rails 指南">
<meta property="og:image" content="http://rails.ruby.tw/images/rails_guides_cover.jpg">
<meta property="og:url" content="http://rails.ruby.tw/">
<meta property="og:type" content="article">
<meta property="og:description" content="Ruby on Rails 指南:系統學習 Rails(Rails 4.2 版本)">
<link rel="stylesheet" href="stylesheets/application.css">
<link href="http://fonts.googleapis.com/css?family=Noto+Sans:400,700|Noto+Serif:700|Source+Code+Pro" rel="stylesheet">
<link href="images/favicon.ico" rel="shortcut icon" type="image/x-icon">
</head>
<body class="guide">
<div id="fb-root"></div>
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/zh-TW/sdk.js#xfbml=1&appId=837401439623727&version=v2.0";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
<script type="text/javascript">
window.twttr=(function(d,s,id){var t,js,fjs=d.getElementsByTagName(s)[0];if(d.getElementById(id)){return}js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);return window.twttr||(t={_e:[],ready:function(f){t._e.push(f)}})}(document,"script","twitter-wjs"));
</script>
<div id="topNav">
<div class="wrapper">
<strong class="more-info-label">更多內容 <a href="http://rubyonrails.org/">rubyonrails.org:</a></strong>
<span class="red-button more-info-button">
更多內容
</span>
<ul class="more-info-links s-hidden">
<li class="more-info"><a href="http://rubyonrails.org/">綜覽</a></li>
<li class="more-info"><a href="http://rubyonrails.org/download">下載</a></li>
<li class="more-info"><a href="http://rubyonrails.org/deploy">部署</a></li>
<li class="more-info"><a href="https://github.com/rails/rails">原始碼</a></li>
<li class="more-info"><a href="http://rubyonrails.org/screencasts">影片</a></li>
<li class="more-info"><a href="http://rubyonrails.org/documentation">文件</a></li>
<li class="more-info"><a href="http://rubyonrails.org/community">社群</a></li>
<li class="more-info"><a href="http://weblog.rubyonrails.org/">Blog</a></li>
</ul>
</div>
</div>
<div id="header">
<div class="wrapper clearfix">
<h1><a href="index.html" title="回首頁">Guides.rubyonrails.org</a></h1>
<ul class="nav">
<li><a class="nav-item" href="index.html">首頁</a></li>
<li class="guides-index guides-index-large">
<a href="index.html" id="guidesMenu" class="guides-index-item nav-item">指南目錄</a>
<div id="guides" class="clearfix" style="display: none;">
<hr>
<dl class="L">
<dt>起步走</dt>
<dd><a href="getting_started.html">Rails 起步走</a></dd>
<dt>Models</dt>
<dd><a href="active_record_basics.html">Active Record 基礎</a></dd>
<dd><a href="active_record_migrations.html">Active Record 遷移</a></dd>
<dd><a href="active_record_validations.html">Active Record 驗證</a></dd>
<dd><a href="active_record_callbacks.html">Active Record 回呼</a></dd>
<dd><a href="association_basics.html">Active Record 關聯</a></dd>
<dd><a href="active_record_querying.html">Active Record 查詢</a></dd>
<dt>Views</dt>
<dd><a href="layouts_and_rendering.html">Rails 算繪與版型</a></dd>
<dd><a href="form_helpers.html">Action View 表單輔助方法</a></dd>
<dt>Controllers</dt>
<dd><a href="action_controller_overview.html">Action Controller 綜覽</a></dd>
<dd><a href="routing.html">Rails 路由:深入淺出</a></dd>
</dl>
<dl class="R">
<dt>深入了解</dt>
<dd><a href="active_support_core_extensions.html">Active Support 核心擴展</a></dd>
<dd><a href="i18n.html">Rails 國際化 API</a></dd>
<dd><a href="action_mailer_basics.html">Action Mailer 基礎</a></dd>
<dd><a href="active_job_basics.html">Active Job 基礎</a></dd>
<dd><a href="security.html">Rails 安全指南</a></dd>
<dd><a href="debugging_rails_applications.html">除錯 Rails 應用程式</a></dd>
<dd><a href="configuring.html">Rails 應用程式設定</a></dd>
<dd><a href="command_line.html">Rake 任務與 Rails 命令列工具</a></dd>
<dd><a href="asset_pipeline.html">Asset Pipeline</a></dd>
<dd><a href="working_with_javascript_in_rails.html">在 Rails 使用 JavaScript</a></dd>
<dd><a href="constant_autoloading_and_reloading.html">Constant Autoloading and Reloading</a></dd>
<dt>擴充 Rails</dt>
<dd><a href="rails_on_rack.html">Rails on Rack</a></dd>
<dd><a href="generators.html">客製與新建 Rails 產生器</a></dd>
<dd><a href="rails_application_templates.html">Rails 應用程式模版</a></dd>
<dt>貢獻 Ruby on Rails</dt>
<dd><a href="contributing_to_ruby_on_rails.html">貢獻 Ruby on Rails</a></dd>
<dd><a href="api_documentation_guidelines.html">API 文件準則</a></dd>
<dd><a href="ruby_on_rails_guides_guidelines.html">Ruby on Rails 指南準則</a></dd>
<dt>維護方針</dt>
<dd><a href="maintenance_policy.html">維護方針</a></dd>
<dt>發佈記</dt>
<dd><a href="upgrading_ruby_on_rails.html">升級 Ruby on Rails</a></dd>
<dd><a href="4_2_release_notes.html">Ruby on Rails 4.2 發佈記</a></dd>
<dd><a href="4_1_release_notes.html">Ruby on Rails 4.1 發佈記</a></dd>
<dd><a href="4_0_release_notes.html">Ruby on Rails 4.0 發佈記</a></dd>
<dd><a href="3_2_release_notes.html">Ruby on Rails 3.2 發佈記</a></dd>
<dd><a href="3_1_release_notes.html">Ruby on Rails 3.1 發佈記</a></dd>
<dd><a href="3_0_release_notes.html">Ruby on Rails 3.0 發佈記</a></dd>
<dd><a href="2_3_release_notes.html">Ruby on Rails 2.3 發佈記</a></dd>
<dd><a href="2_2_release_notes.html">Ruby on Rails 2.2 發佈記</a></dd>
<dt>Rails 指南翻譯術語</dt>
<dd><a href="translation_terms.html">翻譯術語</a></dd>
</dl>
</div>
</li>
<li><a class="nav-item" href="//github.com/docrails-tw/guides">貢獻翻譯</a></li>
<li><a class="nav-item" href="contributing_to_ruby_on_rails.html">貢獻</a></li>
<li><a class="nav-item" href="credits.html">致謝</a></li>
<li class="guides-index guides-index-small">
<select class="guides-index-item nav-item">
<option value="index.html">指南目錄</option>
<optgroup label="起步走">
<option value="getting_started.html">Rails 起步走</option>
</optgroup>
<optgroup label="Models">
<option value="active_record_basics.html">Active Record 基礎</option>
<option value="active_record_migrations.html">Active Record 遷移</option>
<option value="active_record_validations.html">Active Record 驗證</option>
<option value="active_record_callbacks.html">Active Record 回呼</option>
<option value="association_basics.html">Active Record 關聯</option>
<option value="active_record_querying.html">Active Record 查詢</option>
</optgroup>
<optgroup label="Views">
<option value="layouts_and_rendering.html">Rails 算繪與版型</option>
<option value="form_helpers.html">Action View 表單輔助方法</option>
</optgroup>
<optgroup label="Controllers">
<option value="action_controller_overview.html">Action Controller 綜覽</option>
<option value="routing.html">Rails 路由:深入淺出</option>
</optgroup>
<optgroup label="深入了解">
<option value="active_support_core_extensions.html">Active Support 核心擴展</option>
<option value="i18n.html">Rails 國際化 API</option>
<option value="action_mailer_basics.html">Action Mailer 基礎</option>
<option value="active_job_basics.html">Active Job 基礎</option>
<option value="security.html">Rails 安全指南</option>
<option value="debugging_rails_applications.html">除錯 Rails 應用程式</option>
<option value="configuring.html">Rails 應用程式設定</option>
<option value="command_line.html">Rake 任務與 Rails 命令列工具</option>
<option value="asset_pipeline.html">Asset Pipeline</option>
<option value="working_with_javascript_in_rails.html">在 Rails 使用 JavaScript</option>
<option value="constant_autoloading_and_reloading.html">Constant Autoloading and Reloading</option>
</optgroup>
<optgroup label="擴充 Rails">
<option value="rails_on_rack.html">Rails on Rack</option>
<option value="generators.html">客製與新建 Rails 產生器</option>
<option value="rails_application_templates.html">Rails 應用程式模版</option>
</optgroup>
<optgroup label="貢獻 Ruby on Rails">
<option value="contributing_to_ruby_on_rails.html">貢獻 Ruby on Rails</option>
<option value="api_documentation_guidelines.html">API 文件準則</option>
<option value="ruby_on_rails_guides_guidelines.html">Ruby on Rails 指南準則</option>
</optgroup>
<optgroup label="維護方針">
<option value="maintenance_policy.html">維護方針</option>
</optgroup>
<optgroup label="發佈記">
<option value="upgrading_ruby_on_rails.html">升級 Ruby on Rails</option>
<option value="4_2_release_notes.html">Ruby on Rails 4.2 發佈記</option>
<option value="4_1_release_notes.html">Ruby on Rails 4.1 發佈記</option>
<option value="4_0_release_notes.html">Ruby on Rails 4.0 發佈記</option>
<option value="3_2_release_notes.html">Ruby on Rails 3.2 發佈記</option>
<option value="3_1_release_notes.html">Ruby on Rails 3.1 發佈記</option>
<option value="3_0_release_notes.html">Ruby on Rails 3.0 發佈記</option>
<option value="2_3_release_notes.html">Ruby on Rails 2.3 發佈記</option>
<option value="2_2_release_notes.html">Ruby on Rails 2.2 發佈記</option>
</optgroup>
<optgroup label="Rails 指南翻譯術語">
<option value="translation_terms.html">翻譯術語</option>
</optgroup>
</select>
</li>
</ul>
</div>
</div>
</div>
<hr class="hide">
<div id="feature">
<div class="wrapper">
<h2>Action Mailer 基礎</h2><p>本篇提供收發信所需要了解的所有知識,包含 Action Mailer 內部工作原理以及如何測試 Mailer。</p><p>讀完本篇,您將了解:</p>
<ul>
<li>如何在 Rails 裡收發信件。</li>
<li>如何產生、編輯 Action Mailer 的類別與信件預覽(Mailer View)。</li>
<li>如何針對環境設定 Action Mailer。</li>
<li>如何測試 Action Mailer 類別。</li>
</ul>
<div id="subCol">
<h3 class="chapter"><img src="images/chapters_icon.gif" alt="" />Chapters</h3>
<ol class="chapters">
<li><a href="#%E7%B0%A1%E4%BB%8B">簡介</a></li>
<li>
<a href="#%E5%AF%84%E4%BF%A1">寄信</a>
<ul>
<li><a href="#%E9%80%90%E6%AD%A5%E4%BB%8B%E7%B4%B9%E5%A6%82%E4%BD%95%E7%94%A2%E7%94%9F-mailer">逐步介紹如何產生 Mailer</a></li>
<li><a href="#%E6%A8%99%E9%A0%AD%E5%80%BC%E8%87%AA%E5%8B%95%E7%B7%A8%E7%A2%BC">標頭值自動編碼</a></li>
<li><a href="#action-mailer-%E6%96%B9%E6%B3%95%E6%B8%85%E5%96%AE">Action Mailer 方法清單</a></li>
<li><a href="#mailer-views">Mailer Views</a></li>
<li><a href="#action-mailer-%E7%89%88%E5%9E%8B">Action Mailer 版型</a></li>
<li><a href="#%E5%9C%A8-action-mailer-views-%E7%94%A2%E7%94%9F-url">在 Action Mailer Views 產生 URL</a></li>
<li><a href="#%E5%AF%84%E9%80%81%E5%A4%9A%E7%A8%AE%E6%A0%BC%E5%BC%8F%E7%9A%84-email">寄送多種格式的 Email</a></li>
<li><a href="#%E4%BD%BF%E7%94%A8%E5%8B%95%E6%85%8B%E7%99%BC%E9%80%81%E9%81%B8%E9%A0%85%E4%BE%86%E5%AF%84%E4%BF%A1">使用動態發送選項來寄信</a></li>
<li><a href="#%E5%AF%84%E4%BF%A1%E4%BD%86%E4%B8%8D%E4%BD%BF%E7%94%A8%E6%A8%A1%E7%89%88">寄信但不使用模版</a></li>
</ul>
</li>
<li><a href="#%E6%94%B6%E4%BF%A1">收信</a></li>
<li><a href="#action-mailer-%E5%9B%9E%E5%91%BC">Action Mailer 回呼</a></li>
<li><a href="#%E4%BD%BF%E7%94%A8-action-mailer-%E7%9A%84%E8%BC%94%E5%8A%A9%E6%96%B9%E6%B3%95">使用 Action Mailer 的輔助方法</a></li>
<li>
<a href="#action-mailer-%E8%A8%AD%E5%AE%9A">Action Mailer 設定</a>
<ul>
<li><a href="#action-mailer-%E8%A8%AD%E5%AE%9A%E7%AF%84%E4%BE%8B">Action Mailer 設定範例</a></li>
<li><a href="#action-mailer-gmail-%E8%A8%AD%E5%AE%9A%E7%AF%84%E4%BE%8B">Action Mailer Gmail 設定範例</a></li>
</ul>
</li>
<li><a href="#%E6%B8%AC%E8%A9%A6-mailer">測試 Mailer</a></li>
<li><a href="#%E6%94%94%E6%88%AA-email">攔截 Email</a></li>
</ol>
</div>
</div>
</div>
<div id="container">
<div class="wrapper">
<div id="mainCol">
<h3 id="簡介">1 簡介</h3><p>Action Mailer 允許在應用程式裡使用 Mailer 類別與 View 來寄信。Mailer 的工作原理和 Controller 類似。Action Mailer 繼承自 <code>ActionMailer::Base</code>,檔案放在 <code>app/mailers</code>,與信件有關的 View 一樣放在 <code>app/views</code>。</p><h3 id="寄信">2 寄信</h3><p>本節逐步介紹一步步介紹如何建立 Mailer,以及 Mailer 的 View。</p><h4 id="逐步介紹如何產生-mailer">2.1 逐步介紹如何產生 Mailer</h4><h5 id="新建-mailer">2.1.1 新建 Mailer</h5><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ bin/rails generate mailer UserMailer
create app/mailers/user_mailer.rb
create app/mailers/application_mailer.rb
invoke erb
create app/views/user_mailer
create app/views/layouts/mailer.text.erb
create app/views/layouts/mailer.html.erb
invoke test_unit
create test/mailers/user_mailer_test.rb
create test/mailers/previews/user_mailer_preview.rb
</pre>
</div>
<div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
default from: "from@example.com"
layout 'mailer'
end
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
end
</pre>
</div>
<p>如上所見,可以使用產生器來產生 Mailer。Mailer 概念上類似於 Controller,產生的檔案也差不多:有 Mailer、放信件內容的目錄(View),以及測試 Mailer 的檔案。</p><p>若不想使用產生器,可以自己在 <code>app/mailers</code> 建立檔案,記得要繼承 <code>ActionMailer::Base</code>:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class MyMailer < ActionMailer::Base
end
</pre>
</div>
<h5 id="編輯-mailer">2.1.2 編輯 Mailer</h5><p>Mailer 和 Controller 非常類似。方法都叫做“動作”,用 View 來組織信件內容。但 Controller 是產生 HTML 回給客戶端;然而 Mailer 則是建立透過 email 寄出的信件(message)。</p><p>看看剛剛產生出來的 <code>app/mailers/user_mailer.rb</code>,內有一個空的 Mailer:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class UserMailer < ApplicationMailer
end
</pre>
</div>
<p>讓我們新增一個方法,稱之為 <code>welcome_email</code>,會寄信給使用者註冊的信箱:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class UserMailer < ApplicationMailer
default from: 'notifications@example.com'
def welcome_email(user)
@user = user
@url = 'http://example.com/login'
mail(to: @user.email, subject: 'Welcome to My Awesome Site')
end
end
</pre>
</div>
<p>以下是 <code>welcome_email</code> 的快速說明。關於 Action Mailer 所有可用的選項請參考<a href="#action-mailer-%E8%A8%AD%E5%AE%9A">〈Action Mailer 設定〉</a>一節。</p>
<ul>
<li>
<code>default Hash</code> ─ 任何使用這個 Mailer 送出的信件,所有發出去的信都會採用都存在這個 Hash 裡的預設值。上例設定 <code>:from</code> 標頭(header)。但預設值可以在每封信裡覆蓋。</li>
<li>
<code>mail</code> ─ 實際的信件內容。上例傳入了 <code>:to</code> 與 <code>:subject</code> 這兩個標頭(Header)。</li>
</ul>
<p>和 Controller 一樣,動作裡定義的實體變數,在 View 裡都可以取用。</p><h5 id="建立-mailer-的-view">2.1.3 建立 Mailer 的 View</h5><p>在 <code>app/views/user_mailer/</code> 新建叫做 <code>welcome_email.html.erb</code> 檔案。這個檔案會是信件的模版,採用 HTML 格式:</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
<h1>Welcome to example.com, <%= @user.name %></h1>
<p>
You have successfully signed up to example.com,
your username is: <%= @user.login %>.<br>
</p>
<p>
To login to the site, just follow this link: <%= @url %>.
</p>
<p>Thanks for joining and have a great day!</p>
</body>
</html>
</pre>
</div>
<p>再給信件建立一個純文字檔案。因為不是所有客戶端都可以顯示 HTML 格式的信件,兩種格式都寄是最佳實踐。在 <code>app/views/user_mailer/</code> 建立 <code>welcome_email.text.erb</code>:</p><div class="code_container">
<pre class="brush: ruby; html-script: true; gutter: false; toolbar: false">
Welcome to example.com, <%= @user.name %>
===============================================
You have successfully signed up to example.com,
your username is: <%= @user.login %>.
To login to the site, just follow this link: <%= @url %>.
Thanks for joining and have a great day!
</pre>
</div>
<p>呼叫 <code>mail</code> 方法時,Action Mailer 會偵測出有兩個模版(純文字與 HTML),會自動產生類型為 <code>multipart/alternative</code> 的信件。</p><h5 id="呼叫-mailer">2.1.4 呼叫 Mailer</h5><p>Mailer 其實只是另一種算繪(render) View 的方式,只是算繪的 View 不透過 HTTP 協定送出,而是透過 Email 協定送出。也是因為這個原因,成功建立使用者之後,應該用 Controller 呼叫 mailer 來寄信。</p><p>設定起來非常非常簡單。</p><p>首先,用鷹架建立簡單的 <code>User</code> :</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ bin/rails generate scaffold user name email login
$ bin/rake db:migrate
</pre>
</div>
<p>現在有了可以實驗的 <code>User</code> Model,打開 <code>app/controllers/users_controller.rb</code>,修改 <code>create</code> 動作,在成功新建使用者之後,讓 Controller 呼叫 <code>UserMailer</code> 寄信出去。將 <code>UserMailer.welcome_email</code> 這一行,放到成功儲存使用者之後。</p><p>Action Mailer 最近與 Active Job 整併,現在可以在請求響應週期之外寄送信件(背景執行),而無需使用者等候。</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class UsersController < ApplicationController
# POST /users
# POST /users.json
def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
# Tell the UserMailer to send a welcome email after save
UserMailer.welcome_email(@user).deliver_later
format.html { redirect_to(@user, notice: 'User was successfully created.') }
format.json { render json: @user, status: :created, location: @user }
else
format.html { render action: 'new' }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
end
</pre>
</div>
<div class="note"><p>Active Job 的預設行為是即刻(<code>:inline</code>)執行任務,即時寄出信件現在改用 <code>deliver_later</code> 即可。之後要改成背景執行也很簡單,只要給 Active Job 設定一個佇列後台即可(比如 Sidekiq、Resque 等)。</p></div><p>若想馬上寄出信件(比如在定時任務裡),只要呼叫 <code>deliver_now</code> 即可:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class SendWeeklySummary
def run
User.find_each do |user|
UserMailer.weekly_summary(user).deliver_now
end
end
end
</pre>
</div>
<p><code>welcome_email</code> 會回傳 <code>ActionMailer::MessageDelivery</code> 物件,對這個物件呼叫 <code>deliver_now</code> 或 <code>deliver_later</code> 便會將信件發送出去。<code>ActionMailer::MessageDelivery</code> 物件不過是 <code>Mail::Message</code> 物件的封裝。若想查看、修改 <code>Mail::Message</code> 物件,可以對 <code>ActionMailer::MessageDelivery</code> 呼叫 <code>message</code> 方法,來獲得 <code>Mail::Message</code> 物件。</p><h4 id="標頭值自動編碼">2.2 標頭值自動編碼</h4><p>Action Mailer 會自動對標頭(header)與信件主體(body)裡的多位元組字元進行編碼。</p><p>定義其它字元組、自編碼純文字等更複雜的範例,請參考 <a href="https://github.com/mikel/mail">Mail</a> 函式庫的說明文件。</p><h4 id="action-mailer-方法清單">2.3 Action Mailer 方法清單</h4><p>有三個方法最為重要:</p>
<ul>
<li>
<code>headers</code> ─ 指定信件的標頭。可以用 Hash 傳入欄位名與數值,或是使用 <code>headers[:field_name] = 'value'</code> 進行設定。</li>
<li>
<code>attachments</code> ─ 加入附件到信件。例如,<code>attachments['file-name.jpg'] = File.read('file-name.jpg')</code>。</li>
<li>
<code>mail</code> ─ 寄出實際信件。可以將標頭作為 Hash 傳給 <code>mail</code> 作為參數。<code>mail</code> 會新建一封信,純文字或是多種格式(multipart),取決於定義的模版是那種。</li>
</ul>
<h5 id="新增附件">2.3.1 新增附件</h5><p>Action Mailer 把新增附件變得非常簡單。</p>
<ul>
<li>
<p> 傳入檔名與內容,Action Mailer 與 <a href="https://github.com/mikel/mail">Mail gem</a> 會自動推論出 <code>mime_type</code>,設定編碼、建立附件。</p>
<div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
</pre>
</div>
<p>觸發 <code>mail</code> 方法之後,會寄出由多個部分組成的 Email,附件會嵌套在 <code>multipart/mixed</code> 類型裡,<code>multipart/mixed</code> 第一個部分是 <code>multipart/alternative</code>,包含 HTML 與純文字格式的信件,接著是附件。</p>
</li>
</ul>
<div class="note"><p>Mail 會自動使用 Base64 來對附件做編碼。若想用不同的編碼,先自行編碼,再使用 Hash 傳給 <code>attachments</code> 方法。</p></div>
<ul>
<li>
<p>傳入檔名、指定標頭與內容,Action Mailer 與 Mail 會使用傳入的設定來新增附件。</p>
<div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
encoded_content = SpecialEncode(File.read('/path/to/filename.jpg'))
attachments['filename.jpg'] = {
mime_type: 'application/x-gzip',
encoding: 'SpecialEncoding',
content: encoded_content
}
</pre>
</div>
</li>
</ul>
<div class="note"><p>如有指定編碼,Mail 會假設信件內容已經經過編碼了,不會再對附件做 Base64 編碼。</p></div><h5 id="製作行內附件">2.3.2 製作行內附件</h5><p>Action Mailer 3.0 起可製作行內附件(inline attachments)。3.0 以前需要很多 Hacking 才辦的到,3.0 之後,行內附件使用起來變得非常簡單直觀。</p>
<ul>
<li>
<p>首先,告訴 Mail 將附件轉成行內附件。只要對 <code>attachments</code> 方法呼叫 <code>#inline</code> 即可:</p>
<div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
def welcome
attachments.inline['image.jpg'] = File.read('/path/to/image.jpg')
end
</pre>
</div>
</li>
<li>
<p>接著在 View 裡,可以把 <code>attachments</code> 當成 Hash,指定要顯示的附件,對附件呼叫 <code>url</code>,接著傳給 <code>image_tag</code>:</p>
<div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
<p>Hello there, this is our image</p>
<%= image_tag attachments['image.jpg'].url %>
</pre>
</div>
</li>
<li>
<p>這不過是 <code>image_tag</code> 的標準呼叫方式,附件 URL 之後還可以傳別的選項:</p>
<div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
<p>Hello there, this is our image</p>
<%= image_tag attachments['image.jpg'].url, alt: 'My Photo', class: 'photos' %>
</pre>
</div>
</li>
</ul>
<h5 id="寄信給多個收件者">2.3.3 寄信給多個收件者</h5><p>可能會需要將信一次寄給多個人(譬如有人註冊通知所有的管理員),透過將 <code>:to</code> 設定成一組 Email 即可。一組 Email 可以用陣列表示,或是由逗號分開的 Email 字串。</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class AdminMailer < ActionMailer::Base
default to: Proc.new { Admin.pluck(:email) },
from: 'notification@example.com'
def new_registration(user)
@user = user
mail(subject: "New User Signup: #{@user.email}")
end
end
</pre>
</div>
<p>同樣的格式也可以用來設定副本與密件副本,分別設定 <code>:cc</code> 與 <code>:bcc</code> 即可。</p><h5 id="使用名稱寄信">2.3.4 使用名稱寄信</h5><p>有時希望收件者可看到寄件者的名稱,而不是寄件者的 Email。秘訣是以 <code>"Full Name <email>"</code> 格式書寫 Email 地址。</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
def welcome_email(user)
@user = user
email_with_name = %("#{@user.name}" <#{@user.email}>)
mail(to: email_with_name, subject: 'Welcome to My Awesome Site')
end
</pre>
</div>
<h4 id="mailer-views">2.4 Mailer Views</h4><p>Mailer views 檔案在 <code>app/views/name_of_mailer_class</code> 目錄下。Mailer 之所以知道要使用那個 View,是因為 View 的名稱和 Mailer 的方法同名。上面的例子裡,<code>welcome_email</code> 方法的 View 的 HTML 格式會存在 <code>app/views/user_mailer/welcome_email.html.erb</code>;純文字格式則是 <code>app/views/user_mailer/welcome_email.text.erb</code>。</p><p>要修改 Mailer 動作預設使用的 View,可以這麼做:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class UserMailer < ApplicationMailer
default from: 'notifications@example.com'
def welcome_email(user)
@user = user
@url = 'http://example.com/login'
mail(to: @user.email,
subject: 'Welcome to My Awesome Site',
template_path: 'notifications',
template_name: 'another')
end
end
</pre>
</div>
<p>這個例子 <code>UserMailer</code> 會去 <code>app/views/notifications</code> 尋找 <code>another</code> 這個 View。<code>template_path</code> 也可以是一組路徑(陣列形式),會依序在路徑下搜索 View。</p><p>若想更靈活的話,也可以傳入區塊,在區塊內明確算繪要用的模版,或是不使用模版,直接傳入字串也可以:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class UserMailer < ApplicationMailer
default from: 'notifications@example.com'
def welcome_email(user)
@user = user
@url = 'http://example.com/login'
mail(to: @user.email,
subject: 'Welcome to My Awesome Site') do |format|
format.html { render 'another_template' }
format.text { render text: 'Render text' }
end
end
end
</pre>
</div>
<p>上例程式會使用 <code>another_template.html.erb</code> 來算繪出 HTML 格式的信件,使用 <code>'Render text'</code> 來算繪純文字格式。<code>render</code> 方法與 Action Controller 內的 <code>render</code> 相同,接受同樣選項,像是 <code>:text</code>、<code>:inline</code> 等。</p><h4 id="action-mailer-版型">2.5 Action Mailer 版型</h4><p>和 Controller 的 View 類似,可以有 Mailer 版型(layout)。版型名稱必須與 Mailer 名稱相同,譬如 <code>user_mailer.html.erb</code> 或 <code>user_mailer.text.erb</code>,才可以自動視為是 Mailer 所使用的版型。</p><p>為了要使用不同的版型,在 Mailer 裡呼叫 <code>layout</code> 方法:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class UserMailer < ActionMailer::Base
layout 'awesome' # use awesome.(html|text).erb as the layout
end
</pre>
</div>
<p>和 Controller View 一樣,在版型裡使用 <code>yield</code> 來算繪 View。</p><p>也可以在算繪呼叫裡,傳入 <code>layout: 'layout_name'</code> 選項來指定版型:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class UserMailer < ApplicationMailer
def welcome_email(user)
mail(to: user.email) do |format|
format.html { render layout: 'my_layout' }
format.text
end
end
end
</pre>
</div>
<p>HTML 部分會使用 <code>my_layout.html.erb</code>,而純文字部分則會使用一般的 <code>user_mailer.text.erb</code> (如果存在的話)。</p><h4 id="在-action-mailer-views-產生-url">2.6 在 Action Mailer Views 產生 URL</h4><p>跟 Controllers 不一樣,Mailer 實體不知道與請求有關的上下文,所以要自行提供 <code>:host</code> 參數。</p><p>通常應用程式裡的 <code>:host</code> 都是相同的,可以在 <code>config/application.rb</code> 一併設定:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
config.action_mailer.default_url_options = { host: 'example.com' }
</pre>
</div>
<p>因為這個設定的關係,Email 裡不可以使用任何的 <code>*_path</code> 輔助方法,要用 <code>*_url</code>。譬如之前是:</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
<%= link_to 'welcome', welcome_path %>
</pre>
</div>
<p>會需要改為:</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
<%= link_to 'welcome', welcome_url %>
</pre>
</div>
<p>使用完整的 URL,Email 裡的連結才會正常工作。</p><h5 id="使用-url-for-產生-url">2.6.1 使用 <code>url_for</code> 產生 URL</h5><p>使用 <code>url_for</code> 時,需要傳入 <code>only_path: false</code> 選項。確保產生的是絕對 URL,因為 <code>url_for</code> 輔助方法預設會產生相對 URL。</p><div class="code_container">
<pre class="brush: ruby; html-script: true; gutter: false; toolbar: false">
<%= url_for(controller: 'welcome',
action: 'greeting',
only_path: false) %>
</pre>
</div>
<p>若沒有全域設定 <code>:host</code>,記得在用 <code>url_for</code> 時要傳進來。</p><div class="code_container">
<pre class="brush: ruby; html-script: true; gutter: false; toolbar: false">
<%= url_for(host: 'example.com',
controller: 'welcome',
action: 'greeting') %>
</pre>
</div>
<div class="note"><p>當明確傳入 <code>:host</code> 時,Rails 會產生絕對 URL,所以不需要再指定 <code>only_path: false</code>。</p></div><h5 id="使用具名路由產生-url">2.6.2 使用具名路由產生 URL</h5><p>Email 客戶端對 Web 一無所知,無法根據某個基礎 URL 來產生完整的 URL。因此,具名路由應該要永遠使用 <code>*_url</code>。</p><p>若沒有全域設定 <code>:host</code>,記得要傳進來。</p><div class="code_container">
<pre class="brush: ruby; html-script: true; gutter: false; toolbar: false">
<%= user_url(@user, host: 'example.com') %>
</pre>
</div>
<h4 id="寄送多種格式的-email">2.7 寄送多種格式的 Email</h4><p>如果 Action Mailer 的動作有多個模版,Action Mailer 會自動寄出多種格式的 Email。在 <code>UserMailer</code> 例子裡,若 <code>app/views/user_mailer</code> 有 <code>welcome_email.text.erb</code> 以及 <code>welcome_email.html.erb</code>,則 Action Mailer 會自動寄出多種格式的 Email。</p><p>Email 格式收到的順序由 <code>ActionMailer::Base.default</code> 方法裡的 <code>:parts_order</code> 決定。</p><h4 id="使用動態發送選項來寄信">2.8 使用動態發送選項來寄信</h4><p>若想送信時覆蓋預設的發送選項(譬如 SMTP credential),可以在 Mailer 的動作裡使用 <code>delivery_method_options</code>。</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class UserMailer < ApplicationMailer
def welcome_email(user, company)
@user = user
@url = user_url(@user)
delivery_options = { user_name: company.smtp_user,
password: company.smtp_password,
address: company.smtp_host }
mail(to: @user.email,
subject: "Please see the Terms and Conditions attached",
delivery_method_options: delivery_options)
end
end
</pre>
</div>
<h4 id="寄信但不使用模版">2.9 寄信但不使用模版</h4><p>有些情況可能不想要使用模版,需要直接將信件主體(Email Body)作為字串送出。可以使用 <code>:body</code> 選項。同時記得要加上 <code>:content_type</code> 選項(Rails 預設是 <code>text/plain</code>)。</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class UserMailer < ApplicationMailer
def welcome_email(user, email_body)
mail(to: user.email,
body: email_body,
content_type: "text/html",
subject: "Already rendered!")
end
end
</pre>
</div>
<h3 id="收信">3 收信</h3><p>在 Action Mailer 接受與解析信件相對複雜許多。在信件送到 Rails 應用程式之前,需要設定作業系統轉發信件到 Rails,所以作業系統會需要監聽進來的信。總結在 Rails 裡收信會需要:</p>
<ul>
<li><p>在 Mailer 實作 <code>receive</code> 方法。</p></li>
<li><p>設定郵件伺服器轉發信件到 <code>/path/to/app/bin/rails runner
'UserMailer.receive(STDIN.read)'</code>。</p></li>
</ul>
<p>一旦在任何 Mailer 裡定義了 <code>receive</code>,Action Mailer 會將進來的信件解析成 Email 物件、解碼、實體化新的 Mailer,接著將 Email 物件傳給 Mailer 的 <code>receive</code>。以下是範例:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class UserMailer < ApplicationMailer
def receive(email)
page = Page.find_by(address: email.to.first)
page.emails.create(
subject: email.subject,
body: email.body
)
if email.has_attachments?
email.attachments.each do |attachment|
page.attachments.create({
file: attachment,
description: email.subject
})
end
end
end
end
</pre>
</div>
<h3 id="action-mailer-回呼">4 Action Mailer 回呼</h3><p>Action Mailer 允許指定 <code>before_action</code>、<code>after_action</code> 以及 <code>around_action</code> 回呼。</p>
<ul>
<li><p>濾動器(filters)可用方法名稱(符號)指定,也可用區塊,和 Controller 指定方法類似。</p></li>
<li><p>可以使用 <code>before_action</code> 在寄信前對 Mailer 物件做處理,或是用 <code>delivery_method_options</code> 來設定預設值,插入預設的標頭、附件等。</p></li>
<li><p>可以使用 <code>after_action</code> 做和 <code>before_action</code> 類似的事情,但動作裡可以使用實體變數。</p></li>
</ul>
<div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class UserMailer < ApplicationMailer
after_action :set_delivery_options,
:prevent_delivery_to_guests,
:set_business_headers
def feedback_message(business, user)
@business = business
@user = user
mail
end
def campaign_message(business, user)
@business = business
@user = user
end
private
def set_delivery_options
# You have access to the mail instance,
# @business and @user instance variables here
if @business && @business.has_smtp_settings?
mail.delivery_method.settings.merge!(@business.smtp_settings)
end
end
def prevent_delivery_to_guests
if @user && @user.guest?
mail.perform_deliveries = false
end
end
def set_business_headers
if @business
headers["X-SMTPAPI-CATEGORY"] = @business.code
end
end
end
</pre>
</div>
<ul>
<li>若信件的 body 不是 <code>nil</code>,Mailer 的濾動器會終止處理。</li>
</ul>
<h3 id="使用-action-mailer-的輔助方法">5 使用 Action Mailer 的輔助方法</h3><p>Action Mailer 只是繼承自 <code>AbstractController</code>,所以 Action Controller 有的通用輔助方法,Action Mailer 裡也有。</p><h3 id="action-mailer-設定">6 Action Mailer 設定</h3><p>以下設定選項最好在跟環境相關的檔案裡設定(environment.rb, production.rb 等)。</p>
<table>
<thead>
<tr>
<th>Configuration</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>logger</code></td>
<td>產生 Mailer 執行時的記錄檔。設為 <code>nil</code> 則不記錄。可以使用 Ruby 的 <code>Logger</code> 與 <code>log4r</code>。</td>
</tr>
<tr>
<td><code>smtp_settings</code></td>
<td>用來設定 <code>:smtp</code> 發送方法:<ul>
<li>
<code>:address</code> ─ 允許使用遠端郵件伺服器。預設是 <code>"localhost"</code>。</li>
<li>
<code>:port</code> ─ 若郵件伺服器不是使用埠口 25,這個選項可以改。</li>
<li>
<code>:domain</code> ─ 指定 HELO 網域。</li>
<li>
<code>:user_name</code> ─ 如果郵件伺服器需要驗證身分,這個選項可以設定使用者名稱。</li>
<li>
<code>:password</code> ─ 如果郵件伺服器需要驗證身分,這個選項可以設定密碼。</li>
<li>
<code>:authentication</code> ─ 如果郵件伺服器需要驗證身分,這個選項可以設定驗證類型,可用的值有(符號):<code>:plain</code>、<code>:login</code>、<code>:cram_md5</code>。</li>
<li>
<code>:enable_starttls_auto</code> ─ 如果無法解析郵件伺服器的證書,把這個設定設為 <code>false</code>。</li>
</ul>
</td>
</tr>
<tr>
<td><code>sendmail_settings</code></td>
<td>設定 <code>:sendmail</code> 發送方法的選項。<ul>
<li>
<code>:location</code> ─ <code>sendmail</code> 執行檔案的位置。預設是 <code>/usr/sbin/sendmail</code>。</li>
<li>
<code>:arguments</code> ─ 傳給 <code>sendmail</code> 參數的命令列參數,預設是 <code>-i -t</code>。</li>
</ul>
</td>
</tr>
<tr>
<td><code>raise_delivery_errors</code></td>
<td>信件寄送失敗時是否要拋出錯誤。只在外部郵件伺服器設為立即送出時有效。</td>
</tr>
<tr>
<td><code>delivery_method</code></td>
<td>定義送信的方法。可用的數值有:<ul>
<li>
<code>:smtp</code>(預設值),可以透過 <code>config.action_mailer.smtp_settings</code> 來設定。</li>
<li>
<code>:sendmail</code>,可以透過 <code>config.action_mailer.sendmail_settings</code> 來設定。</li>
<li>
<code>:file</code>:把信件存成檔案。可以透過 <code>config.action_mailer.file_settings</code> 來設定。</li>
<li>
<code>:test</code>:把信件存到 <code>ActionMailer::Base.deliveries</code> 陣列裡。</li>
</ul>參考 <a href="http://api.rubyonrails.org/classes/ActionMailer/Base.html">API 文件</a>來了解更多資訊。</td>
</tr>
<tr>
<td><code>perform_deliveries</code></td>
<td>決定 <code>deliver</code> 方法是否真的要送出信件。預設是會,但可以在做功能性測試時關掉。</td>
</tr>
<tr>
<td><code>deliveries</code></td>
<td>由 Action Mailer 使用 <code>:test</code> 方法送出的信件保存到陣列裡。主要用來做功能性與單元測試。</td>
</tr>
<tr>
<td><code>default_options</code></td>
<td>設定 <code>mail</code> 方法的預設值(如 <code>:from</code>、<code>:reply_to</code> 等)。</td>
</tr>
</tbody>
</table>
<p>完整設定選項請參考<a href="configuring.html#configuring-action-mailer">《Rails 應用程式設定》文中的〈Action Mailer〉一節</a>。</p><h4 id="action-mailer-設定範例">6.1 Action Mailer 設定範例</h4><p><code>config/environments/$RAILS_ENV.rb</code> 檔案關於 Mailer 的設定範例:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
config.action_mailer.delivery_method = :sendmail
# Defaults to:
# config.action_mailer.sendmail_settings = {
# location: '/usr/sbin/sendmail',
# arguments: '-i -t'
# }
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.default_options = {from: 'no-reply@example.com'}
</pre>
</div>
<h4 id="action-mailer-gmail-設定範例">6.2 Action Mailer Gmail 設定範例</h4><p>由於 Action Mailer 現在使用 <a href="https://github.com/mikel/mail">Mail gem</a> 了,Gmail 的設定非常簡單,將下面的程式碼加到 <code>config/environments/$RAILS_ENV.rb</code> 檔案即可:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'example.com',
user_name: '<username>',
password: '<password>',
authentication: 'plain',
enable_starttls_auto: true }
</pre>
</div>
<h3 id="測試-mailer">7 測試 Mailer</h3><p>如何測試 Mailer 的詳細教學可以參考<a href="testing.html#testing-your-mailers">測試指南</a>。</p><h3 id="攔截-email">8 攔截 Email</h3><p>有時候需要在信件寄出前做些修改。Action Mailer 提供攔截 Email 的 hook。可以註冊一個攔截器,在信件內容交給發送服務前對信件做修改。</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class SandboxEmailInterceptor
def self.delivering_email(message)
message.to = ['sandbox@example.com']
end
end
</pre>
</div>
<p>攔截器執行任務之前,需要先給 Action Mailer 打聲招呼。建立一個 initializer 檔案,<code>config/initializers/sandbox_email_interceptor.rb</code>:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
ActionMailer::Base.register_interceptor(SandboxEmailInterceptor) if Rails.env.staging?
</pre>
</div>
<div class="note"><p>上例使用了自訂的環境,叫做 “staging”,跟 production 環境類似,做測試之用。自訂 Rails 環境的更多資訊,請閱讀<a href="configuring.html#creating-rails-environments">建立 Rails 環境</a>。</p></div>
<h3>反饋</h3>
<p>
歡迎幫忙改善指南的品質。
</p>
<p>
如發現任何錯誤之處,歡迎修正。開始貢獻前,可以先閱讀<a href="http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#contributing-to-the-rails-documentation">貢獻指南:文件</a>。
</p>
<p>翻譯如有錯誤,深感抱歉,歡迎 <a href="https://github.com/docrails-tw/guides/fork">Fork</a> 修正,或至此處<a href="https://github.com/docsrails-tw/guides/issues/new">回報</a>。</p>
<p>
文章可能有未完成或過時的內容。請先檢查 <a href="http://edgeguides.rubyonrails.org">Edge Guides</a> 來確定問題在 master 是否已經修掉了。再上 master 補上缺少的文件。內容參考 <a href="ruby_on_rails_guides_guidelines.html">Ruby on Rails 指南準則</a>來了解行文風格。
</p>
<p>最後,任何關於 Ruby on Rails 文件的討論,歡迎至 <a href="http://groups.google.com/group/rubyonrails-docs">rubyonrails-docs 郵件論壇</a>。
</p>
</div>
</div>
</div>
<hr class="hide">
<div id="footer">
<div class="wrapper">
<p>本著作係採用<a href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh_TW">創用 CC 姓名標示-相同方式分享 4.0 國際授權條款</a>授權。</p>
<p>“Rails”、“Ruby on Rails”,以及 Rails logo 為 David Heinemeier Hansson 的商標。版權所有。</p>
</div>
</div>
<script src="javascripts/jquery.min.js"></script>
<script src="javascripts/responsive-tables.js"></script>
<script src="javascripts/guides.js"></script>
<script src="javascripts/syntaxhighlighter/shCore.js"></script>
<script src="javascripts/syntaxhighlighter/shBrushRuby.js"></script>
<script src="javascripts/syntaxhighlighter/shBrushXml.js"></script>
<script src="javascripts/syntaxhighlighter/shBrushSql.js"></script>
<script src="javascripts/syntaxhighlighter/shBrushPlain.js"></script>
<script type="text/javascript">
SyntaxHighlighter.all();
$(guidesIndex.bind);
</script>
<script>
(function(i,s,o,g,r,a,m){i["GoogleAnalyticsObject"]=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,"script","//www.google-analytics.com/analytics.js","ga");
ga("create", "UA-49903900-1", "auto");
ga("require", "displayfeatures");
ga("send", "pageview");
</script>
</body>
</html>