email_spy 1.0.3 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,13 @@
1
1
  require "fileutils"
2
2
  require "digest/sha1"
3
3
  require "cgi"
4
+ require "uri"
4
5
  require "launchy"
5
6
 
7
+ module EmailSpy
8
+ EMAIL_DIRECTORY_NAME = "email_spy"
9
+ end
10
+
6
11
  require_relative "email_spy/message"
7
12
  require_relative "email_spy/delivery_method"
8
13
  require_relative "email_spy/railtie" if defined? Rails
@@ -3,20 +3,44 @@ module EmailSpy
3
3
  attr_accessor :settings
4
4
 
5
5
  def initialize(options = {})
6
- @settings = { location: File.join('.', 'email_spy') }
6
+ @settings = { location: email_directory }
7
7
  @settings.merge! options
8
8
  end
9
9
 
10
10
  def deliver!(email)
11
- time = Time.now.to_i
12
- hash = Digest::SHA1.hexdigest(email.encoded)[0..6]
13
- location = File.join settings[:location], "#{time}_#{hash}"
11
+ launch messages(email, location(email, settings))
12
+ end
13
+
14
+ private
14
15
 
15
- messages = email.parts.map { |part| Message.new location, email, part }
16
- messages << Message.new(location, email) if messages.empty?
17
- messages.each &:render
16
+ def location(email, settings)
17
+ File.join settings[:location], "#{Time.now.to_i}_#{digest email}"
18
+ end
19
+
20
+ def digest(email)
21
+ Digest::SHA1.hexdigest(email.encoded)[0..6]
22
+ end
18
23
 
24
+ def messages(email, path)
25
+ if email.html_part || email.text_part
26
+ [email.html_part, email.text_part].compact.map do |part|
27
+ Message.new path, email, part
28
+ end
29
+ else
30
+ [Message.new(path, email)]
31
+ end.each &:render
32
+ end
33
+
34
+ def launch(messages)
19
35
  Launchy.open URI.parse "file://#{messages.first.filepath}"
20
36
  end
37
+
38
+ def email_directory
39
+ if defined?(Rails)
40
+ Rails.root.join "tmp", EMAIL_DIRECTORY_NAME
41
+ else
42
+ File.join '.', EMAIL_DIRECTORY_NAME
43
+ end
44
+ end
21
45
  end
22
46
  end
@@ -1,88 +1,99 @@
1
1
  <meta http-equiv="Content-Type" content="text/html; charset=<%= encoding %>">
2
- <style type="text/css">
3
- #message_headers {
4
- position: relative;
5
- top: 0px;
6
- left: 0;
7
- width: 100%;
8
- height: 85px;
9
- padding: 10px 0 0 0;
10
- margin: 0;
11
- margin-bottom:20px;
12
- background: #fff;
13
- font-size: 12px;
14
- font-family: "Lucida Grande";
15
- border-bottom: 1px solid #dedede;
16
- overflow: hidden;
17
- }
18
-
19
- #message_headers dl {
20
- margin: 0;
21
- padding: 0;
22
- }
23
-
24
- #message_headers dt {
25
- width: 60px;
26
- padding: 1px;
27
- float: left;
28
- text-align: right;
29
- font-weight: bold;
30
- color: #7f7f7f;
31
- }
32
2
 
33
- #message_headers dd {
34
- margin-left: 70px;
35
- padding: 1px;
3
+ <style type="text/css">
4
+ body {
5
+ background: pearl;
36
6
  }
