email_spy 1.0.3 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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