Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 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 project_id]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You cannot update project_id.

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)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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
Copy Markdown

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
168 changes: 168 additions & 0 deletions spec/fixtures/vcr_cassettes/Mailtrap_InboxesAPI/_clean/returns_nil.yml

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

Loading