37
-
38
- #message_headers p.alternate {
39
- position: absolute;
40
- top: 0;
41
- right: 15px;
7
+ .header .clearfix{*zoom:1}.header .clearfix:before,.header .clearfix:after{display:table;content:""}.header .clearfix:after{clear:both}.header .hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.header .input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.header article,.header aside,.header details,.header figcaption,.header figure,.header footer,.header header,.header hgroup,.header nav,.header section{display:block}.header audio,.header canvas,.header video{display:inline-block;*display:inline;*zoom:1}.header audio:not([controls]){display:none}.header html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}.header a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.header a:hover,.header a:active{outline:0}.header sub,.header sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}.header sup{top:-0.5em}.header sub{bottom:-0.25em}.header img{max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}.header #map_canvas img{max-width:none}.header button,.header input,.header select,.header textarea{margin:0;font-size:100%;vertical-align:middle}.header button,.header input{*overflow:visible;line-height:normal}.header button::-moz-focus-inner,.header input::-moz-focus-inner{padding:0;border:0}.header button,.header input[type="button"],.header input[type="reset"],.header input[type="submit"]{cursor:pointer;-webkit-appearance:button}.header input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}.header input[type="search"]::-webkit-search-decoration,.header input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}.header textarea{overflow:auto;vertical-align:top}.header body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#333;background-color:#fff}.header a{color:#08c;text-decoration:none}.header a:hover{color:#005580;text-decoration:underline}.header .row{margin-left:-20px;*zoom:1}.header .row:before,.header .row:after{display:table;content:""}.header .row:after{clear:both}.header [class*="span"]{float:left;margin-left:20px}.header .container,.header .navbar-fixed-top .container,.header .navbar-fixed-bottom .container{width:940px}.header .span12{width:940px}.header .span11{width:860px}.header .span10{width:780px}.header .span9{width:700px}.header .span8{width:620px}.header .span7{width:540px}.header .span6{width:460px}.header .span5{width:380px}.header .span4{width:300px}.header .span3{width:220px}.header .span2{width:140px}.header .span1{width:60px}.header .offset12{margin-left:980px}.header .offset11{margin-left:900px}.header .offset10{margin-left:820px}.header .offset9{margin-left:740px}.header .offset8{margin-left:660px}.header .offset7{margin-left:580px}.header .offset6{margin-left:500px}.header .offset5{margin-left:420px}.header .offset4{margin-left:340px}.header .offset3{margin-left:260px}.header .offset2{margin-left:180px}.header .offset1{margin-left:100px}.header .row-fluid{width:100%;*zoom:1}.header .row-fluid:before,.header .row-fluid:after{display:table;content:""}.header .row-fluid:after{clear:both}.header .row-fluid [class*="span"]{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.127659574%;*margin-left:2.0744680846382977%}.header .row-fluid [class*="span"]:first-child{margin-left:0}.header .row-fluid .span12{width:99.99999998999999%;*width:99.94680850063828%}.header .row-fluid .span11{width:91.489361693%;*width:91.4361702036383%}.header .row-fluid .span10{width:82.97872339599999%;*width:82.92553190663828%}.header .row-fluid .span9{width:74.468085099%;*width:74.4148936096383%}.header .row-fluid .span8{width:65.95744680199999%;*width:65.90425531263828%}.header .row-fluid .span7{width:57.446808505%;*width:57.3936170156383%}.header .row-fluid .span6{width:48.93617020799999%;*width:48.88297871863829%}.header .row-fluid .span5{width:40.425531911%;*width:40.3723404216383%}.header .row-fluid .span4{width:31.914893614%;*width:31.8617021246383%}.header .row-fluid .span3{width:23.404255317%;*width:23.3510638276383%}.header .row-fluid .span2{width:14.89361702%;*width:14.8404255306383%}.header .row-fluid .span1{width:6.382978723%;*width:6.329787233638298%}.header p{margin:0 0 9px}.header p small{font-size:11px;color:#999}.header .lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px}.header h1,.header h2,.header h3,.header h4,.header h5,.header h6{margin:0;font-family:inherit;font-weight:bold;color:inherit;text-rendering:optimizelegibility}.header h1 small,.header h2 small,.header h3 small,.header h4 small,.header h5 small,.header h6 small{font-weight:normal;color:#999}.header h1{font-size:30px;line-height:36px}.header h1 small{font-size:18px}.header h2{font-size:24px;line-height:36px}.header h2 small{font-size:18px}.header h3{font-size:18px;line-height:27px}.header h3 small{font-size:14px}.header h4,.header h5,.header h6{line-height:18px}.header h4{font-size:14px}.header h4 small{font-size:12px}.header h5{font-size:12px}.header h6{font-size:11px;color:#999;text-transform:uppercase}.header .page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eee}.header .page-header h1{line-height:1}.header ul,.header ol{padding:0;margin:0 0 9px 25px}.header ul ul,.header ul ol,.header ol ol,.header ol ul{margin-bottom:0}.header ul{list-style:disc}.header ol{list-style:decimal}.header li{line-height:18px}.header ul.unstyled,.header ol.unstyled{margin-left:0;list-style:none}.header dl{margin-bottom:18px}.header dt,.header dd{line-height:18px}.header dt{font-weight:bold;line-height:17px}.header dd{margin-left:9px}.header .dl-horizontal dt{float:left;width:120px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.header .dl-horizontal dd{margin-left:130px}.header hr{margin:18px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}.header strong{font-weight:bold}.header em{font-style:italic}.header .muted{color:#999}.header abbr[title]{cursor:help;border-bottom:1px dotted #999}.header abbr.initialism{font-size:90%;text-transform:uppercase}.header blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eee}.header blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px}.header blockquote small{display:block;line-height:18px;color:#999}.header blockquote small:before{content:'\2014 \00A0'}.header blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}.header blockquote.pull-right p,.header blockquote.pull-right small{text-align:right}.header q:before,.header q:after,.header blockquote:before,.header blockquote:after{content:""}.header address{display:block;margin-bottom:18px;font-style:normal;line-height:18px}.header small{font-size:100%}.header cite{font-style:normal}.header .label,.header .badge{font-size:10.998px;font-weight:bold;line-height:14px;color:#fff;vertical-align:baseline;white-space:nowrap;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#999}.header .label{padding:1px 4px 2px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.header .badge{padding:1px 9px 2px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.header a.label:hover,.header a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.header .label-important,.header .badge-important{background-color:#b94a48}.header .label-important[href],.header .badge-important[href]{background-color:#953b39}.header .label-warning,.header .badge-warning{background-color:#f89406}.header .label-warning[href],.header .badge-warning[href]{background-color:#c67605}.header .label-success,.header .badge-success{background-color:#468847}.header .label-success[href],.header .badge-success[href]{background-color:#356635}.header .label-info,.header .badge-info{background-color:#3a87ad}.header .label-info[href],.header .badge-info[href]{background-color:#2d6987}.header .label-inverse,.header .badge-inverse{background-color:#333}.header .label-inverse[href],.header .badge-inverse[href]{background-color:#1a1a1a}.header .btn{display:inline-block;*display:inline;*zoom:1;padding:4px 10px 4px;margin-bottom:0;font-size:13px;line-height:18px;*line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;background-image:-moz-linear-gradient(top,white,#e6e6e6);background-image:-ms-linear-gradient(top,white,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(white),to(#e6e6e6));background-image:-webkit-linear-gradient(top,white,#e6e6e6);background-image:-o-linear-gradient(top,white,#e6e6e6);background-image:linear-gradient(top,#fff,#e6e6e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff',endColorstr='#e6e6e6',GradientType=0);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#e6e6e6;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border:1px solid #ccc;*border:0;border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*margin-left:.3em;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.header .btn:hover,.header .btn:active,.header .btn.active,.header .btn.disabled,.header .btn[disabled]{background-color:#e6e6e6;*background-color:#d9d9d9}.header .btn:active,.header .btn.active{background-color:#ccc \9}.header .btn:first-child{*margin-left:0}.header .btn:hover{color:#333;text-decoration:none;background-color:#e6e6e6;*background-color:#d9d9d9;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-ms-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.header .btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.header .btn.active,.header .btn:active{background-color:#e6e6e6;background-color:#d9d9d9 \9;background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.header .btn.disabled,.header .btn[disabled]{cursor:default;background-color:#e6e6e6;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.header .btn-large{padding:9px 14px;font-size:15px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.header .btn-large [class^="icon-"]{margin-top:1px}.header .btn-small{padding:5px 9px;font-size:11px;line-height:16px}.header .btn-small [class^="icon-"]{margin-top:-1px}.header .btn-mini{padding:2px 6px;font-size:11px;line-height:14px}.header .btn-primary,.header .btn-primary:hover,.header .btn-warning,.header .btn-warning:hover,.header .btn-danger,.header .btn-danger:hover,.header .btn-success,.header .btn-success:hover,.header .btn-info,.header .btn-info:hover,.header .btn-inverse,.header .btn-inverse:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.header .btn-primary.active,.header .btn-warning.active,.header .btn-danger.active,.header .btn-success.active,.header .btn-info.active,.header .btn-inverse.active{color:rgba(255,255,255,0.75)}.header .btn{border-color:#ccc;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.header .btn-primary{background-color:#0074cc;background-image:-moz-linear-gradient(top,#08c,#05c);background-image:-ms-linear-gradient(top,#08c,#05c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#05c));background-image:-webkit-linear-gradient(top,#08c,#05c);background-image:-o-linear-gradient(top,#08c,#05c);background-image:linear-gradient(top,#08c,#05c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0055cc',GradientType=0);border-color:#05c #05c #003580;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#05c;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.header .btn-primary:hover,.header .btn-primary:active,.header .btn-primary.active,.header .btn-primary.disabled,.header .btn-primary[disabled]{background-color:#05c;*background-color:#004ab3}.header .btn-primary:active,.header .btn-primary.active{background-color:#004099 \9}.header .btn-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-ms-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(top,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450',endColorstr='#f89406',GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#f89406;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.header .btn-warning:hover,.header .btn-warning:active,.header .btn-warning.active,.header .btn-warning.disabled,.header .btn-warning[disabled]{background-color:#f89406;*background-color:#df8505}.header .btn-warning:active,.header .btn-warning.active{background-color:#c67605 \9}.header .btn-danger{background-color:#da4f49;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-ms-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(top,#ee5f5b,#bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#bd362f',GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#bd362f;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.header .btn-danger:hover,.header .btn-danger:active,.header .btn-danger.active,.header .btn-danger.disabled,.header .btn-danger[disabled]{background-color:#bd362f;*background-color:#a9302a}.header .btn-danger:active,.header .btn-danger.active{background-color:#942a25 \9}.header .btn-success{background-color:#5bb75b;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-ms-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(top,#62c462,#51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462',endColorstr='#51a351',GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#51a351;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.header .btn-success:hover,.header .btn-success:active,.header .btn-success.active,.header .btn-success.disabled,.header .btn-success[disabled]{background-color:#51a351;*background-color:#499249}.header .btn-success:active,.header .btn-success.active{background-color:#408140 \9}.header .btn-info{background-color:#49afcd;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-ms-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(top,#5bc0de,#2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de',endColorstr='#2f96b4',GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#2f96b4;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.header .btn-info:hover,.header .btn-info:active,.header .btn-info.active,.header .btn-info.disabled,.header .btn-info[disabled]{background-color:#2f96b4;*background-color:#2a85a0}.header .btn-info:active,.header .btn-info.active{background-color:#24748c \9}.header .btn-inverse{background-color:#414141;background-image:-moz-linear-gradient(top,#555,#222);background-image:-ms-linear-gradient(top,#555,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#555),to(#222));background-image:-webkit-linear-gradient(top,#555,#222);background-image:-o-linear-gradient(top,#555,#222);background-image:linear-gradient(top,#555,#222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#555555',endColorstr='#222222',GradientType=0);border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#222;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.header .btn-inverse:hover,.header .btn-inverse:active,.header .btn-inverse.active,.header .btn-inverse.disabled,.header .btn-inverse[disabled]{background-color:#222;*background-color:#151515}.header .btn-inverse:active,.header .btn-inverse.active{background-color:#080808 \9}.header button.btn,.header input[type="submit"].btn{*padding-top:2px;*padding-bottom:2px}.header button.btn::-moz-focus-inner,.header input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}.header button.btn.btn-large,.header input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}.header button.btn.btn-small,.header input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}.header button.btn.btn-mini,.header input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.header .well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #eee;border:1px solid rgba(0,0,0,0.05);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.header .well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.header .well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.header .well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}
8
+ .header .label { text-align: right; }
9
+ .header .controls { text-align: center; }
10
+ .message {
11
+ width: 760px;
12
+ margin: 10px auto;
13
+ padding: 0px 5px;
14
+ border: 1px solid grey;
15
+ box-shadow: 3px 3px 3px silver;
42
16
  }
