alchemy_crm 2.0.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 (240) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +12 -0
  3. data/Gemfile +21 -0
  4. data/Guardfile +13 -0
  5. data/LICENSE +24 -0
  6. data/README.md +82 -0
  7. data/Rakefile +27 -0
  8. data/alchemy_crm.gemspec +31 -0
  9. data/app/assets/images/.DS_Store +0 -0
  10. data/app/assets/images/alchemy_crm/.DS_Store +0 -0
  11. data/app/assets/images/alchemy_crm/contact-icons.png +0 -0
  12. data/app/assets/images/alchemy_crm/fill_content.gif +0 -0
  13. data/app/assets/images/alchemy_crm/group-icons.png +0 -0
  14. data/app/assets/images/alchemy_crm/mailing-icons.png +0 -0
  15. data/app/assets/images/alchemy_crm/module_icon.png +0 -0
  16. data/app/assets/images/alchemy_crm/newsletter-icons.png +0 -0
  17. data/app/assets/images/alchemy_crm/statistic.png +0 -0
  18. data/app/assets/images/alchemy_crm/tag-icons.png +0 -0
  19. data/app/assets/javascripts/alchemy_crm/alchemy_crm.base.js +65 -0
  20. data/app/assets/javascripts/alchemy_crm/scripts.js +2 -0
  21. data/app/assets/stylesheets/alchemy_crm/base.css.scss +473 -0
  22. data/app/assets/stylesheets/alchemy_crm/styles.css +3 -0
  23. data/app/controllers/alchemy_crm/admin/base_controller.rb +7 -0
  24. data/app/controllers/alchemy_crm/admin/contact_groups_controller.rb +23 -0
  25. data/app/controllers/alchemy_crm/admin/contacts_controller.rb +112 -0
  26. data/app/controllers/alchemy_crm/admin/deliveries_controller.rb +80 -0
  27. data/app/controllers/alchemy_crm/admin/elements_controller_extension.rb +32 -0
  28. data/app/controllers/alchemy_crm/admin/mailings_controller.rb +47 -0
  29. data/app/controllers/alchemy_crm/admin/newsletters_controller.rb +24 -0
  30. data/app/controllers/alchemy_crm/admin/tags_controller.rb +62 -0
  31. data/app/controllers/alchemy_crm/base_controller.rb +5 -0
  32. data/app/controllers/alchemy_crm/contacts_controller.rb +103 -0
  33. data/app/controllers/alchemy_crm/mailings_controller.rb +20 -0
  34. data/app/controllers/alchemy_crm/recipients_controller.rb +35 -0
  35. data/app/controllers/alchemy_crm/subscriptions_controller.rb +57 -0
  36. data/app/helpers/alchemy/pages_helper_extension.rb +18 -0
  37. data/app/helpers/alchemy_crm/admin/base_helper.rb +12 -0
  38. data/app/helpers/alchemy_crm/mailings_helper.rb +190 -0
  39. data/app/mailers/alchemy_crm/bounce_receiver.rb +13 -0
  40. data/app/mailers/alchemy_crm/contacts_mailer.rb +26 -0
  41. data/app/mailers/alchemy_crm/mailings_mailer.rb +48 -0
  42. data/app/mailers/alchemy_crm/subscriptions_mailer.rb +17 -0
  43. data/app/models/alchemy/essence_element_teaser.rb +19 -0
  44. data/app/models/alchemy_crm/contact.rb +264 -0
  45. data/app/models/alchemy_crm/contact_group.rb +26 -0
  46. data/app/models/alchemy_crm/contact_group_filter.rb +26 -0
  47. data/app/models/alchemy_crm/delivery.rb +57 -0
  48. data/app/models/alchemy_crm/element_extension.rb +28 -0
  49. data/app/models/alchemy_crm/mailing.rb +93 -0
  50. data/app/models/alchemy_crm/newsletter.rb +48 -0
  51. data/app/models/alchemy_crm/reaction.rb +9 -0
  52. data/app/models/alchemy_crm/recipient.rb +48 -0
  53. data/app/models/alchemy_crm/subscription.rb +8 -0
  54. data/app/views/alchemy/admin/elements/_view_not_found.text.erb +0 -0
  55. data/app/views/alchemy/admin/elements/fill.js.erb +13 -0
  56. data/app/views/alchemy/admin/elements/link.js.erb +1 -0
  57. data/app/views/alchemy/elements/_newsletter_article_editor.html.erb +4 -0
  58. data/app/views/alchemy/elements/_newsletter_article_view.html.erb +16 -0
  59. data/app/views/alchemy/elements/_newsletter_article_view.text.erb +5 -0
  60. data/app/views/alchemy/elements/_newsletter_greeting_editor.html.erb +3 -0
  61. data/app/views/alchemy/elements/_newsletter_greeting_view.html.erb +11 -0
  62. data/app/views/alchemy/elements/_newsletter_greeting_view.text.erb +6 -0
  63. data/app/views/alchemy/elements/_newsletter_signout_form_editor.html.erb +3 -0
  64. data/app/views/alchemy/elements/_newsletter_signout_form_view.html.erb +32 -0
  65. data/app/views/alchemy/elements/_newsletter_signout_mail_editor.html.erb +4 -0
  66. data/app/views/alchemy/elements/_newsletter_signup_form_editor.html.erb +6 -0
  67. data/app/views/alchemy/elements/_newsletter_signup_form_view.html.erb +78 -0
  68. data/app/views/alchemy/elements/_newsletter_signup_mail_editor.html.erb +4 -0
  69. data/app/views/alchemy/essences/_essence_date_view.text.erb +3 -0
  70. data/app/views/alchemy/essences/_essence_element_teaser_editor.html.erb +31 -0
  71. data/app/views/alchemy/essences/_essence_element_teaser_view.html.erb +1 -0
  72. data/app/views/alchemy/essences/_essence_element_teaser_view.text.erb +3 -0
  73. data/app/views/alchemy/essences/_essence_richtext_view.text.erb +1 -0
  74. data/app/views/alchemy/essences/_essence_text_view.text.erb +1 -0
  75. data/app/views/alchemy/newsletter_layouts/_standard.html.erb +39 -0
  76. data/app/views/alchemy/newsletter_layouts/_standard.text.erb +5 -0
  77. data/app/views/alchemy_crm/admin/contact_groups/_contact_group.html.erb +32 -0
  78. data/app/views/alchemy_crm/admin/contact_groups/_filter.html.erb +30 -0
  79. data/app/views/alchemy_crm/admin/contact_groups/_form.html.erb +47 -0
  80. data/app/views/alchemy_crm/admin/contact_groups/_tag.html.erb +6 -0
  81. data/app/views/alchemy_crm/admin/contact_groups/add_filter.js.erb +9 -0
  82. data/app/views/alchemy_crm/admin/contact_groups/destroy.rjs +1 -0
  83. data/app/views/alchemy_crm/admin/contact_groups/edit.html.erb +1 -0
  84. data/app/views/alchemy_crm/admin/contact_groups/index.html.erb +41 -0
  85. data/app/views/alchemy_crm/admin/contact_groups/new.html.erb +1 -0
  86. data/app/views/alchemy_crm/admin/contacts/_contact.html.erb +44 -0
  87. data/app/views/alchemy_crm/admin/contacts/_form.html.erb +86 -0
  88. data/app/views/alchemy_crm/admin/contacts/destroy.rjs +1 -0
  89. data/app/views/alchemy_crm/admin/contacts/edit.html.erb +1 -0
  90. data/app/views/alchemy_crm/admin/contacts/import.html.erb +33 -0
  91. data/app/views/alchemy_crm/admin/contacts/import.js.erb +2 -0
  92. data/app/views/alchemy_crm/admin/contacts/index.html.erb +51 -0
  93. data/app/views/alchemy_crm/admin/contacts/new.html.erb +1 -0
  94. data/app/views/alchemy_crm/admin/contacts/vcf_import_result.html.erb +49 -0
  95. data/app/views/alchemy_crm/admin/deliveries/_delivery.html.erb +41 -0
  96. data/app/views/alchemy_crm/admin/deliveries/_form.html.erb +65 -0
  97. data/app/views/alchemy_crm/admin/deliveries/_recipient.html.erb +40 -0
  98. data/app/views/alchemy_crm/admin/deliveries/edit.html.erb +1 -0
  99. data/app/views/alchemy_crm/admin/deliveries/index.html.erb +29 -0
  100. data/app/views/alchemy_crm/admin/deliveries/new.html.erb +1 -0
  101. data/app/views/alchemy_crm/admin/deliveries/show.html.erb +66 -0
  102. data/app/views/alchemy_crm/admin/elements/link.rjs +4 -0
  103. data/app/views/alchemy_crm/admin/elements/teasables.html.erb +57 -0
  104. data/app/views/alchemy_crm/admin/mailings/_form.html.erb +43 -0
  105. data/app/views/alchemy_crm/admin/mailings/_mailing.html.erb +75 -0
  106. data/app/views/alchemy_crm/admin/mailings/edit.html.erb +1 -0
  107. data/app/views/alchemy_crm/admin/mailings/edit_content.html.erb +194 -0
  108. data/app/views/alchemy_crm/admin/mailings/import_result.html.erb +37 -0
  109. data/app/views/alchemy_crm/admin/mailings/index.html.erb +39 -0
  110. data/app/views/alchemy_crm/admin/mailings/new.html.erb +1 -0
  111. data/app/views/alchemy_crm/admin/mailings/show.html.erb +1 -0
  112. data/app/views/alchemy_crm/admin/mailings/show.text.erb +1 -0
  113. data/app/views/alchemy_crm/admin/newsletters/_form.html.erb +54 -0
  114. data/app/views/alchemy_crm/admin/newsletters/_newsletter.html.erb +42 -0
  115. data/app/views/alchemy_crm/admin/newsletters/_tag_with_radiobutton.html.erb +7 -0
  116. data/app/views/alchemy_crm/admin/newsletters/destroy.rjs +1 -0
  117. data/app/views/alchemy_crm/admin/newsletters/edit.html.erb +1 -0
  118. data/app/views/alchemy_crm/admin/newsletters/index.html.erb +42 -0
  119. data/app/views/alchemy_crm/admin/newsletters/new.html.erb +10 -0
  120. data/app/views/alchemy_crm/admin/tags/_radio_tag.html.erb +6 -0
  121. data/app/views/alchemy_crm/admin/tags/_tag.html.erb +32 -0
  122. data/app/views/alchemy_crm/admin/tags/edit.html.erb +40 -0
  123. data/app/views/alchemy_crm/admin/tags/index.html.erb +35 -0
  124. data/app/views/alchemy_crm/admin/tags/new.html.erb +16 -0
  125. data/app/views/alchemy_crm/contacts_mailer/signout_mail.html.erb +8 -0
  126. data/app/views/alchemy_crm/contacts_mailer/signout_mail.text.erb +4 -0
  127. data/app/views/alchemy_crm/contacts_mailer/signup_mail.html.erb +11 -0
  128. data/app/views/alchemy_crm/contacts_mailer/signup_mail.text.erb +4 -0
  129. data/app/views/alchemy_crm/mailings/show.html.erb +1 -0
  130. data/app/views/alchemy_crm/mailings_mailer/verification_mail.html.erb +11 -0
  131. data/app/views/alchemy_crm/subscriptions/index.html.erb +23 -0
  132. data/app/views/alchemy_crm/subscriptions_mailer/overview_mail.html.erb +27 -0
  133. data/app/views/alchemy_crm/subscriptions_mailer/overview_mail.text.erb +19 -0
  134. data/app/views/csv_magic/import_errors.html.erb +44 -0
  135. data/app/views/csv_magic/mapper.html.erb +62 -0
  136. data/app/views/layouts/alchemy_crm/mailings.html.erb +212 -0
  137. data/app/views/layouts/alchemy_crm/mailings.text.erb +3 -0
  138. data/config/alchemy_crm.config.yml +21 -0
  139. data/config/authorization_rules.rb +37 -0
  140. data/config/initializers/assets.rb +4 -0
  141. data/config/initializers/delayed_job.rb +6 -0
  142. data/config/locales/alchemy.de.yml +55 -0
  143. data/config/locales/alchemy.en.yml +52 -0
  144. data/config/locales/alchemy_crm.de.yml +196 -0
  145. data/config/locales/alchemy_crm.en.yml +53 -0
  146. data/config/locales/localized_country_select.de.rb +268 -0
  147. data/config/locales/localized_country_select.en.rb +282 -0
  148. data/config/module_definition.yml +30 -0
  149. data/config/routes.rb +71 -0
  150. data/db/migrate/20100708220434_create_mailings.rb +19 -0
  151. data/db/migrate/20100708220534_create_contacts.rb +27 -0
  152. data/db/migrate/20100708220812_create_contact_groups.rb +13 -0
  153. data/db/migrate/20100708221009_create_newsletters.rb +15 -0
  154. data/db/migrate/20100708221319_create_sent_mailings.rb +15 -0
  155. data/db/migrate/20100708221529_create_recipients.rb +21 -0
  156. data/db/migrate/20100708222620_acts_as_taggable_migration.rb +28 -0
  157. data/db/migrate/20100708223324_create_contact_group_filters.rb +17 -0
  158. data/db/migrate/20100708223727_create_newsletter_subscriptions.rb +14 -0
  159. data/db/migrate/20100708223922_create_essence_element_teasers.rb +15 -0
  160. data/db/migrate/20100714172207_create_contact_groups_newsletters.rb +12 -0
  161. data/db/migrate/20100927152601_create_reactions.rb +14 -0
  162. data/db/migrate/20111028091722_acts_as_taggable_on_migration.rb +15 -0
  163. data/db/migrate/20111028200710_add_counter_cache_columns_for_tags.rb +11 -0
  164. data/db/migrate/20111030204931_create_delayed_jobs.rb +21 -0
  165. data/db/migrate/20111104105854_add_deliver_at_to_sent_mailings.rb +9 -0
  166. data/db/migrate/20111104125306_remove_sent_mailing_pdf_id_from_sent_mailings.rb +9 -0
  167. data/db/migrate/20111104131912_add_delivered_at_to_sent_mailings.rb +9 -0
  168. data/db/migrate/20111124145923_namespace_alchemy_crm_models.rb +17 -0
  169. data/db/migrate/20120306115555_add_disabled_to_alchemy_crm_contacts.rb +5 -0
  170. data/db/migrate/20120307160721_rename_alchemy_crm_recipients_sent_mailing_id.rb +5 -0
  171. data/db/migrate/20120315113522_add_url_to_alchemy_crm_reactions.rb +5 -0
  172. data/db/migrate/20120316161333_add_sha1_and_salt_to_alchemy_crm_recipients.rb +6 -0
  173. data/db/migrate/20120320103412_add_indexes_to_alchemy_crm_sha1_columns.rb +7 -0
  174. data/db/migrate/20120321105455_add_queue_to_delayed_jobs.rb +9 -0
  175. data/db/migrate/20120327174301_add_more_indexes_to_alchemy_crm_tables.rb +12 -0
  176. data/lib/alchemy_crm.rb +18 -0
  177. data/lib/alchemy_crm/bounced_delivery.rb +46 -0
  178. data/lib/alchemy_crm/config.rb +28 -0
  179. data/lib/alchemy_crm/engine.rb +40 -0
  180. data/lib/alchemy_crm/i18n_helpers.rb +35 -0
  181. data/lib/alchemy_crm/newsletter_layout.rb +40 -0
  182. data/lib/alchemy_crm/seeder.rb +30 -0
  183. data/lib/alchemy_crm/version.rb +3 -0
  184. data/lib/generators/alchemy_crm/scaffold/files/_standard.html.erb +1 -0
  185. data/lib/generators/alchemy_crm/scaffold/files/_standard.text.erb +1 -0
  186. data/lib/generators/alchemy_crm/scaffold/files/elements.yml +51 -0
  187. data/lib/generators/alchemy_crm/scaffold/files/newsletter_layouts.yml +3 -0
  188. data/lib/generators/alchemy_crm/scaffold/files/newsletters.html.erb +22 -0
  189. data/lib/generators/alchemy_crm/scaffold/files/newsletters.text.erb +4 -0
  190. data/lib/generators/alchemy_crm/scaffold/files/page_layouts.yml +19 -0
  191. data/lib/generators/alchemy_crm/scaffold/scaffold_generator.rb +26 -0
  192. data/lib/tasks/alchemy_crm.rake +28 -0
  193. data/lib/tasks/routes.rake +29 -0
  194. data/rails/init.rb +1 -0
  195. data/recipes/alchemy-mailings-capistrano-tasks.rb +12 -0
  196. data/spec/alchemy_mailings_spec.rb +7 -0
  197. data/spec/config_spec.rb +28 -0
  198. data/spec/controllers/alchemy_crm/contacts_controller_spec.rb +210 -0
  199. data/spec/controllers/alchemy_crm/mailings_controller_spec.rb +89 -0
  200. data/spec/controllers/alchemy_crm/recipients_controller_spec.rb +155 -0
  201. data/spec/dummy/Rakefile +7 -0
  202. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  203. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  204. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  205. data/spec/dummy/config.ru +4 -0
  206. data/spec/dummy/config/alchemy/config.yml +142 -0
  207. data/spec/dummy/config/alchemy/elements.yml +79 -0
  208. data/spec/dummy/config/alchemy/newsletter_layouts.yml +4 -0
  209. data/spec/dummy/config/alchemy/page_layouts.yml +55 -0
  210. data/spec/dummy/config/application.rb +43 -0
  211. data/spec/dummy/config/boot.rb +10 -0
  212. data/spec/dummy/config/database.yml +22 -0
  213. data/spec/dummy/config/environment.rb +5 -0
  214. data/spec/dummy/config/environments/development.rb +30 -0
  215. data/spec/dummy/config/environments/production.rb +60 -0
  216. data/spec/dummy/config/environments/test.rb +39 -0
  217. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  218. data/spec/dummy/config/initializers/inflections.rb +10 -0
  219. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  220. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  221. data/spec/dummy/config/initializers/session_store.rb +8 -0
  222. data/spec/dummy/config/locales/en.yml +5 -0
  223. data/spec/dummy/config/routes.rb +4 -0
  224. data/spec/dummy/db/schema.rb +452 -0
  225. data/spec/dummy/public/404.html +26 -0
  226. data/spec/dummy/public/422.html +26 -0
  227. data/spec/dummy/public/500.html +26 -0
  228. data/spec/dummy/public/favicon.ico +0 -0
  229. data/spec/dummy/script/rails +6 -0
  230. data/spec/helpers/alchemy_crm/mailings_helper_spec.rb +169 -0
  231. data/spec/mailers/alchemy_crm/contacts_mailer_spec.rb +88 -0
  232. data/spec/mailers/alchemy_crm/mailings_mailer_spec.rb +42 -0
  233. data/spec/models/alchemy_crm/contact_group_spec.rb +41 -0
  234. data/spec/models/alchemy_crm/contact_spec.rb +108 -0
  235. data/spec/models/alchemy_crm/delivery_spec.rb +55 -0
  236. data/spec/models/alchemy_crm/mailing_spec.rb +63 -0
  237. data/spec/models/alchemy_crm/newsletter_spec.rb +45 -0
  238. data/spec/spec_helper.rb +58 -0
  239. data/vendor/assets/javascripts/autocomplete-rails.js +16 -0
  240. metadata +438 -0
