mailkube 1.1.0 → 1.2.1

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: 62f56b63852a247583a1bbb34cbe7f816ecfdfcbbaf672281b1e4396a697c8e7
4
- data.tar.gz: c12d752ba809c48b7d7cf6d1cade536b839be61279d2109d2320c96ee187c3bb
3
+ metadata.gz: afd85d0c480e7cff16fd2df6344b221acf946f644e97e7f9d7b33f2472ac5c51
4
+ data.tar.gz: 32f66b35b8f0e9631ca737ffcc1c51b6e1b98be6746f9a1d4019c623ce24e9ff
5
5
  SHA512:
6
- metadata.gz: 3dd9768193d7ca0a700cdb6d6af906ddb33533adc9182de122be1debb9617cf000899b0102e396549cf55c19e1c3df26ec9d6cf8f94d8b15f676fcede3841f9b
7
- data.tar.gz: b5daed405e91f130357dd2a65e5e03284f5616d2676ce6b0d4eb53adff715a004f07594d6e70d051aa9681e1fe8aebbfff4da0f477222a99307cbd2fff900f3b
6
+ metadata.gz: e7d1a7c1e83031bbd5fca5533ecff6635361726c401b20112e856d3b62ca62211764c3498501a36d9907a6de7a2b9d0d0304d0002a725f4f4c8c013c6e3a35d0
7
+ data.tar.gz: 9c7ecae8c33e302db1a539d4fbc88ec46bd1b3edf60cda62820e7b4d3ae8d499d67f116736bec04a6445f50692dc3b7a76d108b2e209e9faa983eac9890a1a17
data/LICENSE CHANGED
@@ -186,7 +186,7 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright 2026 Mailtactic, Corp.
189
+ Copyright 2026 Mail Tactic Corporation
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
data/NOTICE CHANGED
@@ -1,11 +1,8 @@
1
1
  mailkube-ruby
2
- Copyright 2026 Mailtactic, Corp.
2
+ Copyright 2026 Mail Tactic Corporation
3
3
 
4
4
  This product is licensed under the Apache License, Version 2.0 (the "License");
5
5
  you may not use this product except in compliance with the License. You may
6
6
  obtain a copy of the License at:
7
7
 
8
8
  http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- "mailkube" is a trademark of Mailtactic, Corp. Use of the name is governed by
11
- Section 6 (Trademarks) of the License.
data/README.md CHANGED
@@ -240,6 +240,12 @@ implement it.
240
240
  Every `email.*` payload also carries the message context: `email_id`, `created_at`, `domain`,
241
241
  `subject`, `to`, `from` and `tags`.
242
242
 
243
+ On the `data.open` and `data.click` blocks, `ip_address`, `country` and `user_agent` are recorded
244
+ only where the sending domain has elected them, and both settings are off by default. The server
245
+ omits the key rather than sending an empty value, so the accessor returns `nil` when it was not
246
+ recorded. `country` can be `nil` even where the address was recorded, because it is resolved at the
247
+ edge and is not available on every path.
248
+
243
249
  Two guarantees hold for every released version, so a platform change never breaks a running
244
250
  receiver:
245
251
 
@@ -336,4 +342,4 @@ must pass. Security issues: see [SECURITY.md](SECURITY.md).
336
342
 
337
343
  ## License
338
344
 
339
- [Apache-2.0](LICENSE) © 2026 Mailtactic, Corp.
345
+ [Apache-2.0](LICENSE) © 2026 Mail Tactic Corporation
@@ -63,10 +63,19 @@ module Mailkube
63
63
  # These nested keys are camelCase on the wire, unlike every other block here. The SDK mirrors
64
64
  # the server rather than normalizing it.
65
65
  class EngagementContext < Node
