mitake_sms 1.0.0 → 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f0145815894a3f478ba54c0cc151d8753f0dd99bab584128fdeaad3a5e37bf7b
4
- data.tar.gz: 8a83a7ed6f9b43cced0aa4a1130f361669f0043d78767603f505d7465b3aa773
3
+ metadata.gz: 46484a48ae04607708212f2512b21b7a941a365f3282783beca9f695a79c0fc6
4
+ data.tar.gz: 446cc3b004842cede09f38f6516a5a03ada342a50d0d79e840a7eefdbc6ba398
5
5
  SHA512:
6
- metadata.gz: ec120586bd986581175e851ed2a974cc9452ba1e8f964fa59dad0b23a9564671f62d205339d5f82e90d0fcd21f696c115ef4159c60a88d78a6be6255421e36d4
7
- data.tar.gz: 1716857937144e700d23a88445468856cbd67c7bd5e921e2ac32987216f24acaab4ebba161dadd58fbcce9641c11fbcfe6be307a940e315b3f0b803237818363
6
+ metadata.gz: e1fcbca7044f634e710b7fc34afbf19f576529bd1b155d212b1d4be158ea31cee05e950c5089517ae4112a9c63251af462f8df7213ccde4c517a622b4fa4b214
7
+ data.tar.gz: c3a4955cd4c9b4476bc36bf032b3af9effc002ccd2646db04d3df195d116ca885e76bb03c6f8a5ce1c7fe423a01fa33510774938729040b5d8d7a6da8ef7dff4
data/CHANGELOG.md CHANGED
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.0] - 2025-05-25
11
+ ### Added
12
+ - Added proper handling of newlines in message text (converts to ASCII code 6)
13
+ - Added URL encoding for message content to handle special characters
14
+ - Added advanced batch SMS format support using ClientID $$ dstaddr $$ dlvtime $$ vldtime $$ destname $$ response $$ smbody
15
+ - Added automatic generation of unique ClientIDs for advanced batch SMS
16
+
17
+ ### Changed
18
+ - Improved message formatting to comply with Mitake API requirements
19
+ - Enhanced test coverage to 92.81%
20
+
21
+ ## [1.1.0] - 2025-05-24
22
+ ### Added
23
+ - Added automatic handling of the 500 message limit for batch SMS sending
24
+ - Added UTF-8 encoding support by default for all SMS messages
25
+ - Added `CharsetURL` parameter for single SMS messages
26
+ - Added `Encoding_PostIn` parameter for batch SMS messages
27
+ - Added ability to customize character encoding via options
28
+
29
+ ### Changed
30
+ - Updated documentation to reflect new encoding options
31
+ - Improved batch sending with automatic splitting of large batches
32
+
10
33
  ## [1.0.0] - 2025-05-24
11
34
  ### Added
12
35
  - Initial stable release
data/README.md CHANGED
@@ -7,7 +7,8 @@ A Ruby client for the Mitake SMS API, providing a simple and efficient way to se
7
7
  ## Features
8
8
 
9
9
  - Send single SMS messages
10
- - Send batch SMS messages
10
+ - Send batch SMS messages with automatic handling of the 500 message API limit
11
+ - UTF-8 encoding support by default
11
12
  - Configurable API settings
12
13
  - Simple and intuitive API
13
14
  - Comprehensive error handling
@@ -44,14 +45,14 @@ require 'mitake_sms'
44
45
  MitakeSms.configure do |config|
45
46
  config.username = 'your_username' # Your Mitake SMS API username
46
47
  config.password = 'your_password' # Your Mitake SMS API password
47
- config.api_url = 'https://smsapi.mitake.com.tw/api/mtk/' # Default API URL
48
+ config.api_url = 'https://smsapi.mitake.com.tw/b2c/mtk/' # Default API URL
48
49
  end
49
50
  ```
50
51
 
51
52
  ### Sending a Single SMS
52
53
 
53
54
  ```ruby
