openemail 0.0.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.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +183 -0
  3. data/lib/openemail/api_paths.rb +249 -0
  4. data/lib/openemail/client.rb +69 -0
  5. data/lib/openemail/constants.rb +851 -0
  6. data/lib/openemail/credentials.rb +53 -0
  7. data/lib/openemail/decode.rb +34 -0
  8. data/lib/openemail/defaults.rb +111 -0
  9. data/lib/openemail/endpoint.rb +144 -0
  10. data/lib/openemail/errors.rb +121 -0
  11. data/lib/openemail/http.rb +172 -0
  12. data/lib/openemail/languages.rb +42 -0
  13. data/lib/openemail/pagination.rb +63 -0
  14. data/lib/openemail/protocol.rb +169 -0
  15. data/lib/openemail/raw_body.rb +83 -0
  16. data/lib/openemail/request_path.rb +50 -0
  17. data/lib/openemail/resource.rb +70 -0
  18. data/lib/openemail/resources/account.rb +64 -0
  19. data/lib/openemail/resources/addresses.rb +38 -0
  20. data/lib/openemail/resources/analytics.rb +17 -0
  21. data/lib/openemail/resources/app_host.rb +23 -0
  22. data/lib/openemail/resources/audiences.rb +90 -0
  23. data/lib/openemail/resources/billing.rb +64 -0
  24. data/lib/openemail/resources/branding.rb +24 -0
  25. data/lib/openemail/resources/broadcasts.rb +65 -0
  26. data/lib/openemail/resources/calendar.rb +59 -0
  27. data/lib/openemail/resources/chats.rb +31 -0
  28. data/lib/openemail/resources/contacts.rb +111 -0
  29. data/lib/openemail/resources/dns_connections.rb +19 -0
  30. data/lib/openemail/resources/domains.rb +153 -0
  31. data/lib/openemail/resources/drafts.rb +35 -0
  32. data/lib/openemail/resources/emails.rb +100 -0
  33. data/lib/openemail/resources/encryption.rb +19 -0
  34. data/lib/openemail/resources/exports.rb +27 -0
  35. data/lib/openemail/resources/files.rb +95 -0
  36. data/lib/openemail/resources/forms.rb +111 -0
  37. data/lib/openemail/resources/imports.rb +86 -0
  38. data/lib/openemail/resources/keys.rb +127 -0
  39. data/lib/openemail/resources/labels.rb +39 -0
  40. data/lib/openemail/resources/languages.rb +11 -0
  41. data/lib/openemail/resources/me.rb +19 -0
  42. data/lib/openemail/resources/members.rb +74 -0
  43. data/lib/openemail/resources/provider_imports.rb +40 -0
  44. data/lib/openemail/resources/roles.rb +39 -0
  45. data/lib/openemail/resources/rules.rb +57 -0
  46. data/lib/openemail/resources/security.rb +19 -0
  47. data/lib/openemail/resources/senders.rb +15 -0
  48. data/lib/openemail/resources/settings.rb +16 -0
  49. data/lib/openemail/resources/subscriptions.rb +30 -0
  50. data/lib/openemail/resources/support.rb +11 -0
  51. data/lib/openemail/resources/suppressions.rb +31 -0
  52. data/lib/openemail/resources/temp_mail.rb +67 -0
  53. data/lib/openemail/resources/templates.rb +151 -0
  54. data/lib/openemail/resources/threads.rb +104 -0
  55. data/lib/openemail/resources/tools.rb +19 -0
  56. data/lib/openemail/resources/tracking.rb +63 -0
  57. data/lib/openemail/resources/webhooks.rb +142 -0
  58. data/lib/openemail/resources/workspaces.rb +28 -0
  59. data/lib/openemail/results.rb +33 -0
  60. data/lib/openemail/transport.rb +272 -0
  61. data/lib/openemail/update_notice.rb +69 -0
  62. data/lib/openemail/version.rb +5 -0
  63. data/lib/openemail/webhook.rb +82 -0
  64. data/lib/openemail/wire.rb +95 -0
  65. data/lib/openemail.rb +125 -0
  66. metadata +109 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b529e237ea6cc98204574ecf5b0b0b58fb7e774cd18ed07ac265ec243885fe1c