66
- # @return [String] the opening client's IP address (wire key `ipAddress`).
66
+ # The three connection accessors return nil unless the sending domain elected to record the
67
+ # field, which is off by default. The server omits the key rather than sending a blank, so
68
+ # nil here means "the sender did not record this" and never "the sender recorded an empty
69
+ # value".
70
+ #
71
+ # @return [String, nil] the opening client's IP address (wire key `ipAddress`).
67
72
  def ip_address = self["ipAddress"]
68
- # @return [String] the opening client's user agent (wire key `userAgent`).
73
+ # @return [String, nil] the opening client's user agent (wire key `userAgent`).
69
74
  def user_agent = self["userAgent"]
75
+ # Elected together with {#ip_address}, but can still be nil when the address was recorded:
76
+ # it is resolved at the edge and is not available on every path.
77
+ # @return [String, nil] the two-letter country the address resolves to.
78
+ def country = self["country"]
70
79
  # @return [String] when the interaction was recorded.
71
80
  def timestamp = self["timestamp"]
72
81
  end
@@ -11,5 +11,5 @@ module Mailkube
11
11
  # semantic-release rewrites this line **in the release runner** just before the gem is built, and
12
12
  # commits nothing back to `main` (see `.rules/RELEASE.md`). So a checkout reports `0.0.0` and an
13
13
  # installed gem reports the real version: that is intended, not a bug to fix by hardcoding one.
14
- VERSION = "1.1.0"
14
+ VERSION = "1.2.1"
15
15
  end
@@ -15,8 +15,15 @@ module Mailkube
15
15
  # The prefix the server puts before the hex digest in `X-Webhook-Sig`.
16
16
  SIGNATURE_PREFIX = "sha256="
17
17
  # Decode webhook payloads deep-frozen, so a receiver cannot mutate an event it is about to
18
- # forward or log. Passed **positionally** because that is the shape `JSON.parse` declares
19
- # (`(source, opts)`); as keywords Steep reports an unexpected keyword.
18
+ # forward or log. Splatted as **keywords** at the call site, because json 3.0 made every
19
+ # `JSON.parse` option keyword-only: a positional hash now raises `ArgumentError`, and it is
20
+ # not coming back (ruby/json#1078 is closed as "not planned" — only `JSON.dump`'s positional
21
+ # `limit` was restored, in 3.0.1).
22
+ #
23
+ # The splat is also the compatible direction, which is why there is no `json` floor in the
24
+ # gemspec and the gem stays stdlib-only: json 2.x declares `(source, opts = nil)`, and Ruby
25
+ # collects keywords into the trailing positional Hash for a method that declares none. One
26
+ # call site, both majors. Verified against json 2.21.2 and 3.0.2 on Ruby 3.4.
20
27
  PARSE_OPTIONS = { freeze: true }.freeze
21
28
 
22
29
  # Verify a webhook's signature and timestamp freshness over the raw body.
@@ -65,7 +72,7 @@ module Mailkube
65
72
  # @return [Events::Event] the parsed event; narrow it with `case` or `is_a?`.
66
73
  # @raise [Error] when the body is not a JSON object.
67
74
  def self.parse_event(payload)
68
- body = JSON.parse(payload, PARSE_OPTIONS)
75
+ body = JSON.parse(payload, **PARSE_OPTIONS)
69
76
  raise Error, "webhook payload is not a JSON object" unless body.is_a?(Hash)
70
77
 
71
78
  Events::REGISTRY.fetch(body["type"], Events::UnknownEvent).new(body)
@@ -22,8 +22,9 @@ module Mailkube
22
22
  end
23
23
 
24
24
  class EngagementContext < Node
25
- def ip_address: () -> String
26
- def user_agent: () -> String
25
+ def ip_address: () -> String?
26
+ def user_agent: () -> String?
27
+ def country: () -> String?
27
28
  def timestamp: () -> String
28
29
  end
29
30
 
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mailkube
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
- - Mailtactic, Corp.
7
+ - Mail Tactic Corporation
8
8
  bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z