17
+ </style>
18
+ <div class="header">
19
+ <div class="well">
20
+ <div class="row">
21
+ <div class="from field span6">
22
+ <strong class="label label-info span1">From:</strong>
23
+ &nbsp;
24
+ <%= from %>
25
+ </div>
43
26
 
44
- #message_headers p.alternate a {
45
- color: #09c;
46
- }
27
+ <div class="to field span6">
28
+ <strong class="label label-info span1">To:</strong>
29
+ &nbsp;
30
+ <%= email.to.join ", " unless email.to.empty? %>
31
+ </div>
47
32
 
48
- pre#message_body {
49
- padding: 10px;
50
- word-wrap: break-word;
51
- }
33
+ <% if email.cc || email.bcc %>
34
+ <% if email.cc %>
35
+ <div class="cc field span6">
36
+ <strong class="label label-info span1">CC:</strong>
37
+ &nbsp;
38
+ <%= email.cc.join ", " %>
39
+ </div>
40
+ <% end %>
52
41
 
53
- body {
54
- margin-top: 96px !important;
55
- }
56
- </style>
42
+ <% if email.bcc %>
43
+ <div class="cc field span6">
44
+ <strong class="label label-info span1">BCC:</strong>
45
+ &nbsp;
46
+ <%= email.bcc.join ", " %>
47
+ </div>
48
+ <% end %>
49
+ <% end %>
57
50
 
