Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ Email API:
Email Sandbox (Testing):

- Project management CRUD – [`projects_api.rb`](examples/projects_api.rb)
- Inboxes CRUD - [`inboxes_api.rb`](examples/inboxes_api.rb)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor. inconsistent with the previous line


Contact management:

Expand Down
33 changes: 33 additions & 0 deletions examples/inboxes_api.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
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)
# => #<struct Mailtrap::Inbox id=1, name="Test Inbox">

# Get all Inboxes
inboxes.list
# => [#<struct Mailtrap::Inbox id=1, name="Test Inbox">]

# Update inbox
inboxes.update(inbox.id, name: 'Test List Updated')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Test Inbox Updated"

# => #<struct Mailtrap::Inbox id=1, name="Test Inbox Updated">

# Get contact list
inbox = inboxes.get(inbox.id)
# => #<struct Mailtrap::Inbox id=1, name="Test Inbox Updated">

# 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)

# Delete unbox list
inboxes.delete(inbox.id)
1 change: 1 addition & 0 deletions lib/mailtrap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
require_relative 'mailtrap/contact_imports_api'
require_relative 'mailtrap/suppressions_api'
require_relative 'mailtrap/projects_api'
require_relative 'mailtrap/inboxes_api'

module Mailtrap
# @!macro api_errors
Expand Down
98 changes: 98 additions & 0 deletions lib/mailtrap/inboxes_api.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# frozen_string_literal: true

require_relative 'base_api'
require_relative 'inbox'

module Mailtrap
class InboxesAPI
include BaseAPI

self.supported_options = %i[name email_username]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can't specify email_username on inbox creation

self.response_class = Inbox

# Lists all Inboxes for the account
# @return [Array<Inbox>] 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
Comment on lines +28 to +39
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing validation for required project_id parameter.

The create method uses options[:project_id] to construct the API path, but there's no validation ensuring it's present. If project_id is nil or missing, the path becomes malformed (e.g., /api/accounts/123/projects//inboxes), which could result in unexpected errors.

Additionally, the @option documentation only mentions :name but project_id is effectively required.

Proposed fix
     # Creates a new inbox
     # `@param` [Hash] options The parameters to create
     # `@option` options [String] :name The inbox name
+    # `@option` options [Integer] :project_id The project identifier (required)
     # `@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])
+      raise ArgumentError, 'project_id is required' unless options[:project_id]
       response = client.post("/api/accounts/#{account_id}/projects/#{options[:project_id]}/inboxes",
                              wrap_request(options))
       handle_response(response)
     end
🧰 Tools
🪛 ast-grep (0.40.5)

[warning] 35-36: Found the use of an hardcoded passphrase for RSA. The passphrase can be easily discovered, and therefore should not be stored in source-code. It is recommended to remove the passphrase from source-code, and use system environment variables or a restricted configuration file.
Context: client.post("/api/accounts/#{account_id}/projects/#{options[:project_id]}/inboxes",
wrap_request(options))
Note: [CWE-798]: Use of Hard-coded Credentials [OWASP A07:2021]: Identification and Authentication Failures [REFERENCES]
https://cwe.mitre.org/data/definitions/522.html

(hardcoded-secret-rsa-passphrase-ruby)

🤖 Prompt for AI Agents
In `@lib/mailtrap/inboxes_api.rb` around lines 28 - 39, The create method uses
options[:project_id] in the path but doesn't ensure it's present, so add an
explicit validation that options[:project_id] is provided (raise ArgumentError
with a clear message if missing or nil) before calling client.post; keep the
existing validate_options! call for supported keys but ensure project_id is
treated as required by either adding a presence check or adjusting
validate_options! usage for required keys; also update the YARD docs above
create to include `@option` options [Integer, String] :project_id (marked
required) so callers know project_id is mandatory.


# 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)
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

private

def wrap_request(options)
{ inbox: options }
end

def base_path
"/api/accounts/#{account_id}/inboxes"
end
end
end

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading