msg 0.1.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.
Files changed (119) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +9 -0
  3. data/Rakefile +35 -0
  4. data/app/assets/images/msg/message.png +0 -0
  5. data/app/assets/images/msg/ping.png +0 -0
  6. data/app/assets/images/msg/sending.png +0 -0
  7. data/app/assets/javascripts/lib/jquery.peity.js +261 -0
  8. data/app/assets/javascripts/msg.js.coffee +6 -0
  9. data/app/assets/stylesheets/msg.css.sass +218 -0
  10. data/app/controllers/msg/bounces_controller.rb +67 -0
  11. data/app/controllers/msg/engine_controller.rb +23 -0
  12. data/app/controllers/msg/envelopes_controller.rb +22 -0
  13. data/app/controllers/msg/messages_controller.rb +85 -0
  14. data/app/controllers/msg/sendings_controller.rb +58 -0
  15. data/app/helpers/msg/msg_helper.rb +40 -0
  16. data/app/mailers/msg/devise_mailer.rb +20 -0
  17. data/app/mailers/msg/msg_mailer.rb +23 -0
  18. data/app/models/msg/bounce.rb +19 -0
  19. data/app/models/msg/envelope.rb +56 -0
  20. data/app/models/msg/message.rb +26 -0
  21. data/app/models/msg/sending.rb +54 -0
  22. data/app/views/layouts/msg/default.html.haml +30 -0
  23. data/app/views/layouts/msg/email.html.haml +10 -0
  24. data/app/views/msg/bounces/_listing.html.haml +5 -0
  25. data/app/views/msg/bounces/_report.html.haml +10 -0
  26. data/app/views/msg/bounces/index.html.haml +5 -0
  27. data/app/views/msg/devise_mailer/confirmation_instructions.en.html.haml +1 -0
  28. data/app/views/msg/devise_mailer/reset_password_instructions.en.html.haml +1 -0
  29. data/app/views/msg/envelopes/_listing.html.haml +5 -0
  30. data/app/views/msg/messages/_action_menu.html.haml +10 -0
  31. data/app/views/msg/messages/_form.html.haml +38 -0
  32. data/app/views/msg/messages/_instructions.html.haml +28 -0
  33. data/app/views/msg/messages/_message.html.haml +11 -0
  34. data/app/views/msg/messages/_saved_messages.html.haml +2 -0
  35. data/app/views/msg/messages/_transactional_messages.html.haml +3 -0
  36. data/app/views/msg/messages/edit.html.haml +7 -0
  37. data/app/views/msg/messages/index.html.haml +23 -0
  38. data/app/views/msg/messages/new.html.haml +7 -0
  39. data/app/views/msg/messages/preview.html.haml +4 -0
  40. data/app/views/msg/messages/show.html.haml +25 -0
  41. data/app/views/msg/msg_mailer/message_in_envelope.html.haml +2 -0
  42. data/app/views/msg/sendings/_form.html.haml +45 -0
  43. data/app/views/msg/sendings/_listing.html.haml +17 -0
  44. data/app/views/msg/sendings/_report.html.haml +8 -0
  45. data/app/views/msg/sendings/_sending.html.haml +22 -0
  46. data/app/views/msg/sendings/_sendings.html.haml +2 -0
  47. data/app/views/msg/sendings/index.html.haml +8 -0
  48. data/app/views/msg/sendings/new.html.haml +9 -0
  49. data/app/views/msg/sendings/review.html.haml +2 -0
  50. data/app/views/msg/sendings/show.html.haml +50 -0
  51. data/app/views/msg/shared/_toolbar.html.haml +17 -0
  52. data/config/cucumber.yml +8 -0
  53. data/config/locales/en.yml +76 -0
  54. data/config/routes.rb +26 -0
  55. data/db/migrate/20130320141926_msg_data.rb +54 -0
  56. data/db/migrate/20130327134754_sending_circumstances.rb +6 -0
  57. data/lib/msg.rb +88 -0
  58. data/lib/msg/engine.rb +23 -0
  59. data/lib/msg/receivers.rb +64 -0
  60. data/lib/msg/version.rb +3 -0
  61. data/lib/tasks/cucumber.rake +65 -0
  62. data/lib/tasks/msg_tasks.rake +4 -0
  63. data/spec/controllers/msg/bounces_controller_spec.rb +48 -0
  64. data/spec/controllers/msg/envelopes_controller_spec.rb +22 -0
  65. data/spec/controllers/msg/messages_controller_spec.rb +9 -0
  66. data/spec/controllers/msg/sendings_controller_spec.rb +47 -0
  67. data/spec/dummy/README.rdoc +261 -0
  68. data/spec/dummy/Rakefile +7 -0
  69. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  70. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  71. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  72. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  73. data/spec/dummy/app/models/user.rb +14 -0
  74. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  75. data/spec/dummy/config.ru +4 -0
  76. data/spec/dummy/config/application.rb +59 -0
  77. data/spec/dummy/config/boot.rb +10 -0
  78. data/spec/dummy/config/database.yml +25 -0
  79. data/spec/dummy/config/environment.rb +5 -0
  80. data/spec/dummy/config/environments/development.rb +37 -0
  81. data/spec/dummy/config/environments/production.rb +67 -0
  82. data/spec/dummy/config/environments/test.rb +41 -0
  83. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  84. data/spec/dummy/config/initializers/devise.rb +285 -0
  85. data/spec/dummy/config/initializers/inflections.rb +15 -0
  86. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  87. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  88. data/spec/dummy/config/initializers/session_store.rb +8 -0
  89. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  90. data/spec/dummy/config/locales/en.yml +5 -0
  91. data/spec/dummy/config/routes.rb +9 -0
  92. data/spec/dummy/db/development.sqlite3 +0 -0
  93. data/spec/dummy/db/migrate/2013032210540_users.rb +49 -0
  94. data/spec/dummy/db/migrate/20130326093048_msg_data.msg.rb +55 -0
  95. data/spec/dummy/db/schema.rb +96 -0
  96. data/spec/dummy/db/test.sqlite3 +0 -0
  97. data/spec/dummy/log/development.log +143 -0
  98. data/spec/dummy/log/test.log +1022 -0
  99. data/spec/dummy/public/404.html +26 -0
  100. data/spec/dummy/public/422.html +26 -0
  101. data/spec/dummy/public/500.html +25 -0
  102. data/spec/dummy/public/favicon.ico +0 -0
  103. data/spec/dummy/script/rails +6 -0
  104. data/spec/factories/msg/bounces.rb +9 -0
  105. data/spec/factories/msg/envelopes.rb +10 -0
  106. data/spec/factories/msg/messages.rb +10 -0
  107. data/spec/factories/msg/sendings.rb +7 -0
  108. data/spec/factories/users.rb +11 -0
  109. data/spec/helpers/msg/msg_helper_spec.rb +17 -0
  110. data/spec/lib/msg_spec.rb +15 -0
  111. data/spec/mailers/msg/devise_mailer_spec.rb +21 -0
  112. data/spec/mailers/msg/msg_mailer_spec.rb +36 -0
  113. data/spec/models/msg/bounce_spec.rb +19 -0
  114. data/spec/models/msg/envelope_spec.rb +62 -0
  115. data/spec/models/msg/message_spec.rb +19 -0
  116. data/spec/models/msg/sending_spec.rb +10 -0
  117. data/spec/routing/sendings_routing_spec.rb +31 -0
  118. data/spec/spec_helper.rb +70 -0
  119. metadata +446 -0
