diff --git a/README.md b/README.md index 562275ef..36779169 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ Send emails to your Sandbox for testing purposes: ```ruby require 'mailtrap' -client = Mailtrap::Client.new(api_key: 'your-api-key', sandbox: true, inbox_id: YOUR_INBOX_ID) +client = Mailtrap::Client.new(api_key: 'your-api-key', sandbox: true, sandbox_id: YOUR_SANDBOX_ID) client.send(mail) # You can also pass the request parameters directly @@ -139,9 +139,8 @@ Meaning your recipients will receive emails only in the default encoding which is `quoted-printable`, if you send with Mailtrap API. For those who need to use `7bit` or any other encoding, SMTP provides -better flexibility in that regard. Go to your _Mailtrap account_ → _Email Sending_ -→ _Sending Domains_ → _Your domain_ → _SMTP/API Settings_ to find the SMTP -configuration example. +better flexibility in that regard. Go to your _Mailtrap account_ → _Domains_ +→ _Your domain_ → _Integration_ to find the SMTP configuration example. ### Multiple Mailtrap Clients @@ -175,17 +174,17 @@ Email API: - Full Email Sending – [`full.rb`](examples/full.rb) - Batch Sending – [`batch.rb`](examples/batch.rb) -- Sending Domains API – [`sending_domains_api.rb`](examples/sending_domains_api.rb) +- Domains API – [`domains_api.rb`](examples/domains_api.rb) - Sending Stats API – [`stats_api.rb`](examples/stats_api.rb) - Email Logs API – [`email_logs_api.rb`](examples/email_logs_api.rb) - Webhooks API – [`webhooks_api.rb`](examples/webhooks_api.rb) - Suppressions API – [`suppressions_api.rb`](examples/suppressions_api.rb) - Tracking Opt-outs API – [`tracking_opt_outs_api.rb`](examples/tracking_opt_outs_api.rb) -Email Sandbox (Testing): +Email Sandbox: - Projects CRUD – [`projects_api.rb`](examples/projects_api.rb) -- Inboxes CRUD - [`inboxes_api.rb`](examples/inboxes_api.rb) +- Sandboxes CRUD - [`sandboxes_api.rb`](examples/sandboxes_api.rb) - Sandbox Messages CRUD - [`sandbox_messages_api.rb`](examples/sandbox_messages_api.rb) - Sandbox Attachments API - [`sandbox_attachments_api.rb`](examples/sandbox_attachments_api.rb) @@ -218,6 +217,40 @@ General: - Action Mailer – [`action_mailer.rb`](examples/action_mailer.rb) - Verifying webhook signatures – [`webhooks_signature_verification.ru`](examples/webhooks_signature_verification.ru) +## Renamed APIs + +Email Sandbox inboxes are now called sandboxes, and sending domains are now called +domains. The old names still work and call the same API endpoints, but they print a +deprecation warning and will be removed in a future major release. + +| Deprecated | Use instead | +|------------|-------------| +| `Mailtrap::InboxesAPI` | `Mailtrap::SandboxesAPI` | +| `Mailtrap::Inbox` | `Mailtrap::Sandbox` | +| `Mailtrap::SendingDomainsAPI` | `Mailtrap::DomainsAPI` | +| `Mailtrap::SendingDomain` | `Mailtrap::Domain` | +| `Mailtrap::Client.new(inbox_id:)` and the ActionMailer `inbox_id` setting | `sandbox_id` | +| `#inbox_id` on `Client`, `SandboxMessagesAPI` and `SandboxAttachmentsAPI` | `#sandbox_id` | + +The other old names warn once per process. `Mailtrap::Inbox` and `Mailtrap::SendingDomain` +use Ruby's `deprecate_constant`, so they warn only when Ruby's deprecation warnings are +enabled (for example, `ruby -W:deprecated`), and they can warn more than once. Attributes and filters that +mirror API fields keep their names, such as `SandboxMessage#inbox_id`, `Project#inboxes` +and the `sending_domain_ids:` stats filter. + +The once-per-process warnings print whether or not Ruby's deprecation warnings are +enabled, so `-W:no-deprecated` doesn't hide them. To silence them, filter out the +warnings tagged `[mailtrap]`: + +```ruby +module SilenceMailtrapDeprecations + def warn(message, ...) + super unless message.include?('[mailtrap]') + end +end +Warning.extend(SilenceMailtrapDeprecations) +``` + ## Migration guide v1 → v2 Change `Mailtrap::Sending::Client` to `Mailtrap::Client`. diff --git a/bin/record-vcr b/bin/record-vcr index 78136b13..b9e02e63 100755 --- a/bin/record-vcr +++ b/bin/record-vcr @@ -6,8 +6,8 @@ # # Usage: # bin/record-vcr # all specs -# bin/record-vcr spec/mailtrap/sending_domains_api_spec.rb # single file -# bin/record-vcr spec/mailtrap/sending_domains_api_spec.rb:42 # single example +# bin/record-vcr spec/mailtrap/domains_api_spec.rb # single file +# bin/record-vcr spec/mailtrap/domains_api_spec.rb:42 # single example # bin/record-vcr -e "#update" # filter by name # bin/record-vcr --org spec/mailtrap/sub_accounts_api_spec.rb # use organization API token # diff --git a/examples/action_mailer.rb b/examples/action_mailer.rb index 11ba3405..14c7727d 100644 --- a/examples/action_mailer.rb +++ b/examples/action_mailer.rb @@ -10,7 +10,7 @@ # # Switch to bulk sending (@see https://help.mailtrap.io/article/113-sending-streams) # bulk: true, # # Switch to sandbox sending (@see https://help.mailtrap.io/article/109-getting-started-with-mailtrap-email-testing) -# sandbox: true, inbox_id: 12, +# sandbox: true, sandbox_id: 12, # } # Now you can use ActionMailer to deliver mail through Mailtrap. diff --git a/examples/batch.rb b/examples/batch.rb index 47e8b141..c3ea7121 100644 --- a/examples/batch.rb +++ b/examples/batch.rb @@ -10,7 +10,7 @@ # Bulk sending (@see https://help.mailtrap.io/article/113-sending-streams) # client = Mailtrap::Client.new(bulk: true) # Sandbox sending (@see https://help.mailtrap.io/article/109-getting-started-with-mailtrap-email-testing) -# client = Mailtrap::Client.new(sandbox: true, inbox_id: 12) +# client = Mailtrap::Client.new(sandbox: true, sandbox_id: 12) # Batch sending with text and html content batch_base = Mailtrap::Mail.batch_base_from_content( diff --git a/examples/company_info_api.rb b/examples/company_info_api.rb index 64914ef9..497048a2 100644 --- a/examples/company_info_api.rb +++ b/examples/company_info_api.rb @@ -1,13 +1,13 @@ require 'mailtrap' account_id = 3229 -sending_domain_id = 1 +domain_id = 1 client = Mailtrap::Client.new(api_key: 'your-api-key') company_info_api = Mailtrap::CompanyInfoAPI.new(account_id, client) -# Create company info for a sending domain +# Create company info for a domain company_info_api.create( - sending_domain_id, + domain_id, name: 'Mailtrap', address: '123 Main St', city: 'San Francisco', diff --git a/examples/domains_api.rb b/examples/domains_api.rb new file mode 100644 index 00000000..74871ef4 --- /dev/null +++ b/examples/domains_api.rb @@ -0,0 +1,36 @@ +require 'mailtrap' + +account_id = 3229 +client = Mailtrap::Client.new(api_key: 'your-api-key') +domains = Mailtrap::DomainsAPI.new(account_id, client) + +# Create new domain +domain = domains.create(domain_name: 'example.com') +# => # + +# Get all domains +domains.list +# => [#] + +# Get domain +domain = domains.get(domain.id) +# => # + +# Update domain configuration +domains.update( + domain.id, + open_tracking_enabled: true, + click_tracking_enabled: true, + tracking_opt_out_enabled: true, + auto_unsubscribe_link_enabled: false, + inbound_enabled: false +) +# => # + +# Send setup email +domains.send_setup_instructions(domain.id, email: 'jonathan@mail.com') +# => nil + +# Delete domain +domains.delete(domain.id) +# => nil diff --git a/examples/full.rb b/examples/full.rb index 57053d6b..a92597f4 100644 --- a/examples/full.rb +++ b/examples/full.rb @@ -53,7 +53,7 @@ # client = Mailtrap::Client.new(api_key: 'your-api-key', bulk: true) # Sandbox sending (@see https://help.mailtrap.io/article/109-getting-started-with-mailtrap-email-testing) -# client = Mailtrap::Client.new(api_key: 'your-api-key', sandbox: true, inbox_id: 12) +# client = Mailtrap::Client.new(api_key: 'your-api-key', sandbox: true, sandbox_id: 12) client.send(mail) diff --git a/examples/inboxes_api.rb b/examples/inboxes_api.rb deleted file mode 100644 index 579dec2f..00000000 --- a/examples/inboxes_api.rb +++ /dev/null @@ -1,39 +0,0 @@ -require 'mailtrap' - -account_id = 3229 -client = Mailtrap::Client.new(api_key: 'your-api-key') -inboxes = Mailtrap::InboxesAPI.new(account_id, client) - -# Create new Inbox -inbox = inboxes.create(name: 'Test Inbox', project_id: 123_456) -# => # - -# Get all Inboxes -inboxes.list -# => [#] - -# Update inbox -inboxes.update(inbox.id, name: 'Test Inbox Updated') -# => # - -# Get contact list -inbox = inboxes.get(inbox.id) -# => # - -# Delete all messages (emails) from Inbox -inboxes.clean(inbox.id) - -# Mark all messages in the inbox as read -inboxes.mark_as_read(inbox.id) - -# Reset SMTP credentials of the inbox -inboxes.reset_credentials(inbox.id) - -# Turn the email address of the inbox on/off -inboxes.toggle_email_username(inbox.id) - -# Reset username of email address per inbox -inboxes.reset_email_username(inbox.id) - -# Delete unbox list -inboxes.delete(inbox.id) diff --git a/examples/marketing_stats_api.rb b/examples/marketing_stats_api.rb index dddafaad..824506ce 100644 --- a/examples/marketing_stats_api.rb +++ b/examples/marketing_stats_api.rb @@ -17,7 +17,7 @@ # unsubscription_count=12, unsubscription_rate=0.01, # sent_count=1250> -# Narrow to campaigns only (or automations only), for some sending domains and email service providers +# Narrow to campaigns only (or automations only), for some domains and email service providers marketing_stats.get( start_date: today - 29, end_date: today, diff --git a/examples/sandbox_attachments_api.rb b/examples/sandbox_attachments_api.rb index a81570ad..31277a01 100644 --- a/examples/sandbox_attachments_api.rb +++ b/examples/sandbox_attachments_api.rb @@ -1,10 +1,10 @@ require 'mailtrap' account_id = 3229 -inbox_id = 12 +sandbox_id = 12 message_id = 123 client = Mailtrap::Client.new(api_key: 'your-api-key') -sandbox_attachments = Mailtrap::SandboxAttachmentsAPI.new(account_id, inbox_id, message_id, client) +sandbox_attachments = Mailtrap::SandboxAttachmentsAPI.new(account_id, sandbox_id, message_id, client) # List all attachments for a sandbox message (up to 30) sandbox_attachments.list diff --git a/examples/sandbox_messages_api.rb b/examples/sandbox_messages_api.rb index 7523909b..59ff1ce1 100644 --- a/examples/sandbox_messages_api.rb +++ b/examples/sandbox_messages_api.rb @@ -1,11 +1,11 @@ require 'mailtrap' account_id = 3229 -inbox_id = 12 +sandbox_id = 12 client = Mailtrap::Client.new(api_key: 'your-api-key') -sandbox_messages = Mailtrap::SandboxMessagesAPI.new(account_id, inbox_id, client) +sandbox_messages = Mailtrap::SandboxMessagesAPI.new(account_id, sandbox_id, client) -# List all sandbox messages in the inbox (optional: search, page, last_id) +# List all messages in the sandbox (optional: search, page, last_id) sandbox_messages.list # => [#] diff --git a/examples/sandboxes_api.rb b/examples/sandboxes_api.rb new file mode 100644 index 00000000..5a4d5e40 --- /dev/null +++ b/examples/sandboxes_api.rb @@ -0,0 +1,39 @@ +require 'mailtrap' + +account_id = 3229 +client = Mailtrap::Client.new(api_key: 'your-api-key') +sandboxes = Mailtrap::SandboxesAPI.new(account_id, client) + +# Create new sandbox +sandbox = sandboxes.create(name: 'Test Sandbox', project_id: 123_456) +# => # + +# Get all sandboxes +sandboxes.list +# => [#] + +# Update sandbox +sandboxes.update(sandbox.id, name: 'Test Sandbox Updated') +# => # + +# Get sandbox +sandbox = sandboxes.get(sandbox.id) +# => # + +# Delete all messages (emails) from the sandbox +sandboxes.clean(sandbox.id) + +# Mark all messages in the sandbox as read +sandboxes.mark_as_read(sandbox.id) + +# Reset SMTP credentials of the sandbox +sandboxes.reset_credentials(sandbox.id) + +# Turn the email address of the sandbox on/off +sandboxes.toggle_email_username(sandbox.id) + +# Reset username of email address per sandbox +sandboxes.reset_email_username(sandbox.id) + +# Delete sandbox +sandboxes.delete(sandbox.id) diff --git a/examples/sending_domains_api.rb b/examples/sending_domains_api.rb deleted file mode 100644 index 3cc6efe4..00000000 --- a/examples/sending_domains_api.rb +++ /dev/null @@ -1,36 +0,0 @@ -require 'mailtrap' - -account_id = 3229 -client = Mailtrap::Client.new(api_key: 'your-api-key') -sending_domains = Mailtrap::SendingDomainsAPI.new(account_id, client) - -# Create new Sending Domain -sending_domain = sending_domains.create(domain_name: 'example.com') -# => # - -# Get all Sending Domains -sending_domains.list -# => [#] - -# Get sending domain -sending_domain = sending_domains.get(sending_domain.id) -# => # - -# Update sending domain configuration -sending_domains.update( - sending_domain.id, - open_tracking_enabled: true, - click_tracking_enabled: true, - tracking_opt_out_enabled: true, - auto_unsubscribe_link_enabled: false, - inbound_enabled: false -) -# => # - -# Send setup email -sending_domains.send_setup_instructions(sending_domain.id, email: 'jonathan@mail.com') -# => nil - -# Delete sending domain -sending_domains.delete(sending_domain.id) -# => nil diff --git a/examples/tracking_opt_outs_api.rb b/examples/tracking_opt_outs_api.rb index 71166847..466da6e5 100644 --- a/examples/tracking_opt_outs_api.rb +++ b/examples/tracking_opt_outs_api.rb @@ -37,7 +37,7 @@ puts page.data.size end -# Opt an email out of open and click tracking for a sending domain +# Opt an email out of open and click tracking for a domain opt_out = tracking_opt_outs.create(email: 'tracked@example.com', domain_id: 12_345) # => # diff --git a/lib/mailtrap.rb b/lib/mailtrap.rb index 6f739f34..f4889c94 100644 --- a/lib/mailtrap.rb +++ b/lib/mailtrap.rb @@ -22,10 +22,12 @@ require_relative 'mailtrap/tracking_opt_outs_api' require_relative 'mailtrap/email_campaigns_api' require_relative 'mailtrap/marketing_stats_api' +require_relative 'mailtrap/domains_api' require_relative 'mailtrap/sending_domains_api' require_relative 'mailtrap/company_info_api' require_relative 'mailtrap/email_logs_api' require_relative 'mailtrap/projects_api' +require_relative 'mailtrap/sandboxes_api' require_relative 'mailtrap/inboxes_api' require_relative 'mailtrap/sandbox_messages_api' require_relative 'mailtrap/sandbox_attachments_api' diff --git a/lib/mailtrap/account_accesses_api.rb b/lib/mailtrap/account_accesses_api.rb index b6c596ae..513d838d 100644 --- a/lib/mailtrap/account_accesses_api.rb +++ b/lib/mailtrap/account_accesses_api.rb @@ -9,9 +9,9 @@ class AccountAccessesAPI self.response_class = AccountAccess - # Retrieves a list of account accesses with optional filtering by domain, inbox, or project IDs + # Retrieves a list of account accesses with optional filtering by domain, sandbox, or project IDs # @param domain_ids [Array] Optional array of domain IDs to filter by - # @param inbox_ids [Array] Optional array of inbox IDs to filter by + # @param inbox_ids [Array] Optional array of sandbox IDs to filter by # @param project_ids [Array] Optional array of project IDs to filter by # @return [Array] List of account access objects # @!macro api_errors diff --git a/lib/mailtrap/action_mailer/delivery_method.rb b/lib/mailtrap/action_mailer/delivery_method.rb index f0c0929a..19f4112a 100644 --- a/lib/mailtrap/action_mailer/delivery_method.rb +++ b/lib/mailtrap/action_mailer/delivery_method.rb @@ -1,11 +1,13 @@ # frozen_string_literal: true +require_relative '../deprecation' + module Mailtrap module ActionMailer class DeliveryMethod attr_accessor :settings - ALLOWED_PARAMS = %i[api_key api_host api_port bulk sandbox inbox_id].freeze + ALLOWED_PARAMS = %i[api_key api_host api_port bulk sandbox sandbox_id].freeze def initialize(settings) self.settings = settings @@ -22,7 +24,16 @@ def deliver!(message) private def client - @client ||= Mailtrap::Client.new(**settings.slice(*ALLOWED_PARAMS)) + @client ||= Mailtrap::Client.new(**client_settings) + end + + def client_settings + params = settings.slice(*ALLOWED_PARAMS) + inbox_id = settings[:inbox_id] + return params if inbox_id.nil? + + Deprecation.warn('The ActionMailer mailtrap_settings inbox_id', 'sandbox_id') + params.merge(sandbox_id: Deprecation.resolve_sandbox_id(params[:sandbox_id], inbox_id)) end end end diff --git a/lib/mailtrap/base_api.rb b/lib/mailtrap/base_api.rb index 6d5b250a..e15a9ad1 100644 --- a/lib/mailtrap/base_api.rb +++ b/lib/mailtrap/base_api.rb @@ -10,6 +10,12 @@ def self.included(base) module ClassMethods attr_accessor :supported_options, :response_class + + def inherited(subclass) + super + subclass.supported_options = supported_options + subclass.response_class = response_class + end end # @param account_id [Integer] The account ID diff --git a/lib/mailtrap/billing_usage.rb b/lib/mailtrap/billing_usage.rb index d6648c27..5ea4b08e 100644 --- a/lib/mailtrap/billing_usage.rb +++ b/lib/mailtrap/billing_usage.rb @@ -4,7 +4,7 @@ module Mailtrap # Data Transfer Object for Billing Usage data # @see https://docs.mailtrap.io/developers/account-management/billing # @attr_reader billing [Hash] The billing cycle details - # @attr_reader testing [Hash] Testing subscription usage + # @attr_reader testing [Hash] Email Sandbox subscription usage # @attr_reader sending [Hash] Sending subscription usage # BillingUsage = Struct.new( diff --git a/lib/mailtrap/client.rb b/lib/mailtrap/client.rb index db2af436..edc17536 100644 --- a/lib/mailtrap/client.rb +++ b/lib/mailtrap/client.rb @@ -3,6 +3,7 @@ require 'json' require 'net/http' require 'uri' +require_relative 'deprecation' module Mailtrap class Client @@ -12,7 +13,7 @@ class Client GENERAL_API_HOST = 'mailtrap.io' API_PORT = 443 - attr_reader :api_key, :api_host, :general_api_host, :api_port, :bulk, :sandbox, :inbox_id + attr_reader :api_key, :api_host, :general_api_host, :api_port, :bulk, :sandbox, :sandbox_id # Initializes a new Mailtrap::Client instance. # @@ -25,8 +26,9 @@ class Client # If enabled, it is incompatible with `sandbox: true`. # @param [Boolean] sandbox Whether to use the Mailtrap sandbox API. Default: false. # If enabled, it is incompatible with `bulk: true`. - # @param [Integer] inbox_id The sandbox inbox ID to send to. Required if sandbox API is used. - # @raise [ArgumentError] If api_key or api_port is nil, or if sandbox is true but inbox_id is nil, + # @param [Integer] sandbox_id The sandbox ID to send to. Required if sandbox API is used. + # @param [Integer] inbox_id Deprecated: use `sandbox_id` instead. + # @raise [ArgumentError] If api_key or api_port is nil, or if sandbox is true but sandbox_id is nil, # or if incompatible options are provided. def initialize( # rubocop:disable Metrics/ParameterLists api_key: ENV.fetch('MAILTRAP_API_KEY'), @@ -35,9 +37,14 @@ def initialize( # rubocop:disable Metrics/ParameterLists api_port: API_PORT, bulk: false, sandbox: false, + sandbox_id: nil, inbox_id: nil ) - validate_args!(api_key, api_port, bulk, sandbox, inbox_id) + unless inbox_id.nil? + Deprecation.warn('Mailtrap::Client.new(inbox_id:)', 'Mailtrap::Client.new(sandbox_id:)') + sandbox_id = Deprecation.resolve_sandbox_id(sandbox_id, inbox_id) + end + validate_args!(api_key, api_port, bulk, sandbox, sandbox_id) api_host ||= select_api_host(bulk:, sandbox:) @@ -47,10 +54,17 @@ def initialize( # rubocop:disable Metrics/ParameterLists @api_port = api_port @bulk = bulk @sandbox = sandbox - @inbox_id = inbox_id + @sandbox_id = sandbox_id @http_clients = {} end + # @deprecated Use {#sandbox_id} instead. + # @return [Integer, nil] The sandbox ID + def inbox_id + Deprecation.warn('Mailtrap::Client#inbox_id', 'Mailtrap::Client#sandbox_id') + sandbox_id + end + # Sends a batch of emails. # @example Batch sending with template # batch_base = Mailtrap::Mail.batch_base_from_template( @@ -235,11 +249,11 @@ def delete(path) private - def validate_args!(api_key, api_port, bulk, sandbox, inbox_id) + def validate_args!(api_key, api_port, bulk, sandbox, sandbox_id) raise ArgumentError, 'api_key is required' if api_key.nil? raise ArgumentError, 'api_port is required' if api_port.nil? raise ArgumentError, 'bulk stream is not applicable for sandbox API' if bulk && sandbox - raise ArgumentError, 'inbox_id is required for sandbox API' if sandbox && inbox_id.nil? + raise ArgumentError, 'sandbox_id is required for sandbox API' if sandbox && sandbox_id.nil? end def select_api_host(bulk:, sandbox:) @@ -344,11 +358,11 @@ def json_response(body) end def send_path - "/api/send#{"/#{inbox_id}" if sandbox}" + "/api/send#{"/#{sandbox_id}" if sandbox}" end def batch_request_path - "/api/batch#{"/#{inbox_id}" if sandbox}" + "/api/batch#{"/#{sandbox_id}" if sandbox}" end end end diff --git a/lib/mailtrap/company_info.rb b/lib/mailtrap/company_info.rb index 722f69cc..c8d5c41f 100644 --- a/lib/mailtrap/company_info.rb +++ b/lib/mailtrap/company_info.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Mailtrap - # Data Transfer Object for Sending Domain Company Info + # Data Transfer Object for Domain Company Info # @see https://docs.mailtrap.io/developers/management/sending-domains # @attr_reader name [String, nil] Company or individual name # @attr_reader address [String, nil] Street address diff --git a/lib/mailtrap/company_info_api.rb b/lib/mailtrap/company_info_api.rb index 1e3785b1..37bc7c24 100644 --- a/lib/mailtrap/company_info_api.rb +++ b/lib/mailtrap/company_info_api.rb @@ -22,17 +22,17 @@ class CompanyInfoAPI self.response_class = CompanyInfo - # Gets company information for a sending domain - # @param sending_domain_id [Integer] The sending domain ID + # Gets company information for a domain + # @param domain_id [Integer] The domain ID # @return [CompanyInfo] Company information # @!macro api_errors - def get(sending_domain_id) - response = client.get(base_path(sending_domain_id)) + def get(domain_id) + response = client.get(base_path(domain_id)) build_entity(response[:data], CompanyInfo) end - # Creates company information for a sending domain - # @param sending_domain_id [Integer] The sending domain ID + # Creates company information for a domain + # @param domain_id [Integer] The domain ID # @param [Hash] options The company info attributes # @option options [String] :name Company or individual name # @option options [String] :address Street address @@ -47,28 +47,28 @@ def get(sending_domain_id) # @return [CompanyInfo] Created company information # @!macro api_errors # @raise [ArgumentError] If invalid options are provided - def create(sending_domain_id, options) + def create(domain_id, options) validate_options!(options, supported_options) - response = client.post(base_path(sending_domain_id), wrap_request(options)) + response = client.post(base_path(domain_id), wrap_request(options)) build_entity(response[:data], CompanyInfo) end - # Updates company information for a sending domain - # @param sending_domain_id [Integer] The sending domain ID + # Updates company information for a domain + # @param domain_id [Integer] The domain ID # @param [Hash] options The company info attributes to update # @return [CompanyInfo] Updated company information # @!macro api_errors # @raise [ArgumentError] If invalid options are provided - def update(sending_domain_id, options) + def update(domain_id, options) validate_options!(options, supported_options) - response = client.patch(base_path(sending_domain_id), wrap_request(options)) + response = client.patch(base_path(domain_id), wrap_request(options)) build_entity(response[:data], CompanyInfo) end private - def base_path(sending_domain_id) - "/api/accounts/#{account_id}/sending_domains/#{sending_domain_id}/company_info" + def base_path(domain_id) + "/api/accounts/#{account_id}/sending_domains/#{domain_id}/company_info" end def wrap_request(options) diff --git a/lib/mailtrap/deprecation.rb b/lib/mailtrap/deprecation.rb new file mode 100644 index 00000000..ff0dd04c --- /dev/null +++ b/lib/mailtrap/deprecation.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'set' + +module Mailtrap + # Emits a deprecation warning once per process for each deprecated name, and maps the + # deprecated inbox_id onto sandbox_id. + # @api private + module Deprecation + WARNED = Set.new + MUTEX = Mutex.new + + # Call it directly from the deprecated method: the warning points at that method's caller. + # @param old_name [String] The deprecated name + # @param new_name [String] The name to use instead + def self.warn(old_name, new_name) + return unless MUTEX.synchronize { WARNED.add?(old_name) } + + Kernel.warn( + "[mailtrap] #{old_name} is deprecated and will be removed in a future major release; " \ + "use #{new_name} instead.", + uplevel: 2 + ) + end + + # @param sandbox_id [Integer, String, nil] The ID given as sandbox_id + # @param inbox_id [Integer, String] The ID given as the deprecated inbox_id + # @return [Integer, String] The sandbox ID to use + # @raise [ArgumentError] If both IDs are given and differ + def self.resolve_sandbox_id(sandbox_id, inbox_id) + return inbox_id if sandbox_id.nil? + return sandbox_id if sandbox_id.to_s == inbox_id.to_s + + raise ArgumentError, 'sandbox_id and inbox_id differ; pass only sandbox_id' + end + end +end diff --git a/lib/mailtrap/domain.rb b/lib/mailtrap/domain.rb new file mode 100644 index 00000000..c6c0260f --- /dev/null +++ b/lib/mailtrap/domain.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +module Mailtrap + # Data Transfer Object for Domain + # @see https://docs.mailtrap.io/developers/management/sending-domains + # @attr_reader id [Integer] The domain ID + # @attr_reader domain_name [String] The domain name + # @attr_reader demo [Boolean] Whether the domain is a demo domain + # @attr_reader compliance_status [String] The compliance status of the domain + # @attr_reader dns_verified [Boolean] Whether the DNS records are verified + # @attr_reader dns_verified_at [String, nil] The timestamp when DNS was verified + # @attr_reader dns_records [Array] The DNS records for the domain + # @attr_reader open_tracking_enabled [Boolean] Whether open tracking is enabled + # @attr_reader click_tracking_enabled [Boolean] Whether click tracking is enabled + # @attr_reader tracking_opt_out_enabled [Boolean] Whether the tracking opt-out link is enabled + # @attr_reader auto_unsubscribe_link_enabled [Boolean] Whether auto unsubscribe link is enabled + # @attr_reader custom_domain_tracking_enabled [Boolean] Whether custom domain tracking is enabled + # @attr_reader health_alerts_enabled [Boolean] Whether health alerts are enabled + # @attr_reader critical_alerts_enabled [Boolean] Whether critical alerts are enabled + # @attr_reader alert_recipient_email [String, nil] The email address for alert recipients + # @attr_reader inbound_enabled [Boolean] Whether inbound email is enabled for this domain + # @attr_reader inbound_verified [Boolean] Whether the domain's inbound MX records are verified + # @attr_reader permissions [Hash] The permissions for the domain + # + Domain = Struct.new( + :id, + :domain_name, + :demo, + :compliance_status, + :dns_verified, + :dns_verified_at, + :dns_records, + :open_tracking_enabled, + :click_tracking_enabled, + :tracking_opt_out_enabled, + :auto_unsubscribe_link_enabled, + :custom_domain_tracking_enabled, + :health_alerts_enabled, + :critical_alerts_enabled, + :alert_recipient_email, + :inbound_enabled, + :inbound_verified, + :permissions, + :created_at, + :updated_at, + keyword_init: true + ) +end diff --git a/lib/mailtrap/domains_api.rb b/lib/mailtrap/domains_api.rb new file mode 100644 index 00000000..ef7764a7 --- /dev/null +++ b/lib/mailtrap/domains_api.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +require_relative 'base_api' +require_relative 'domain' + +module Mailtrap + class DomainsAPI + include BaseAPI + + self.supported_options = %i[ + open_tracking_enabled + click_tracking_enabled + tracking_opt_out_enabled + auto_unsubscribe_link_enabled + inbound_enabled + ] + + self.response_class = Domain + + # Lists all domains for the account + # @return [Array] Array of domains + # @!macro api_errors + def list + response = client.get(base_path) + response[:data].map { |item| handle_response(item) } + end + + # Retrieves a specific domain + # @param domain_id [Integer] The domain ID + # @return [Domain] Domain object + # @!macro api_errors + def get(domain_id) + base_get(domain_id) + end + + # Creates a new domain + # @param [Hash] options The parameters to create + # @option options [String] :domain_name The domain name + # @return [Domain] Created domain + # @!macro api_errors + # @raise [ArgumentError] If invalid options are provided + def create(options) + base_create(options, %i[domain_name]) + end + + # Deletes a domain + # @param domain_id [Integer] The domain ID + # @return nil + # @!macro api_errors + def delete(domain_id) + base_delete(domain_id) + end + + # Updates configuration settings for a domain + # @param domain_id [Integer] The domain ID + # @param [Hash] options The parameters to update + # @option options [Boolean] :open_tracking_enabled Enable open tracking for emails sent from this domain + # @option options [Boolean] :click_tracking_enabled Enable click tracking for links in emails sent from this domain + # @option options [Boolean] :tracking_opt_out_enabled Enable the tracking opt-out link in tracked emails + # @option options [Boolean] :auto_unsubscribe_link_enabled Automatically add an unsubscribe link to emails + # @option options [Boolean] :inbound_enabled Enable inbound email for this domain + # @return [Domain] Updated domain + # @!macro api_errors + # @raise [ArgumentError] If invalid options are provided + def update(domain_id, options) + base_update(domain_id, options) + end + + # Email DNS configuration instructions for the domain + # @param domain_id [Integer] The domain ID + # @param email [String] The email for instructions + # @return nil + # @!macro api_errors + def send_setup_instructions(domain_id, email:) + client.post("#{base_path}/#{domain_id}/send_setup_instructions", email:) + end + + private + + def base_path + "/api/accounts/#{account_id}/sending_domains" + end + + def wrap_request(options) + { sending_domain: options } + end + end +end diff --git a/lib/mailtrap/email_campaign.rb b/lib/mailtrap/email_campaign.rb index bb6199db..5db110cf 100644 --- a/lib/mailtrap/email_campaign.rb +++ b/lib/mailtrap/email_campaign.rb @@ -39,9 +39,9 @@ module Mailtrap # Data Transfer Object for Email Campaign # @see https://api-docs.mailtrap.io/docs/mailtrap-api-docs/email-campaigns # @attr_reader id [Integer] The email campaign ID - # @attr_reader domain_id [Integer] ID of the sending domain used for the campaign, - # as returned by the Sending Domains endpoints - # @attr_reader domain_name [String] Name of the sending domain used for the campaign + # @attr_reader domain_id [Integer] ID of the domain used for the campaign, + # as returned by the Domains endpoints + # @attr_reader domain_name [String] Name of the domain used for the campaign # @attr_reader name [String] Campaign name # @attr_reader from_local_part [String] Local part (before the @) of the From address # @attr_reader from_display_name [String] Display name shown in the From header diff --git a/lib/mailtrap/email_campaigns_api.rb b/lib/mailtrap/email_campaigns_api.rb index fd1d6e0c..5442bc49 100644 --- a/lib/mailtrap/email_campaigns_api.rb +++ b/lib/mailtrap/email_campaigns_api.rb @@ -58,8 +58,8 @@ def get(email_campaign_id) # Creates a new email campaign in the +draft+ state # @param [Hash] options The parameters to create # @option options [String] :name Campaign name (required) - # @option options [Integer] :domain_id ID of the verified sending domain (required), - # as returned by the Sending Domains endpoints + # @option options [Integer] :domain_id ID of the verified domain (required), + # as returned by the Domains endpoints # @option options [String] :from_display_name Display name shown in the From header # @option options [String] :from_local_part Local part (before the @) of the From address (required) # @option options [Hash] :reply_to Reply-To address parts (+display_name+, +local_part+, +domain+) @@ -82,8 +82,8 @@ def create(options) # @param email_campaign_id [Integer] The email campaign ID # @param [Hash] options The parameters to update; accepts the same fields as {#create} # @option options [String] :name Campaign name - # @option options [Integer] :domain_id ID of the verified sending domain, - # as returned by the Sending Domains endpoints + # @option options [Integer] :domain_id ID of the verified domain, + # as returned by the Domains endpoints # @option options [String] :from_display_name Display name shown in the From header # @option options [String] :from_local_part Local part (before the @) of the From address # @option options [Hash] :reply_to Reply-To address parts (+display_name+, +local_part+, +domain+) diff --git a/lib/mailtrap/email_log_message.rb b/lib/mailtrap/email_log_message.rb index c595900f..7175d6ba 100644 --- a/lib/mailtrap/email_log_message.rb +++ b/lib/mailtrap/email_log_message.rb @@ -17,7 +17,7 @@ module Mailtrap # @attr_reader category [String, nil] Message category # @attr_reader custom_variables [Hash, nil] Custom variables # @attr_reader sending_stream [String] transactional or bulk - # @attr_reader sending_domain_id [Integer] Sending domain ID + # @attr_reader sending_domain_id [Integer] Domain ID # @attr_reader template_id [Integer, nil] Template ID if sent from template # @attr_reader template_variables [Hash, nil] Template variables # @attr_reader opens_count [Integer] Number of opens diff --git a/lib/mailtrap/inbound_inbox.rb b/lib/mailtrap/inbound_inbox.rb index b28a553a..24a3e0e3 100644 --- a/lib/mailtrap/inbound_inbox.rb +++ b/lib/mailtrap/inbound_inbox.rb @@ -6,7 +6,7 @@ module Mailtrap # @attr_reader id [Integer] The inbox ID # @attr_reader name [String] The inbox name # @attr_reader address [String] The inbox's inbound address - # @attr_reader domain_id [Integer] The sending domain the inbox is attached to + # @attr_reader domain_id [Integer] The domain the inbox is attached to InboundInbox = Struct.new( :id, :name, diff --git a/lib/mailtrap/inbox.rb b/lib/mailtrap/inbox.rb index ccce6b2e..812b6c5e 100644 --- a/lib/mailtrap/inbox.rb +++ b/lib/mailtrap/inbox.rb @@ -1,57 +1,9 @@ # frozen_string_literal: true +require_relative 'sandbox' + module Mailtrap - # Data Transfer Object for Inbox - # @see https://api-docs.mailtrap.io/docs/mailtrap-api-docs/ee252e413d78a-create-project - # @attr_reader id [Integer] The inbox ID - # @attr_reader name [String] The inbox name - # @attr_reader username [String] The inbox username - # @attr_reader password [String, nil] The inbox password - # @attr_reader max_size [Integer] The maximum inbox size in MB - # @attr_reader status [String] The inbox status - # @attr_reader email_username [String] The email username - # @attr_reader email_username_enabled [Boolean] Whether the email username is enabled - # @attr_reader sent_messages_count [Integer] The count of sent messages - # @attr_reader forwarded_messages_count [Integer] The count of forwarded messages - # @attr_reader used [Integer] The used inbox size in MB - # @attr_reader forward_from_email_address [String] The forwarding email address - # @attr_reader project_id [Integer] The associated project ID - # @attr_reader domain [String] The inbox domain - # @attr_reader pop3_domain [String] The POP3 domain - # @attr_reader email_domain [String] The email domain - # @attr_reader api_domain [String] The API domain - # @attr_reader emails_count [Integer] The total number of emails - # @attr_reader emails_unread_count [Integer] The number of unread emails - # @attr_reader last_message_sent_at [String, nil] The timestamp of the last sent message - # @attr_reader smtp_ports [Array] The list of SMTP ports - # @attr_reader pop3_ports [Array] The list of POP3 ports - # @attr_reader max_message_size [Integer] The maximum message size in MB - # @attr_reader permissions [Hash] List of permissions - Inbox = Struct.new( - :id, - :name, - :username, - :password, - :max_size, - :status, - :email_username, - :email_username_enabled, - :sent_messages_count, - :forwarded_messages_count, - :used, - :forward_from_email_address, - :project_id, - :domain, - :pop3_domain, - :email_domain, - :api_domain, - :emails_count, - :emails_unread_count, - :last_message_sent_at, - :smtp_ports, - :pop3_ports, - :max_message_size, - :permissions, - keyword_init: true - ) + # @deprecated Use {Sandbox} instead. + Inbox = Sandbox + deprecate_constant :Inbox end diff --git a/lib/mailtrap/inboxes_api.rb b/lib/mailtrap/inboxes_api.rb index bed615a4..478159de 100644 --- a/lib/mailtrap/inboxes_api.rb +++ b/lib/mailtrap/inboxes_api.rb @@ -1,116 +1,15 @@ # frozen_string_literal: true -require_relative 'base_api' +require_relative 'deprecation' +require_relative 'sandboxes_api' require_relative 'inbox' module Mailtrap - class InboxesAPI - include BaseAPI - - self.supported_options = %i[name] - self.response_class = Inbox - - # Lists all Inboxes for the account - # @return [Array] Array of Inboxes - # @!macro api_errors - def list - base_list - end - - # Retrieves a specific inbox - # @param inbox_id [Integer] The inbox identifier - # @return [Inbox] Inbox object - # @!macro api_errors - def get(inbox_id) - base_get(inbox_id) - end - - # Creates a new inbox - # @param [Hash] options The parameters to create - # @option options [String] :name The inbox name - # @return [Inbox] Created inbox object - # @!macro api_errors - # @raise [ArgumentError] If invalid options are provided - def create(options) - validate_options!(options, supported_options + [:project_id]) - response = client.post("/api/accounts/#{account_id}/projects/#{options[:project_id]}/inboxes", - wrap_request(options)) - handle_response(response) - end - - # Deletes an inbox - # @param inbox_id [Integer] The Inbox identifier - # @return nil - # @!macro api_errors - def delete(inbox_id) - base_delete(inbox_id) - end - - # Updates an existing Inbox - # @param inbox_id [Integer] The Inbox identifier - # @param [Hash] options The parameters to update - # @option options [String] :name The inbox name - # @option options [String] :email_username The inbox email username - # @return [Inbox] Updated Inbox object - # @!macro api_errors - # @raise [ArgumentError] If invalid options are provided - def update(inbox_id, options) - base_update(inbox_id, options, supported_options + [:email_username]) - end - - # Delete all messages (emails) from Inbox - # @param inbox_id [Integer] The Inbox identifier - # @return [Inbox] Updated Inbox object - # @!macro api_errors - def clean(inbox_id) - response = client.patch("#{base_path}/#{inbox_id}/clean") - handle_response(response) - end - - # Mark all messages in the inbox as read - # @param inbox_id [Integer] The Inbox identifier - # @return [Inbox] Updated Inbox object - # @!macro api_errors - def mark_as_read(inbox_id) - response = client.patch("#{base_path}/#{inbox_id}/all_read") - handle_response(response) - end - - # Reset SMTP credentials of the inbox - # @param inbox_id [Integer] The Inbox identifier - # @return [Inbox] Updated Inbox object - # @!macro api_errors - def reset_credentials(inbox_id) - response = client.patch("#{base_path}/#{inbox_id}/reset_credentials") - handle_response(response) - end - - # Turn the email address of the inbox on/off - # @param inbox_id [Integer] The Inbox identifier - # @return [Inbox] Updated Inbox object - # @!macro api_errors - def toggle_email_username(inbox_id) - response = client.patch("#{base_path}/#{inbox_id}/toggle_email_username") - handle_response(response) - end - - # Reset username of email address per inbox - # @param inbox_id [Integer] The Inbox identifier - # @return [Inbox] Updated Inbox object - # @!macro api_errors - def reset_email_username(inbox_id) - response = client.patch("#{base_path}/#{inbox_id}/reset_email_username") - handle_response(response) - end - - private - - def wrap_request(options) - { inbox: options } - end - - def base_path - "/api/accounts/#{account_id}/inboxes" + # @deprecated Use {SandboxesAPI} instead. + class InboxesAPI < SandboxesAPI + def initialize(*) + Deprecation.warn('Mailtrap::InboxesAPI', 'Mailtrap::SandboxesAPI') + super end end end diff --git a/lib/mailtrap/marketing_stats_api.rb b/lib/mailtrap/marketing_stats_api.rb index 60120a39..1cb3e23a 100644 --- a/lib/mailtrap/marketing_stats_api.rb +++ b/lib/mailtrap/marketing_stats_api.rb @@ -18,7 +18,7 @@ def initialize(client = Mailtrap::Client.new) # as Email Marketing > Stats Overview in the app. Email API/SMTP traffic is reported by {StatsAPI}. # @param start_date [String, Date, Time] Start of the period, inclusive (required) # @param end_date [String, Date, Time] End of the period, inclusive (required) - # @param sending_domain_ids [Array] Filter by sending domain IDs + # @param sending_domain_ids [Array] Filter by domain IDs # @param sources [Array] Filter by source: +campaigns+ or +automations+; # omit it, or pass both, to include campaigns and automations together # @param email_service_providers [Array] Filter by recipient email service providers diff --git a/lib/mailtrap/project.rb b/lib/mailtrap/project.rb index f8a6a367..7b35ba40 100644 --- a/lib/mailtrap/project.rb +++ b/lib/mailtrap/project.rb @@ -6,7 +6,7 @@ module Mailtrap # @attr_reader id [Integer] The project ID # @attr_reader name [String] The project name # @attr_reader share_links [Hash] Admin and viewer share links - # @attr_reader inboxes [Array] Array of inboxes + # @attr_reader inboxes [Array] Array of the project's sandboxes # @attr_reader permissions [Hash] List of permissions # Project = Struct.new( diff --git a/lib/mailtrap/projects_api.rb b/lib/mailtrap/projects_api.rb index 618d41ba..0f1acc2c 100644 --- a/lib/mailtrap/projects_api.rb +++ b/lib/mailtrap/projects_api.rb @@ -2,7 +2,7 @@ require_relative 'base_api' require_relative 'project' -require_relative 'inbox' +require_relative 'sandbox' module Mailtrap class ProjectsAPI @@ -60,7 +60,7 @@ def delete(project_id) def handle_response(response) build_entity( response.merge( - inboxes: response[:inboxes]&.map { |inbox| build_entity(inbox, Mailtrap::Inbox) } + inboxes: response[:inboxes]&.map { |sandbox| build_entity(sandbox, Mailtrap::Sandbox) } ), response_class ) diff --git a/lib/mailtrap/sandbox.rb b/lib/mailtrap/sandbox.rb new file mode 100644 index 00000000..0b28f5f8 --- /dev/null +++ b/lib/mailtrap/sandbox.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module Mailtrap + # Data Transfer Object for Sandbox + # @see https://api-docs.mailtrap.io/docs/mailtrap-api-docs/ee252e413d78a-create-project + # @attr_reader id [Integer] The sandbox ID + # @attr_reader name [String] The sandbox name + # @attr_reader username [String] The sandbox username + # @attr_reader password [String, nil] The sandbox password + # @attr_reader max_size [Integer] The maximum sandbox size in MB + # @attr_reader status [String] The sandbox status + # @attr_reader email_username [String] The email username + # @attr_reader email_username_enabled [Boolean] Whether the email username is enabled + # @attr_reader sent_messages_count [Integer] The count of sent messages + # @attr_reader forwarded_messages_count [Integer] The count of forwarded messages + # @attr_reader used [Boolean] Whether the sandbox has been used + # @attr_reader forward_from_email_address [String] The forwarding email address + # @attr_reader project_id [Integer] The associated project ID + # @attr_reader domain [String] The sandbox domain + # @attr_reader pop3_domain [String] The POP3 domain + # @attr_reader email_domain [String] The email domain + # @attr_reader api_domain [String] The API domain + # @attr_reader emails_count [Integer] The total number of emails + # @attr_reader emails_unread_count [Integer] The number of unread emails + # @attr_reader last_message_sent_at [String, nil] The timestamp of the last sent message + # @attr_reader smtp_ports [Array] The list of SMTP ports + # @attr_reader pop3_ports [Array] The list of POP3 ports + # @attr_reader max_message_size [Integer] The maximum message size in bytes + # @attr_reader permissions [Hash] List of permissions + Sandbox = Struct.new( + :id, + :name, + :username, + :password, + :max_size, + :status, + :email_username, + :email_username_enabled, + :sent_messages_count, + :forwarded_messages_count, + :used, + :forward_from_email_address, + :project_id, + :domain, + :pop3_domain, + :email_domain, + :api_domain, + :emails_count, + :emails_unread_count, + :last_message_sent_at, + :smtp_ports, + :pop3_ports, + :max_message_size, + :permissions, + keyword_init: true + ) +end diff --git a/lib/mailtrap/sandbox_attachments_api.rb b/lib/mailtrap/sandbox_attachments_api.rb index befe3ed8..4e5b4d85 100644 --- a/lib/mailtrap/sandbox_attachments_api.rb +++ b/lib/mailtrap/sandbox_attachments_api.rb @@ -1,32 +1,40 @@ # frozen_string_literal: true require_relative 'base_api' +require_relative 'deprecation' require_relative 'sandbox_attachment' module Mailtrap class SandboxAttachmentsAPI include BaseAPI - attr_reader :inbox_id, :sandbox_message_id + attr_reader :sandbox_id, :sandbox_message_id self.response_class = SandboxAttachment # @param account_id [Integer] The account ID - # @param inbox_id [Integer] The inbox ID + # @param sandbox_id [Integer] The sandbox ID # @param sandbox_message_id [Integer] The message ID # @param client [Mailtrap::Client] The client instance # @raise [ArgumentError] If account_id is nil - # @raise [ArgumentError] If inbox_id is nil - def initialize(account_id, inbox_id, sandbox_message_id, client = Mailtrap::Client.new) - raise ArgumentError, 'inbox_id is required' if inbox_id.nil? + # @raise [ArgumentError] If sandbox_id is nil + def initialize(account_id, sandbox_id, sandbox_message_id, client = Mailtrap::Client.new) + raise ArgumentError, 'sandbox_id is required' if sandbox_id.nil? raise ArgumentError, 'sandbox_message_id is required' if sandbox_message_id.nil? - @inbox_id = inbox_id + @sandbox_id = sandbox_id @sandbox_message_id = sandbox_message_id super(account_id, client) end + # @deprecated Use {#sandbox_id} instead. + # @return [Integer] The sandbox ID + def inbox_id + Deprecation.warn('Mailtrap::SandboxAttachmentsAPI#inbox_id', 'Mailtrap::SandboxAttachmentsAPI#sandbox_id') + sandbox_id + end + # Retrieves a specific sandbox attachment # @param sandbox_attachment_id [Integer] The sandbox attachment ID # @return [SandboxAttachment] Sandbox attachment object @@ -45,7 +53,7 @@ def list private def base_path - "/api/accounts/#{account_id}/inboxes/#{inbox_id}/messages/#{sandbox_message_id}/attachments" + "/api/accounts/#{account_id}/inboxes/#{sandbox_id}/messages/#{sandbox_message_id}/attachments" end end end diff --git a/lib/mailtrap/sandbox_message.rb b/lib/mailtrap/sandbox_message.rb index 0bbf7bfb..8f32d931 100644 --- a/lib/mailtrap/sandbox_message.rb +++ b/lib/mailtrap/sandbox_message.rb @@ -4,7 +4,7 @@ module Mailtrap # Data Transfer Object for Sandbox Message # @see https://docs.mailtrap.io/developers/email-sandbox/email-sandbox-api/messages # @attr_reader id [Integer] The message ID - # @attr_reader inbox_id [Integer] The inbox ID + # @attr_reader inbox_id [Integer] The sandbox ID # @attr_reader subject [String] The message subject # @attr_reader sent_at [String] The timestamp when the message was sent # @attr_reader from_email [String] The sender's email address diff --git a/lib/mailtrap/sandbox_messages_api.rb b/lib/mailtrap/sandbox_messages_api.rb index d0ba3740..ba4de88c 100644 --- a/lib/mailtrap/sandbox_messages_api.rb +++ b/lib/mailtrap/sandbox_messages_api.rb @@ -1,32 +1,40 @@ # frozen_string_literal: true require_relative 'base_api' +require_relative 'deprecation' require_relative 'sandbox_message' module Mailtrap class SandboxMessagesAPI include BaseAPI - attr_reader :inbox_id + attr_reader :sandbox_id self.supported_options = %i[is_read] self.response_class = SandboxMessage # @param account_id [Integer] The account ID - # @param inbox_id [Integer] The inbox ID + # @param sandbox_id [Integer] The sandbox ID # @param client [Mailtrap::Client] The client instance # @raise [ArgumentError] If account_id is nil - # @raise [ArgumentError] If inbox_id is nil - def initialize(account_id, inbox_id, client = Mailtrap::Client.new) - raise ArgumentError, 'inbox_id is required' if inbox_id.nil? + # @raise [ArgumentError] If sandbox_id is nil + def initialize(account_id, sandbox_id, client = Mailtrap::Client.new) + raise ArgumentError, 'sandbox_id is required' if sandbox_id.nil? - @inbox_id = inbox_id + @sandbox_id = sandbox_id super(account_id, client) end - # Retrieves a specific sandbox message from inbox + # @deprecated Use {#sandbox_id} instead. + # @return [Integer] The sandbox ID + def inbox_id + Deprecation.warn('Mailtrap::SandboxMessagesAPI#inbox_id', 'Mailtrap::SandboxMessagesAPI#sandbox_id') + sandbox_id + end + + # Retrieves a specific sandbox message # @param message_id [Integer] The sandbox message ID # @return [SandboxMessage] Sandbox message object # @!macro api_errors @@ -165,7 +173,7 @@ def mail_headers(message_id) private def base_path - "/api/accounts/#{account_id}/inboxes/#{inbox_id}/messages" + "/api/accounts/#{account_id}/inboxes/#{sandbox_id}/messages" end def wrap_request(options) diff --git a/lib/mailtrap/sandboxes_api.rb b/lib/mailtrap/sandboxes_api.rb new file mode 100644 index 00000000..8782fa8d --- /dev/null +++ b/lib/mailtrap/sandboxes_api.rb @@ -0,0 +1,117 @@ +# frozen_string_literal: true + +require_relative 'base_api' +require_relative 'sandbox' + +module Mailtrap + class SandboxesAPI + include BaseAPI + + self.supported_options = %i[name] + self.response_class = Sandbox + + # Lists all sandboxes for the account + # @return [Array] Array of sandboxes + # @!macro api_errors + def list + base_list + end + + # Retrieves a specific sandbox + # @param sandbox_id [Integer] The sandbox identifier + # @return [Sandbox] Sandbox object + # @!macro api_errors + def get(sandbox_id) + base_get(sandbox_id) + end + + # Creates a new sandbox + # @param [Hash] options The parameters to create + # @option options [String] :name The sandbox name + # @option options [Integer] :project_id The project ID. Required. + # @return [Sandbox] Created sandbox object + # @!macro api_errors + # @raise [ArgumentError] If invalid options are provided + def create(options) + validate_options!(options, supported_options + [:project_id]) + response = client.post("/api/accounts/#{account_id}/projects/#{options[:project_id]}/inboxes", + wrap_request(options)) + handle_response(response) + end + + # Deletes a sandbox + # @param sandbox_id [Integer] The sandbox identifier + # @return [Hash, nil] Deleted sandbox data, or nil when the API returns no content + # @!macro api_errors + def delete(sandbox_id) + base_delete(sandbox_id) + end + + # Updates an existing sandbox + # @param sandbox_id [Integer] The sandbox identifier + # @param [Hash] options The parameters to update + # @option options [String] :name The sandbox name + # @option options [String] :email_username The sandbox email username + # @return [Sandbox] Updated sandbox object + # @!macro api_errors + # @raise [ArgumentError] If invalid options are provided + def update(sandbox_id, options) + base_update(sandbox_id, options, supported_options + [:email_username]) + end + + # Delete all messages (emails) from the sandbox + # @param sandbox_id [Integer] The sandbox identifier + # @return [Sandbox] Updated sandbox object + # @!macro api_errors + def clean(sandbox_id) + response = client.patch("#{base_path}/#{sandbox_id}/clean") + handle_response(response) + end + + # Mark all messages in the sandbox as read + # @param sandbox_id [Integer] The sandbox identifier + # @return [Sandbox] Updated sandbox object + # @!macro api_errors + def mark_as_read(sandbox_id) + response = client.patch("#{base_path}/#{sandbox_id}/all_read") + handle_response(response) + end + + # Reset SMTP credentials of the sandbox + # @param sandbox_id [Integer] The sandbox identifier + # @return [Sandbox] Updated sandbox object + # @!macro api_errors + def reset_credentials(sandbox_id) + response = client.patch("#{base_path}/#{sandbox_id}/reset_credentials") + handle_response(response) + end + + # Turn the email address of the sandbox on/off + # @param sandbox_id [Integer] The sandbox identifier + # @return [Sandbox] Updated sandbox object + # @!macro api_errors + def toggle_email_username(sandbox_id) + response = client.patch("#{base_path}/#{sandbox_id}/toggle_email_username") + handle_response(response) + end + + # Reset username of email address per sandbox + # @param sandbox_id [Integer] The sandbox identifier + # @return [Sandbox] Updated sandbox object + # @!macro api_errors + def reset_email_username(sandbox_id) + response = client.patch("#{base_path}/#{sandbox_id}/reset_email_username") + handle_response(response) + end + + private + + def wrap_request(options) + { inbox: options } + end + + def base_path + "/api/accounts/#{account_id}/inboxes" + end + end +end diff --git a/lib/mailtrap/sending_domain.rb b/lib/mailtrap/sending_domain.rb index be37b911..507de84c 100644 --- a/lib/mailtrap/sending_domain.rb +++ b/lib/mailtrap/sending_domain.rb @@ -1,48 +1,9 @@ # frozen_string_literal: true +require_relative 'domain' + module Mailtrap - # Data Transfer Object for Sending Domain - # @see https://docs.mailtrap.io/developers/management/sending-domains - # @attr_reader id [Integer] The sending domain ID - # @attr_reader domain_name [String] The sending domain name - # @attr_reader demo [Boolean] Whether the sending domain is a demo domain - # @attr_reader compliance_status [String] The compliance status of the sending domain - # @attr_reader dns_verified [Boolean] Whether the DNS records are verified - # @attr_reader dns_verified_at [String, nil] The timestamp when DNS was verified - # @attr_reader dns_records [Array] The DNS records for the sending domain - # @attr_reader open_tracking_enabled [Boolean] Whether open tracking is enabled - # @attr_reader click_tracking_enabled [Boolean] Whether click tracking is enabled - # @attr_reader tracking_opt_out_enabled [Boolean] Whether the tracking opt-out link is enabled - # @attr_reader auto_unsubscribe_link_enabled [Boolean] Whether auto unsubscribe link is enabled - # @attr_reader custom_domain_tracking_enabled [Boolean] Whether custom domain tracking is enabled - # @attr_reader health_alerts_enabled [Boolean] Whether health alerts are enabled - # @attr_reader critical_alerts_enabled [Boolean] Whether critical alerts are enabled - # @attr_reader alert_recipient_email [String, nil] The email address for alert recipients - # @attr_reader inbound_enabled [Boolean] Whether inbound email is enabled for this domain - # @attr_reader inbound_verified [Boolean] Whether the domain's inbound MX records are verified - # @attr_reader permissions [Hash] The permissions for the sending domain - # - SendingDomain = Struct.new( - :id, - :domain_name, - :demo, - :compliance_status, - :dns_verified, - :dns_verified_at, - :dns_records, - :open_tracking_enabled, - :click_tracking_enabled, - :tracking_opt_out_enabled, - :auto_unsubscribe_link_enabled, - :custom_domain_tracking_enabled, - :health_alerts_enabled, - :critical_alerts_enabled, - :alert_recipient_email, - :inbound_enabled, - :inbound_verified, - :permissions, - :created_at, - :updated_at, - keyword_init: true - ) + # @deprecated Use {Domain} instead. + SendingDomain = Domain + deprecate_constant :SendingDomain end diff --git a/lib/mailtrap/sending_domains_api.rb b/lib/mailtrap/sending_domains_api.rb index fadedab2..50a80f58 100644 --- a/lib/mailtrap/sending_domains_api.rb +++ b/lib/mailtrap/sending_domains_api.rb @@ -1,88 +1,15 @@ # frozen_string_literal: true -require_relative 'base_api' +require_relative 'deprecation' +require_relative 'domains_api' require_relative 'sending_domain' module Mailtrap - class SendingDomainsAPI - include BaseAPI - - self.supported_options = %i[ - open_tracking_enabled - click_tracking_enabled - tracking_opt_out_enabled - auto_unsubscribe_link_enabled - inbound_enabled - ] - - self.response_class = SendingDomain - - # Lists all sending domains for the account - # @return [Array] Array of sending domains - # @!macro api_errors - def list - response = client.get(base_path) - response[:data].map { |item| handle_response(item) } - end - - # Retrieves a specific sending domain - # @param domain_id [Integer] The sending domain ID - # @return [SendingDomain] Sending domain object - # @!macro api_errors - def get(domain_id) - base_get(domain_id) - end - - # Creates a new sending domain - # @param [Hash] options The parameters to create - # @option options [String] :domain_name The sending domain name - # @return [SendingDomain] Created sending domain - # @!macro api_errors - # @raise [ArgumentError] If invalid options are provided - def create(options) - base_create(options, %i[domain_name]) - end - - # Deletes a sending domain - # @param domain_id [Integer] The sending domain ID - # @return nil - # @!macro api_errors - def delete(domain_id) - base_delete(domain_id) - end - - # Updates configuration settings for a sending domain - # @param domain_id [Integer] The sending domain ID - # @param [Hash] options The parameters to update - # @option options [Boolean] :open_tracking_enabled Enable open tracking for emails sent from this domain - # @option options [Boolean] :click_tracking_enabled Enable click tracking for links in emails sent from this domain - # @option options [Boolean] :tracking_opt_out_enabled Enable the tracking opt-out link in tracked emails - # @option options [Boolean] :auto_unsubscribe_link_enabled Automatically add an unsubscribe link to emails - # @option options [Boolean] :inbound_enabled Enable inbound email for this domain - # @return [SendingDomain] Updated sending domain - # @!macro api_errors - # @raise [ArgumentError] If invalid options are provided - def update(domain_id, options) - base_update(domain_id, options) - end - - # Email DNS configuration instructions for the sending domain - # @param domain_id [Integer] The sending domain ID - # @param email [String] The email for instructions - # @return nil - # @!macro api_errors - def send_setup_instructions(domain_id, email:) - client.post("#{base_path}/#{domain_id}/send_setup_instructions", email:) - end - - private - - def base_path - "/api/accounts/#{account_id}/sending_domains" - end - - def wrap_request(options) - { sending_domain: options } + # @deprecated Use {DomainsAPI} instead. + class SendingDomainsAPI < DomainsAPI + def initialize(*) + Deprecation.warn('Mailtrap::SendingDomainsAPI', 'Mailtrap::DomainsAPI') + super end end end diff --git a/lib/mailtrap/stats_api.rb b/lib/mailtrap/stats_api.rb index d4c867ca..5a5df428 100644 --- a/lib/mailtrap/stats_api.rb +++ b/lib/mailtrap/stats_api.rb @@ -20,7 +20,7 @@ class StatsAPI # Get aggregated sending stats # @param start_date [String, Date, Time] Start date for the stats period (required) # @param end_date [String, Date, Time] End date for the stats period (required) - # @param sending_domain_ids [Array] Filter by sending domain IDs + # @param sending_domain_ids [Array] Filter by domain IDs # @param sending_streams [Array] Filter by sending streams # @param categories [Array] Filter by categories # @param email_service_providers [Array] Filter by email service providers @@ -39,7 +39,7 @@ def get(start_date:, end_date:, sending_domain_ids: nil, sending_streams: nil, c # Get sending stats grouped by domain # @param start_date [String, Date, Time] Start date for the stats period (required) # @param end_date [String, Date, Time] End date for the stats period (required) - # @param sending_domain_ids [Array] Filter by sending domain IDs + # @param sending_domain_ids [Array] Filter by domain IDs # @param sending_streams [Array] Filter by sending streams # @param categories [Array] Filter by categories # @param email_service_providers [Array] Filter by email service providers @@ -54,7 +54,7 @@ def by_domain(start_date:, end_date:, sending_domain_ids: nil, sending_streams: # Get sending stats grouped by category # @param start_date [String, Date, Time] Start date for the stats period (required) # @param end_date [String, Date, Time] End date for the stats period (required) - # @param sending_domain_ids [Array] Filter by sending domain IDs + # @param sending_domain_ids [Array] Filter by domain IDs # @param sending_streams [Array] Filter by sending streams # @param categories [Array] Filter by categories # @param email_service_providers [Array] Filter by email service providers @@ -69,7 +69,7 @@ def by_category(start_date:, end_date:, sending_domain_ids: nil, sending_streams # Get sending stats grouped by email service provider # @param start_date [String, Date, Time] Start date for the stats period (required) # @param end_date [String, Date, Time] End date for the stats period (required) - # @param sending_domain_ids [Array] Filter by sending domain IDs + # @param sending_domain_ids [Array] Filter by domain IDs # @param sending_streams [Array] Filter by sending streams # @param categories [Array] Filter by categories # @param email_service_providers [Array] Filter by email service providers @@ -84,7 +84,7 @@ def by_email_service_provider(start_date:, end_date:, sending_domain_ids: nil, s # Get sending stats grouped by date # @param start_date [String, Date, Time] Start date for the stats period (required) # @param end_date [String, Date, Time] End date for the stats period (required) - # @param sending_domain_ids [Array] Filter by sending domain IDs + # @param sending_domain_ids [Array] Filter by domain IDs # @param sending_streams [Array] Filter by sending streams # @param categories [Array] Filter by categories # @param email_service_providers [Array] Filter by email service providers diff --git a/lib/mailtrap/tracking_opt_out.rb b/lib/mailtrap/tracking_opt_out.rb index c3710155..0ac35f63 100644 --- a/lib/mailtrap/tracking_opt_out.rb +++ b/lib/mailtrap/tracking_opt_out.rb @@ -6,7 +6,7 @@ module Mailtrap # @attr_reader id [String] The tracking opt-out UUID # @attr_reader email [String] The email address opted out of tracking # @attr_reader created_at [String] The creation timestamp - # @attr_reader domain_name [String, nil] Sending domain the tracking opt-out applies to + # @attr_reader domain_name [String, nil] Domain the tracking opt-out applies to TrackingOptOut = Struct.new( :id, :email, diff --git a/lib/mailtrap/tracking_opt_outs_api.rb b/lib/mailtrap/tracking_opt_outs_api.rb index 4f3238ba..fed3f675 100644 --- a/lib/mailtrap/tracking_opt_outs_api.rb +++ b/lib/mailtrap/tracking_opt_outs_api.rb @@ -39,10 +39,10 @@ def list(email: nil, start_time: nil, end_time: nil, last_id: nil) ) end - # Adds an email address to the tracking opt-out list for a sending domain + # Adds an email address to the tracking opt-out list for a domain # @param [Hash] options The tracking opt-out attributes # @option options [String] :email Email address to opt out of tracking - # @option options [Integer] :domain_id ID of the sending domain the opt-out applies to + # @option options [Integer] :domain_id ID of the domain the opt-out applies to # @return [TrackingOptOut] Created tracking opt-out # @!macro api_errors # @raise [ArgumentError] If invalid options are provided diff --git a/lib/mailtrap/webhook.rb b/lib/mailtrap/webhook.rb index 4204789f..617d7aeb 100644 --- a/lib/mailtrap/webhook.rb +++ b/lib/mailtrap/webhook.rb @@ -11,7 +11,7 @@ module Mailtrap # @attr_reader payload_format [String] The webhook payload format (`json` or `jsonlines`) # @attr_reader sending_stream [String, nil] The sending stream (`transactional` or `bulk`). # Applicable only for `email_sending` webhooks. - # @attr_reader domain_id [Integer, nil] The sending domain ID the webhook is scoped to, + # @attr_reader domain_id [Integer, nil] The domain ID the webhook is scoped to, # or nil for all domains. Applicable only for `email_sending` webhooks. # @attr_reader inbound_inbox_id [Integer, nil] The inbound inbox ID the webhook is linked to. # Applicable only for `inbound_receiving` webhooks. diff --git a/lib/mailtrap/webhooks_api.rb b/lib/mailtrap/webhooks_api.rb index 82dc0b33..fc5ec661 100644 --- a/lib/mailtrap/webhooks_api.rb +++ b/lib/mailtrap/webhooks_api.rb @@ -39,7 +39,7 @@ def get(webhook_id) # Required for `email_sending` webhook type. # @option options [Array] :event_types Event types to subscribe to. # Required for `email_sending` webhook type. - # @option options [Integer] :domain_id Sending domain ID to scope the webhook to. + # @option options [Integer] :domain_id Domain ID to scope the webhook to. # Applicable only for `email_sending` webhooks. # @option options [Integer] :inbound_inbox_id Inbound inbox ID to link the webhook to. # Applicable only for `inbound_receiving` webhooks; omit to apply to all inboxes diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_CompanyInfoAPI/_create/when_sending_domain_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_CompanyInfoAPI/_create/when_domain_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_CompanyInfoAPI/_create/when_sending_domain_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_CompanyInfoAPI/_create/when_domain_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_CompanyInfoAPI/_get/when_sending_domain_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_CompanyInfoAPI/_get/when_domain_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_CompanyInfoAPI/_get/when_sending_domain_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_CompanyInfoAPI/_get/when_domain_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_CompanyInfoAPI/_update/when_sending_domain_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_CompanyInfoAPI/_update/when_domain_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_CompanyInfoAPI/_update/when_sending_domain_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_CompanyInfoAPI/_update/when_domain_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_create/maps_response_data_to_sending_domain_object.yml b/spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_create/maps_response_data_to_domain_object.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_create/maps_response_data_to_sending_domain_object.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_create/maps_response_data_to_domain_object.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_create/when_API_returns_an_error/raises_a_Mailtrap_Error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_create/when_API_returns_an_error/raises_a_Mailtrap_Error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_create/when_API_returns_an_error/raises_a_Mailtrap_Error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_create/when_API_returns_an_error/raises_a_Mailtrap_Error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_delete/returns_deleted_sending_domain_data.yml b/spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_delete/returns_deleted_domain_data.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_delete/returns_deleted_sending_domain_data.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_delete/returns_deleted_domain_data.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_delete/when_sending_domain_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_delete/when_domain_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_delete/when_sending_domain_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_delete/when_domain_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_get/maps_response_data_to_SendingDomain_object.yml b/spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_get/maps_response_data_to_Domain_object.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_get/maps_response_data_to_SendingDomain_object.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_get/maps_response_data_to_Domain_object.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_get/when_sending_domain_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_get/when_domain_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_get/when_sending_domain_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_get/when_domain_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_list/maps_response_data_to_SendingDomain_objects.yml b/spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_list/maps_response_data_to_Domain_objects.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_list/maps_response_data_to_SendingDomain_objects.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_list/maps_response_data_to_Domain_objects.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_list/when_api_key_is_incorrect/raises_authorization_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_list/when_api_key_is_incorrect/raises_authorization_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_list/when_api_key_is_incorrect/raises_authorization_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_list/when_api_key_is_incorrect/raises_authorization_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_send_setup_instructions/returns_nil.yml b/spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_send_setup_instructions/returns_nil.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_send_setup_instructions/returns_nil.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_send_setup_instructions/returns_nil.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_send_setup_instructions/when_sending_domain_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_send_setup_instructions/when_domain_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_send_setup_instructions/when_sending_domain_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_send_setup_instructions/when_domain_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_update/maps_response_data_to_SendingDomain_object.yml b/spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_update/maps_response_data_to_Domain_object.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_update/maps_response_data_to_SendingDomain_object.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_update/maps_response_data_to_Domain_object.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_update/when_sending_domain_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_update/when_domain_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_update/when_sending_domain_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_DomainsAPI/_update/when_domain_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_clean/cleans_Inbox_and_returns_Inbox_object.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_clean/cleans_Sandbox_and_returns_Sandbox_object.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_clean/cleans_Inbox_and_returns_Inbox_object.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_clean/cleans_Sandbox_and_returns_Sandbox_object.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_clean/when_inbox_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_clean/when_sandbox_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_clean/when_inbox_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_clean/when_sandbox_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_create/maps_response_data_to_Inbox_object.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_create/maps_response_data_to_Sandbox_object.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_create/maps_response_data_to_Inbox_object.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_create/maps_response_data_to_Sandbox_object.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_create/when_API_returns_an_error/raises_a_Mailtrap_Error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_create/when_API_returns_an_error/raises_a_Mailtrap_Error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_create/when_API_returns_an_error/raises_a_Mailtrap_Error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_create/when_API_returns_an_error/raises_a_Mailtrap_Error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_delete/returns_deleted_inbox_data.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_delete/returns_deleted_sandbox_data.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_delete/returns_deleted_inbox_data.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_delete/returns_deleted_sandbox_data.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_delete/when_inbox_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_delete/when_sandbox_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_delete/when_inbox_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_delete/when_sandbox_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_get/maps_response_data_to_Inbox_object.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_get/maps_response_data_to_Sandbox_object.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_get/maps_response_data_to_Inbox_object.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_get/maps_response_data_to_Sandbox_object.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_get/when_inbox_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_get/when_sandbox_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_get/when_inbox_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_get/when_sandbox_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_list/maps_response_data_to_Inboxes_objects.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_list/maps_response_data_to_Sandbox_objects.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_list/maps_response_data_to_Inboxes_objects.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_list/maps_response_data_to_Sandbox_objects.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_list/when_api_key_is_incorrect/raises_authorization_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_list/when_api_key_is_incorrect/raises_authorization_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_list/when_api_key_is_incorrect/raises_authorization_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_list/when_api_key_is_incorrect/raises_authorization_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_mark_as_read/returns_nil.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_mark_as_read/returns_nil.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_mark_as_read/returns_nil.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_mark_as_read/returns_nil.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_mark_as_read/when_inbox_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_mark_as_read/when_sandbox_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_mark_as_read/when_inbox_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_mark_as_read/when_sandbox_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_reset_credentials/returns_nil.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_reset_credentials/returns_nil.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_reset_credentials/returns_nil.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_reset_credentials/returns_nil.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_reset_credentials/when_inbox_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_reset_credentials/when_sandbox_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_reset_credentials/when_inbox_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_reset_credentials/when_sandbox_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_reset_email_username/returns_Inbox_object.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_reset_email_username/returns_Sandbox_object.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_reset_email_username/returns_Inbox_object.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_reset_email_username/returns_Sandbox_object.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_reset_email_username/when_inbox_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_reset_email_username/when_sandbox_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_reset_email_username/when_inbox_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_reset_email_username/when_sandbox_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_toggle_email_username/returns_Inbox_object.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_toggle_email_username/returns_Sandbox_object.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_toggle_email_username/returns_Inbox_object.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_toggle_email_username/returns_Sandbox_object.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_toggle_email_username/when_inbox_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_toggle_email_username/when_sandbox_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_toggle_email_username/when_inbox_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_toggle_email_username/when_sandbox_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_update/maps_response_data_to_Inbox_object.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_update/maps_response_data_to_Sandbox_object.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_update/maps_response_data_to_Inbox_object.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_update/maps_response_data_to_Sandbox_object.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_update/when_inbox_does_not_exist/raises_not_found_error.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_update/when_sandbox_does_not_exist/raises_not_found_error.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_update/when_inbox_does_not_exist/raises_not_found_error.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_update/when_sandbox_does_not_exist/raises_not_found_error.yml diff --git a/spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_update/with_hash_request/maps_response_data_to_Inbox_object.yml b/spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_update/with_hash_request/maps_response_data_to_Sandbox_object.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_update/with_hash_request/maps_response_data_to_Inbox_object.yml rename to spec/fixtures/vcr_cassettes/Mailtrap_SandboxesAPI/_update/with_hash_request/maps_response_data_to_Sandbox_object.yml diff --git a/spec/mailtrap/action_mailer/delivery_method_spec.rb b/spec/mailtrap/action_mailer/delivery_method_spec.rb index f4446672..55eac72f 100644 --- a/spec/mailtrap/action_mailer/delivery_method_spec.rb +++ b/spec/mailtrap/action_mailer/delivery_method_spec.rb @@ -51,5 +51,52 @@ expect(message['X-MT-Message-IDs'].to_s).to eq(expected_message_ids.join(', ')) expect(Mailtrap::Client).to have_received(:new).with(api_key: 'correct-api-key') end + + context 'with sandbox settings' do + let(:settings) { { api_key: 'correct-api-key', sandbox: true, sandbox_id: 12 } } + + before do + stub_request(:post, 'https://sandbox.api.mailtrap.io/api/send/12') + .to_return(status: 200, body: '{"success":true,"message_ids":["1"]}', + headers: { 'Content-Type' => 'application/json' }) + end + + it 'sends to the sandbox' do + expect(deliver!).to eq({ success: true, message_ids: ['1'] }) + expect(Mailtrap::Client).to have_received(:new).with(api_key: 'correct-api-key', sandbox: true, sandbox_id: 12) + end + + context 'when the deprecated inbox_id is set' do + let(:settings) { { api_key: 'correct-api-key', sandbox: true, inbox_id: 12 } } + + it 'passes it to the client as sandbox_id and warns about the setting' do + expect { deliver! } + .to output(/ActionMailer mailtrap_settings inbox_id is deprecated .*; use sandbox_id instead/).to_stderr + expect(Mailtrap::Client).to have_received(:new).with(api_key: 'correct-api-key', sandbox: true, + sandbox_id: 12) + end + end + + context 'when sandbox_id and the deprecated inbox_id are both set' do + let(:settings) { { api_key: 'correct-api-key', sandbox: true, sandbox_id: 12, inbox_id: 12 } } + + it 'passes only sandbox_id to the client and warns about the setting' do + expect { deliver! } + .to output(/ActionMailer mailtrap_settings inbox_id is deprecated .*; use sandbox_id instead/).to_stderr + expect(Mailtrap::Client).to have_received(:new).with(api_key: 'correct-api-key', sandbox: true, + sandbox_id: 12) + end + end + + context 'when sandbox_id and the deprecated inbox_id differ' do + let(:settings) { { api_key: 'correct-api-key', sandbox: true, sandbox_id: 12, inbox_id: 13 } } + + it 'raises' do + expect { deliver! } + .to raise_error(ArgumentError, 'sandbox_id and inbox_id differ; pass only sandbox_id') + .and output.to_stderr + end + end + end end end diff --git a/spec/mailtrap/client_spec.rb b/spec/mailtrap/client_spec.rb index 65d8a44f..5246724d 100644 --- a/spec/mailtrap/client_spec.rb +++ b/spec/mailtrap/client_spec.rb @@ -89,7 +89,7 @@ context 'with sandbox flag' do let(:client) do - described_class.new(api_key:, sandbox: true, inbox_id: 12) + described_class.new(api_key:, sandbox: true, sandbox_id: 12) end it 'chooses host for sandbox sending' do @@ -97,12 +97,27 @@ end end - context 'with sandbox flag without inbox id' do + context 'with sandbox flag and the deprecated inbox id' do + let(:client) do + described_class.new(api_key:, sandbox: true, inbox_id: 12) + end + + it 'chooses host for sandbox sending and warns', vcr: { + cassette_name: 'Mailtrap_Client/_send/when_mail/with_sandbox_flag/chooses_host_for_sandbox_sending' + } do + expect { send } + .to output(/client_spec.rb:\d+: .*Client.new\(inbox_id:\) is deprecated .*Client.new\(sandbox_id:\)/) + .to_stderr + expect(send).to eq({ success: true }) + end + end + + context 'with sandbox flag without sandbox id' do let(:client) do described_class.new(api_key:, sandbox: true) end - it { expect { send }.to raise_error(ArgumentError, 'inbox_id is required for sandbox API') } + it { expect { send }.to raise_error(ArgumentError, 'sandbox_id is required for sandbox API') } end context 'with bulk and sandbox flag' do @@ -170,7 +185,7 @@ context 'when using sandbox' do let(:client) do - described_class.new(api_key:, sandbox: true, inbox_id: 13) + described_class.new(api_key:, sandbox: true, sandbox_id: 13) end it 'sending is successful' do @@ -333,7 +348,7 @@ def stub_post(path, status, body) end context 'when in sandbox mode' do - let(:client) { described_class.new(api_key:, sandbox: true, inbox_id: 3_861_666) } + let(:client) { described_class.new(api_key:, sandbox: true, sandbox_id: 3_861_666) } it 'successfully sends a batch of emails', :vcr do response = client.send_batch(base_mail, recipients) @@ -403,4 +418,37 @@ def stub_post(path, status, body) end end end + + describe 'deprecated inbox_id' do + it 'accepts the same value in sandbox_id' do + client = nil + + expect { client = described_class.new(api_key:, sandbox: true, sandbox_id: 12, inbox_id: 12) }.to output.to_stderr + expect(client.sandbox_id).to eq(12) + end + + it 'accepts the same value given as a string in sandbox_id' do + client = nil + + expect { client = described_class.new(api_key:, sandbox: true, sandbox_id: '12', inbox_id: 12) } + .to output.to_stderr + expect(client.sandbox_id).to eq('12') + end + + it 'raises when it differs from sandbox_id' do + expect { described_class.new(api_key:, sandbox: true, sandbox_id: 12, inbox_id: 13) } + .to raise_error(ArgumentError, 'sandbox_id and inbox_id differ; pass only sandbox_id') + .and output.to_stderr + end + + it 'is still readable and warns' do + client = described_class.new(api_key:, sandbox: true, sandbox_id: 12) + inbox_id = nil + + expect { inbox_id = client.inbox_id } + .to output(/client_spec.rb:\d+: .*Mailtrap::Client#inbox_id is deprecated .*; use Mailtrap::Client#sandbox_id/) + .to_stderr + expect(inbox_id).to eq(12) + end + end end diff --git a/spec/mailtrap/company_info_api_spec.rb b/spec/mailtrap/company_info_api_spec.rb index fb50dc22..f38c92e8 100644 --- a/spec/mailtrap/company_info_api_spec.rb +++ b/spec/mailtrap/company_info_api_spec.rb @@ -5,10 +5,10 @@ let(:account_id) { ENV.fetch('MAILTRAP_ACCOUNT_ID', 1_111_111) } let(:client) { Mailtrap::Client.new(api_key: ENV.fetch('MAILTRAP_API_KEY', 'local-api-key')) } - let(:sending_domain_id) { 122_392 } + let(:domain_id) { 122_392 } describe '#get' do - subject(:get) { company_info_api.get(sending_domain_id) } + subject(:get) { company_info_api.get(domain_id) } it 'maps response data to CompanyInfo object' do expect(get).to be_a(Mailtrap::CompanyInfo) @@ -23,8 +23,8 @@ ) end - context 'when sending domain does not exist' do - let(:sending_domain_id) { -1 } + context 'when domain does not exist' do + let(:domain_id) { -1 } it 'raises not found error' do expect { get }.to raise_error do |error| @@ -37,7 +37,7 @@ end describe '#create' do - subject(:create) { company_info_api.create(sending_domain_id, request) } + subject(:create) { company_info_api.create(domain_id, request) } let(:request) do { @@ -90,8 +90,8 @@ end end - context 'when sending domain does not exist' do - let(:sending_domain_id) { -1 } + context 'when domain does not exist' do + let(:domain_id) { -1 } it 'raises not found error' do expect { create }.to raise_error do |error| @@ -104,7 +104,7 @@ end describe '#update' do - subject(:update) { company_info_api.update(sending_domain_id, request) } + subject(:update) { company_info_api.update(domain_id, request) } let(:request) do { @@ -129,8 +129,8 @@ end end - context 'when sending domain does not exist' do - let(:sending_domain_id) { -1 } + context 'when domain does not exist' do + let(:domain_id) { -1 } it 'raises not found error' do expect { update }.to raise_error do |error| diff --git a/spec/mailtrap/deprecation_spec.rb b/spec/mailtrap/deprecation_spec.rb new file mode 100644 index 00000000..20dd0c40 --- /dev/null +++ b/spec/mailtrap/deprecation_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +RSpec.describe Mailtrap::Deprecation do + describe '.warn' do + it 'warns once per deprecated name' do + expect { described_class.warn('Old', 'New') }.to output( + /warning: \[mailtrap\] Old is deprecated and will be removed in a future major release; use New instead\.$/ + ).to_stderr + expect { described_class.warn('Old', 'New') }.not_to output.to_stderr + expect { described_class.warn('Older', 'New') }.to output(/Older is deprecated/).to_stderr + end + end +end diff --git a/spec/mailtrap/domain_spec.rb b/spec/mailtrap/domain_spec.rb new file mode 100644 index 00000000..e36c7b0b --- /dev/null +++ b/spec/mailtrap/domain_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +RSpec.describe Mailtrap::Domain do + describe '#initialize' do + subject(:domain) { described_class.new(attributes) } + + let(:attributes) do + { + id: '123456', + domain_name: 'My Domain', + dns_verified: false, + compliance_status: 'pending', + created_at: '2024-01-01T00:00:00Z', + updated_at: '2024-01-02T00:00:00Z' + } + end + + it 'creates a domain with all attributes' do + expect(domain).to have_attributes( + id: '123456', + domain_name: 'My Domain', + dns_verified: false, + compliance_status: 'pending', + created_at: '2024-01-01T00:00:00Z', + updated_at: '2024-01-02T00:00:00Z' + ) + end + end + + describe 'deprecated Mailtrap::SendingDomain alias', :ruby_deprecation_warnings do + it 'is Domain and warns when deprecation warnings are enabled' do + constant = nil + + expect { constant = Mailtrap::SendingDomain } + .to output(/constant Mailtrap::SendingDomain is deprecated/).to_stderr + expect(constant).to be(described_class) + end + end +end diff --git a/spec/mailtrap/domains_api_spec.rb b/spec/mailtrap/domains_api_spec.rb new file mode 100644 index 00000000..d39692e2 --- /dev/null +++ b/spec/mailtrap/domains_api_spec.rb @@ -0,0 +1,242 @@ +# frozen_string_literal: true + +RSpec.describe Mailtrap::DomainsAPI, :vcr do + subject(:domains_api) { described_class.new(account_id, client) } + + let(:account_id) { ENV.fetch('MAILTRAP_ACCOUNT_ID', 1_111_111) } + let(:client) { Mailtrap::Client.new(api_key: ENV.fetch('MAILTRAP_API_KEY', 'local-api-key')) } + + describe '#list' do + subject(:list) { domains_api.list } + + it 'maps response data to Domain objects' do + expect(list).not_to be_empty + expect(list).to all(be_a(Mailtrap::Domain)) + end + + context 'when api key is incorrect' do + let(:client) { Mailtrap::Client.new(api_key: 'incorrect-api-key') } + + it 'raises authorization error' do + expect { list }.to raise_error do |error| + expect(error).to be_a(Mailtrap::AuthorizationError) + expect(error.message).to include('Incorrect API token') + expect(error.messages.any? { |msg| msg.include?('Incorrect API token') }).to be true + end + end + end + end + + describe '#get' do + subject(:get) { domains_api.get(domain_id) } + + let(:domain_id) { 617_882 } + + it 'maps response data to Domain object' do + expect(get).to be_a(Mailtrap::Domain) + + expect(get).to match_struct( + id: 617_882, + domain_name: 'demomailtrap.co', + demo: true, + compliance_status: 'demo', + dns_verified: true, + dns_verified_at: '2025-05-21T14:04:52.363Z', + dns_records: + [ + { key: 'verification', domain: 'demo.demomailtrap.co', type: 'CNAME', value: 'smtp.mailtrap.live', + status: 'pass', name: 'demo' }, + { key: 'dkim1', domain: 'rwmt1._domainkey.demomailtrap.co', type: 'CNAME', + value: 'rwmt1.dkim.smtp.mailtrap.live', status: 'pass', name: 'rwmt1._domainkey' }, + { key: 'dkim2', domain: 'rwmt2._domainkey.demomailtrap.co', type: 'CNAME', + value: 'rwmt2.dkim.smtp.mailtrap.live', status: 'pass', name: 'rwmt2._domainkey' }, + { key: 'dmarc', name: '_dmarc' }, + { key: 'link_verification', domain: 'mt-link.demomailtrap.co', type: 'CNAME', value: 't.mailtrap.live', + status: 'pass', name: 'mt-link' } + ], + open_tracking_enabled: true, + click_tracking_enabled: false, + tracking_opt_out_enabled: false, + auto_unsubscribe_link_enabled: false, + custom_domain_tracking_enabled: false, + health_alerts_enabled: true, + critical_alerts_enabled: true, + alert_recipient_email: nil, + inbound_enabled: false, + inbound_verified: false, + permissions: { can_read: true, can_update: true, can_destroy: true }, + created_at: nil, + updated_at: nil + ) + end + + context 'when domain does not exist' do + let(:domain_id) { -1 } + + it 'raises not found error' do + expect { get }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('Not Found') + expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true + end + end + end + end + + describe '#create' do + subject(:create) { domains_api.create(**request) } + + let(:request) do + { + domain_name: 'mailtrappio.com' + } + end + + it 'maps response data to domain object' do + expect(create).to be_a(Mailtrap::Domain) + + expect(create).to match_struct( + id: 943_758, + domain_name: 'mailtrappio.com', + demo: false, + compliance_status: 'unverified_dns', + dns_verified: false, + dns_verified_at: '', + dns_records: + [ + { key: 'verification', domain: 'mt07.mailtrappio.com', type: 'CNAME', value: 'smtp.mailtrap.live', + status: 'missing', name: 'mt07' }, + { key: 'dkim1', domain: 'rwmt1._domainkey.mailtrappio.com', type: 'CNAME', + value: 'rwmt1.dkim.smtp.mailtrap.live', status: 'missing', name: 'rwmt1._domainkey' }, + { key: 'dkim2', domain: 'rwmt2._domainkey.mailtrappio.com', type: 'CNAME', + value: 'rwmt2.dkim.smtp.mailtrap.live', status: 'missing', name: 'rwmt2._domainkey' }, + { key: 'dmarc', name: '_dmarc' }, + { key: 'link_verification', domain: 'mt-link.mailtrappio.com', type: 'CNAME', value: 't.mailtrap.live', + status: 'missing', name: 'mt-link' } + ], + open_tracking_enabled: true, + click_tracking_enabled: false, + tracking_opt_out_enabled: false, + auto_unsubscribe_link_enabled: false, + custom_domain_tracking_enabled: false, + health_alerts_enabled: true, + critical_alerts_enabled: true, + alert_recipient_email: nil, + inbound_enabled: false, + inbound_verified: false, + permissions: { can_read: true, can_update: true, can_destroy: true }, + created_at: nil, + updated_at: nil + ) + end + + context 'when API returns an error' do + let(:request) do + { + domain_name: '' # Invalid value, but present + } + end + + it 'raises a Mailtrap::Error' do + expect { create }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('client error') + end + end + end + end + + describe '#send_setup_instructions' do + subject(:send_setup_instructions) do + domains_api.send_setup_instructions(domain_id, email: 'example@railsware.com') + end + + let(:domain_id) { 943_758 } + + it 'returns nil' do + expect(send_setup_instructions).to be_nil + end + + context 'when domain does not exist' do + let(:domain_id) { -1 } + + it 'raises not found error' do + expect { send_setup_instructions }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('Not Found') + expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true + end + end + end + end + + describe '#delete' do + subject(:delete) { domains_api.delete(domain_id) } + + let(:domain_id) { 943_758 } + + it 'returns deleted domain data' do + expect(delete).to be_nil + end + + context 'when domain does not exist' do + let(:domain_id) { -1 } + + it 'raises not found error' do + expect { delete }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('Not Found') + expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true + end + end + end + end + + describe '#update' do + subject(:update) { domains_api.update(domain_id, **request) } + + let(:domain_id) { 61_802 } + + let(:request) do + { + open_tracking_enabled: true, + click_tracking_enabled: true, + tracking_opt_out_enabled: true, + auto_unsubscribe_link_enabled: false, + inbound_enabled: false + } + end + + it 'maps response data to Domain object' do + expect(update).to be_a(Mailtrap::Domain) + expect(update).to have_attributes( + id: domain_id, + open_tracking_enabled: true, + click_tracking_enabled: true, + tracking_opt_out_enabled: true, + auto_unsubscribe_link_enabled: false, + inbound_enabled: false + ) + end + + context 'when invalid options are provided' do + let(:request) { { unknown_option: true } } + + it 'raises ArgumentError' do + expect { update }.to raise_error(ArgumentError, /invalid options are given/) + end + end + + context 'when domain does not exist' do + let(:domain_id) { -1 } + + it 'raises not found error' do + expect { update }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('Not Found') + expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true + end + end + end + end +end diff --git a/spec/mailtrap/inboxes_api_spec.rb b/spec/mailtrap/inboxes_api_spec.rb index e2f730b4..f80c7e93 100644 --- a/spec/mailtrap/inboxes_api_spec.rb +++ b/spec/mailtrap/inboxes_api_spec.rb @@ -1,287 +1,35 @@ # frozen_string_literal: true -RSpec.describe Mailtrap::InboxesAPI, :vcr do - subject(:inboxes_api) { described_class.new(account_id, client) } +RSpec.describe Mailtrap::InboxesAPI do + let(:client) { Mailtrap::Client.new(api_key: 'local-api-key') } - let(:account_id) { ENV.fetch('MAILTRAP_ACCOUNT_ID', 1_111_111) } - let(:client) { Mailtrap::Client.new(api_key: ENV.fetch('MAILTRAP_API_KEY', 'local-api-key')) } + it 'works as SandboxesAPI and warns that it is deprecated', + vcr: { cassette_name: 'Mailtrap_SandboxesAPI/_list/maps_response_data_to_Sandbox_objects' } do + inboxes_api = nil - describe '#list' do - subject(:list) { inboxes_api.list } - - it 'maps response data to Inboxes objects' do - expect(list).to all(be_a(Mailtrap::Inbox)) - end - - context 'when api key is incorrect' do - let(:client) { Mailtrap::Client.new(api_key: 'incorrect-api-key') } - - it 'raises authorization error' do - expect { list }.to raise_error do |error| - expect(error).to be_a(Mailtrap::AuthorizationError) - expect(error.message).to include('Incorrect API token') - expect(error.messages.any? { |msg| msg.include?('Incorrect API token') }).to be true - end - end - end - end - - describe '#get' do - subject(:get) { inboxes_api.get(inbox_id) } - - let(:inbox_id) { 4_278_175 } - - it 'maps response data to Inbox object' do - expect(get).to be_a(Mailtrap::Inbox) - expect(get).to have_attributes( - id: inbox_id, - name: 'Test Inbox' - ) - end - - context 'when inbox does not exist' do - let(:inbox_id) { -1 } - - it 'raises not found error' do - expect { get }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('Not Found') - expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true - end - end - end - end - - describe '#create' do - subject(:create) { inboxes_api.create(**request) } - - let(:request) do - { - name: 'Test Inbox', - project_id: 2_379_735 - } - end - - it 'maps response data to Inbox object' do - expect(create).to be_a(Mailtrap::Inbox) - expect(create).to have_attributes( - name: 'Test Inbox' - ) - end - - context 'when API returns an error' do - let(:request) do - { - name: '', # Invalid value, but present - project_id: 2_379_735 - } - end - - it 'raises a Mailtrap::Error' do - expect { create }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('client error') - end - end - end - end - - describe '#update' do - subject(:update) { inboxes_api.update(inbox_id, **request) } - - let(:inbox_id) { 4_278_175 } - - let(:request) do - { - name: 'Updated Inbox', - email_username: 'updated_username' - } - end - - it 'maps response data to Inbox object' do - expect(update).to be_a(Mailtrap::Inbox) - expect(update).to have_attributes( - name: 'Updated Inbox', - email_username: '1234abcd' - ) - end - - context 'with hash request' do - let(:request) do - { - name: 'Updated Inbox' - } - end - - it 'maps response data to Inbox object' do - expect(update).to be_a(Mailtrap::Inbox) - expect(update).to have_attributes( - name: 'Updated Inbox' - ) - end - end - - context 'when inbox does not exist' do - let(:inbox_id) { -1 } - - it 'raises not found error' do - expect { update }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('Not Found') - expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true - end - end - end - end - - describe '#clean' do - subject(:clean) { inboxes_api.clean(inbox_id) } - - let(:inbox_id) { 4_278_175 } - - it 'cleans Inbox and returns Inbox object' do - expect(clean).to have_attributes( - id: inbox_id, - name: 'Updated Inbox' - ) - end - - context 'when inbox does not exist' do - let(:inbox_id) { -1 } - - it 'raises not found error' do - expect { clean }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('Not Found') - expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true - end - end - end - end - - describe '#mark_as_read' do - subject(:mark_as_read) { inboxes_api.mark_as_read(inbox_id) } - - let(:inbox_id) { 4_278_175 } - - it 'returns nil' do - expect(mark_as_read).to have_attributes( - id: inbox_id, - name: 'Updated Inbox' - ) - end - - context 'when inbox does not exist' do - let(:inbox_id) { -1 } - - it 'raises not found error' do - expect { mark_as_read }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('Not Found') - expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true - end - end - end + expect { inboxes_api = described_class.new(1_111_111, client) } + .to output(/inboxes_api_spec.rb:\d+: .*Mailtrap::InboxesAPI is deprecated .*; use Mailtrap::SandboxesAPI/).to_stderr + expect(inboxes_api).to be_a(Mailtrap::SandboxesAPI) + expect(inboxes_api.list).to all(be_a(Mailtrap::Sandbox)) end - describe '#reset_credentials' do - subject(:reset_credentials) { inboxes_api.reset_credentials(inbox_id) } - - let(:inbox_id) { 4_278_175 } - - it 'returns nil' do - expect(reset_credentials).to have_attributes( - id: inbox_id, - name: 'Updated Inbox' - ) - end + it 'creates a sandbox with the options it inherits', + vcr: { cassette_name: 'Mailtrap_SandboxesAPI/_create/maps_response_data_to_Sandbox_object' } do + sandbox = nil - context 'when inbox does not exist' do - let(:inbox_id) { -1 } - - it 'raises not found error' do - expect { reset_credentials }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('Not Found') - expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true - end - end - end + expect { sandbox = described_class.new(1_111_111, client).create(name: 'Test Inbox', project_id: 2_379_735) } + .to output.to_stderr + expect(sandbox).to be_a(Mailtrap::Sandbox).and have_attributes(name: 'Test Inbox') end - describe '#toggle_email_username' do - subject(:toggle_email_username) { inboxes_api.toggle_email_username(inbox_id) } - - let(:inbox_id) { 4_578_672 } - - it 'returns Inbox object' do - expect(toggle_email_username).to be_a(Mailtrap::Inbox) - expect(toggle_email_username).to have_attributes( - id: inbox_id, - email_username_enabled: true - ) - end - - context 'when inbox does not exist' do - let(:inbox_id) { -1 } - - it 'raises not found error' do - expect { toggle_email_username }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('Not Found') - expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true - end - end - end - end - - describe '#reset_email_username' do - subject(:reset_email_username) { inboxes_api.reset_email_username(inbox_id) } - - let(:inbox_id) { 4_578_672 } - - it 'returns Inbox object' do - expect(reset_email_username).to have_attributes( - id: inbox_id, - email_username: '1234abcd' - ) - end - - context 'when inbox does not exist' do - let(:inbox_id) { -1 } - - it 'raises not found error' do - expect { reset_email_username }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('Not Found') - expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true - end - end - end - end - - describe '#delete' do - subject(:delete) { inboxes_api.delete(inbox_id) } - - let(:inbox_id) { 4_278_175 } - - it 'returns deleted inbox data' do - expect(delete).to include( - id: inbox_id, - name: 'Updated Inbox' - ) - end - - context 'when inbox does not exist' do - let(:inbox_id) { -1 } + it 'updates a sandbox with the options it inherits', + vcr: { cassette_name: 'Mailtrap_SandboxesAPI/_update/maps_response_data_to_Sandbox_object' } do + sandbox = nil - it 'raises not found error' do - expect { delete }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('Not Found') - expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true - end - end - end + expect do + sandbox = described_class.new(1_111_111, client) + .update(4_278_175, name: 'Updated Inbox', email_username: 'updated_username') + end.to output.to_stderr + expect(sandbox).to be_a(Mailtrap::Sandbox).and have_attributes(name: 'Updated Inbox') end end diff --git a/spec/mailtrap/projects_api_spec.rb b/spec/mailtrap/projects_api_spec.rb index e16ca1d2..91ddd74e 100644 --- a/spec/mailtrap/projects_api_spec.rb +++ b/spec/mailtrap/projects_api_spec.rb @@ -38,7 +38,7 @@ name: 'Ruby SDK Project' ) - expect(get.inboxes).to all(be_a(Mailtrap::Inbox)) + expect(get.inboxes).to all(be_a(Mailtrap::Sandbox)) expect(get.inboxes.first).to match_struct( id: 4_294_015, name: 'Main sandbox', diff --git a/spec/mailtrap/sandbox_attachments_api_spec.rb b/spec/mailtrap/sandbox_attachments_api_spec.rb index 05812af2..28c62284 100644 --- a/spec/mailtrap/sandbox_attachments_api_spec.rb +++ b/spec/mailtrap/sandbox_attachments_api_spec.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true RSpec.describe Mailtrap::SandboxAttachmentsAPI, :vcr do - subject(:sandbox_attachments_api) { described_class.new(account_id, inbox_id, message_id, client) } + subject(:sandbox_attachments_api) { described_class.new(account_id, sandbox_id, message_id, client) } let(:account_id) { ENV.fetch('MAILTRAP_ACCOUNT_ID', 1_111_111) } let(:client) { Mailtrap::Client.new(api_key: ENV.fetch('MAILTRAP_API_KEY', 'local-api-key')) } - let(:inbox_id) { ENV.fetch('MAILTRAP_INBOX_ID', 4_288_340) } + let(:sandbox_id) { ENV.fetch('MAILTRAP_SANDBOX_ID', 4_288_340) } let(:message_id) { ENV.fetch('MAILTRAP_SANDBOX_MESSAGE_ID', 5_274_457_639) } describe '#list' do @@ -53,4 +53,15 @@ end end end + + describe '#inbox_id' do + it 'returns the sandbox ID and warns that it is deprecated' do + inbox_id = nil + + expect { inbox_id = sandbox_attachments_api.inbox_id } + .to output(/attachments_api_spec.rb:\d+: .*SandboxAttachmentsAPI#inbox_id is deprecated .*#sandbox_id/) + .to_stderr + expect(inbox_id).to eq(sandbox_id) + end + end end diff --git a/spec/mailtrap/sandbox_messages_api_spec.rb b/spec/mailtrap/sandbox_messages_api_spec.rb index c128ecbc..e622c272 100644 --- a/spec/mailtrap/sandbox_messages_api_spec.rb +++ b/spec/mailtrap/sandbox_messages_api_spec.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true RSpec.describe Mailtrap::SandboxMessagesAPI, :vcr do - subject(:sandbox_messages_api) { described_class.new(account_id, inbox_id, client) } + subject(:sandbox_messages_api) { described_class.new(account_id, sandbox_id, client) } let(:account_id) { ENV.fetch('MAILTRAP_ACCOUNT_ID', 1_111_111) } let(:client) { Mailtrap::Client.new(api_key: ENV.fetch('MAILTRAP_API_KEY', 'local-api-key')) } - let(:inbox_id) { ENV.fetch('MAILTRAP_INBOX_ID', 4_288_340) } + let(:sandbox_id) { ENV.fetch('MAILTRAP_SANDBOX_ID', 4_288_340) } describe '#get' do subject(:get) { sandbox_messages_api.get(sandbox_message_id) } @@ -426,4 +426,15 @@ end end end + + describe '#inbox_id' do + it 'returns the sandbox ID and warns that it is deprecated' do + inbox_id = nil + + expect { inbox_id = sandbox_messages_api.inbox_id } + .to output(/messages_api_spec.rb:\d+: .*SandboxMessagesAPI#inbox_id is deprecated .*#sandbox_id/) + .to_stderr + expect(inbox_id).to eq(sandbox_id) + end + end end diff --git a/spec/mailtrap/inbox_spec.rb b/spec/mailtrap/sandbox_spec.rb similarity index 73% rename from spec/mailtrap/inbox_spec.rb rename to spec/mailtrap/sandbox_spec.rb index 4e4ca00e..69899cef 100644 --- a/spec/mailtrap/inbox_spec.rb +++ b/spec/mailtrap/sandbox_spec.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true -RSpec.describe Mailtrap::Inbox do +RSpec.describe Mailtrap::Sandbox do let(:attributes) do { id: 123, - name: 'Example Inbox', + name: 'Example Sandbox', username: 'example-username', password: 'example-password', max_size: 123, @@ -13,7 +13,7 @@ email_username_enabled: true, sent_messages_count: 123, forwarded_messages_count: 123, - used: 123, + used: true, forward_from_email_address: 'asd@mail.com', project_id: 123, domain: 'example.com', @@ -36,12 +36,12 @@ end describe '#initialize' do - subject(:inbox) { described_class.new(attributes) } + subject(:sandbox) { described_class.new(attributes) } - it 'creates an Inbox with all attributes' do - expect(inbox).to have_attributes( + it 'creates a Sandbox with all attributes' do + expect(sandbox).to have_attributes( id: 123, - name: 'Example Inbox', + name: 'Example Sandbox', username: 'example-username', password: 'example-password', max_size: 123, @@ -50,7 +50,7 @@ email_username_enabled: true, sent_messages_count: 123, forwarded_messages_count: 123, - used: 123, + used: true, forward_from_email_address: 'asd@mail.com', project_id: 123, domain: 'example.com', @@ -72,4 +72,14 @@ ) end end + + describe 'deprecated Mailtrap::Inbox alias', :ruby_deprecation_warnings do + it 'is Sandbox and warns when deprecation warnings are enabled' do + constant = nil + + expect { constant = Mailtrap::Inbox } + .to output(/constant Mailtrap::Inbox is deprecated/).to_stderr + expect(constant).to be(described_class) + end + end end diff --git a/spec/mailtrap/sandboxes_api_spec.rb b/spec/mailtrap/sandboxes_api_spec.rb new file mode 100644 index 00000000..ac2859b1 --- /dev/null +++ b/spec/mailtrap/sandboxes_api_spec.rb @@ -0,0 +1,288 @@ +# frozen_string_literal: true + +RSpec.describe Mailtrap::SandboxesAPI, :vcr do + subject(:sandboxes_api) { described_class.new(account_id, client) } + + let(:account_id) { ENV.fetch('MAILTRAP_ACCOUNT_ID', 1_111_111) } + let(:client) { Mailtrap::Client.new(api_key: ENV.fetch('MAILTRAP_API_KEY', 'local-api-key')) } + + describe '#list' do + subject(:list) { sandboxes_api.list } + + it 'maps response data to Sandbox objects' do + expect(list).to all(be_a(Mailtrap::Sandbox)) + expect(list).to contain_exactly(have_attributes(id: 3_715_083, name: 'My Inbox')) + end + + context 'when api key is incorrect' do + let(:client) { Mailtrap::Client.new(api_key: 'incorrect-api-key') } + + it 'raises authorization error' do + expect { list }.to raise_error do |error| + expect(error).to be_a(Mailtrap::AuthorizationError) + expect(error.message).to include('Incorrect API token') + expect(error.messages.any? { |msg| msg.include?('Incorrect API token') }).to be true + end + end + end + end + + describe '#get' do + subject(:get) { sandboxes_api.get(sandbox_id) } + + let(:sandbox_id) { 4_278_175 } + + it 'maps response data to Sandbox object' do + expect(get).to be_a(Mailtrap::Sandbox) + expect(get).to have_attributes( + id: sandbox_id, + name: 'Test Inbox' + ) + end + + context 'when sandbox does not exist' do + let(:sandbox_id) { -1 } + + it 'raises not found error' do + expect { get }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('Not Found') + expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true + end + end + end + end + + describe '#create' do + subject(:create) { sandboxes_api.create(**request) } + + let(:request) do + { + name: 'Test Inbox', + project_id: 2_379_735 + } + end + + it 'maps response data to Sandbox object' do + expect(create).to be_a(Mailtrap::Sandbox) + expect(create).to have_attributes( + name: 'Test Inbox' + ) + end + + context 'when API returns an error' do + let(:request) do + { + name: '', # Invalid value, but present + project_id: 2_379_735 + } + end + + it 'raises a Mailtrap::Error' do + expect { create }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('client error') + end + end + end + end + + describe '#update' do + subject(:update) { sandboxes_api.update(sandbox_id, **request) } + + let(:sandbox_id) { 4_278_175 } + + let(:request) do + { + name: 'Updated Inbox', + email_username: 'updated_username' + } + end + + it 'maps response data to Sandbox object' do + expect(update).to be_a(Mailtrap::Sandbox) + expect(update).to have_attributes( + name: 'Updated Inbox', + email_username: '1234abcd' + ) + end + + context 'with hash request' do + let(:request) do + { + name: 'Updated Inbox' + } + end + + it 'maps response data to Sandbox object' do + expect(update).to be_a(Mailtrap::Sandbox) + expect(update).to have_attributes( + name: 'Updated Inbox' + ) + end + end + + context 'when sandbox does not exist' do + let(:sandbox_id) { -1 } + + it 'raises not found error' do + expect { update }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('Not Found') + expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true + end + end + end + end + + describe '#clean' do + subject(:clean) { sandboxes_api.clean(sandbox_id) } + + let(:sandbox_id) { 4_278_175 } + + it 'cleans Sandbox and returns Sandbox object' do + expect(clean).to have_attributes( + id: sandbox_id, + name: 'Updated Inbox' + ) + end + + context 'when sandbox does not exist' do + let(:sandbox_id) { -1 } + + it 'raises not found error' do + expect { clean }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('Not Found') + expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true + end + end + end + end + + describe '#mark_as_read' do + subject(:mark_as_read) { sandboxes_api.mark_as_read(sandbox_id) } + + let(:sandbox_id) { 4_278_175 } + + it 'returns nil' do + expect(mark_as_read).to have_attributes( + id: sandbox_id, + name: 'Updated Inbox' + ) + end + + context 'when sandbox does not exist' do + let(:sandbox_id) { -1 } + + it 'raises not found error' do + expect { mark_as_read }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('Not Found') + expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true + end + end + end + end + + describe '#reset_credentials' do + subject(:reset_credentials) { sandboxes_api.reset_credentials(sandbox_id) } + + let(:sandbox_id) { 4_278_175 } + + it 'returns nil' do + expect(reset_credentials).to have_attributes( + id: sandbox_id, + name: 'Updated Inbox' + ) + end + + context 'when sandbox does not exist' do + let(:sandbox_id) { -1 } + + it 'raises not found error' do + expect { reset_credentials }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('Not Found') + expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true + end + end + end + end + + describe '#toggle_email_username' do + subject(:toggle_email_username) { sandboxes_api.toggle_email_username(sandbox_id) } + + let(:sandbox_id) { 4_578_672 } + + it 'returns Sandbox object' do + expect(toggle_email_username).to be_a(Mailtrap::Sandbox) + expect(toggle_email_username).to have_attributes( + id: sandbox_id, + email_username_enabled: true + ) + end + + context 'when sandbox does not exist' do + let(:sandbox_id) { -1 } + + it 'raises not found error' do + expect { toggle_email_username }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('Not Found') + expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true + end + end + end + end + + describe '#reset_email_username' do + subject(:reset_email_username) { sandboxes_api.reset_email_username(sandbox_id) } + + let(:sandbox_id) { 4_578_672 } + + it 'returns Sandbox object' do + expect(reset_email_username).to have_attributes( + id: sandbox_id, + email_username: '1234abcd' + ) + end + + context 'when sandbox does not exist' do + let(:sandbox_id) { -1 } + + it 'raises not found error' do + expect { reset_email_username }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('Not Found') + expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true + end + end + end + end + + describe '#delete' do + subject(:delete) { sandboxes_api.delete(sandbox_id) } + + let(:sandbox_id) { 4_278_175 } + + it 'returns deleted sandbox data' do + expect(delete).to include( + id: sandbox_id, + name: 'Updated Inbox' + ) + end + + context 'when sandbox does not exist' do + let(:sandbox_id) { -1 } + + it 'raises not found error' do + expect { delete }.to raise_error do |error| + expect(error).to be_a(Mailtrap::Error) + expect(error.message).to include('Not Found') + expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true + end + end + end + end +end diff --git a/spec/mailtrap/sending_domain_spec.rb b/spec/mailtrap/sending_domain_spec.rb deleted file mode 100644 index 9b7859ef..00000000 --- a/spec/mailtrap/sending_domain_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Mailtrap::SendingDomain do - describe '#initialize' do - subject(:sending_domain) { described_class.new(attributes) } - - let(:attributes) do - { - id: '123456', - domain_name: 'My Sending Domain', - dns_verified: false, - compliance_status: 'pending', - created_at: '2024-01-01T00:00:00Z', - updated_at: '2024-01-02T00:00:00Z' - } - end - - it 'creates a sending domain with all attributes' do - expect(sending_domain).to have_attributes( - id: '123456', - domain_name: 'My Sending Domain', - dns_verified: false, - compliance_status: 'pending', - created_at: '2024-01-01T00:00:00Z', - updated_at: '2024-01-02T00:00:00Z' - ) - end - end -end diff --git a/spec/mailtrap/sending_domains_api_spec.rb b/spec/mailtrap/sending_domains_api_spec.rb index 70014ab6..69668aec 100644 --- a/spec/mailtrap/sending_domains_api_spec.rb +++ b/spec/mailtrap/sending_domains_api_spec.rb @@ -1,241 +1,31 @@ # frozen_string_literal: true -RSpec.describe Mailtrap::SendingDomainsAPI, :vcr do - subject(:sending_domains_api) { described_class.new(account_id, client) } - - let(:account_id) { ENV.fetch('MAILTRAP_ACCOUNT_ID', 1_111_111) } - let(:client) { Mailtrap::Client.new(api_key: ENV.fetch('MAILTRAP_API_KEY', 'local-api-key')) } - - describe '#list' do - subject(:list) { sending_domains_api.list } - - it 'maps response data to SendingDomain objects' do - expect(list).to all(be_a(Mailtrap::SendingDomain)) - end - - context 'when api key is incorrect' do - let(:client) { Mailtrap::Client.new(api_key: 'incorrect-api-key') } - - it 'raises authorization error' do - expect { list }.to raise_error do |error| - expect(error).to be_a(Mailtrap::AuthorizationError) - expect(error.message).to include('Incorrect API token') - expect(error.messages.any? { |msg| msg.include?('Incorrect API token') }).to be true - end - end - end - end - - describe '#get' do - subject(:get) { sending_domains_api.get(sending_domain_id) } - - let(:sending_domain_id) { 617_882 } - - it 'maps response data to SendingDomain object' do - expect(get).to be_a(Mailtrap::SendingDomain) - - expect(get).to match_struct( - id: 617_882, - domain_name: 'demomailtrap.co', - demo: true, - compliance_status: 'demo', - dns_verified: true, - dns_verified_at: '2025-05-21T14:04:52.363Z', - dns_records: - [ - { key: 'verification', domain: 'demo.demomailtrap.co', type: 'CNAME', value: 'smtp.mailtrap.live', - status: 'pass', name: 'demo' }, - { key: 'dkim1', domain: 'rwmt1._domainkey.demomailtrap.co', type: 'CNAME', - value: 'rwmt1.dkim.smtp.mailtrap.live', status: 'pass', name: 'rwmt1._domainkey' }, - { key: 'dkim2', domain: 'rwmt2._domainkey.demomailtrap.co', type: 'CNAME', - value: 'rwmt2.dkim.smtp.mailtrap.live', status: 'pass', name: 'rwmt2._domainkey' }, - { key: 'dmarc', name: '_dmarc' }, - { key: 'link_verification', domain: 'mt-link.demomailtrap.co', type: 'CNAME', value: 't.mailtrap.live', - status: 'pass', name: 'mt-link' } - ], - open_tracking_enabled: true, - click_tracking_enabled: false, - tracking_opt_out_enabled: false, - auto_unsubscribe_link_enabled: false, - custom_domain_tracking_enabled: false, - health_alerts_enabled: true, - critical_alerts_enabled: true, - alert_recipient_email: nil, - inbound_enabled: false, - inbound_verified: false, - permissions: { can_read: true, can_update: true, can_destroy: true }, - created_at: nil, - updated_at: nil - ) - end - - context 'when sending domain does not exist' do - let(:sending_domain_id) { -1 } - - it 'raises not found error' do - expect { get }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('Not Found') - expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true - end - end - end - end - - describe '#create' do - subject(:create) { sending_domains_api.create(**request) } - - let(:request) do - { - domain_name: 'mailtrappio.com' - } - end - - it 'maps response data to sending domain object' do - expect(create).to be_a(Mailtrap::SendingDomain) - - expect(create).to match_struct( - id: 943_758, - domain_name: 'mailtrappio.com', - demo: false, - compliance_status: 'unverified_dns', - dns_verified: false, - dns_verified_at: '', - dns_records: - [ - { key: 'verification', domain: 'mt07.mailtrappio.com', type: 'CNAME', value: 'smtp.mailtrap.live', - status: 'missing', name: 'mt07' }, - { key: 'dkim1', domain: 'rwmt1._domainkey.mailtrappio.com', type: 'CNAME', - value: 'rwmt1.dkim.smtp.mailtrap.live', status: 'missing', name: 'rwmt1._domainkey' }, - { key: 'dkim2', domain: 'rwmt2._domainkey.mailtrappio.com', type: 'CNAME', - value: 'rwmt2.dkim.smtp.mailtrap.live', status: 'missing', name: 'rwmt2._domainkey' }, - { key: 'dmarc', name: '_dmarc' }, - { key: 'link_verification', domain: 'mt-link.mailtrappio.com', type: 'CNAME', value: 't.mailtrap.live', - status: 'missing', name: 'mt-link' } - ], - open_tracking_enabled: true, - click_tracking_enabled: false, - tracking_opt_out_enabled: false, - auto_unsubscribe_link_enabled: false, - custom_domain_tracking_enabled: false, - health_alerts_enabled: true, - critical_alerts_enabled: true, - alert_recipient_email: nil, - inbound_enabled: false, - inbound_verified: false, - permissions: { can_read: true, can_update: true, can_destroy: true }, - created_at: nil, - updated_at: nil - ) - end - - context 'when API returns an error' do - let(:request) do - { - domain_name: '' # Invalid value, but present - } - end - - it 'raises a Mailtrap::Error' do - expect { create }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('client error') - end - end - end +RSpec.describe Mailtrap::SendingDomainsAPI do + let(:client) { Mailtrap::Client.new(api_key: 'local-api-key') } + + it 'works as DomainsAPI and warns that it is deprecated', + vcr: { cassette_name: 'Mailtrap_DomainsAPI/_list/maps_response_data_to_Domain_objects' } do + sending_domains_api = nil + + expect { sending_domains_api = described_class.new(1_111_111, client) } + .to output(/sending_domains_api_spec.rb:\d+: .*Mailtrap::SendingDomainsAPI is deprecated .*; use Mailtrap::DomainsAPI/) + .to_stderr + expect(sending_domains_api).to be_a(Mailtrap::DomainsAPI) + expect(sending_domains_api.list).to all(be_a(Mailtrap::Domain)) end - describe '#send_setup_instructions' do - subject(:send_setup_instructions) do - sending_domains_api.send_setup_instructions(sending_domain_id, email: 'example@railsware.com') - end - - let(:sending_domain_id) { 943_758 } - - it 'returns nil' do - expect(send_setup_instructions).to be_nil - end - - context 'when sending domain does not exist' do - let(:sending_domain_id) { -1 } - - it 'raises not found error' do - expect { send_setup_instructions }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('Not Found') - expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true - end - end - end - end - - describe '#delete' do - subject(:delete) { sending_domains_api.delete(sending_domain_id) } - - let(:sending_domain_id) { 943_758 } - - it 'returns deleted sending domain data' do - expect(delete).to be_nil - end - - context 'when sending domain does not exist' do - let(:sending_domain_id) { -1 } - - it 'raises not found error' do - expect { delete }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('Not Found') - expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true - end - end - end - end - - describe '#update' do - subject(:update) { sending_domains_api.update(sending_domain_id, **request) } - - let(:sending_domain_id) { 61_802 } - - let(:request) do - { - open_tracking_enabled: true, - click_tracking_enabled: true, - tracking_opt_out_enabled: true, - auto_unsubscribe_link_enabled: false, - inbound_enabled: false - } - end - - it 'maps response data to SendingDomain object' do - expect(update).to be_a(Mailtrap::SendingDomain) - expect(update).to have_attributes( - id: sending_domain_id, - open_tracking_enabled: true, - click_tracking_enabled: true, - tracking_opt_out_enabled: true, - auto_unsubscribe_link_enabled: false, - inbound_enabled: false - ) - end - - context 'when invalid options are provided' do - let(:request) { { unknown_option: true } } - - it 'raises ArgumentError' do - expect { update }.to raise_error(ArgumentError, /invalid options are given/) - end - end - - context 'when sending domain does not exist' do - let(:sending_domain_id) { -1 } - - it 'raises not found error' do - expect { update }.to raise_error do |error| - expect(error).to be_a(Mailtrap::Error) - expect(error.message).to include('Not Found') - expect(error.messages.any? { |msg| msg.include?('Not Found') }).to be true - end - end - end + it 'updates a domain with the options it inherits', + vcr: { cassette_name: 'Mailtrap_DomainsAPI/_update/maps_response_data_to_Domain_object' } do + domain = nil + request = { + open_tracking_enabled: true, + click_tracking_enabled: true, + tracking_opt_out_enabled: true, + auto_unsubscribe_link_enabled: false, + inbound_enabled: false + } + + expect { domain = described_class.new(1_111_111, client).update(61_802, **request) }.to output.to_stderr + expect(domain).to be_a(Mailtrap::Domain).and have_attributes(id: 61_802, open_tracking_enabled: true) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 036f3194..d066dea7 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -70,6 +70,16 @@ config.expect_with :rspec do |c| c.syntax = :expect end + + config.before { Mailtrap::Deprecation::WARNED.clear } + + config.around(:example, :ruby_deprecation_warnings) do |example| + enabled = Warning[:deprecated] + Warning[:deprecated] = true + example.run + ensure + Warning[:deprecated] = enabled + end end RSpec::Matchers.define :match_struct do |expected_attributes|