58
- <div id="message_headers">
59
- <dl>
60
- <dt>From:</dt>
61
- <dd><%= from %></dd>
51
+ <% unless reply_to.empty? %>
52
+ <div class="reply-to field span6">
53
+ <strong class="label label-info span1">Reply-To:</strong>
54
+ &nbsp;
55
+ <%= reply_to %>
56
+ </div>
57
+ <% end %>
62
58
 
63
- <dt>Subject:</dt>
64
- <dd><strong><%= email.subject %></strong></dd>
59
+ <div class="subject field span6">
60
+ <strong class="label label-info span1">Subject:</strong>
61
+ &nbsp;
62
+ <%= email.subject %>
63
+ </div>
65
64
 
66
- <dt>Date:</dt>
67
- <dd><%= Time.now.strftime("%b %e, %Y %I:%M:%S %p %Z") %></dd>
65
+ <div class="date field span6">
66
+ <strong class="label label-info span1">Date:</strong>
67
+ &nbsp;
68
+ <%= Time.now.strftime "%b %e, %Y %I:%M:%S %p %Z" %>
69
+ </div>
68
70
 
69
- <dt>To:</dt>
70
- <dd><%= email.to.join ", " %></dd>
71
- </dl>
71
+ <% if attachments.any? %>
72
+ <div class="attachments field span12">
73
+ <strong class="label label-info span2">Attachments:</strong>
74
+ &nbsp;
75
+ <%= attachments.map { |a| "<a href='#{a.last}'>#{a.first}</a>" }.join ', ' %>
76
+ </div>
77
+ <% end %>
78
+ </div>
79
+ </div>
72
80
 
