courrier 0.9.0 → 0.11.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +16 -24
  4. data/README.md +178 -74
  5. data/courrier.gemspec +4 -4
  6. data/lib/courrier/configuration.rb +2 -4
  7. data/lib/courrier/email/provider.rb +14 -6
  8. data/lib/courrier/email/providers/base.rb +7 -2
  9. data/lib/courrier/email/providers/cloudflare.rb +35 -0
  10. data/lib/courrier/email/providers/lettermint.rb +31 -0
  11. data/lib/courrier/email/providers/loops.rb +1 -1
  12. data/lib/courrier/email/providers/mailgun.rb +1 -1
  13. data/lib/courrier/email/providers/mailjet.rb +1 -1
  14. data/lib/courrier/email/providers/mailpace.rb +1 -1
  15. data/lib/courrier/email/providers/postmark.rb +1 -1
  16. data/lib/courrier/email/providers/resend.rb +1 -1
  17. data/lib/courrier/email/providers/sendgrid.rb +1 -1
  18. data/lib/courrier/email/providers/ses.rb +75 -0
  19. data/lib/courrier/email/providers/smtp2go.rb +29 -0
  20. data/lib/courrier/email/providers/sparkpost.rb +1 -1
  21. data/lib/courrier/email/providers/userlist.rb +1 -1
  22. data/lib/courrier/email/request.rb +1 -1
  23. data/lib/courrier/email/transformer.rb +9 -9
  24. data/lib/courrier/email.rb +50 -38
  25. data/lib/courrier/errors.rb +0 -2
  26. data/lib/courrier/markdown.rb +52 -0
  27. data/lib/courrier/test.rb +38 -0
  28. data/lib/courrier/test_helper.rb +65 -0
  29. data/lib/courrier/version.rb +1 -1
  30. data/lib/courrier.rb +2 -2
  31. metadata +18 -31
  32. data/app/controllers/courrier/previews/cleanups_controller.rb +0 -13
  33. data/app/controllers/courrier/previews_controller.rb +0 -23
  34. data/app/views/courrier/previews/index.html.erb +0 -171
  35. data/config/routes.rb +0 -8
  36. data/lib/courrier/configuration/inbox.rb +0 -21
  37. data/lib/courrier/email/providers/inbox/default.html.erb +0 -126
  38. data/lib/courrier/email/providers/inbox.rb +0 -83
  39. data/lib/courrier/engine.rb +0 -7
  40. data/lib/courrier/jobs/email_delivery_job.rb +0 -23
  41. data/lib/courrier/railtie.rb +0 -23
  42. data/lib/courrier/tasks/courrier.rake +0 -13
  43. data/lib/generators/courrier/email_generator.rb +0 -42
  44. data/lib/generators/courrier/install_generator.rb +0 -11
  45. data/lib/generators/courrier/templates/email/password_reset.rb.tt +0 -29
  46. data/lib/generators/courrier/templates/email/welcome.rb.tt +0 -43
  47. data/lib/generators/courrier/templates/email.rb.tt +0 -15
  48. data/lib/generators/courrier/templates/initializer.rb.tt +0 -43
metadata CHANGED
@@ -1,35 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: courrier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rails Designer
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-02-04 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
- name: launchy
13
+ name: logger
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '3.1'
18
+ version: '1.5'
20
19
  - - "<"
21
20
  - !ruby/object:Gem::Version
22
- version: '4'
21
+ version: '3'
23
22
  type: :runtime
24
23
  prerelease: false
25
24
  version_requirements: !ruby/object:Gem::Requirement
26
25
  requirements:
27
26
  - - ">="
28
27
  - !ruby/object:Gem::Version
29
- version: '3.1'
28
+ version: '1.5'
30
29
  - - "<"
31
30
  - !ruby/object:Gem::Version
32
- version: '4'
31
+ version: '3'
33
32
  - !ruby/object:Gem::Dependency
34
33
  name: nokogiri
35
34
  requirement: !ruby/object:Gem::Requirement
@@ -62,17 +61,12 @@ files:
62
61
  - Gemfile.lock
63
62
  - README.md
64
63
  - Rakefile
65
- - app/controllers/courrier/previews/cleanups_controller.rb
66
- - app/controllers/courrier/previews_controller.rb
67
- - app/views/courrier/previews/index.html.erb
68
64
  - bin/console