54
- # Send a simple SMS
55
+ # Send a simple SMS (uses UTF-8 encoding by default)
55
56
  response = MitakeSms.send_sms('0912345678', 'Hello, this is a test message!')
56
57
 
57
58
  if response.success?
@@ -67,7 +68,8 @@ response = MitakeSms.send_sms(
67
68
  'Hello with options!',
68
69
  from: 'YourBrand',
69
70
  response_url: 'https://your-callback-url.com/delivery-reports',
70
- client_id: 'your-client-reference-id'
71
+ client_id: 'your-client-reference-id',
72
+ charset: 'BIG5' # Override the default UTF-8 encoding if needed
71
73
  )
72
74
  ```
73
75
 
@@ -80,17 +82,119 @@ messages = [
80
82
  { to: '0933555777', text: 'Third message', response_url: 'https://your-callback-url.com/reports' }
81
83
  ]
82
84
 
85
+ # Automatically handles batches according to the Mitake SMS API limit (500 messages per request)
86
+ # If you send more than 500 messages, they will be automatically split into multiple requests
87
+ # Uses UTF-8 encoding by default
83
88
  response = MitakeSms.batch_send(messages)
84
89
 
85
- if response.success?
90
+ # You can specify a different character encoding if needed
91
+ response = MitakeSms.batch_send(messages, charset: 'BIG5')
92
+
93
+ # If fewer than 500 messages, you'll get a single response
94
+ if response.is_a?(MitakeSms::Response) && response.success?
86
95
  puts "Batch sent successfully!"
87
96
  puts "Message ID: #{response.message_id}"
88
97
  puts "Remaining points: #{response.account_point}"
98
+
99
+ # If more than 500 messages, you'll get an array of responses
100
+ elsif response.is_a?(Array)
101
+ response.each_with_index do |batch_response, index|
102
+ if batch_response.success?
103
+ puts "Batch #{index + 1} sent successfully!"
104
+ puts "Message ID: #{batch_response.message_id}"
105
+ puts "Remaining points: #{batch_response.account_point}"
106
+ else
107
+ puts "Batch #{index + 1} failed: #{batch_response.error}"
108
+ end
109
+ end
89
110
  else
90
111
  puts "Failed to send batch: #{response.error}"
91
112
  end
92
113
  ```
93
114
 