73
81
  <% if email.multipart? %>
74
- <p class="alternate">
75
- <% if type == "plain" %>
76
- <a href="rich.html">View HTML version</a>
77
- <% else %>
78
- <a href="plain.html">View plain text version</a>
82
+ <div class="controls">
83
+ <% case when type == "rich" && email.text_part %>
84
+ <a href="plain.html" class="btn btn-large">Text</a>
85
+ <% when type == "plain" && email.html_part %>
86
+ <a href="rich.html" class="btn btn-large">HTML</a>
79
87
  <% end %>
80
- </p>
88
+ </div>
81
89
  <% end %>
90
+ </div>
82
91
  </div>
83
92
 
84
- <% if type == "plain" %>
85
- <pre id="message_body"><%= CGI.escapeHTML(body) %></pre>
86
- <% else %>
87
- <%= body %>
88
- <% end %>
93
+ <div class="message">
94
+ <% unless type == "plain" %>
95
+ <%= body %>
96
+ <% else %>
97
+ <pre><%= CGI.escapeHTML body %></pre>
98
+ <% end %>
99
+ </div>
@@ -1,19 +1,15 @@
1
1
  module EmailSpy
2
2
  class Message
3
3
  attr_reader :email
4
+ attr_reader :attachments
4
5
 
5
6
  def initialize(location, email, part = nil)
