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 CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## [Unreleased]

- Add Email Logs API (list and get email sending logs with filters and cursor pagination)
- Add `list_each` to Sandbox Messages API for automatic pagination over all messages

## [2.9.0] - 2026-03-13

Expand Down
21 changes: 12 additions & 9 deletions lib/mailtrap/email_logs_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,19 @@ def list(filters: nil, search_after: nil)
# @return [Enumerator<EmailLogMessage>] if no block given; otherwise the result of the block
# @!macro api_errors
def list_each(filters: nil, &block)
return to_enum(__method__, filters: filters) unless block

search_after = nil
loop do
response = list(filters: filters, search_after: search_after)
response.messages.each { |message| block.call(message) }
break if response.next_page_cursor.nil?

search_after = response.next_page_cursor
first_page = nil
fetch_first_page = -> { first_page ||= list(filters: filters) }
enum = Enumerator.new(-> { fetch_first_page.call.total_count }) do |yielder|
response = fetch_first_page.call
loop do
response.messages.each { |message| yielder << message }
break if response.next_page_cursor.nil?

response = list(filters: filters, search_after: response.next_page_cursor)
end
end

block ? enum.each(&block) : enum
end

# Fetches a single email log message by ID.
Expand Down
20 changes: 20 additions & 0 deletions lib/mailtrap/sandbox_messages_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ def mark_as_read(message_id, is_read: true)
base_update(message_id, { is_read: is_read })
end

# Iterates over all sandbox messages, automatically fetching each page
# using cursor-based pagination. Use this when you want to process messages
# without manually handling pagination.
# @param search [String] Search query string. Matches subject, to_email, and to_name.
# @yield [SandboxMessage] Gives each message from every page when a block is given.
# @return [Enumerator<SandboxMessage>] if no block given; otherwise the result of the block
# @!macro api_errors
def list_each(search: nil, &block)
return to_enum(__method__, search: search) unless block

last_id = nil
loop do
messages = list(search: search, last_id: last_id)
break if messages.empty?

messages.each { |message| block.call(message) }
last_id = messages.last.id
end
end

# Lists all sandbox messages for the account, limited up to 30 at once
# @param search [String] Search query string. Matches subject, to_email, and to_name.
# @param last_id [Integer] If specified, a page of records before last_id is returned.
Expand Down
Loading
Loading