mitake_sms 1.0.0 → 1.3.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: 42774c4aed1ba07e126a7023b8e2baedf85dc25e53bbeafc4739cff39765d0b3
4
+ data.tar.gz: 978e2c9b36e5cc2a2b79ad6f05b90f360f49c8930f50c5131851eb170a10aaf3
5
5
  SHA512:
6
- metadata.gz: ec120586bd986581175e851ed2a974cc9452ba1e8f964fa59dad0b23a9564671f62d205339d5f82e90d0fcd21f696c115ef4159c60a88d78a6be6255421e36d4
7
- data.tar.gz: 1716857937144e700d23a88445468856cbd67c7bd5e921e2ac32987216f24acaab4ebba161dadd58fbcce9641c11fbcfe6be307a940e315b3f0b803237818363
6
+ metadata.gz: '0859b813573741a6ff71f8339c1a56bb4c625a6acdb0f861b1f2407a5981fce7619cd70580301558b0bac4e682350ccbb6ffb9e35b7a8ff30f45f3f6e80c4992'
7
+ data.tar.gz: 350a37d091491be985e03b736b39ea999e28edf7a90eb5edc378a0119719a343eb3aeb6f4d558a17e1ea9bdb233d886e8aba585f38f1894b62d46f8500c03b30
data/CHANGELOG.md CHANGED
@@ -7,6 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.3.0] - 2025-05-25
11
+ ### Changed
12
+ - Removed automatic URL encoding of message content
13
+ - Simplified message handling by only converting newlines to ASCII code 6
14
+ - Modified tests to match the updated implementation
15
+
16
+ ## [1.2.0] - 2025-05-25
17
+ ### Added
18
+ - Added proper handling of newlines in message text (converts to ASCII code 6)
19
+ - Added URL encoding for message content to handle special characters
20
+ - Added advanced batch SMS format support using ClientID $$ dstaddr $$ dlvtime $$ vldtime $$ destname $$ response $$ smbody
21
+ - Added automatic generation of unique ClientIDs for advanced batch SMS
22
+
23
+ ### Changed
24
+ - Improved message formatting to comply with Mitake API requirements
25
+ - Enhanced test coverage to 92.81%
26
+
27
+ ## [1.1.0] - 2025-05-24
28
+ ### Added
29
+ - Added automatic handling of the 500 message limit for batch SMS sending
30
+ - Added UTF-8 encoding support by default for all SMS messages
31
+ - Added `CharsetURL` parameter for single SMS messages
32
+ - Added `Encoding_PostIn` parameter for batch SMS messages
33
+ - Added ability to customize character encoding via options
34
+
35
+ ### Changed
36
+ - Updated documentation to reflect new encoding options
37
+ - Improved batch sending with automatic splitting of large batches
38
+
10
39
  ## [1.0.0] - 2025-05-24
11
40
  ### Added
12
41
  - 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,22 @@ 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
+
31
39
  params = {
32
40
  username: @config.username,
33
41
  password: @config.password,
34
42
  dstaddr: to,
35
- smbody: text.encode('BIG5', invalid: :replace, undef: :replace, replace: '?')
43
+ smbody: processed_text,
44
+ CharsetURL: charset
36
45
  }.merge(options.slice(:from, :response_url, :client_id))
37
46
 
38
47
  response = @connection.post('SmSend', params)
@@ -42,22 +51,153 @@ module MitakeSms
42
51
  # Send multiple SMS in a single request
43
52
  # @param messages [Array<Hash>] array of message hashes
44
53
  # Each hash should contain :to and :text keys, and can include :from, :response_url, :client_id
54
+ # @param options [Hash] additional options
55
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
56
+ # @option options [Boolean] :skip_encoding skip URL encoding (for tests)
57
+ # @return [MitakeSms::Response, Array<MitakeSms::Response>] response object or array of response objects if batch was split
58
+ def batch_send(messages, options = {})
59
+ # Mitake SMS API has a limit of 500 messages per request
60
+ # Automatically split larger batches into multiple requests of 500 messages each
61
+ batch_send_with_limit(messages, 500, options)
62
+ end
63
+
64
+ # Send multiple SMS in a single request with a limit per request
65
+ # @param messages [Array<Hash>] array of message hashes
66
+ # Each hash should contain :to and :text keys, and can include :from, :response_url, :client_id
67
+ # @param limit [Integer] maximum number of messages per request (default: 500)
68
+ # @param options [Hash] additional options
69
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
70
+ # @option options [Boolean] :skip_encoding skip URL encoding (for tests)
71
+ # @return [MitakeSms::Response, Array<MitakeSms::Response>] response object or array of response objects if batch was split
72
+ def batch_send_with_limit(messages, limit = 500, options = {})
73
+ charset = options[:charset] || 'UTF8'
74
+
75
+ # If messages count is within the limit, use the regular batch send
76
+ return send_batch(messages, charset, options) if messages.size <= limit
77
+
78
+ # Otherwise, split into batches of the specified limit
79
+ responses = []
80
+ messages.each_slice(limit) do |batch|
81
+ responses << send_batch(batch, charset, options)
82
+ end
83
+
84
+ # Return array of responses
85
+ responses
86
+ end
87
+
88
+ # Send multiple SMS in a single request using advanced format
89
+ # @param messages [Array<Hash>] array of message hashes with advanced options
90
+ # Each hash can contain the following keys:
91
+ # - :client_id [String] client reference ID (required)
92
+ # - :to [String] recipient phone number (required)
93
+ # - :dlvtime [String] delivery time in format YYYYMMDDHHMMSS (optional)
94
+ # - :vldtime [String] valid until time in format YYYYMMDDHHMMSS (optional)
95
+ # - :dest_name [String] recipient name (optional)
96
+ # - :response [String] callback URL for delivery reports (optional)
97
+ # - :text [String] message content (required)
98
+ # @param options [Hash] additional options
99
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
100
+ # @option options [Boolean] :skip_encoding skip URL encoding (for tests)
101
+ # @return [MitakeSms::Response, Array<MitakeSms::Response>] response object or array of response objects if batch was split
102
+ def advanced_batch_send(messages, options = {})
103
+ # Mitake SMS API has a limit of 500 messages per request
104
+ # Automatically split larger batches into multiple requests of 500 messages each
105
+ advanced_batch_send_with_limit(messages, 500, options)
106
+ end
107
+
108
+ # Send multiple SMS in a single request with a limit per request using advanced format
109
+ # @param messages [Array<Hash>] array of message hashes with advanced options
110
+ # @param limit [Integer] maximum number of messages per request (default: 500)
111
+ # @param options [Hash] additional options
112
+ # @option options [String] :charset character encoding, defaults to 'UTF8'
113
+ # @option options [Boolean] :skip_encoding skip URL encoding (for tests)
114
+ # @return [MitakeSms::Response, Array<MitakeSms::Response>] response object or array of response objects if batch was split
115
+ def advanced_batch_send_with_limit(messages, limit = 500, options = {})
116
+ charset = options[:charset] || 'UTF8'
117
+
118
+ # If messages count is within the limit, use the regular batch send
119
+ return send_advanced_batch(messages, charset, options) if messages.size <= limit
120
+
121
+ # Otherwise, split into batches of the specified limit
122
+ responses = []
123
+ messages.each_slice(limit) do |batch|
124
+ responses << send_advanced_batch(batch, charset, options)
125
+ end
126
+
127
+ # Return array of responses
128
+ responses
129
+ end
130
+
131
+ private
132
+
133
+ # Internal method to send a single batch
134
+ # @param batch [Array<Hash>] array of message hashes for a single batch
135
+ # @param charset [String] character encoding, defaults to 'UTF8'
136
+ # @param options [Hash] additional options
45
137
  # @return [MitakeSms::Response] response object
