smbcloud-email 1.0.0-x86_64-linux
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 +7 -0
- data/CHANGELOG.md +8 -0
- data/README.md +68 -0
- data/Rakefile +16 -0
- data/ext/.keep +0 -0
- data/lib/email/3.1/email.so +0 -0
- data/lib/email/3.2/email.so +0 -0
- data/lib/email/3.3/email.so +0 -0
- data/lib/email/3.4/email.so +0 -0
- data/lib/email/4.0/email.so +0 -0
- data/lib/email/version.rb +5 -0
- data/lib/email.rb +132 -0
- data/sig/email.rbs +28 -0
- metadata +77 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: fdfa94e477228e1a9a72921e3019626671bd8e444efbd03977158dbffdcb96e6
|
|
4
|
+
data.tar.gz: bac9c3b12c512b99d386bdf5c1dde38137feb5ced0a292bf90b0f576f6bce0ba
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a29a51de615228acfaed0f405ac9f3d0d67726c8a988723c0dbf1023cd9fd0d2d99426465291aa21156c838006d2e89d72dd2570bba8a8cb579683a272e160c9
|
|
7
|
+
data.tar.gz: cf9230f941020c2ef39a01800e254a9deb8c53db698d820babb4ce3df1d4327a3fd8c418ecaa9ec074b5bb31831d4921dbb90d0097b843a7f4ab20e8a8be1d49
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.4.7] - 2026-06-30
|
|
4
|
+
|
|
5
|
+
- Initial release. Ruby bindings for the smbCloud transactional email API:
|
|
6
|
+
`SmbCloud::Email::Client#send`, `#get_message`, and `#list_messages`,
|
|
7
|
+
powered by the shared Rust SDK (`smbcloud-email-sdk`) via a native Magnus
|
|
8
|
+
extension.
|
data/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# smbcloud-email (Ruby)
|
|
2
|
+
|
|
3
|
+
Ruby bindings for the **smbCloud transactional email API**, powered by the shared
|
|
4
|
+
Rust SDK ([`smbcloud-email-sdk`](../../../crates/smbcloud-email-sdk)) and a native
|
|
5
|
+
[Magnus](https://github.com/matsadler/magnus) extension.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'smbcloud-email'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The gem ships a native extension; `bundle install` compiles it (Rust toolchain
|
|
14
|
+
required).
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
require 'email'
|
|
20
|
+
|
|
21
|
+
client = SmbCloud::Email.client(
|
|
22
|
+
environment: SmbCloud::Email::Environment::PRODUCTION,
|
|
23
|
+
api_key: 'smb_mail_your_key',
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Send
|
|
27
|
+
sent = client.send(
|
|
28
|
+
from: 'billing@example.com',
|
|
29
|
+
to: ['customer@acme.com'],
|
|
30
|
+
subject: 'Your receipt',
|
|
31
|
+
html: '<h1>Thanks!</h1>',
|
|
32
|
+
text: 'Thanks!',
|
|
33
|
+
idempotency_key: 'receipt-2026-0001',
|
|
34
|
+
)
|
|
35
|
+
sent[:id] # => "eml_…"
|
|
36
|
+
sent[:status] # => 1 (sent)
|
|
37
|
+
|
|
38
|
+
# Attachments, cc/bcc, headers, tags
|
|
39
|
+
client.send(
|
|
40
|
+
from: 'billing@example.com',
|
|
41
|
+
to: ['customer@acme.com'],
|
|
42
|
+
subject: 'Invoice',
|
|
43
|
+
html: '<p>See attached.</p>',
|
|
44
|
+
cc: ['accounts@acme.com'],
|
|
45
|
+
attachments: [{ filename: 'invoice.pdf', content_base64: 'JVBERi0xLjQ...' }],
|
|
46
|
+
headers: { 'X-Entity-Ref-ID' => 'inv_123' },
|
|
47
|
+
tags: { 'category' => 'invoice' },
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Delivery status (needs a read-scope key)
|
|
51
|
+
message = client.get_message('eml_…')
|
|
52
|
+
message[:status]
|
|
53
|
+
message[:events]
|
|
54
|
+
|
|
55
|
+
client.list_messages(status: 'bounced', limit: 20)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Mint an API key for your Mail app in the smbCloud console. Sending is scoped to
|
|
59
|
+
that app's verified domain; reading messages needs a read-scope key.
|
|
60
|
+
|
|
61
|
+
## Errors
|
|
62
|
+
|
|
63
|
+
Non-2xx API responses and transport failures raise `SmbCloud::Email::Error`, with
|
|
64
|
+
the parsed response body available on `#payload`.
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
MIT
|
data/Rakefile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/gem_tasks'
|
|
4
|
+
require 'rb_sys/extensiontask'
|
|
5
|
+
|
|
6
|
+
task build: :compile
|
|
7
|
+
|
|
8
|
+
GEMSPEC = Gem::Specification.load('email.gemspec')
|
|
9
|
+
|
|
10
|
+
RbSys::ExtensionTask.new('email', GEMSPEC) do |ext|
|
|
11
|
+
ext.lib_dir = 'lib/email'
|
|
12
|
+
ext.cross_compile = true
|
|
13
|
+
ext.cross_platform = %w[x86_64-linux aarch64-linux arm64-darwin x86_64-darwin]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
task default: :compile
|
data/ext/.keep
ADDED
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/lib/email.rb
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require_relative 'email/version'
|
|
5
|
+
# Fat native gems ship one extension per Ruby minor (lib/email/3.4/email.bundle);
|
|
6
|
+
# source and single-ABI builds put it directly under lib/email/.
|
|
7
|
+
begin
|
|
8
|
+
RUBY_VERSION =~ /(\d+\.\d+)/
|
|
9
|
+
require_relative "email/#{Regexp.last_match(1)}/email"
|
|
10
|
+
rescue LoadError
|
|
11
|
+
require_relative 'email/email'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
module Email
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
module SmbCloud
|
|
18
|
+
# Ruby bindings for the smbCloud transactional email API, powered by the shared
|
|
19
|
+
# Rust SDK (smbcloud-email-sdk) and a native Magnus extension.
|
|
20
|
+
#
|
|
21
|
+
# @example
|
|
22
|
+
# client = SmbCloud::Email.client(environment: "production", api_key: "smb_mail_…")
|
|
23
|
+
# sent = client.send(
|
|
24
|
+
# from: "billing@example.com",
|
|
25
|
+
# to: ["customer@acme.com"],
|
|
26
|
+
# subject: "Your receipt",
|
|
27
|
+
# html: "<h1>Thanks!</h1>",
|
|
28
|
+
# idempotency_key: "receipt-2026-0001",
|
|
29
|
+
# )
|
|
30
|
+
# sent[:id] # => "eml_…"
|
|
31
|
+
module Email
|
|
32
|
+
class Error < StandardError
|
|
33
|
+
attr_reader :payload
|
|
34
|
+
|
|
35
|
+
def initialize(message = nil, payload: nil)
|
|
36
|
+
super(message)
|
|
37
|
+
@payload = payload
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
module Environment
|
|
42
|
+
DEV = 'dev'
|
|
43
|
+
PRODUCTION = 'production'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class Client
|
|
47
|
+
attr_reader :environment, :api_key
|
|
48
|
+
|
|
49
|
+
def initialize(environment:, api_key:)
|
|
50
|
+
@environment = environment
|
|
51
|
+
@api_key = api_key
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Send a transactional email. `from` must be on the API key's verified
|
|
55
|
+
# domain; provide at least one of `html`/`text`. `attachments` is an array
|
|
56
|
+
# of { filename:, content_base64: }. Returns the created message hash.
|
|
57
|
+
def send(from:, to:, subject: nil, html: nil, text: nil, cc: nil, bcc: nil,
|
|
58
|
+
reply_to: nil, attachments: nil, headers: nil, tags: nil,
|
|
59
|
+
idempotency_key: nil)
|
|
60
|
+
message = {
|
|
61
|
+
from: from,
|
|
62
|
+
to: Array(to),
|
|
63
|
+
cc: Array(cc),
|
|
64
|
+
bcc: Array(bcc),
|
|
65
|
+
reply_to: Array(reply_to),
|
|
66
|
+
subject: subject,
|
|
67
|
+
html: html,
|
|
68
|
+
text: text,
|
|
69
|
+
attachments: Array(attachments),
|
|
70
|
+
headers: headers || {},
|
|
71
|
+
tags: tags || {},
|
|
72
|
+
idempotency_key: idempotency_key
|
|
73
|
+
}.compact
|
|
74
|
+
|
|
75
|
+
Email.send(:parse_json, Email.__send(environment, api_key, JSON.generate(message)))
|
|
76
|
+
rescue RuntimeError => e
|
|
77
|
+
raise Email.send(:normalize_error, e)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Fetch one message by id, including its delivery-event timeline. Requires
|
|
81
|
+
# a read-scope key.
|
|
82
|
+
def get_message(id)
|
|
83
|
+
Email.send(:parse_json, Email.__get_message(environment, api_key, id))
|
|
84
|
+
rescue RuntimeError => e
|
|
85
|
+
raise Email.send(:normalize_error, e)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# List recent messages. `status` filters by delivery status name; `limit`
|
|
89
|
+
# is clamped server-side to 1..=100. Requires a read-scope key.
|
|
90
|
+
def list_messages(status: nil, limit: nil)
|
|
91
|
+
Email.send(:parse_json,
|
|
92
|
+
Email.__list_messages(environment, api_key, status.to_s, limit.to_i))
|
|
93
|
+
rescue RuntimeError => e
|
|
94
|
+
raise Email.send(:normalize_error, e)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class << self
|
|
99
|
+
def client(environment:, api_key:)
|
|
100
|
+
Client.new(environment:, api_key:)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def send_with_client(environment:, api_key:, **kwargs)
|
|
104
|
+
client(environment:, api_key:).send(**kwargs)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def get_message_with_client(environment:, api_key:, id:)
|
|
108
|
+
client(environment:, api_key:).get_message(id)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def list_messages_with_client(environment:, api_key:, status: nil, limit: nil)
|
|
112
|
+
client(environment:, api_key:).list_messages(status:, limit:)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
def parse_json(payload)
|
|
118
|
+
return payload unless payload.is_a?(String)
|
|
119
|
+
|
|
120
|
+
JSON.parse(payload, symbolize_names: true)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def normalize_error(error)
|
|
124
|
+
payload = parse_json(error.message)
|
|
125
|
+
message = payload.is_a?(Hash) ? (payload[:message] || error.message) : error.message
|
|
126
|
+
Error.new(message, payload: payload)
|
|
127
|
+
rescue JSON::ParserError, NoMethodError, TypeError
|
|
128
|
+
Error.new(error.message)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
data/sig/email.rbs
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Email
|
|
2
|
+
VERSION: String
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
module SmbCloud
|
|
6
|
+
module Email
|
|
7
|
+
class Error < StandardError
|
|
8
|
+
attr_reader payload: untyped
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module Environment
|
|
12
|
+
DEV: String
|
|
13
|
+
PRODUCTION: String
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Client
|
|
17
|
+
attr_reader environment: String
|
|
18
|
+
attr_reader api_key: String
|
|
19
|
+
|
|
20
|
+
def initialize: (environment: String, api_key: String) -> void
|
|
21
|
+
def send: (from: String, to: untyped, ?subject: String?, ?html: String?, ?text: String?, ?cc: untyped, ?bcc: untyped, ?reply_to: untyped, ?attachments: untyped, ?headers: untyped, ?tags: untyped, ?idempotency_key: String?) -> Hash[Symbol, untyped]
|
|
22
|
+
def get_message: (String) -> Hash[Symbol, untyped]
|
|
23
|
+
def list_messages: (?status: String?, ?limit: Integer?) -> Array[Hash[Symbol, untyped]]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.client: (environment: String, api_key: String) -> Client
|
|
27
|
+
end
|
|
28
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: smbcloud-email
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: x86_64-linux
|
|
6
|
+
authors:
|
|
7
|
+
- Seto Elkahfi
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-10-31 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: json
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
description: Send transactional email from a verified domain and read delivery status,
|
|
28
|
+
powered by the shared Rust SDK and a native Magnus extension.
|
|
29
|
+
email:
|
|
30
|
+
- seto@smbcloud.xyz
|
|
31
|
+
executables: []
|
|
32
|
+
extensions: []
|
|
33
|
+
extra_rdoc_files: []
|
|
34
|
+
files:
|
|
35
|
+
- CHANGELOG.md
|
|
36
|
+
- README.md
|
|
37
|
+
- Rakefile
|
|
38
|
+
- ext/.keep
|
|
39
|
+
- lib/email.rb
|
|
40
|
+
- lib/email/3.1/email.so
|
|
41
|
+
- lib/email/3.2/email.so
|
|
42
|
+
- lib/email/3.3/email.so
|
|
43
|
+
- lib/email/3.4/email.so
|
|
44
|
+
- lib/email/4.0/email.so
|
|
45
|
+
- lib/email/version.rb
|
|
46
|
+
- sig/email.rbs
|
|
47
|
+
homepage: https://github.com/smbcloudXYZ/smbcloud-cli/tree/main/sdk/gems/email
|
|
48
|
+
licenses:
|
|
49
|
+
- MIT
|
|
50
|
+
metadata:
|
|
51
|
+
allowed_push_host: https://rubygems.org
|
|
52
|
+
homepage_uri: https://github.com/smbcloudXYZ/smbcloud-cli/tree/main/sdk/gems/email
|
|
53
|
+
source_code_uri: https://github.com/smbcloudXYZ/smbcloud-cli/tree/main/sdk/gems/email
|
|
54
|
+
changelog_uri: https://github.com/smbcloudXYZ/smbcloud-cli/tree/main/sdk/gems/email/CHANGELOG.md
|
|
55
|
+
post_install_message:
|
|
56
|
+
rdoc_options: []
|
|
57
|
+
require_paths:
|
|
58
|
+
- lib
|
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
60
|
+
requirements:
|
|
61
|
+
- - ">="
|
|
62
|
+
- !ruby/object:Gem::Version
|
|
63
|
+
version: '3.1'
|
|
64
|
+
- - "<"
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: 4.1.dev
|
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: 3.3.11
|
|
72
|
+
requirements: []
|
|
73
|
+
rubygems_version: 3.5.23
|
|
74
|
+
signing_key:
|
|
75
|
+
specification_version: 4
|
|
76
|
+
summary: Ruby bindings for the smbCloud transactional email API.
|
|
77
|
+
test_files: []
|