115
+ ### Sending Large Batches with Custom Limit
116
+
117
+ ```ruby
118
+ # Create a large batch of messages
119
+ messages = (1..1000).map do |i|
120
+ { to: '0912345678', text: "Message #{i}" }
121
+ end
122
+
123
+ # The Mitake SMS API has a limit of 500 messages per request
124
+ # However, you can set a lower limit if needed for your use case
125
+ # This will split into batches of 300 messages each
126
+ # Uses UTF-8 encoding by default
127
+ responses = MitakeSms.batch_send_with_limit(messages, 300)
128
+
129
+ # You can specify a different character encoding if needed
130
+ responses = MitakeSms.batch_send_with_limit(messages, 300, charset: 'BIG5')
131
+
132
+ # Process the array of responses
133
+ responses.each_with_index do |batch_response, index|
134
+ if batch_response.success?
135
+ puts "Batch #{index + 1} sent successfully!"
136
+ else
137
+ puts "Batch #{index + 1} failed: #{batch_response.error}"
138
+ end
139
+ end
140
+ ```
141
+
142
+ ### Sending Advanced Format Batch SMS
143
+
144
+ The advanced format allows more control over each message in the batch, including scheduled delivery, validity period, recipient name, and more:
145
+
146
+ ```ruby
147
+ # Create messages with advanced options
148
+ messages = [
149
+ {
150
+ client_id: 'unique-id-20250525-001', # Client reference ID (auto-generated if not provided)
151
+ to: '0912345678', # Required recipient phone number
152
+ dlvtime: '20250526120000', # Optional delivery time (YYYYMMDDhhmmss)
153
+ vldtime: '20250527120000', # Optional validity period (YYYYMMDDhhmmss)
154
+ dest_name: '大寶', # Optional recipient name
155
+ response: 'https://callback.url', # Optional callback URL
156
+ text: '這是一則測試簡訊' # Required message content
157
+ },
158
+ {
159
+ # client_id will be auto-generated if not provided
160
+ to: '0922333444',
161
+ text: '這是另一則測試簡訊'
162
+ # Other fields are optional
163
+ }
164
+ ]
165
+
166
+ # Note about ClientID:
167
+ # - ClientID is used by Mitake to prevent duplicate message sending within 12 hours
168
+ # - If not provided, a unique ID will be automatically generated using timestamp and random values
169
+ # - For custom tracking, you can provide your own unique ClientID
170
+ #
171
+ # Note about message text formatting:
172
+ # - If your message text contains line breaks (\n), they will be automatically converted
173
+ # to ASCII code 6 as required by the Mitake API
174
+ # - Example: "First line\nSecond line" will be properly displayed with a line break on the recipient's device
175
+ # - Special characters like '&' are automatically URL encoded to ensure proper transmission
176
+ # - Long messages will be automatically split into multiple SMS messages if your account doesn't
177
+ # have long message permissions
178
+
179
+ # Send using advanced format (automatically handles 500 message limit)
180
+ response = MitakeSms.advanced_batch_send(messages)
181
+
182
+ # Process response similar to regular batch sending
183
+ if response.is_a?(MitakeSms::Response) && response.success?
184
+ puts "Advanced batch sent successfully!"
185
+ puts "Message ID: #{response.message_id}"
186
+ puts "Remaining points: #{response.account_point}"
187
+ elsif response.is_a?(Array)
188
+ response.each_with_index do |batch_response, index|
189
+ if batch_response.success?
190
+ puts "Batch #{index + 1} sent successfully!"
191
+ else
192
+ puts "Batch #{index + 1} failed: #{batch_response.error}"
193
+ end
194
+ end
195
+ end
196
+ ```
197
+
94
198
  ### Error Handling
95
199
 
96
200
  The gem provides specific error classes for different types of errors:
@@ -26,13 +26,26 @@ module MitakeSms
26
26
  # @option options [String] :from sender ID
27
27
  # @option options [String] :response_url callback URL for delivery reports
28
28
  # @option options [String] :client_id client reference ID
29
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
29
30
  # @return [MitakeSms::Response] response object
30
31
  def send_sms(to, text, options = {})
32
+ require 'uri'
33
+ charset = options.delete(:charset) || 'UTF8'
34
+
35
+ # Replace any newline characters with ASCII code 6 (ACK)
36
+ # This is required by the Mitake API to represent line breaks
37
+ processed_text = text.to_s.gsub("\n", 6.chr)
38
+
39
+ # URL encode the message content to handle special characters like '&'
40
+ # This is required by the Mitake API
41
+ message_text = URI.encode_www_form_component(processed_text)
42
+
31
43
  params = {
32
44
  username: @config.username,
33
45
  password: @config.password,
34
46
  dstaddr: to,
35
- smbody: text.encode('BIG5', invalid: :replace, undef: :replace, replace: '?')
47
+ smbody: message_text,
48
+ CharsetURL: charset
36
49
  }.merge(options.slice(:from, :response_url, :client_id))
37
50
 
38
51
  response = @connection.post('SmSend', params)
@@ -42,22 +55,161 @@ module MitakeSms
42
55
  # Send multiple SMS in a single request
43
56
  # @param messages [Array<Hash>] array of message hashes
44
57
  # Each hash should contain :to and :text keys, and can include :from, :response_url, :client_id