69
65
  - bin/release
70
66
  - bin/setup
71
- - config/routes.rb
72
67
  - courrier.gemspec
73
68
  - lib/courrier.rb
74
69
  - lib/courrier/configuration.rb
75
- - lib/courrier/configuration/inbox.rb
76
70
  - lib/courrier/configuration/providers.rb
77
71
  - lib/courrier/email.rb
78
72
  - lib/courrier/email/address.rb
@@ -80,8 +74,8 @@ files:
80
74
  - lib/courrier/email/options.rb
81
75
  - lib/courrier/email/provider.rb
82
76
  - lib/courrier/email/providers/base.rb
83
- - lib/courrier/email/providers/inbox.rb
84
- - lib/courrier/email/providers/inbox/default.html.erb
77
+ - lib/courrier/email/providers/cloudflare.rb
78
+ - lib/courrier/email/providers/lettermint.rb
85
79
  - lib/courrier/email/providers/logger.rb
86
80
  - lib/courrier/email/providers/loops.rb
87
81
  - lib/courrier/email/providers/mailgun.rb
@@ -90,15 +84,15 @@ files:
90
84
  - lib/courrier/email/providers/postmark.rb
91
85
  - lib/courrier/email/providers/resend.rb
92
86
  - lib/courrier/email/providers/sendgrid.rb
87
+ - lib/courrier/email/providers/ses.rb
88
+ - lib/courrier/email/providers/smtp2go.rb
93
89
  - lib/courrier/email/providers/sparkpost.rb
94
90
  - lib/courrier/email/providers/userlist.rb
95
91
  - lib/courrier/email/request.rb
96
92
  - lib/courrier/email/result.rb
97
93
  - lib/courrier/email/transformer.rb
98
- - lib/courrier/engine.rb
99
94
  - lib/courrier/errors.rb
100
- - lib/courrier/jobs/email_delivery_job.rb
101
- - lib/courrier/railtie.rb
95
+ - lib/courrier/markdown.rb
102
96
  - lib/courrier/subscriber.rb
103
97
  - lib/courrier/subscriber/base.rb
104
98
  - lib/courrier/subscriber/beehiiv.rb
@@ -108,21 +102,15 @@ files:
108
102
  - lib/courrier/subscriber/mailchimp.rb
109
103
  - lib/courrier/subscriber/mailerlite.rb
110
104
  - lib/courrier/subscriber/result.rb
111
- - lib/courrier/tasks/courrier.rake
105
+ - lib/courrier/test.rb
106
+ - lib/courrier/test_helper.rb
112
107
  - lib/courrier/version.rb
113
- - lib/generators/courrier/email_generator.rb
114
- - lib/generators/courrier/install_generator.rb
115
- - lib/generators/courrier/templates/email.rb.tt
116
- - lib/generators/courrier/templates/email/password_reset.rb.tt
117
- - lib/generators/courrier/templates/email/welcome.rb.tt
118
- - lib/generators/courrier/templates/initializer.rb.tt
119
- homepage: https://railsdesigner.com/courrier/
108
+ homepage: https://railsdesigner.com/open-source/courrier/
120
109
  licenses:
121
110
  - MIT
122
111
  metadata:
123
- homepage_uri: https://railsdesigner.com/courrier/
112
+ homepage_uri: https://railsdesigner.com/open-source/courrier/
124
113
  source_code_uri: https://github.com/Rails-Designer/courrier/
125
- post_install_message:
126
114
  rdoc_options: []
127
115
  require_paths:
128
116
  - lib
@@ -130,15 +118,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
118
  requirements:
131
119
  - - ">="
132
120
  - !ruby/object:Gem::Version
133
- version: 3.2.0
121
+ version: 4.0.0
134
122
  required_rubygems_version: !ruby/object:Gem::Requirement
135
123
  requirements:
136
124
  - - ">="
137
125
  - !ruby/object:Gem::Version
138
126
  version: '0'
139
127
  requirements: []
140
- rubygems_version: 3.4.1
141
- signing_key:
128
+ rubygems_version: 4.0.3
142
129
  specification_version: 4
143
130
  summary: API-powered email delivery for Ruby apps
