leanweb 0.5.1 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54fc1b8b4dff318eb3ccc51e8f0862706c0b8de9879dadf403580f00a224b9df
4
- data.tar.gz: e2a5d17a9f7a2f13f0cb2983031f91127387021a26d70a7bc91e0722ffb19bf3
3
+ metadata.gz: f4420d0acf838a96016cabcbdf4fb5977044c4c43c7102bbb7c520dab34a3908
4
+ data.tar.gz: 861d7f89f86f9749ac69e007ffd23218047f6cabf825a53074df2aab953e9bb3
5
5
  SHA512:
6
- metadata.gz: 0563e596c38aefdd7af7150ed4f87dbbb55c6bee5459d397574e5fb1da18fe31e5091d6f8346e952729118fed9fda8f6e0b3f2579e0b39fc54d426cee76b81ed
7
- data.tar.gz: 579991147e69766158a1168d28ec58f8da90a94ad4383e2fe8001b15cc4460895892600d53968e063e067a7be2c12347f25e37ec94cb2237e5adc32c04333a1a
6
+ metadata.gz: 3377a07bfdee4a0fe5ebfdd40d3094786ac204b2301eafbf796b296bcce86ab6728352246f74abea581d5910f0f3868d5d11c7706ee4f61ce5275f74914365c4
7
+ data.tar.gz: 616f2bcc6979253f43d20135a72a3537c6eb3680278c39fa73c879e0a088434c1242f10f200202ab0ec5533c746cab0ca971e655ed79956cdd3f3bca6886bac8
@@ -12,6 +12,7 @@ require 'net/smtp'
12
12
  require 'securerandom'
13
13
  require 'socket'
14
14
  require 'time'
15
+ require 'uri/mailto'
15
16
 
16
17
  # Send an email with SMTP easily.
17
18
  #
@@ -25,27 +26,32 @@ require 'time'
25
26
  # - SMTP_FROM: In the format `Name <user@mail>` or `user@mail`.
26
27
  #
27
28
  # @example Single address
28
- # LeanMail.deliver('to@mail', 'subject', 'body')
29
+ # LeanMail.deliver('to@mail', 'subject', 'body', reply_to: 'to@other.host')
29
30
  #
30
31
  # @example Multiple addresses
31
32
  # LeanMail.deliver(['to@mail', 'to2@mail'], 'subject', 'body')
32
33
  module LeanMail
33
34
  # RFC 2821 message data representation.
34
35
  class Data
35
- attr_reader :from, :to, :subject, :message
36
+ attr_reader :from, :to, :subject, :message, :reply_to
37
+
38
+ def initialize(from, to, subject, message, reply_to: nil)
39
+ self.class.validate_recipients(to)
40
+ self.class.validate_recipients(reply_to) if reply_to
36
41
 
37
- def initialize(from, to, subject, message)
38
42
  @from = from
39
43
  @to = to
40
44
  @subject = subject
41
45
  @message = message
46
+ @reply_to = reply_to
42
47
  end
43
48
 
44
49
  def to_s
45
50
  <<~MAIL
46
51
  Content-type: text/plain; charset=UTF-8
47
52
  From: #{@from}
48
- To: #{to.instance_of?(Array) ? to.join(', ') : to}
53
+ To: #{@to.instance_of?(Array) ? @to.join(', ') : @to}
54
+ Reply-To: #{@reply_to || @from}
49
55
  Subject: =?UTF-8?B?#{Base64.strict_encode64(subject)}?=
50
56
  Date: #{Time.new.rfc2822}
51
57
  Message-Id: <#{SecureRandom.uuid}@#{Socket.gethostname}>
@@ -53,6 +59,29 @@ module LeanMail
53
59
  #{@message}
54
60
  MAIL
55
61
  end
62
+
63
+ class << self
64
+ def validate_recipients(recipients)
65
+ return recipients.each{ |recipient| validate_recipients(recipient) } if
66
+ recipients.instance_of?(Array)
67
+
68
+ raise(ArgumentError, "#{recipients} is not a valid recipient") unless
69
+ URI::MailTo::EMAIL_REGEXP.match?(extract_addr(recipients))
70
+ end
71
+
72
+ def extract_addr(str)
73
+ match = str.match(/\A[^\n\r<]+<([^\n\r>]+)>\z/)
74
+ return match[1] if match
75
+
76
+ str
77
+ end
78
+
79
+ def extract_addrs(to)
80
+ return to.map{ |addr| extract_addr(addr) } if to.instance_of?(Array)
81
+
82
+ extract_addr(to)
83
+ end
84
+ end
56
85
  end
57
86
 
58
87
  # Email deliverer.