58
+ # @param options [Hash] additional options
59
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
60
+ # @option options [Boolean] :skip_encoding skip URL encoding (for tests)
61
+ # @return [MitakeSms::Response, Array<MitakeSms::Response>] response object or array of response objects if batch was split
62
+ def batch_send(messages, options = {})
63
+ # Mitake SMS API has a limit of 500 messages per request
64
+ # Automatically split larger batches into multiple requests of 500 messages each
65
+ batch_send_with_limit(messages, 500, options)
66
+ end
67
+
68
+ # Send multiple SMS in a single request with a limit per request
69
+ # @param messages [Array<Hash>] array of message hashes
70
+ # Each hash should contain :to and :text keys, and can include :from, :response_url, :client_id
71
+ # @param limit [Integer] maximum number of messages per request (default: 500)
72
+ # @param options [Hash] additional options
73
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
74
+ # @option options [Boolean] :skip_encoding skip URL encoding (for tests)
75
+ # @return [MitakeSms::Response, Array<MitakeSms::Response>] response object or array of response objects if batch was split
76
+ def batch_send_with_limit(messages, limit = 500, options = {})
77
+ charset = options[:charset] || 'UTF8'
78
+
79
+ # If messages count is within the limit, use the regular batch send
80
+ return send_batch(messages, charset, options) if messages.size <= limit
81
+
82
+ # Otherwise, split into batches of the specified limit
83
+ responses = []
84
+ messages.each_slice(limit) do |batch|
85
+ responses << send_batch(batch, charset, options)
86
+ end
87
+
88
+ # Return array of responses
89
+ responses
90
+ end
91
+
92
+ # Send multiple SMS in a single request using advanced format
93
+ # @param messages [Array<Hash>] array of message hashes with advanced options
94
+ # Each hash can contain the following keys:
95
+ # - :client_id [String] client reference ID (required)
96
+ # - :to [String] recipient phone number (required)
97
+ # - :dlvtime [String] delivery time in format YYYYMMDDHHMMSS (optional)
98
+ # - :vldtime [String] valid until time in format YYYYMMDDHHMMSS (optional)
99
+ # - :dest_name [String] recipient name (optional)
100
+ # - :response [String] callback URL for delivery reports (optional)
101
+ # - :text [String] message content (required)
102
+ # @param options [Hash] additional options
103
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
104
+ # @option options [Boolean] :skip_encoding skip URL encoding (for tests)
105
+ # @return [MitakeSms::Response, Array<MitakeSms::Response>] response object or array of response objects if batch was split
106
+ def advanced_batch_send(messages, options = {})
107
+ # Mitake SMS API has a limit of 500 messages per request
108
+ # Automatically split larger batches into multiple requests of 500 messages each
109
+ advanced_batch_send_with_limit(messages, 500, options)
110
+ end
111
+
112
+ # Send multiple SMS in a single request with a limit per request using advanced format
113
+ # @param messages [Array<Hash>] array of message hashes with advanced options
114
+ # @param limit [Integer] maximum number of messages per request (default: 500)
115
+ # @param options [Hash] additional options
116
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
117
+ # @option options [Boolean] :skip_encoding skip URL encoding (for tests)
118
+ # @return [MitakeSms::Response, Array<MitakeSms::Response>] response object or array of response objects if batch was split
119
+ def advanced_batch_send_with_limit(messages, limit = 500, options = {})
120
+ charset = options[:charset] || 'UTF8'
121
+
122
+ # If messages count is within the limit, use the regular batch send
123
+ return send_advanced_batch(messages, charset, options) if messages.size <= limit
124
+
125
+ # Otherwise, split into batches of the specified limit
126
+ responses = []
127
+ messages.each_slice(limit) do |batch|
128
+ responses << send_advanced_batch(batch, charset, options)
129
+ end
130
+
131
+ # Return array of responses
132
+ responses
133
+ end
134
+
135
+ private
136
+
137
+ # Internal method to send a single batch
138
+ # @param batch [Array<Hash>] array of message hashes for a single batch
139
+ # @param charset [String] character encoding, defaults to 'UTF8'
140
+ # @param options [Hash] additional options
45
141
  # @return [MitakeSms::Response] response object