4
+ data.tar.gz: 26844441518ca76d25b0908248924119c0528f56bf874b919c6f4a8dd1942e2d
5
+ SHA512:
6
+ metadata.gz: b6236ffe92657e77e6478042d728023a16826bbc194b70178d7cdb809815ef577bae64b62d1ada664760ad4f0a3771a04a2b993254a43bccceb9db541680c9bd
7
+ data.tar.gz: 871936c1946ea670dd8728a4651295114be58d11328307ba9bc298eb9b6c556793cb8112d932fe3a0958eb429f0c38721cd7072cc35fb8e2cf7d0f36fc033f47
data/README.md ADDED
@@ -0,0 +1,183 @@
1
+ <div align='center'>
2
+ <a href='https://openemail.uk'>
3
+ <img
4
+ src='https://openemail.uk/logo.svg'
5
+ alt='OpenEmail Logo'
6
+ width='180'
7
+ />
8
+ </a>
9
+
10
+ <br />
11
+ </div>
12
+
13
+ <p align='center'>
14
+ Email you can build on. Send mail, read the mailbox and automate a workspace from Ruby.
15
+ </p>
16
+
17
+ <p align='center'>
18
+ <a href='https://openemail.uk'><b>Website</b></a>
19
+ •
20
+ <a href='https://openemail.uk/docs/ruby'><b>Documentation</b></a>
21
+ •
22
+ <a href='https://openemail.uk/docs/ruby/reference/methods'><b>Every method</b></a>
23
+ •
24
+ <a href='https://openemail.uk/docs/api/reference'><b>API Reference</b></a>
25
+ </p>
26
+
27
+ <br />
28
+
29
+ ## The Ruby gem
30
+
31
+ The official Ruby client for the OpenEmail API. It has one method for every method of the TypeScript SDK, under the same names in snake_case, and a parity check proves that each one sends the same request. It needs Ruby 3.2 or later and has no runtime dependencies: the HTTP client is Net::HTTP from the standard library, with a pool of kept-alive connections that one client shares safely across threads and that is rebuilt after a fork.
32
+
33
+ It carries a workspace API key or an OAuth access token, so it belongs on a server, in a job or in a tool that runs on your own machine.
34
+
35
+ ### Installing
36
+ ```bash
37
+ bundle add openemail
38
+ ```
39
+
40
+ Or `gem install openemail` without Bundler.
41
+
42
+ ### Using
43
+ ```ruby
44
+ require "openemail"
45
+
46
+ client = OpenEmail::Client.new(api_key: ENV.fetch("OPENEMAIL_API_KEY"))
47
+
48
+ sent = client.emails.send(
49
+ from: "Acme Billing <billing@acme.com>",
50
+ to: "ada@example.com",
51
+ subject: "Your September invoice",
52
+ html: "<p>Your invoice is attached.</p>",
53
+ attachments: [{filename: "invoice.pdf", content: File.binread("invoice.pdf"), contentType: "application/pdf"}]
54
+ )
55
+
56
+ puts sent[:id], sent[:status]
57
+ ```
58
+
59
+ Create a key in OpenEmail under Settings, API keys. It is shown once, and it belongs in an environment variable or your credentials store rather than in code.
60
+
61
+ A request body goes in as keyword arguments or as one Hash, and its keys keep the API's names, so `replyTo:`, `scheduledAt:` and `contentType:` stay camelCase. Options of the call itself are snake_case: `idempotency_key:`, `api_key:`, `limit:`, `cursor:`. What comes back is the parsed JSON as a Hash with Symbol keys, read with `sent[:id]`.
62
+
63
+ Or skip building a client. `OpenEmail.emails`, `OpenEmail.threads` and every other namespace use a shared client built from `OPENEMAIL_API_KEY` the first time one is touched:
64
+
65
+ ```ruby
66
+ OpenEmail.emails.send(from: "hello@acme.com", to: "ada@example.com", subject: "Welcome", text: "Glad you are here.")
67
+ ```
68
+
69
+ Every send carries an idempotency key, generated once per call and reused by its retries, so a retried request replays the original message rather than sending a second one. Pass your own with `idempotency_key:` to make that hold across processes and restarts.
70
+
71
+ ### Reading the mailbox
72
+ ```ruby
73
+ page = client.threads.list(folder: "inbox", limit: 25)
74
+ page.items.each { |thread| puts thread[:subject] }
75
+
76
+ client.threads.iterate(folder: "inbox", query: "invoice") do |thread|
77
+ full = client.threads.get(thread[:id])
78
+ puts full[:messageCount], full[:hasUnread]
79
+ end
80
+ ```
81
+
82
+ Every paginated resource has `list` for one page (an `OpenEmail::Page` with `items`, `has_more?` and `next_cursor`), `list_all` for every page at once as an Array, and `iterate`, which yields each item to a block, or without one returns an Enumerator that fetches the next page only when it gets there, so `first(10)` stops early. `addresses.list_all` is the exception and returns the whole address book.
83
+
84
+ ### Errors
85
+ ```ruby
86
+ template = "order-shipped"
87
+
88
+ begin
89
+ client.templates.send(template, from: "dispatch@acme.com", to: "ada@example.com", props: {orderId: "AC-4192"})
90
+ rescue OpenEmail::ValidationError => error
91
+ warn [error.code, error.param, error.request_id].join(" ")
92
+ raise
93
+ end
94
+ ```
95
+
96
+ An API refusal raises an `OpenEmail::ApiError`, or the subclass for its type: `AuthenticationError`, `PermissionError`, `NotFoundError`, `ConflictError`, `ValidationError`, `RateLimitError` or `InvalidRequestError`. Each carries `status`, `type`, `code`, `param`, `request_id` and `body`, plus `validation?`, `not_found?`, `rate_limited?` and friends to branch on. No response at all raises `OpenEmail::NetworkError`, with `timeout?` when the deadline passed. A mistake in the call itself, such as a malformed key or an empty id, raises `ArgumentError` before anything is sent.
97
+
98
+ ### Webhooks
99
+ ```ruby
100
+ class OpenEmailWebhooksController < ActionController::API
101
+ def create
102
+ event = OpenEmail.verify_webhook_signature(
103
+ payload: request.raw_post,
104
+ headers: request.headers,
105
+ secret: Rails.application.credentials.openemail_webhook_secret
106
+ )
107
+
108
+ Rails.logger.info("#{event[:type]} #{event[:data]}")
109
+ head :no_content
110
+ rescue OpenEmail::WebhookSignatureError
111
+ head :bad_request
112
+ end
113
+ end
114
+ ```
115
+
116
+ It checks the HMAC in constant time and rejects a delivery more than five minutes old, then returns the parsed event. Pass the raw body: a parsed or re-encoded body no longer matches its signature. The headers can be a Hash in any case, a Rack env or Rails' `request.headers`.
117
+
118
+ ### Disposable inboxes
119
+ ```ruby
120
+ temp_mail = OpenEmail.create_temp_mail
121
+
122
+ inbox = temp_mail.create(ttlMinutes: 60)
123
+
124
+ page = temp_mail.list_messages(inbox[:id], inbox_token: inbox[:token])
125
+ ```
126
+
127
+ `create` needs no credential and is the only call that returns the inbox token, so keep it.
128
+
129
+ ### OAuth access tokens
130
+ An app a person connected to OpenEmail with OAuth, such as a command line tool or an agent, holds an access token rather than an API key. Pass it as `access_token:`, either the token itself or anything that responds to `call` and returns it:
131
+
132
+ ```ruby
133
+ client = OpenEmail::Client.new(access_token: -> { session.fresh_access_token })
134
+ ```
135
+
136
+ The callable runs before every request, so renew the token there when it is close to expiring and the client never has to be rebuilt. Pass `api_key:` or `access_token:`, not both. `OpenEmail.create_client` reads `OPENEMAIL_ACCESS_TOKEN` when you pass neither and `OPENEMAIL_API_KEY` is not set.
137
+
138
+ A token acts for a person, so before a sensitive change, such as deleting a domain or changing a webhook, it is asked for the same verification code the web app asks for. The request raises with `step_up_required?`. Ask for a code, check it, then replay the request:
139
+
140
+ ```ruby
141
+ begin
142
+ client.domains.delete(domain_id)
143
+ rescue OpenEmail::ApiError => error
144
+ raise unless error.step_up_required?
145
+
146
+ challenge = client.security.begin_step_up
147
+ code = ask(challenge[:method] == "email" ? "Enter the code we emailed to #{challenge[:sentTo]}" : "Enter the code from your authenticator app")
148
+
149
+ client.security.verify_step_up(code:)
150
+ client.domains.delete(domain_id)
151
+ end
152
+ ```
153
+
154
+ API keys are never asked for a code.
155
+
156
+ ### Configuring
157
+ ```ruby
158
+ client = OpenEmail::Client.new(
159
+ api_key: ENV.fetch("OPENEMAIL_API_KEY"),
160
+ base_url: "https://api.openemail.uk",
161
+ timeout: 30,
162
+ max_retries: 2,
163
+ headers: {"X-Team" => "billing"}
164
+ )
165
+ ```
166
+
167
+ `OpenEmail.create_client(...)` takes the same options and reads what you leave out from the environment: `OPENEMAIL_API_KEY`, then `OPENEMAIL_ACCESS_TOKEN`, and `OPENEMAIL_BASE_URL`, where a bare host such as `localhost:2222` gets its scheme added. `OpenEmail.init(...)` does the same for the shared client.
168
+
169
+ Use an `https:` origin: the client refuses to send an API key, an access token or an inbox token over plain `http:` unless the server is on this machine, at `localhost`, a `127.x.x.x` address or `::1`. A `base_url` on `0.0.0.0` raises when the client is built, since that is the address a server listens on: use `127.0.0.1` with the same port. `timeout:` is in seconds and bounds a whole attempt, 0 turns it off, and uploads wait at least ten minutes. Reads, sends and every write that is safe to repeat are retried on 408, 500, 502, 503 and 504 with backoff, and on a 429 only when it carries a `Retry-After` of a minute or less. Any other write is never retried. Every method takes `api_key:` to act with another key for one call, so one process can serve several workspaces with one client, and the `temp_mail` methods take `inbox_token:` instead. `HTTPS_PROXY` and `NO_PROXY` are honoured.
170
+
171
+ An endpoint no method wraps yet is one `client.raw.request` away, with the client's credential, base URL, timeout and retry policy applied:
172
+
173
+ ```ruby
174
+ client.raw.request("/something-new", method: :post, body: {name: "Invoices"})
175
+ ```
176
+
177
+ The path must begin with a single `/`, and a path whose finished URL leaves the base URL's origin raises before a request is sent, so the credential never reaches another host.
178
+
179
+ `adapter:` swaps the HTTP layer for anything that responds to `call(request)` and returns an `OpenEmail::HttpResponse`, which is how a test drives the client without a network.
180
+
181
+ When a newer version is on RubyGems the client says so once on a TTY. `OPENEMAIL_DISABLE_UPDATE_NOTICE=1` or `disable_update_notice: true` turns that off.
182
+
183
+ Everything else, from templates, rules, tracking, calendar, contacts, audiences and broadcasts to roles, members, settings, mailbox imports and provider imports, plus the full reference for every method, lives in the [documentation](https://openemail.uk/docs/ruby). What changed in each release is in the [changelog](https://openemail.uk/docs/ruby/changelog).
@@ -0,0 +1,249 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenEmail
4
+ module ApiPaths
5
+ ACCOUNT_CONNECTED_APP = "/account/connected-apps/:clientId"
6
+ ACCOUNT_CONNECTED_APPS = "/account/connected-apps"
7
+ ACCOUNT_INVITATIONS = "/account/invitations"
8
+ ACCOUNT_INVITATION_ACCEPT = "/account/invitations/:invitationId/accept"
9
+ ACCOUNT_INVITATION_DECLINE = "/account/invitations/:invitationId/decline"
10
+ ACCOUNT_NOTIFICATIONS = "/account/notifications"
11
+ ACCOUNT_NOTIFICATION_EMAIL = "/account/notifications/email/:category"
12
+ ACCOUNT_NOTIFICATION_PUSH = "/account/notifications/push/:workspaceId"
13
+ ACCOUNT_PHOTO = "/account/photo"
14
+ ACCOUNT_USERNAME = "/account/username"
15
+ ACCOUNT_USERNAME_AVAILABILITY = "/account/username/availability"
16
+ ADDRESSES = "/addresses"
17
+ ANALYTICS_MAILBOX = "/analytics/mailbox"
18
+ ANALYTICS_SENDING = "/analytics/sending"
19
+ APP_HOST = "/app-host"
20
+ APP_HOST_VERIFY = "/app-host/verify"
21
+ AUDIENCE = "/audiences/:id"
22
+ AUDIENCES = "/audiences"
23
+ AUDIENCES_GROWTH = "/audiences/growth"
24
+ AUDIENCE_CONTACT = "/audiences/:id/contacts/:email"
25
+ AUDIENCE_CONTACTS = "/audiences/:id/contacts"
26
+ AUDIENCE_CONTACTS_BATCH = "/audiences/:id/contacts/batch"
27
+ AUDIENCE_CONTACTS_BATCH_REMOVE = "/audiences/:id/contacts/batch-remove"
28
+ AUDIENCE_EMPTY = "/audiences/:id/empty"
29
+ AUDIENCE_IMPORT = "/audiences/:id/import"
30
+ BILLING = "/billing"
31
+ BILLING_ALERTS = "/billing/alerts"
32
+ BILLING_CHECKOUT = "/billing/checkout"
33
+ BILLING_COUNTRIES = "/billing/countries"
34
+ BILLING_INVOICE = "/billing/invoices/:orderId"
35
+ BILLING_INVOICES = "/billing/invoices"
36
+ BILLING_INVOICE_DETAILS = "/billing/invoices/:orderId/details"
37
+ BILLING_PAY_AS_YOU_GO = "/billing/pay-as-you-go"
38
+ BILLING_PAY_AS_YOU_GO_CONFIRM = "/billing/pay-as-you-go/confirm"
39
+ BILLING_PAY_AS_YOU_GO_LIMIT = "/billing/pay-as-you-go/limit"
40
+ BILLING_PLANS = "/billing/plans"
41
+ BILLING_PORTAL = "/billing/portal"
42
+ BILLING_USAGE = "/billing/usage"
43
+ BRANDING = "/branding"
44
+ BRANDING_IMAGE = "/branding/images/:variant"
45
+ BROADCAST = "/broadcasts/:id"
46
+ BROADCASTS = "/broadcasts"
47
+ BROADCASTS_ANALYTICS = "/broadcasts/analytics"
48
+ BROADCASTS_PREVIEW = "/broadcasts/preview"
49
+ BROADCAST_CANCEL = "/broadcasts/:id/cancel"
50
+ BROADCAST_RECIPIENT = "/broadcasts/:id/recipients/:emailId"
51
+ BROADCAST_RECIPIENTS = "/broadcasts/:id/recipients"
52
+ BROADCAST_STATS = "/broadcasts/:id/stats"
53
+ CALENDAR_EVENT = "/calendar/events/:id"
54
+ CALENDAR_EVENTS = "/calendar/events"
55
+ CALENDAR_EVENT_CANCEL = "/calendar/events/:id/cancel"
56
+ CALENDAR_EVENT_ICS = "/calendar/events/:id/ics"
57
+ CALENDAR_EVENT_RESPOND = "/calendar/events/:id/respond"
58
+ CHAT = "/chats/:id"
59
+ CHATS = "/chats"
60
+ CONTACT = "/contacts/:email"
61
+ CONTACTS = "/contacts"
62
+ CONTACTS_BATCH_DELETE = "/contacts/batch-delete"
63
+ CONTACTS_PEOPLE = "/contacts/people"
64
+ CONTACT_ACTIVITY = "/contacts/:email/activity"
65
+ CONTACT_AUDIENCES = "/contacts/:email/audiences"
66
+ CONTACT_BLOCK = "/contacts/:email/block"
67
+ CONTACT_PHOTO = "/contacts/:email/photo"
68
+ CONTACT_THREADS = "/contacts/:email/threads"
69
+ DNS_CONNECTION = "/dns-connections/:id"
70
+ DNS_CONNECTIONS = "/dns-connections"
71
+ DOMAIN = "/domains/:id"
72
+ DOMAINS = "/domains"
73
+ DOMAIN_ADDRESS = "/domains/:id/addresses/:addressId"
74
+ DOMAIN_ADDRESSES = "/domains/:id/addresses"
75
+ DOMAIN_ADDRESS_FORWARD = "/domains/:id/addresses/:addressId/forwards/:forwardId"
76
+ DOMAIN_ADDRESS_FORWARDS = "/domains/:id/addresses/:addressId/forwards"
77
+ DOMAIN_ADDRESS_FORWARD_RESEND = "/domains/:id/addresses/:addressId/forwards/:forwardId/resend"
78
+ DOMAIN_ADDRESS_LOGIN = "/domains/:id/addresses/:addressId/login"
79
+ DOMAIN_ADDRESS_MEMBERS = "/domains/:id/addresses/:addressId/members"
80
+ DOMAIN_ADDRESS_PHOTO = "/domains/:id/addresses/:addressId/photo"
81
+ DOMAIN_DNS = "/domains/:id/dns"
82
+ DOMAIN_DNS_SYNC = "/domains/:id/dns/sync"
83
+ DOMAIN_LOGO = "/domains/:id/logo"
84
+ DOMAIN_LOGO_CERTIFICATE = "/domains/:id/logo/certificate"
85
+ DOMAIN_VERIFY = "/domains/:id/verify"
86
+ DRAFT = "/drafts/:id"
87
+ DRAFTS = "/drafts"
88
+ EMAIL = "/emails/:id"
89
+ EMAILS = "/emails"
90
+ EMAILS_BATCH = "/emails/batch"
91
+ EMAILS_CHECK = "/emails/check"
92
+ EMAILS_COMPOSE = "/emails/compose"
93
+ EMAILS_REWRITE = "/emails/rewrite"
94
+ EMAILS_SUBJECT = "/emails/subject"
95
+ EMAILS_TRANSLATE = "/emails/translate"
96
+ EMAIL_CANCEL = "/emails/:id/cancel"
97
+ EMAIL_EVENTS = "/emails/:id/events"
98
+ EMAIL_TRACKING = "/emails/:id/tracking"
99
+ ENCRYPTION_KEYS = "/encryption/keys"
100
+ ENCRYPTION_KEYS_LOOKUP = "/encryption/keys/lookup"
101
+ FILE = "/files/:id"
102
+ FILES = "/files"
103
+ FILES_BATCH_DELETE = "/files/batch-delete"
104
+ FILES_STATS = "/files/stats"
105
+ FILE_CONTENT = "/files/:id/content"
106
+ FILE_LINK = "/files/:id/links/:linkId"
107
+ FILE_LINKS = "/files/:id/links"
108
+ FORM = "/forms/:id"
109
+ FORMS = "/forms"
110
+ FORMS_DESIGN = "/forms/design"
111
+ FORM_ANALYTICS = "/forms/:id/analytics"
112
+ FORM_DUPLICATE = "/forms/:id/duplicate"
113
+ FORM_PAUSE = "/forms/:id/pause"
114
+ FORM_PUBLISH = "/forms/:id/publish"
115
+ FORM_REDESIGN = "/forms/:id/redesign"
116
+ FORM_RESUME = "/forms/:id/resume"
117
+ FORM_STARTER = "/forms/starters/:slug"
118
+ FORM_STARTERS = "/forms/starters"
119
+ FORM_SUBMISSION = "/forms/:id/submissions/:submissionId"
120
+ FORM_SUBMISSIONS = "/forms/:id/submissions"
121
+ FORM_SUBMISSIONS_BATCH_REMOVE = "/forms/:id/submissions/batch-remove"
122
+ FORM_SUBMISSION_APPROVE = "/forms/:id/submissions/:submissionId/approve"
123
+ FORM_SUBMISSION_RESEND = "/forms/:id/submissions/:submissionId/resend"
124
+ IMPORT = "/imports/:id"
125
+ IMPORTS = "/imports"
126
+ IMPORT_CANCEL = "/imports/:id/cancel"
127
+ IMPORT_FAILURES = "/imports/:id/failures"
128
+ IMPORT_FILE_CHUNK = "/imports/:id/files/:file/chunks/:chunk"
129
+ IMPORT_START = "/imports/:id/start"
130
+ IMPORT_UPLOAD = "/imports/:id/upload"
131
+ KEY = "/keys/:id"
132
+ KEYS = "/keys"
133
+ KEYS_ACTIVITY = "/keys/activity"
134
+ KEYS_REQUESTS = "/keys/requests"
135
+ KEYS_STATS = "/keys/stats"
136
+ KEY_ACTIVITY = "/keys/:id/activity"
137
+ KEY_REQUESTS = "/keys/:id/requests"
138
+ KEY_REVOKE = "/keys/:id/revoke"
139
+ KEY_ROTATE = "/keys/:id/rotate"
140
+ KEY_SELF = "/keys/self"
141
+ KEY_SELF_ROTATE = "/keys/self/rotate"
142
+ LABEL = "/labels/:id"
143
+ LABELS = "/labels"
144
+ LABEL_COLORS = "/labels/colors"
145
+ LANGUAGES = "/languages"
146
+ MAILBOX_EXPORT = "/exports/:id"
147
+ MAILBOX_EXPORTS = "/exports"
148
+ MAILBOX_EXPORTS_PREVIEW = "/exports/preview"
149
+ MAILBOX_EXPORT_CONTENT = "/exports/:id/content"
150
+ MEMBER = "/members/:userId"
151
+ MEMBERS = "/members"
152
+ MEMBER_ADDRESS = "/members/:userId/addresses/:addressId"
153
+ MEMBER_ADDRESSES = "/members/:userId/addresses"
154
+ MEMBER_DOMAIN = "/members/:userId/domains/:domainId"
155
+ MEMBER_DOMAINS = "/members/:userId/domains"
156
+ MEMBER_INVITATION = "/members/invitations/:invitationId"
157
+ MEMBER_INVITATIONS = "/members/invitations"
158
+ MEMBER_INVITATION_RESEND = "/members/invitations/:invitationId/resend"
159
+ PING = "/ping"
160
+ PROVIDER_IMPORT = "/provider-imports/:id"
161
+ PROVIDER_IMPORTS = "/provider-imports"
162
+ PROVIDER_IMPORTS_INSPECT = "/provider-imports/inspect"
163
+ PROVIDER_IMPORT_CANCEL = "/provider-imports/:id/cancel"
164
+ ROLE = "/roles/:id"
165
+ ROLES = "/roles"
166
+ ROLE_PERMISSIONS = "/roles/permissions"
167
+ RULE = "/rules/:id"
168
+ RULES = "/rules"
169
+ RULES_REORDER = "/rules/reorder"
170
+ RULE_RUNS = "/rules/runs"
171
+ RULE_TEST = "/rules/:id/test"
172
+ SECURITY_STEP_UP = "/security/step-up"
173
+ SECURITY_STEP_UP_VERIFY = "/security/step-up/verify"
174
+ SENDER = "/senders/:email"
175
+ SENDER_RESEARCH = "/senders/:email/research"
176
+ SETTINGS = "/settings"
177
+ SUBSCRIBE_FORM = "/subscribe/:formId"
178
+ SUBSCRIPTIONS = "/subscriptions"
179
+ SUBSCRIPTION_DOMAINS = "/subscriptions/domains"
180
+ SUBSCRIPTION_DOMAIN_UNSUBSCRIBE = "/subscriptions/domains/:domain/unsubscribe"
181
+ SUBSCRIPTION_MOVE = "/subscriptions/:id/move"
182
+ SUBSCRIPTION_UNSUBSCRIBE = "/subscriptions/:id/unsubscribe"
183
+ SUPPORT = "/support"
184
+ SUPPRESSION = "/suppressions/:id"
185
+ SUPPRESSIONS = "/suppressions"
186
+ TEMPLATE = "/templates/:id"
187
+ TEMPLATES = "/templates"
188
+ TEMPLATES_DESIGN = "/templates/design"
189
+ TEMPLATE_ANALYTICS = "/templates/:id/analytics"
190
+ TEMPLATE_CONTENT = "/templates/:id/content"
191
+ TEMPLATE_DUPLICATE = "/templates/:id/duplicate"
192
+ TEMPLATE_FONTS = "/templates/fonts"
193
+ TEMPLATE_IMAGES = "/templates/images"
194
+ TEMPLATE_PREVIEW = "/templates/:id/preview"
195
+ TEMPLATE_REDESIGN = "/templates/:id/redesign"
196
+ TEMPLATE_RENDER = "/templates/render"
197
+ TEMPLATE_SEND = "/templates/:id/send"
198
+ TEMPLATE_SENDS = "/templates/:id/sends"
199
+ TEMPLATE_STARTER = "/templates/starters/:slug"
200
+ TEMPLATE_STARTERS = "/templates/starters"
201
+ TEMPLATE_VERSION = "/templates/:id/versions/:version"
202
+ TEMPLATE_VERSIONS = "/templates/:id/versions"
203
+ TEMPLATE_VERSION_RESTORE = "/templates/:id/versions/:version/restore"
204
+ TEMP_MAIL_DOMAINS = "/temp-mail/domains"
205
+ TEMP_MAIL_INBOX = "/temp-mail/inboxes/:id"
206
+ TEMP_MAIL_INBOXES = "/temp-mail/inboxes"
207
+ TEMP_MAIL_INBOX_EXTEND = "/temp-mail/inboxes/:id/extend"
208
+ TEMP_MAIL_MESSAGE = "/temp-mail/inboxes/:id/messages/:messageId"
209
+ TEMP_MAIL_MESSAGES = "/temp-mail/inboxes/:id/messages"
210
+ TEMP_MAIL_MESSAGE_ATTACHMENTS = "/temp-mail/inboxes/:id/messages/:messageId/attachments"
211
+ THREAD = "/threads/:id"
212
+ THREADS = "/threads"
213
+ THREADS_COUNTS = "/threads/counts"
214
+ THREAD_EVENT = "/threads/:id/event"
215
+ THREAD_MESSAGE_ATTACHMENTS = "/threads/:id/messages/:messageId/attachments"
216
+ THREAD_NOTE = "/threads/:id/notes/:noteId"
217
+ THREAD_NOTES = "/threads/:id/notes"
218
+ THREAD_NOTES_REORDER = "/threads/:id/notes/reorder"
219
+ THREAD_RESTORE = "/threads/:id/restore"
220
+ THREAD_SNOOZE = "/threads/:id/snooze"
221
+ THREAD_SUMMARY = "/threads/:id/summary"
222
+ THREAD_TRASH = "/threads/:id/trash"
223
+ THREAD_UNSNOOZE = "/threads/:id/unsnooze"
224
+ THREAD_UNSUBSCRIBE = "/threads/:id/unsubscribe"
225
+ TOOLS_BIMI = "/tools/bimi"
226
+ TOOLS_DELIVERABILITY = "/tools/deliverability"
227
+ TOOLS_DMARC = "/tools/dmarc"
228
+ TRACKED = "/tracking/:id"
229
+ TRACKED_CLICKS = "/tracking/:id/clicks"
230
+ TRACKED_OPENS = "/tracking/:id/opens"
231
+ TRACKING = "/tracking"
232
+ TRACKING_STATS = "/tracking/stats"
233
+ WEBHOOK = "/webhooks/:id"
234
+ WEBHOOKS = "/webhooks"
235
+ WEBHOOKS_ACTIVITY = "/webhooks/activity"
236
+ WEBHOOKS_DELIVERIES = "/webhooks/deliveries"
237
+ WEBHOOKS_EVENTS = "/webhooks/events"
238
+ WEBHOOKS_STATS = "/webhooks/stats"
239
+ WEBHOOK_ACTIVITY = "/webhooks/:id/activity"
240
+ WEBHOOK_DELIVERIES = "/webhooks/:id/deliveries"
241
+ WEBHOOK_DELIVERY = "/webhooks/:id/deliveries/:deliveryId"
242
+ WEBHOOK_DELIVERY_REPLAY = "/webhooks/:id/deliveries/:deliveryId/replay"
243
+ WEBHOOK_ROTATE_SECRET = "/webhooks/:id/rotate-secret"
244
+ WEBHOOK_TEST = "/webhooks/:id/test"
245
+ WORKSPACE = "/workspaces/:id"
246
+ WORKSPACES = "/workspaces"
247
+ WORKSPACES_ACTIVE = "/workspaces/active"
248
+ end
249
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenEmail
4
+ class Client
5
+ NAMESPACES = {
6
+ me: Resources::Me,
7
+ security: Resources::Security,
8
+ keys: Resources::Keys,
9
+ addresses: Resources::Addresses,
10
+ languages: Resources::Languages,
11
+ emails: Resources::Emails,
12
+ templates: Resources::Templates,
13
+ tracking: Resources::Tracking,
14
+ threads: Resources::Threads,
15
+ drafts: Resources::Drafts,
16
+ labels: Resources::Labels,
17
+ contacts: Resources::Contacts,
18
+ audiences: Resources::Audiences,
19
+ billing: Resources::Billing,
20
+ forms: Resources::Forms,
21
+ broadcasts: Resources::Broadcasts,
22
+ domains: Resources::Domains,
23
+ app_host: Resources::AppHost,
24
+ branding: Resources::Branding,
25
+ rules: Resources::Rules,
26
+ webhooks: Resources::Webhooks,
27
+ imports: Resources::Imports,
28
+ provider_imports: Resources::ProviderImports,
29
+ calendar: Resources::Calendar,
30
+ settings: Resources::Settings,
31
+ roles: Resources::Roles,
32
+ members: Resources::Members,
33
+ suppressions: Resources::Suppressions,
34
+ files: Resources::Files,
35
+ temp_mail: Resources::TempMail,
36
+ exports: Resources::Exports,
37
+ chats: Resources::Chats,
38
+ encryption: Resources::Encryption,
39
+ support: Resources::Support,
40
+ tools: Resources::Tools,
41
+ senders: Resources::Senders,
42
+ analytics: Resources::Analytics,
43
+ subscriptions: Resources::Subscriptions,
44
+ dns_connections: Resources::DnsConnections,
45
+ workspaces: Resources::Workspaces,
46
+ account: Resources::Account
47
+ }.freeze
48
+
49
+ attr_reader :mode, :raw, *NAMESPACES.keys
50
+
51
+ def initialize(key = nil, api_key: nil, access_token: nil, base_url: nil, adapter: nil, max_retries: nil,
52
+ timeout: nil, user_agent: nil, headers: nil, disable_update_notice: false)
53
+ raise ArgumentError, Defaults::MESSAGES[:KEY_TWICE] unless key.nil? || api_key.nil?
54
+
55
+ api_key = key if api_key.nil?
56
+ Credentials.assert_credential(api_key, access_token, required: true)
57
+
58
+ @raw = Transport.new(api_key:, access_token:, base_url:, adapter:, max_retries:, timeout:, user_agent:, headers:,
59
+ disable_update_notice:)
60
+ @mode = Credentials.mode_of(api_key)
61
+ NAMESPACES.each { |name, resource| instance_variable_set(:"@#{name}", resource.new(@raw)) }
62
+ freeze
63
+ end
64
+
65
+ def inspect
66
+ "#<#{self.class.name} mode=#{@mode.inspect} base_url=#{@raw.base_url.inspect}>"
67
+ end
68
+ end
69
+ end