@@ -0,0 +1,54 @@
1
+ module Msg
2
+ class Sending < ActiveRecord::Base
3
+ attr_accessible :message_id, :envelopes_attributes
4
+
5
+ belongs_to :message
6
+ belongs_to :created_by, :class_name => Msg.user_class
7
+ has_many :envelopes, :dependent => :destroy
8
+
9
+ def receivers=(receivers)
10
+ receivers.each do |rec|
11
+ self.envelopes.build(:receiver => rec, :sending => self)
12
+ end
13
+ end
14
+
15
+ def statistics
16
+ sent = envelopes.count || 0
17
+ bounced = envelopes.bounced.count || 0
18
+ read = envelopes.opened.count || 0
19
+ unread = sent-read-bounced
20
+ [unread, read, bounced]
21
+ end
22
+
23
+ def self.add_receiver_hooks(klass, options)
24
+ key = klass.to_s.underscore
25
+
26
+ define_method :"#{key}_group" do
27
+ self.receiving_group if self.receiving_class == key
28
+ end
29
+
30
+ # class_group= is called from the SendingsController and given the _name_ of a messaging group,
31
+ # we get the designated proc from the class messaging rules, then call it to get an array of receivers
32
+ #
33
+ define_method :"#{key}_group=" do |name|
34
+ self.receiving_class = key
35
+ self.receiving_group = name
36
+ self.receivers = klass.messaging_groups[name.to_sym].call unless name == 'selected'
37
+ end
38
+ attr_accessible :"#{key}_group"
39
+
40
+ define_method :"#{key}_receiver_ids" do
41
+ self.envelopes.map(&:receiver_id) if self.receiving_class == key
42
+ end
43
+ attr_accessible :"#{key}_receiver_ids"
44
+
45
+ # class_receiver_ids= is called from the SendingsController and given a list of receiver ids of this class.
46
+ # they are instantiated and passed to receivers=
47
+ #
48
+ define_method :"#{key}_receiver_ids=" do |ids|
49
+ self.receivers = klass.find(ids)
50
+ end
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,30 @@
1
+ !!!
2
+ %html{:lang => 'en'}
3
+ %head
4
+ %title
5
+ - if content_for?(:pagetitle)
6
+ = yield :pagetitle
7
+ \|
8
+ = t(:msg)
9
+
10
+ = stylesheet_link_tag "msg"
11
+ = javascript_include_tag "msg"
12
+ = content_for :head
13
+ = csrf_meta_tags
14
+
15
+ %body
16
+ #header
17
+ %p.warning
18
+ = t :please_set_layout
19
+
20
+ #page
21
+ #content
22
+ = yield
23
+ #margin
24
+ = content_for :margin
25
+
26
+ #flashes
27
+ %p.notice= notice
28
+ %p.alert= alert
29
+
30
+ #mask
@@ -0,0 +1,10 @@
1
+ !!!
2
+ %html{:lang => 'en'}
3
+ %head
4
+ %title
5
+ = @subject
6
+
7
+ %body
8
+ #content
9
+ = yield
10
+
@@ -0,0 +1,5 @@
1
+ - bounce ||= listing
2
+
3
+ %li.bounce
4
+ = bounce.envelope.to_address
5
+ = l(bounce.created_at, :format => :natural_with_date)
@@ -0,0 +1,10 @@
1
+ - bounces ||= @bounces || Msg::Bounce.order('created_at DESC').limit(5)
2
+
3
+ #bouncebox{:data => {:refreshable => true, :url => msg.bounces_path(:format => :js)}}
4
+ - if bounces.any?
5
+ %h3
6
+ = link_to t(:bounce_report), msg.bounces_url
7
+
8
+ %ul.bounces
9
+ = render :partial => "msg/bounces/listing", :collection => bounces
10
+
@@ -0,0 +1,5 @@
1
+ #bounces
2
+ = render :partial => "msg/bounces/bounce", :collection => @bounces
3
+
4
+ -content_for :title do
5
+ = t :bounces
@@ -0,0 +1 @@
1
+ = sanitize(@contents.html_safe, :tags => Msg.tags_allowed_in_email, :attributes => Msg.attributes_allowed_in_email)
@@ -0,0 +1 @@
1
+ = sanitize(@contents.html_safe, :tags => Msg.tags_allowed_in_email, :attributes => Msg.attributes_allowed_in_email)
@@ -0,0 +1,5 @@
1
+ - envelope ||= listing
2
+
3
+ %li{:class => "envelope #{envelope.status}"}
4
+ = envelope.receiver.name
5
+
@@ -0,0 +1,10 @@
1
+ - if editable?(message)
2
+ .menu{:data => {:for => "message_#{message.id}"}}
3
+ %ul.actions
4
+ %li
5
+ = link_to t(:edit_message), msg.edit_message_url(message), :class => 'edit', :data => {:action => "popup", :affected => "#message_#{message.id}, #sentbox", :group => "messages"}
6
+ %li
7
+ = link_to t(:preview_and_send), msg.message_url(message), :class => "edit", :data => {:action => "popup", :affected => "#sentbox", :group => "messages"}
8
+ - unless message.transactional?
9
+ %li
10
+ = link_to t(:delete_message), msg.message_url(message), :method => 'delete', :class => 'delete', :data => {:action => "remove", :removed => "#message_#{message.id}", :confirm => t(:confirm_delete_message, :subject => message.subject)}
@@ -0,0 +1,38 @@
1
+ = form_for @message, :html => {:class => 'edit message', :remote => true, :data => {:type => :html}} do |f|
2
+ %p.subject
3
+ = f.text_field :subject, :class => 'name', :placeholder => t(:message_subject)
4
+
5
+ %p.sender.messagedetail
6
+ = f.text_field :from_name, :class => 'from_name', :placeholder => t(:from) + ": " + Msg.default_from_name
7
+ = f.text_field :from_address, :class => 'from_address', :placeholder => Msg.default_from_address
8
+
9
+ %p.function.messagedetail
10
+ %span.transactional_detail
11
+ = f.text_field :function, :class => "function", :placeholder => t(:message_function)
12
+ = f.check_box :transactional, :data => {:action => "reveal", :affected => ".transactional_detail", :converse => ".saved"}
13
+ = f.label :transactional, t(:transactional_message)
14
+ %span.formnote
15
+ = t :transactional_message_note
16
+
17
+ .messagebody.wysihtml#e1
18
+ %p.show_details
19
+ = link_to t(:more_detail), "#", :class => "expander", :data => {:action => "toggle", :affected => ".messagedetail"}
20
+
21
+ = render "msg/messages/instructions"
22
+ .toolbar#t1
23
+ = render 'msg/shared/toolbar'
24
+ = f.text_area :body, :id => 'd1', :class => "body"
25
+
26
+ %p.saved
27
+ = f.check_box :saved, :data => {:action => "reveal", :affected => ".saved_detail"}
28
+ = f.label :saved, t(:save_for_reuse)
29
+ %span.formnote
30
+ = t :saved_note
31
+ %span.saved_detail
32
+ = f.text_field :description, :class => "description", :placeholder => t(:message_description)
33
+
34
+ .buttons
35
+ = f.submit t(:save_and_preview)
36
+ = t :or
37
+ = link_to t(:cancel), "/", :class => 'cancel'
38
+
@@ -0,0 +1,28 @@
1
+ .instructions
2
+ %p
3
+ Use double braces to insert these computed values into each message:
4
+ %ul
5
+ %li
6
+ %strong
7
+ {{formal_name}}
8
+ the recipient's full name and title
9
+ %li
10
+ %strong
11
+ {{informal_name}}
12
+ forename, if we know it, or full name without title
13
+ %li
14
+ %strong
15
+ {{email}}
16
+ the receiving email address
17
+ %li
18
+ %strong
19
+ {{sign_in_url}}
20
+ the address of the login page
21
+ %li
22
+ %strong
23
+ {{confirmation_url}}
24
+ a confirmation address for use in invitations
25
+ %li
26
+ %strong
27
+ {{password_reset_url}}
28
+ a reset address for use in reminder messages
@@ -0,0 +1,11 @@
1
+ - message ||= @message
2
+
3
+ .message{:id => "message_#{message.id}", :data => {:refreshable => true, :url => message_path(message, :format => :js)} }
4
+ %h2.name
5
+ = link_to shorten(message.subject, 54), msg.message_url(message), :class => "message", :data => {:action => "popup", :affected => "#sentbox", :group => "messages"}
6
+ = action_menulink(message)
7
+ = action_menu(message)
8
+ %p.description
9
+ = message.description
10
+ %p.excerpt
11
+ = shorten(message.body, 128)
@@ -0,0 +1,2 @@
1
+ #saved_messages.message_list{:data => {:refreshable => true, :url => msg.saved_messages_path(:format => :js)}}
2
+ = render :partial => "msg/messages/message", :collection => @saved_messages
@@ -0,0 +1,3 @@
1
+ #transactional_messages.message_list{:data => {:refreshable => true, :url => msg.transactional_messages_path(:format => :js)}}
2
+ = render :partial => "msg/messages/message", :collection => @transactional_messages
3
+
@@ -0,0 +1,7 @@
1
+ #message
2
+ .header
3
+ = link_to "X", '#', :class => "closer", :data => {:action => "close"}
4
+ %h2
5
+ = t :edit_message
6
+
7
+ = render :partial => 'form'
@@ -0,0 +1,23 @@
1
+ #messages
2
+
3
+ %p.action
4
+ = link_to t(:create_message), msg.new_message_url, :class => "add", :data => {:action => "popup", :affected => "#saved_messages"}
5
+
6
+ %h2.section
7
+ = t :transactional_messages
8
+
9
+ = render "msg/messages/transactional_messages"
10
+
11
+ %h2.section
12
+ = t :saved_messages
13
+ %span.action
14
+ = link_to t(:create_message), msg.new_message_url, :class => "add minimal", :data => {:action => "popup", :affected => "#saved_messages"}
15
+ = render "msg/messages/saved_messages"
16
+
17
+
18
+ -content_for :margin do
19
+ = render :partial => "msg/bounces/report"
20
+ = render :partial => "msg/sendings/report"
21
+
22
+ -content_for :title do
23
+ = t :messages
@@ -0,0 +1,7 @@
1
+ #message
2
+ .header
3
+ = link_to "X", '#', :class => "closer", :data => {:action => "close"}
4
+ %h2
5
+ = t :add_message
6
+
7
+ = render :partial => 'form'
@@ -0,0 +1,4 @@
1
+ - message ||= @message
2
+ - receiver ||= @receiver
3
+
4
+ = sanitize(message.render_for(receiver), :tags => Msg.tags_allowed_in_email, :attributes => Msg.attributes_allowed_in_email)
@@ -0,0 +1,25 @@
1
+ #preview_message
2
+ .header
3
+ = link_to "X", '#', :class => "closer", :data => {:action => "close"}
4
+ %h2
5
+ = t :preview_message
6
+ .headers
7
+ %p
8
+ %span.field
9
+ = t(:subject).titlecase + ":"
10
+ %strong
11
+ = @message.subject
12
+ %p
13
+ %span.field
14
+ = t(:to).titlecase + ":"
15
+ %strong
16
+ = @receiver.email
17
+ %p
18
+ %span.field
19
+ = t(:from).titlecase + ":"
20
+ %strong
21
+ = @message.from
22
+
23
+ - sending = @message.sendings.build
24
+ = render :partial => "msg/sendings/form", :locals => {:sending => sending}
25
+
@@ -0,0 +1,2 @@
1
+ = sanitize(@contents.html_safe, :tags => Msg.tags_allowed_in_email, :attributes => Msg.attributes_allowed_in_email)
2
+ %img{:src => msg.envelope_url(@envelope)}
@@ -0,0 +1,45 @@
1
+ - sending ||= @sending
2
+ - message ||= @message
3
+ - receiver ||= @receiver
4
+ - klasses = Msg.receiving_classes
5
+
6
+ = form_for [message, sending], :as => :sending do |f|
7
+
8
+ .receivers
9
+ - klasses.each do |klass|
10
+ - key = klass.underscore
11
+
12
+ %h3
13
+ = t(:send_to)
14
+ = t("msg.#{key}") unless klasses.length == 1
15
+
16
+ %ul.choose_group
17
+ - klass.constantize.messaging_groups.each_pair do |name, proc|
18
+ - count = proc.call.count
19
+ %li.group
20
+ = f.radio_button "#{key}_group", name, :data => {:action => "reveal", :converse => "ul.choose_receivers"}, :disabled => count == 0
21
+ %label{:for => "sending_#{key}_group_#{name}"}
22
+ = t("msg.groups.#{name}")
23
+ %span.note
24
+ = t(:receiver_count, :count => count)
25
+
26
+ %li.group
27
+ = f.radio_button "#{key}_group", :selected, :data => {:action => "reveal", :affected => "ul.choose_receivers"}
28
+ %label{:for => "sending_#{key}_group_selected"}
29
+ = t("msg.groups.selected")
30
+
31
+ %ul.choose_receivers
32
+ - klass.constantize.order('name ASC').each do |rec|
33
+ %li.receiver
34
+ = check_box_tag "sending[#{key}_receiver_ids][]", rec.id, false, :id => "sending_#{key}_receiver_ids_#{rec.id}"
35
+ %label{:for => "sending_#{key}_receiver_ids_#{rec.id}"}
36
+ = rec.name
37
+
38
+ // #todo: update the preview on selection, and add a control to page through the selected group of people
39
+ %iframe.body{:src => msg.preview_message_url(message, :receiver_type => receiver.class.to_s.downcase.underscore.to_s, :receiver_id => receiver.id)}
40
+
41
+ .buttons
42
+ = f.submit t(:send_message)
43
+ = t :or
44
+ = link_to t(:close), "/", :class => 'cancel'
45
+
@@ -0,0 +1,17 @@
1
+ - sending ||= listing
2
+ - receiver_count = sending.envelopes.count
3
+
4
+ %li.sending
5
+ %a{:href => msg.sending_url(sending)}
6
+ %span.pie{:data => {:diameter => 16}}<
7
+ = sending.statistics.join(',')
8
+ = shorten(sending.message.subject, 36)
9
+ - if sending.receiving_group
10
+ = t(:sent_to)
11
+ = t("msg.groups.#{sending.receiving_group}")
12
+ = t(:receiver_count, :count => sending.envelopes.count)
13
+
14
+ - else
15
+ = t(:sent_to_count, :count => sending.envelopes.count)
16
+ = t(:at)
17
+ = l(sending.created_at, :format => :natural_with_date)
@@ -0,0 +1,8 @@
1
+ - sendings ||= @sendings || Msg::Sending.order('created_at DESC').limit(5)
2
+
3
+ #sentbox{:data => {:refreshable => true, :url => msg.sendings_path(:format => :js, :show => 5)}}
4
+ %h3
5
+ = link_to t(:sent_report), msg.sendings_url
6
+
7
+ %ul.sendings
8
+ = render :partial => "msg/sendings/listing", :collection => sendings
@@ -0,0 +1,22 @@
1
+ - sending ||= @sending
2
+
3
+ .sending{:id => "sending_#{sending.id}", :data => {:refreshable => true, :url => sending_path(sending, :format => :js)} }
4
+ %h2.name
5
+ %span.pie{:data => {:diameter => 20}}<
6
+ = sending.statistics.join(',')
7
+ = link_to shorten(sending.message.subject, 54), msg.sending_url(sending)
8
+
9
+ %p.description
10
+ - if sending.receiving_group
11
+ = t(:sent_to)
12
+ = t("msg.groups.#{sending.receiving_group}")
13
+ = t(:receiver_count, :count => sending.envelopes.count)
14
+ - else
15
+ = t(:sent)
16
+ = t(:at)
17
+ = l(sending.created_at, :format => :natural_with_date)
18
+
19
+ %p.responses
20
+ = t(:sent_count, :count => sending.envelopes.count) + '.'
21
+ = t(:opened_count, :count => sending.envelopes.opened.count) + '.'
22
+ = t(:bounced_count, :count => sending.envelopes.bounced.count) + '.'
@@ -0,0 +1,2 @@
1
+ .sending_list{:data => {:refreshable => true, :url => msg.sendings_path(:format => :js)}}
2
+ = render :partial => "msg/sendings/sending", :collection => @sendings
@@ -0,0 +1,8 @@
1
+ #sent_messages
2
+ = render "msg/sendings/sendings"
3
+
4
+ -content_for :title do
5
+ = t :sent_messages
6
+
7
+ -content_for :margin do
8
+ = render :partial => "msg/bounces/report"
@@ -0,0 +1,9 @@
1
+ #send_message
2
+ .header
3
+ = link_to "X", '#', :class => "closer", :data => {:action => "close"}
4
+ %h2
5
+ = t(:send_the_message)
6
+ %strong
7
+ = @message.subject
8
+
9
+ = render :partial => 'form'
@@ -0,0 +1,2 @@
1
+ - if @sending.envelopes.any?
2
+ = sanitize(@sending.envelopes.first.contents.html_safe , :tags => Msg.tags_allowed_in_email, :attributes => Msg.attributes_allowed_in_email)