46
- def batch_send(messages)
142
+ def send_batch(batch, charset = 'UTF8', options = {})
143
+ require 'uri'
144
+
47
145
  params = {
48
146
  username: @config.username,
49
147
  password: @config.password,
50
- smbody: messages.map do |msg|
148
+ smbody: batch.map do |msg|
51
149
  to = msg[:to]
52
- text = msg[:text].to_s.encode('BIG5', invalid: :replace, undef: :replace, replace: '?')
53
- "#{to}:#{text}"
54
- end.join("\n")
150
+
151
+ # Replace any newline characters with ASCII code 6 (ACK)
152
+ # This is required by the Mitake API to represent line breaks
153
+ processed_text = msg[:text].to_s.gsub("\n", 6.chr)
154
+
155
+ # URL encode the message content to handle special characters like '&'
156
+ # This is required by the Mitake API
157
+ message_text = URI.encode_www_form_component(processed_text)
158
+
159
+ "#{to}:#{message_text}"
160
+ end.join("\n"),
161
+ Encoding_PostIn: charset
55
162
  }
163
+
56
164
  response = @connection.post('SmBulkSend', params)
57
165
  handle_response(response)
58
166
  end
59
167
 
60
- private
168
+ # Internal method to send a single batch using advanced format
169
+ # @param batch [Array<Hash>] array of message hashes for a single batch with advanced options
170
+ # @param charset [String] character encoding, defaults to 'UTF8'
171
+ # @param options [Hash] additional options
172
+ # @return [MitakeSms::Response] response object
173
+ def send_advanced_batch(batch, charset = 'UTF8', options = {})
174
+ require 'uri'
175
+
176
+ # Format each message according to the advanced format
177
+ # ClientID $$ dstaddr $$ dlvtime $$ vldtime $$ destname $$ response $$ smbody
178
+ body = batch.map do |msg|
179
+ # ClientID is required and must be unique
180
+ # If not provided, generate a unique ID
181
+ client_id = msg[:client_id]
182
+ if client_id.nil? || client_id.empty?
183
+ client_id = generate_unique_client_id
184
+ end
185
+
186
+ to = msg[:to]
187
+ dlvtime = msg[:dlvtime] || ''
188
+ vldtime = msg[:vldtime] || ''
189
+ dest_name = msg[:dest_name] || ''
190
+ response_url = msg[:response] || ''
191
+
192
+ # Replace any newline characters in the message text with ASCII code 6 (ACK)
193
+ # This is required by the Mitake API to represent line breaks within message content
194
+ processed_text = msg[:text].to_s.gsub("\n", 6.chr)
195
+
196
+ # URL encode the message content to handle special characters like '&'
197
+ # This is required by the Mitake API
198
+ text = URI.encode_www_form_component(processed_text)
199
+
200
+ [client_id, to, dlvtime, vldtime, dest_name, response_url, text].join('$$')
201
+ end.join("\n")
202
+
203
+ params = {
204
+ username: @config.username,
205
+ password: @config.password,
206
+ data: body,
207
+ Encoding_PostIn: charset
208
+ }
209
+
210
+ response = @connection.post('SmPost', params)
211
+ handle_response(response)
212
+ end
61
213
 
62
214
  def build_connection
63
215
  Faraday.new(url: @config.api_url) do |conn|
@@ -83,5 +235,16 @@ module MitakeSms
83
235
  raise Error, "Unexpected error: #{response.status}"
84
236
  end
85
237
  end
238
+
239
+ # Generate a unique client ID for SMS messages
240
+ # @return [String] a unique ID combining timestamp and random values
241
+ def generate_unique_client_id
242
+ require 'securerandom'
243
+
244
+ # Generate a unique ID using timestamp (to milliseconds) and a random UUID portion
245
+ timestamp = Time.now.strftime('%Y%m%d%H%M%S%L')
246
+ random_part = SecureRandom.uuid.gsub('-', '')[0, 8]
247
+ "#{timestamp}-#{random_part}"
248
+ end
86
249
  end