6
- @location = location
7
- @email = email
8
- @part = part
7
+ @location, @email, @part, @attachments = location, email, part, []
9
8
  end
10
9
 
11
10
  def render
12
- FileUtils.mkdir_p @location
13
-
14
- File.open filepath, 'w' do |file|
15
- file.write ERB.new(template).result binding
16
- end
11
+ create_attachments unless email.attachments.empty?
12
+ create_templates filepath, binding
17
13
  end
18
14
 
19
15
  def template
@@ -33,15 +29,51 @@ module EmailSpy
33
29
  end
34
30
 
35
31
  def from
36
- @from ||= @email.from.kind_of?(Array) && @email.from.join(", ") || @email.from
32
+ @from ||= Array(@email.from).join ", "
33
+ end
34
+
35
+ def reply_to
36
+ @reply_to ||= Array(@email.reply_to).join ", "
37
37
  end
38
38
 
39
39
  def type
40
- content_type =~ /html/ ? "rich" : "plain"
40
+ if content_type =~ /html/ then "rich" else "plain" end
41
41
  end
42
42
 
43
43
  def encoding
44
- body.respond_to?(:encoding) ? body.encoding : "utf-8"
44
+ if body.respond_to? :encoding then body.encoding else "utf-8" end
45
+ end
46
+
47
+ private
48
+
49
+ def create_templates(file_path, binding)
50
+ FileUtils.mkdir_p @location
51
+
52
+ File.open file_path, 'w' do |file|
53
+ file.write ERB.new(template).result binding
54
+ end
55
+ end
56
+
57
+ def create_attachments
58
+ FileUtils.mkdir_p attachments_directory
59
+
60
+ email.attachments.each &method(:save_attachment)
61
+ end
62
+
63
+ def attachments_directory
64
+ File.join @location, 'attachments'
65
+ end
66
+
67
+ def attachment_path(attachment)
68
+ File.join attachments_directory, attachment.filename
69
+ end
70
+
71
+ def save_attachment(attachment)
72
+ File.open attachment_path(attachment), 'wb' do |file|
73
+ file.write attachment.body.raw_source
74
+ end unless File.exists? attachment_path attachment
75
+
76
+ @attachments << [attachment.filename, "attachments/#{URI.escape attachment.filename }"]
45
77
  end
46
78
  end
47
79
  end
@@ -1,7 +1,8 @@
1
1
  module EmailSpy
2
2
  class Railtie < Rails::Railtie
3
3
  initializer "emailspy.add_delivery_method" do
4
- ActionMailer::Base.add_delivery_method :email_spy, EmailSpy::DeliveryMethod, location: Rails.root.join("tmp", "email_spy")
4
+ path_to_emails = Rails.root.join "tmp", EMAIL_DIRECTORY_NAME
5
+ ActionMailer::Base.add_delivery_method :email_spy, EmailSpy::DeliveryMethod, location: path_to_emails
5
6
  end
6
7
  end
7
8
  end
@@ -1,3 +1,3 @@
1
1
  module EmailSpy
2
- VERSION = "1.0.3"
2
+ VERSION = "1.6.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: email_spy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-19 00:00:00.000000000 Z
12
+ date: 2012-06-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: launchy