46
- def batch_send(messages)
138
+ def send_batch(batch, charset = 'UTF8', options = {})
139
+ require 'uri'
140
+
47
141
  params = {
48
142
  username: @config.username,
49
143
  password: @config.password,
50
- smbody: messages.map do |msg|
144
+ smbody: batch.map do |msg|
51
145
  to = msg[:to]
52
- text = msg[:text].to_s.encode('BIG5', invalid: :replace, undef: :replace, replace: '?')
53
- "#{to}:#{text}"
54
- end.join("\n")
146
+
147
+ # Replace any newline characters with ASCII code 6 (ACK)
148
+ # This is required by the Mitake API to represent line breaks
149
+ processed_text = msg[:text].to_s.gsub("\n", 6.chr)
150
+
151
+ "#{to}:#{processed_text}"
152
+ end.join("\n"),
153
+ Encoding_PostIn: charset
55
154
  }
155
+
56
156
  response = @connection.post('SmBulkSend', params)
57
157
  handle_response(response)
58
158
  end
59
159
 
60
- private
160
+ # Internal method to send a single batch using advanced format
161
+ # @param batch [Array<Hash>] array of message hashes for a single batch with advanced options
162
+ # @param charset [String] character encoding, defaults to 'UTF8'
163
+ # @param options [Hash] additional options
164
+ # @return [MitakeSms::Response] response object
165
+ def send_advanced_batch(batch, charset = 'UTF8', options = {})
166
+ require 'uri'
167
+
168
+ # Format each message according to the advanced format
169
+ # ClientID $$ dstaddr $$ dlvtime $$ vldtime $$ destname $$ response $$ smbody
170
+ body = batch.map do |msg|
171
+ # ClientID is required and must be unique
172
+ # If not provided, generate a unique ID
173
+ client_id = msg[:client_id]
174
+ if client_id.nil? || client_id.empty?
175
+ client_id = generate_unique_client_id
176
+ end
177
+
178
+ to = msg[:to]
179
+ dlvtime = msg[:dlvtime] || ''
180
+ vldtime = msg[:vldtime] || ''
181
+ dest_name = msg[:dest_name] || ''
182
+ response_url = msg[:response] || ''
183
+
184
+ # Replace any newline characters in the message text with ASCII code 6 (ACK)
185
+ # This is required by the Mitake API to represent line breaks within message content
186
+ processed_text = msg[:text].to_s.gsub("\n", 6.chr)
187
+
188
+ [client_id, to, dlvtime, vldtime, dest_name, response_url, processed_text].join('$$')
189
+ end.join("\n")
190
+
191
+ params = {
192
+ username: @config.username,
193
+ password: @config.password,
194
+ data: body,
195
+ Encoding_PostIn: charset
196
+ }
197
+
198
+ response = @connection.post('SmPost', params)
199
+ handle_response(response)
200
+ end
61
201
 
62
202
  def build_connection
63
203
  Faraday.new(url: @config.api_url) do |conn|
@@ -83,5 +223,16 @@ module MitakeSms
83
223
  raise Error, "Unexpected error: #{response.status}"
84
224
  end
85
225
  end
226
+
227
+ # Generate a unique client ID for SMS messages
228
+ # @return [String] a unique ID combining timestamp and random values
229
+ def generate_unique_client_id
230
+ require 'securerandom'
231
+
232
+ # Generate a unique ID using timestamp (to milliseconds) and a random UUID portion
233
+ timestamp = Time.now.strftime('%Y%m%d%H%M%S%L')
234
+ random_part = SecureRandom.uuid.gsub('-', '')[0, 8]
235
+ "#{timestamp}-#{random_part}"
236
+ end
86
237
  end
87
238
  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.3.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.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zac