144
131
  test_files: []
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Courrier
4
- module Previews
5
- class CleanupsController < ActionController::Base
6
- def create
7
- system("bin/rails courrier:clear")
8
-
9
- redirect_to root_path
10
- end
11
- end
12
- end
13
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Courrier
4
- class PreviewsController < ActionController::Base
5
- def index
6
- @emails = emails.map { Courrier::Email::Providers::Inbox::Email.from_file(_1) }
7
- end
8
-
9
- def show
10
- file_path = File.join(Courrier.configuration.inbox.destination, params[:id])
11
- content = File.read(file_path)
12
-
13
- render html: content.html_safe, layout: false
14
- end
15
-
16
- private
17
-
18
- def emails
19
- @emails ||= Dir.glob("#{Courrier.configuration.inbox.destination}/*.html")
20
- .sort_by { -File.basename(_1, ".html").to_i }
21
- end
22
- end
23
- end
@@ -1,171 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>Courrier Inbox</title>
6
-
7
- <style>
8
- *, *::before, *::after { box-sizing: border-box; }
9
- * { margin: 0; padding: 0; }
10
- body { margin: 0; padding: 0; font-size: 16px; line-height: 1.5; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; background-color: rgb(241, 245, 249); }
11
-
12
- .sidebar {
13
- display: flex;
14
- flex-direction: column;
15
- position: sticky;
16
- top: 0;
17
- padding: .5rem;
18
- width: min(350px, 33.3333%); height: 100dvh;
19
- border-right: 1px solid rgb(226, 232, 240);
20
- }
21
-
22
- .sidebar__options {
23
- position: sticky;
24
- bottom: 0;
25
- padding: .5rem;
26
- background-color: rgb(241, 245, 249);
27
- }
28
-
29
- .sidebar__btn-clear {
30
- border: none;
31
- display: flex;
32
- align-items: center;
33
- justify-content: center;
34
- column-gap: 0.25rem;
35
- width: 100%;
36
- padding: .5rem;
37
- font-size: .875rem; line-height: 1.25rem;
38
- font-weight: 500;
39
- color: rgb(71, 85, 105);
40
- background-color: rgb(226, 232, 240);
41
- border-radius: .5rem;
42
- cursor: default;
43
-
44
- &:hover { background-color: rgb(203, 213, 225); }
45
- &:active { transform: scale(.98); }
46
-
47
- [data-slot="icon"] {
48
- width: .875rem; height: .875rem;
49
- }
50
- }
51
-
52
- .email-previews {
53
- display: flex;
54
- flex-direction: column;
55
- flex: 1;
56
- row-gap: .5rem;
57
- overflow-y: auto;
58
- width: 100%;
59
- }
60
-
61
- .email-preview {
62
- display: flex;
63
- flex-direction: row;
64
- column-gap: .5rem;
65
- width: 100%;
66
- padding: .5rem .75rem;
67
- text-decoration: none;
68
- border-radius: .5rem;
69
-
70
- &:hover {
71
- background-color: rgba(226, 232, 240, .75);
72
- }
73
- }
74
-
75
- .email-preview--empty {
76
- display: none;
77
- text-align: center;
78
-
79
- &:only-child {
80
- display: block;
81
- }
82
- }
83
-
84
- .email-preview__avatar {
85
- flex-shrink: 0;
86
- padding: .25rem;
87
- width: 1.5rem; height: 1.5rem;
88
- background-color: rgb(203, 213, 225);
89
- color: rgb(51, 65, 85);
90
- border-radius: 9999px;
91
- }
92
-
93
- .email-preview__content {
94
- font-size: 0.875rem; line-height: 1.25rem;
95
- }
96
-
97
- .email-preview__recipient {
98
- font-size: 1rem; line-height: 1.5rem;
99
- font-weight: 600;
100
- letter-spacing: -.025em;
101
- color: rgb(51, 65, 85);
102
- }
103
-
104
- .email-preview__subject {
105
- margin-top: .125rem;
106
- overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1;
107
- color: rgb(100, 116, 139);
108
- }
109
- </style>
110
- </head>
111
- <body>
112
- <div style="display: flex; column-gap: 1rem;">
113
- <aside class="sidebar">
114
- <ul class="email-previews">
115
- <li class="email-preview--empty">
116
- <p class="email-preview__subject">
117
- No emails yet…
118
- </p>
119
- </li>
120
-
121
- <% @emails.each do |email| %>
122
- <li>
123
- <%= link_to courrier.preview_path(email.filename), data: {remote: true}, class: "email-preview" do %>
124
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon" class="email-preview__avatar">
125
- <path fill-rule="evenodd" d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z" clip-rule="evenodd"/>
126
- </svg>
127
-
128
- <div class="email-preview__content">
129
- <small class="email-preview__recipient">
130
- <%= email.metadata.to %>
131
- </small>
132
-
133
- <p class="email-preview__subject">
134
- <%= email.metadata.subject || "No subject" %>
135
- </p>
136
- </div>
137
- <% end %>
138
- </li>
139
- <% end %>
140
- </ul>
141
-
142
- <div class="sidebar__options">
143
- <%= button_to courrier.cleanup_path, class: "sidebar__btn-clear" do %>
144
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon">
145
- <path fill-rule="evenodd" d="M16.5 4.478v.227a48.816 48.816 0 0 1 3.878.512.75.75 0 1 1-.256 1.478l-.209-.035-1.005 13.07a3 3 0 0 1-2.991 2.77H8.084a3 3 0 0 1-2.991-2.77L4.087 6.66l-.209.035a.75.75 0 0 1-.256-1.478A48.567 48.567 0 0 1 7.5 4.705v-.227c0-1.564 1.213-2.9 2.816-2.951a52.662 52.662 0 0 1 3.369 0c1.603.051 2.815 1.387 2.815 2.951Zm-6.136-1.452a51.196 51.196 0 0 1 3.273 0C14.39 3.05 15 3.684 15 4.478v.113a49.488 49.488 0 0 0-6 0v-.113c0-.794.609-1.428 1.364-1.452Zm-.355 5.945a.75.75 0 1 0-1.5.058l.347 9a.75.75 0 1 0 1.499-.058l-.346-9Zm5.48.058a.75.75 0 1 0-1.498-.058l-.347 9a.75.75 0 0 0 1.5.058l.345-9Z" clip-rule="evenodd"/>
146
- </svg>
147
-
148
- Clear inbox
149
- <% end %>
150
- </div>
151
- </aside>
152
-
153
- <article style="flex: 1;" id="email-preview">
154
- </article>
155
- </div>
156
-
157
- <script>
158
- document.querySelectorAll("a[data-remote]").forEach(link => {
159
- link.addEventListener("click", (event) => {
160
- event.preventDefault();
161
-
162
- fetch(link.href)
163
- .then(response => response.text())
164
- .then(html => {
165
- document.getElementById("email-preview").innerHTML = html;
166
- });
167
- });
168
- });
169
- </script>
170
- </body>
171
- </html>
data/config/routes.rb DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Courrier::Engine.routes.draw do
4
- resources :previews, only: %w[show], constraints: {id: /.*\.html/}
5
- resource :cleanup, only: %w[create], module: "previews"
6
-
7
- root "previews#index"
8
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Courrier
4
- class Configuration
5
- class Inbox
6
- attr_accessor :destination, :auto_open, :template_path
7
-
8
- def initialize
9
- @destination = default_destination
10
- @auto_open = false
11
- @template_path = File.expand_path("../../../courrier/email/providers/inbox/default.html.erb", __FILE__)
12
- end
13
-
14
- private
15
-
16
- def default_destination
17
- defined?(Rails) ? Rails.root.join("tmp", "courrier", "emails").to_s : File.join(Dir.tmpdir, "courrier", "emails")
18
- end
19
- end
20
- end
21
- end
@@ -1,126 +0,0 @@
1
- <!--
2
- {
3
- "to": "<%= email %>",
4
- "subject": "<%= @options.subject %>"
5
- }
6
- -->
7
-
8
- <!DOCTYPE html>
9
- <html>
10
- <head>
11
- <meta charset="UTF-8">
12
- <title><%= @options.subject %></title>
13
- <style>
14
- *, *::before, *::after { box-sizing: border-box; }
15
- * { margin: 0; padding: 0; }
16
- body { margin: 0; padding: 0; line-height: 1.5; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; background-color: rgb(241, 245, 249); }
17
- pre { margin: 0; white-space: pre-wrap; }
18
- .email {
19
- width: 100%;
20
- max-width: 65rem;
21
- margin-left: auto; margin-right: auto;
22
- background-color: #fff;
23
- box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
24
- border-bottom-right-radius: 1rem; border-bottom-left-radius: 1rem;
25
- }
26
-
27
- .email__header { display: flex; align-items: center; padding: .75rem; -moz-column-gap: .75rem; column-gap: .75rem; }
28
-
29
- .email__avatar {
30
- flex-shrink: 0;
31
- padding: .25rem;
32
- width: 2rem; height: 2rem;
33
- background-color: rgb(203, 213, 225);
34
- color: rgb(51, 65, 85);
35
- border-radius: 9999px;
36
- }
37
-
38
- .email__recipient { flex-grow: 1; font-size: .875rem; line-height: 1.25rem; }
39
-
40
- .email__recipient-name { font-weight: 600; color: rgb(51, 65, 85); }
41
-
42
- .email__metadata { display: flex; align-items: center; justify-content: space-between; }
43
-
44
- .email__recipient-email { color: rgb(100, 116, 139); }
45
-
46
- .email__datetime { font-size: .75rem; line-height: 1rem; color: rgb(148, 163, 184); }
47
-
48
- .email__subject {
49
- margin-left: 3.5rem;
50
- font-size: 1.25rem; line-height: 1.75rem;
51
- font-weight: 700;
52
- letter-spacing: -.025em;
53
- color: rgb(30, 41, 59)
54
- }
55
-
56
- .email__preview { margin-top: .75rem; margin-left: 3.5rem; padding-bottom: 1rem; }
57
-
58
- .preview-toggle { display: none; }
59
- .preview-toggle-label {
60
- display: inline-block;
61
- padding: .25rem .875rem;
62
- font-size: .75rem; line-height: 1rem;
63
- font-weight: 600;
64
- color: rgb(30, 41, 59);
65
- background-color: rgb(255, 255, 255);
66
- border: 1px solid rgb(226, 232, 240);
67
- border-radius: .375rem;
68
- box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
69
- cursor: pointer;
70
-
71
- &:hover { border-color: rgb(203, 213, 225); }
72
- &:active { transform: scale(.98); }
73
- }
74
- .preview-toggle[disabled] + .preview-toggle-label { opacity: 0.5; cursor: not-allowed; }
75
-
76
- .email__preview-html, .email__preview-text { margin-top: 1.5rem;}
77
- .email__preview-html { display: none; }
78
- .preview-toggle:checked ~ .email__preview-text { display: none; }
79
- .preview-toggle:checked ~ .email__preview-html { display: block; }
80
- </style>
81
- </head>
82
- <body>
83
- <article class="email">
84
- <header class="email__header">
85
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon" class="email__avatar">
86
- <path fill-rule="evenodd" d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z" clip-rule="evenodd"/>
87
- </svg>
88
-
89
- <div class="email__recipient">
90
- <% if name %>
91
- <p class="email__recipient-name">
92
- <%= name %>
93
- </p>
94
- <% end %>
95
-
96
- <div class="email__metadata">
97
- <p class="email__recipient-email">
98
- <%= email %>
99
- </p>
100
-
101
- <time class="email__datetime" datetime="#{Time.now.strftime("%Y-%m-%d %H:%M:%S %z")}">
102
- <%= Time.now.strftime("%Y-%m-%d %H:%M:%S %z") %>
103
- </time>
104
- </div>
105
- </div>
106
- </header>
107
-
108
- <p class="email__subject">
109
- <%= @options.subject %>
110
- </p>
111
-
112
- <div class="email__preview">
113
- <input type="checkbox" id="preview-toggle" class="preview-toggle" <%= html ? "" : "disabled" %>>
114
- <label for="preview-toggle" class="preview-toggle-label">Toggle HTML/Text</label>
115
-
116
- <div class="email__preview-text">
117
- <pre><%= text || "(no text content)" %></pre>
118
- </div>
119
-
120
- <div class="email__preview-html">
121
- <%= html || "<p>(no HTML content)</p>" %>
122
- </div>
123
- </div>
124
- </article>
125
- </body>
126
- </html>
@@ -1,83 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "tmpdir"
4
- require "fileutils"
5
- require "launchy"
6
-
7
- module Courrier
8
- class Email
9
- module Providers
10
- class Inbox < Base
11
- def deliver
12
- FileUtils.mkdir_p(config.destination)
13
-
14
- file_path = File.join(config.destination, "#{Time.now.to_i}.html")
15
-
16
- File.write(file_path, ERB.new(File.read(config.template_path)).result(binding))
17
-
18
- Launchy.open(file_path) if config.auto_open
19
-
20
- "📮 Email saved to #{file_path} and #{email_destination}"
21
- end
22
-
23
- def name = extract(@options.to)[:name]
24
-
25
- def email = extract(@options.to)[:email]
26
-
27
- def text = prepare(@options.text)
28
-
29
- def html = prepare(@options.html)
30
-
31
- private
32
-
33
- def extract(to)
34
- if to.to_s =~ /(.*?)\s*<(.+?)>/
35
- {name: $1.strip, email: $2.strip}
36
- else
37
- {name: nil, email: to.to_s.strip}
38
- end
39
- end
40
-
41
- def prepare(content)
42
- content.to_s.gsub(URL_PARSER.make_regexp(%w[http https])) do |url|
43
- %(<a href="#{url}">#{url}</a>)
44
- end
45
- end
46
-
47
- def config = @config ||= Courrier.configuration.inbox
48
-
49
- def email_destination
50
- return "opened in your default browser" if config.auto_open
51
-
52
- path = begin
53
- Rails.application.routes.url_helpers.courrier_path
54
- rescue
55
- "/courrier/ (Note: Add `mount Courrier::Engine => \"/courrier\"` to your routes.rb to enable proper routing)"
56
- end
57
-
58
- "available at #{path}"
59
- end
60
-
61
- URL_PARSER = (
62
- defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
63
- )
64
-
65
- class Email < Data.define(:path, :filename, :metadata)
66
- Metadata = Data.define(:to, :subject)
67
-
68
- def self.from_file(path)
69
- content = File.read(path)
70
- json = content[/<!--\s*(.*?)\s*-->/m, 1]
71
- metadata = JSON.parse(json, symbolize_names: true)
72
-
73
- new(
74
- path: path,
75
- filename: File.basename(path),
76
- metadata: Metadata.new(**metadata)
77
- )
78
- end
79
- end
80
- end
81
- end
82
- end
83
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Courrier
4
- class Engine < ::Rails::Engine
5
- isolate_namespace Courrier
6
- end
7
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Courrier
4
- module Jobs
5
- class EmailDeliveryJob < ActiveJob::Base
6
- def perform(data)
7
- email_class = data[:email_class].constantize
8
-
9
- email_class.new(
10
- provider: data[:provider],
11
- api_key: data[:api_key],
12
- from: data[:options][:from],
13
- to: data[:options][:to],
14
- reply_to: data[:options][:reply_to],
15
- cc: data[:options][:cc],
16
- bcc: data[:options][:bcc],
17
- provider_options: data[:provider_options],
18
- context_options: data[:context_options]
19
- ).deliver_now
20
- end
21
- end
22
- end
23
- end
@@ -1,23 +0,0 @@
1
- module Courrier
2
- class Railtie < Rails::Railtie
3
- config.after_initialize do
4
- Courrier::Email.default_url_options = Courrier.configuration.default_url_options
5
- end
6
-
7
- ActiveSupport.on_load(:action_view) do
8
- include Courrier::Email::Address
9
- end
10
-
11
- ActiveSupport.on_load(:action_controller) do
12
- include Courrier::Email::Address
13
- end
14
-
15
- ActiveSupport.on_load(:active_job) do
16
- include Courrier::Email::Address
17
- end
18
-
19
- rake_tasks do
20
- load File.expand_path("../tasks/courrier.rake", __FILE__)
21
- end
22
- end
23
- end
@@ -1,13 +0,0 @@
1
- namespace :tmp do
2
- task :courrier do
3
- rm_rf Dir["#{Courrier.configuration.inbox.destination}/[^.]*"], verbose: false
4
- end
5
-
6
- task clear: :courrier
7
- end
8
-
9
- namespace :courrier do
10
- desc "Clear email files from `#{Courrier.configuration.inbox.destination}`"
11
-
12
- task clear: "tmp:courrier"
13
- end