87
250
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MitakeSms
4
- VERSION = "1.0.0"
4
+ VERSION = "1.2.0"
5
5
  end
data/lib/mitake_sms.rb CHANGED
@@ -42,17 +42,65 @@ module MitakeSms
42
42
  # @option options [String] :from sender ID
43
43
  # @option options [String] :response_url callback URL for delivery reports
44
44
  # @option options [String] :client_id client reference ID
45
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
46
+
45
47
  # @return [MitakeSms::Response] response object
46
48
  def send_sms(to, text, options = {})
47
49
  client.send_sms(to, text, options)
48
50
  end
49
51
 
50
52
  # Send multiple SMS messages in a single request
53
+ # The Mitake SMS API has a limit of 500 messages per request
54
+ # If more than 500 messages are provided, they will be automatically split into multiple requests
51
55
  # @param messages [Array<Hash>] array of message hashes
52
56
  # Each hash should contain :to and :text keys, and can include :from, :response_url, :client_id
53
- # @return [MitakeSms::Response] response object
54
- def batch_send(messages)
55
- client.batch_send(messages)
57
+ # @param options [Hash] additional options
58
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
59
+
60
+ # @return [MitakeSms::Response, Array<MitakeSms::Response>] response object or array of response objects if batch was split
61
+ def batch_send(messages, options = {})
62
+ client.batch_send_with_limit(messages, 500, options)
63
+ end
64
+
65
+ # Send multiple SMS messages in a single request with a limit per request
66
+ # @param messages [Array<Hash>] array of message hashes
67
+ # Each hash should contain :to and :text keys, and can include :from, :response_url, :client_id
68
+ # @param limit [Integer] maximum number of messages per request (default: 500)
69
+ # @param options [Hash] additional options
70
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
71
+
72
+ # @return [MitakeSms::Response, Array<MitakeSms::Response>] response object or array of response objects if batch was split
73
+ def batch_send_with_limit(messages, limit = 500, options = {})
74
+ client.batch_send_with_limit(messages, limit, options)
75
+ end
76
+
77
+ # Send multiple SMS messages in a single request using advanced format
78
+ # @param messages [Array<Hash>] array of message hashes with advanced options
79
+ # Each hash can contain the following keys:
80
+ # - :client_id [String] client reference ID (optional)
81
+ # - :to [String] recipient phone number (required)
82
+ # - :dlvtime [String] delivery time in format YYYYMMDDHHMMSS (optional)
83
+ # - :vldtime [String] valid until time in format YYYYMMDDHHMMSS (optional)
84
+ # - :dest_name [String] recipient name (optional)
85
+ # - :response [String] callback URL for delivery reports (optional)
86
+ # - :text [String] message content (required)
87
+ # @param options [Hash] additional options
88
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
89
+
90
+ # @return [MitakeSms::Response, Array<MitakeSms::Response>] response object or array of response objects if batch was split
91
+ def advanced_batch_send(messages, options = {})
92
+ client.advanced_batch_send(messages, options)
93
+ end
94
+
95
+ # Send multiple SMS messages in a single request with a limit per request using advanced format
96
+ # @param messages [Array<Hash>] array of message hashes with advanced options
97
+ # @param limit [Integer] maximum number of messages per request (default: 500)
98
+ # @param options [Hash] additional options
99
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
100
+
101
+ # @return [MitakeSms::Response, Array<MitakeSms::Response>] response object or array of response objects if batch was split
102
+ def advanced_batch_send_with_limit(messages, limit = 500, options = {})
103
+ client.advanced_batch_send_with_limit(messages, limit, options)
56
104
  end
57
105
  end
58
106
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mitake_sms
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zac