@@ -0,0 +1,20 @@
1
+ module AlchemyCrm
2
+ class MailingsController < AlchemyCrm::BaseController
3
+
4
+ def show
5
+ @mailing = Mailing.find_by_sha1(params[:m])
6
+ if @mailing.nil? && !params[:id].blank?
7
+ @mailing = Mailing.find(params[:id])
8
+ end
9
+ @page = @mailing.page
10
+ if params[:r].present?
11
+ @recipient = @mailing.recipients.find_by_sha1(params[:r])
12
+ @contact = @recipient.contact || Contact.new_from_recipient(@recipient)
13
+ else
14
+ @contact = Contact.fake
15
+ @recipient = Recipient.new_from_contact(@contact)
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ module AlchemyCrm
2
+ class RecipientsController < AlchemyCrm::BaseController
3
+
4
+ def reads
5
+ recipient = Recipient.find_by_sha1(params[:h])
6
+ if recipient && !recipient.read?
7
+ recipient.reads!
8
+ end
9
+ render :nothing => true
10
+ end
11
+
12
+ def reacts
13
+ recipient = Recipient.find_by_sha1(params[:h])
14
+ if recipient
15
+ recipient.reacts!({
16
+ :page_id => params[:page_id],
17
+ :element_id => params[:element_id],
18
+ :url => params[:r]
19
+ })
20
+ end
21
+ if params[:r].present?
22
+ redirect_to params[:r]
23
+ else
24
+ page = Alchemy::Page.includes(:elements).find(params[:page_id])
25
+ element = page.elements.find_by_id(params[:element_id])
26
+ redirect_to alchemy.show_page_url(
27
+ :urlname => page.urlname,
28
+ :lang => multi_language? ? page.language_code : nil,
29
+ :anchor => element ? element.dom_id : nil
30
+ )
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,57 @@
1
+ # Caution: Not yet implemmented!
2
+ module AlchemyCrm
3
+ class SubscriptionsController < AlchemyCrm::BaseController
4
+
5
+ before_filter :load_contact, :except => :deliver_subscriptions_overview
6
+
7
+ def index
8
+ @page = Alchemy::Page.find_by_page_layout('newsletter_views')
9
+ @root_page = @page.get_language_root
10
+ render :template => 'alchemy/pages/show', :layout => layout_for_page
11
+ end
12
+
13
+ def new
14
+
15
+ end
16
+
17
+ def create
18
+
19
+ end
20
+
21
+ def edit
22
+
23
+ end
24
+
25
+ def update
26
+
27
+ end
28
+
29
+ def destroy
30
+ @subscription = @contact.subscriptions.find(params[:subscription_id])
31
+ @subscription.destroy
32
+ flash[:notice] = t(:subscription_destroyed)
33
+ @page = Alchemy::Page.find_by_page_layout('newsletter_views')
34
+ @root_page = @page.get_language_root
35
+ render :template => 'alchemy/pages/show', :layout => layout_for_page
36
+ end
37
+
38
+ def overview
39
+ @contact = Contact.find_by_email(params[:email])
40
+ if @contact
41
+ SubscriptionsMailer.overview_mail.deliver(@contact, @element)
42
+ flash[:notice] = t(:send_subscriptions_overview_via_email)
43
+ redirect_to :index
44
+ else
45
+ flash[:error] = t(:no_subscriber_found)
46
+ render :index
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def load_contact
53
+ @contact = Contact.find_by_email_sha1(params[:token])
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,18 @@
1
+ Alchemy::PagesHelper.module_eval do
2
+
3
+ def render_page_layout(options={})
4
+ default_options = {
5
+ :render_format => "html"
6
+ }
7
+ options = default_options.merge(options)
8
+ if @page.layout_description['newsletter']
9
+ render :partial => "alchemy/newsletter_layouts/#{@page.page_layout.downcase}.#{options[:render_format]}.erb"
10
+ else
11
+ render :partial => "alchemy/page_layouts/#{@page.page_layout.downcase}.#{options[:render_format]}.erb"
12
+ end
13
+ rescue ActionView::MissingTemplate
14
+ warning("PageLayout: '#{@page.page_layout}' not found. Rendering standard page_layout.")
15
+ render :partial => "alchemy/page_layouts/standard"
16
+ end
17
+
18
+ end
@@ -0,0 +1,12 @@
1
+ module AlchemyCrm
2
+ module Admin
3
+ module BaseHelper
4
+
5
+ # Renders a <small> html tag with the contact count for current tag in it.
6
+ def contact_count_from_tag(tag)
7
+ content_tag('small', "(#{Contact.tagged_with(tag).count})")
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,190 @@
1
+ module AlchemyCrm
2
+ module MailingsHelper
3
+
4
+ include Alchemy::PagesHelper
5
+
6
+ # Renders the newsletter layout for +@mailing.page+
7
+ #
8
+ # The +@mailing.page.page_layout+ must have a +newsletter_layout+ prefix.
9
+ # The partial itself is named without the +newsletter_layout+ prefix.
10
+ # The partial resists in +/app/views/newsletter_layouts/+
11
+ #
12
+ # === Example:
13
+ #
14
+ # Given a mailing page with a +standard+ layout has partials named +_standard.html.erb+ and +_standard.text.erb+
15
+ # But the page page_layout attribute is +newsletter_layout_standard+
16
+ #
17
+ def render_newsletter_layout(options={})
18
+ options = {:format => 'html'}.update(options)
19
+ render "alchemy/newsletter_layouts/#{@page.page_layout.downcase.gsub(Regexp.new(Mailing::MAILING_PAGE_LAYOUT_PREFIX), '')}.#{options[:format]}.erb"
20
+ end
21
+
22
+ # Renders the tracking image that records the receivement of the mailing inside the mail client.
23
+ def render_tracking_image
24
+ return "" if @preview_mode || @recipient.nil?
25
+ image_tag(
26
+ alchemy_crm.recipient_reads_url(:h => @recipient.sha1, :host => current_host),
27
+ :style => "width: 0; height: 0; display: none",
28
+ :width => 0,
29
+ :height => 0,
30
+ :alt => ''
31
+ )
32
+ end
33
+
34
+ # Renders a link to the unsubscribe page.
35
+ #
36
+ # Please notice that you have to create a page with a +newsletter_signout+ page layout and this page has to be public.
37
+ #
38
+ # The text inside the link is translated.
39
+ #
40
+ # === Example translation:
41
+ #
42
+ # de:
43
+ # alchemy_crm:
44
+ # unsubscribe: 'abmelden'
45
+ #
46
+ # === Options:
47
+ #
48
+ # html_options [Hash] # Passed to the link. Useful for styling the link with inline css.
49
+ #
50
+ # You can pass an optional block thats gets passed to +link_to+
51
+ #
52
+ def link_to_unsubscribe_page(html_options={})
53
+ text = ::I18n.t(:unsubscribe, :scope => :alchemy_crm)
54
+ if block_given?
55
+ link_to(url_for_unsubscribe_page, html_options) do
56
+ yield
57
+ end
58
+ else
59
+ link_to(text, url_for_unsubscribe_page, html_options)
60
+ end
61
+ end
62
+
63
+ # Returns the url for the unsubscribe page.
64
+ # Used by +link_to_unsubscribe_page+ helper and inside of plain text views of mailings.
65
+ def url_for_unsubscribe_page
66
+ unsubscribe_page = Alchemy::Page.find_by_page_layout('newsletter_signout')
67
+ if unsubscribe_page.nil?
68
+ raise('Newsletter Signout Page Could Not Be Found. Please create one!')
69
+ else
70
+ alchemy.show_page_url(
71
+ :urlname => unsubscribe_page.urlname,
72
+ :lang => multi_language? ? unsubscribe_page.language_code : nil,
73
+ :email => @contact ? @contact.email : nil,
74
+ :host => current_host
75
+ )
76
+ end
77
+ end
78
+
79
+ # Renders a notice to open the mailing inside a browser, if it does not displays correctly.
80
+ #
81
+ # The notice and the link inside are translated via I18n.
82
+ #
83
+ # === Example translation:
84
+ #
85
+ # de:
86
+ # alchemy_crm:
87
+ # here: 'hier'
88
+ # read_in_browser_notice: "Falls der Newsletter nicht richtig dargestellt wird, klicken Sie bitte %{link}."
89
+ #
90
+ # === Options:
91
+ #
92
+ # html_options [Hash] # Passed to the link. Useful for styling the link with inline css.
93
+ #
94
+ def read_in_browser_notice(html_options = {})
95
+ return "" if @recipient.nil?
96
+ ::I18n.t(
97
+ :read_in_browser_notice,
98
+ :link => link_to(
99
+ ::I18n.t(:here, :scope => :alchemy_crm),
100
+ alchemy_crm.show_mailing_url(
101
+ :m => @mailing.sha1,
102
+ :r => @recipient.sha1,
103
+ :host => current_host
104
+ ),
105
+ html_options,
106
+ :host => current_host
107
+ ),
108
+ :scope => :alchemy_crm
109
+ ).html_safe
110
+ end
111
+
112
+ # Use this helper to render an image from your server.
113
+ #
114
+ # The notice and the link inside are translated via I18n.
115
+ #
116
+ # === Example:
117
+ #
118
+ # <%= image_from_server_tag('logo.png', :alt => 'Logo', :width => 230, :height => 116, :style => 'outline:none; text-decoration:none; -ms-interpolation-mode: bicubic;') %>
119
+ # => <img src="http://example.com/assets/logo.png"
120
+ #
121
+ # === Options:
122
+ #
123
+ # html_options [Hash] # Passed to the image_tag helper.
124
+ #
125
+ def image_from_server_tag(image, html_options={})
126
+ image_tag([current_server, Rails.application.config.assets.prefix, image].join('/'), html_options)
127
+ end
128
+
129
+ # Renders a link that tracks the reaction of a recipient.
130
+ #
131
+ # After getting tracked the controller redirects to the url passed in.
132
+ #
133
+ # It has the same arguments that the Rails +link_to+ helper has.
134
+ #
135
+ # === Example:
136
+ #
137
+ # <%= tracked_link_tag('read more', :r => 'http://example.com/my-article', :style => 'color: black') %>
138
+ # => <a href="http://example.com/recipient/s3cr3tSh41/reacts?r=http%3A%2F%2Fexample.com%2Fmy-article" style="color: black">
139
+ #
140
+ # *NOTE:* You can even pass a block like you could for +link_to+ helper from Rails.
141
+ #
142
+ def tracked_link_tag(*args)
143
+ if block_given?
144
+ link_to(tracked_url_for(args.first), args.last) do
145
+ yield
146
+ end
147
+ else
148
+ link_to(args.first, tracked_url_for(args[1]), args.last)
149
+ end
150
+ end
151
+
152
+ # Returns the url for tracking a link that's clicked inside a mailing.
153
+ # Used by +tracked_link_tag+ helper and plain text mailing views.
154
+ def tracked_url_for(redirect_url)
155
+ alchemy_crm.recipient_reacts_url(:h => @recipient.sha1, :r => redirect_url, :host => current_host)
156
+ end
157
+
158
+ def current_host
159
+ (defined?(request)).nil? || request.nil? ? @options[:host] : request.host
160
+ end
161
+
162
+ def current_server
163
+ if (defined?(request)).nil? || request.nil?
164
+ protocol = @options.nil? || @options[:protocol].blank? ? 'http://' : @options[:protocol]
165
+ else
166
+ protocol = request.protocol
167
+ end
168
+ if (defined?(request)).nil? || request.nil?
169
+ if @options
170
+ port = @options[:port] && @options[:port] != 80 ? @options[:port] : nil
171
+ else
172
+ port = nil
173
+ end
174
+ else
175
+ port = request.port != 80 ? request.port : nil
176
+ end
177
+ [protocol, current_host, port ? ":#{port}" : nil].join
178
+ end
179
+
180
+ def current_language
181
+ return @language if @language
182
+ if @options && @options[:language_id]
183
+ @language = Alchemy::Language.find(@options[:language_id])
184
+ else
185
+ @language = Alchemy::Language.get_default
186
+ end
187
+ end
188
+
189
+ end
190
+ end
@@ -0,0 +1,13 @@
1
+ module AlchemyCrm
2
+ class BounceReceiver < ActionMailer::Base
3
+
4
+ def receive(email)
5
+ return unless email.content_type == "multipart/report"
6
+ bounce = BouncedDelivery.from_email(email)
7
+ recipient = Recipient.find_by_message_id(bounce.original_message_id)
8
+ recipient.bounced = (bounce.status == "Failure")
9
+ recipient.save!
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,26 @@
1
+ module AlchemyCrm
2
+ class ContactsMailer < ActionMailer::Base
3
+
4
+ def signup_mail(contact, page)
5
+ @contact = contact
6
+ @newsletter_ids = @contact.subscriptions.collect(&:newsletter_id)
7
+ @element = page.elements.where(:name => 'newsletter_signup_mail').first
8
+ mail(
9
+ :from => @element.ingredient('mail_from'),
10
+ :to => contact.email,
11
+ :subject => @element.ingredient('subject')
12
+ )
13
+ end
14
+
15
+ def signout_mail(contact, page)
16
+ @element = page.elements.where(:name => 'newsletter_signout_mail').first
17
+ @contact = contact
18
+ mail(
19
+ :from => @element.ingredient("mail_from"),
20
+ :to => contact.email,
21
+ :subject => @element.ingredient('subject')
22
+ )
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,48 @@
1
+ module AlchemyCrm
2
+ class MailingsMailer < ActionMailer::Base
3
+
4
+ default :from => AlchemyCrm::Config.get(:mail_from)
5
+
6
+ helper "AlchemyCrm::Mailings"
7
+ helper_method :logged_in?, :configuration
8
+
9
+ # Renders the email sent to the mailing recipient
10
+ # It takes the layout from +layouts/alchemy_crm/mailings.erb+ and renders a html and a text part from it.
11
+ def build(mailing, recipient, options = {})
12
+ @options = options
13
+ ::I18n.locale = @options[:locale]
14
+ @mailing = mailing
15
+ @page = @mailing.page
16
+ @recipient = recipient
17
+ @contact = @recipient.contact || Contact.new_from_recipient(@recipient)
18
+
19
+ mail(:to => @recipient.mail_to, :subject => mailing.subject) do |format|
20
+ format.html { render("layouts/alchemy_crm/mailings.html") }
21
+ format.text { render("layouts/alchemy_crm/mailings.text") }
22
+ end
23
+ end
24
+
25
+ # Faking that we are not logged in
26
+ def logged_in?
27
+ false
28
+ end
29
+
30
+ # Proxy to Alchemy config for view helpers
31
+ def configuration(name)
32
+ Alchemy::Config.get(name)
33
+ end
34
+
35
+ # Simple session object that contains the language id for view helpers.
36
+ def session
37
+ {
38
+ :language_id => @options[:language_id]
39
+ }
40
+ end
41
+
42
+ # Setting default url options for rails url_for helpers.
43
+ def default_url_options
44
+ {:host => @options[:host], :port => @options[:port]}
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: UTF-8
2
+ module AlchemyCrm
3
+ class SubscriptionsMailer < ActionMailer::Base
4
+
5
+ def overview_mail(contact, element)
6
+ @contact = contact
7
+ @subscriptions = contact.subscriptions
8
+ @element = element
9
+ mail(
10
+ :from => element.ingredient("mail_from"),
11
+ :to => contact.email,
12
+ :subject => element.ingredient("mail_subject")
13
+ )
14
+ end
15
+
16
+ end
17
+ end