@@ -76,12 +105,17 @@ module LeanMail
76
105
  # @param to [Array, String] In the format `Name <user@mail>` or `user@mail`.
77
106
  # @param subject [String]
78
107
  # @param body [String]
108
+ # @param reply_to [Array, String] In the same format as `to`.
79
109
  # @return [Deliver]
80
- def call(to, subject, body)
81
- @data = Data.new(@from, to, subject, body)
110
+ def call(to, subject, body, reply_to: nil)
111
+ @data = Data.new(@from, to, subject, body, reply_to: reply_to)
82
112
 
83
113
  @smtp.start(Socket.gethostname, @user, @password, :plain) do |smtp|
84
- smtp.send_message(@data.to_s, extract_addr(@from), extract_addrs(to))
114
+ smtp.send_message(
115
+ @data.to_s,
116
+ Data.extract_addr(@from),
117
+ Data.extract_addrs(to)
118
+ )
85
119
  end
86
120
 
87
121
  self
@@ -100,19 +134,6 @@ module LeanMail
100
134
  when 'starttls' then @smtp.enable_starttls
101
135
  end
102
136
  end
103
-
104
- def extract_addr(str)
105
- match = str.match(%r{<([^/]+)>})
106
- return match[1] if match
107
-
108
- str
109
- end
110
-
111
- def extract_addrs(to)
112
- return to.map{ |addr| extract_addr(addr) } if to.instance_of?(Array)
113
-
114
- extract_addr(to)
115
- end
116
137
  end
117
138
 
118
139
  # Deliver email.
@@ -120,8 +141,9 @@ module LeanMail
120
141
  # @param to [Array, String] In the format `Name <user@mail>` or `user@mail`.
121
142
  # @param subject [String]
122
143
  # @param body [String]
144
+ # @param reply_to [Array, String] In the same format as `to`.
123
145
  # @return [Deliver]
124
- def self.deliver(to, subject, body)
125
- LeanMail::Deliver.new.call(to, subject, body)
146
+ def self.deliver(to, subject, body, reply_to: nil)
147
+ LeanMail::Deliver.new.call(to, subject, body, reply_to: reply_to)
126
148
  end
127
149
  end
data/lib/leanweb/route.rb CHANGED
@@ -72,11 +72,6 @@ module LeanWeb
72
72
  return respond_proc(request) if @action.instance_of?(Proc)
73
73
 
74
74
  respond_method(request)
75
- rescue NoMethodError
76
- raise unless @static == true && (view_path = guess_view_path)
77
-
78
- controller = default_controller_class.new(self)
79
- controller.default_static_action(view_path)
80
75
  end
81
76
 
82
77
  # String path, independent if {#path} is Regexp or String.
@@ -159,14 +154,28 @@ module LeanWeb
159
154
  Controller
160
155
  end
161
156
 
157
+ def default_static_action
158
+ default_controller_class.new(self).default_static_action(guess_view_path)
159
+ end
160
+
161
+ def controller_for_request(request)
162
+ require_relative("#{CONTROLLER_PATH}/#{@action.controller.to_s.snakeize}")
163
+ Object.const_get(@action.controller).new(self, request)
164
+ rescue LoadError
165
+ nil
166
+ end
167
+
162
168
  # @param request [Rack::Request]
163
169
  # @return [Array] a valid Rack response.
164
170
  def respond_method(request)
165
171
  params = action_params(request.path)
166
- require_relative("#{CONTROLLER_PATH}/#{@action.controller.to_s.snakeize}")
167
- controller = Object.const_get(@action.controller).new(self, request)
168
- return controller.public_send(@action.action, **params) \
169
- if params.instance_of?(Hash)
172
+ controller = controller_for_request(request)
173
+
174
+ return default_static_action unless
175
+ controller&.class&.method_defined?(@action.action)
176
+
177
+ return controller.public_send(@action.action, **params) if
178
+ params.instance_of?(Hash)
170
179
 
171
180
  controller.public_send(@action.action, *params)
172
181
  end
@@ -9,5 +9,5 @@
9
9
 
10
10
 
11
11
  module LeanWeb
12
- VERSION = '0.5.1'
12
+ VERSION = '0.5.3'
13
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leanweb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Freeman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-13 00:00:00.000000000 Z
11
+ date: 2023-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -222,7 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
222
  - !ruby/object:Gem::Version
223
223
  version: '0'
224
224
  requirements: []
225
- rubygems_version: 3.4.7
225
+ rubygems_version: 3.4.10
226
226
  signing_key:
227
227
  specification_version: 4
228
228
  summary: LeanWeb is a minimal hybrid static / dynamic web framework