Class: MailCapture::Client
- Inherits:
-
Object
- Object
- MailCapture::Client
- Defined in:
- lib/mailcapture/client.rb
Overview
MailCapture API client. Create one with new or new and reuse it across your test suite.
Constant Summary collapse
- MAX_POLL_SECONDS =
30- SERVER_POLL_BUFFER =
5- ADJECTIVES =
%w[ angry bold brave calm cold cool dark dizzy dusty eager fierce fluffy funky fuzzy glad gloomy grumpy hasty hungry icy itchy jolly jumpy keen lazy lucky mad mean moody muddy noisy odd pale peppy proud quick quiet rowdy rusty silly sleepy sneaky spooky swift tiny tough vivid weird wild young ].freeze
- ANIMALS =
%w[ ant bear boar cat crab crow deer dove duck eel elk finch fox frog goat hawk hare ibis jay kiwi lamb lark lion lynx mink mole moth mule newt owl panda pig puma ram rat rook seal slug snail swan toad vole wasp wolf wren yak zebra bat bee carp ].freeze
Class Method Summary collapse
-
.generate_tag ⇒ String
Generate a unique, human-readable tag such as “funky-otter-a3f2b8”.
Instance Method Summary collapse
-
#address(tag) ⇒ String
Return the capture email address for a tag.
-
#delete(tag) ⇒ Object
Delete all captures for a tag.
-
#generate ⇒ GenerateResult
Generate a unique tag and its capture email address.
-
#generate_tag ⇒ String
Instance-level shortcut so you can call
mc.generate_tagtoo. -
#get(capture_id) ⇒ Capture
Get a single capture by ID.
-
#inbox(tag) ⇒ Inbox
Return a scoped Inbox for a specific tag.
-
#initialize(api_key:, base_url: 'https://mailcapture.app', timeout: 10, username: nil) ⇒ Client
constructor
A new instance of Client.
-
#list(tag: nil, limit: nil, after: nil) ⇒ CaptureList
List recent captures (newest first).
-
#ping ⇒ PingResult
Validate your API key and return your capture address template.
-
#username ⇒ String?
Your cached username, set after #ping or via the constructor.
-
#wait_for(tag, timeout: 60, poll_timeout: 10, after: nil) ⇒ Capture
Wait for an email to arrive at the given tag and return it.
Constructor Details
#initialize(api_key:, base_url: 'https://mailcapture.app', timeout: 10, username: nil) ⇒ Client
Returns a new instance of Client.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/mailcapture/client.rb', line 46 def initialize(api_key:, base_url: 'https://mailcapture.app', timeout: 10, username: nil) raise ArgumentError, "MailCapture: api_key is required.\n" \ " MailCapture.new(api_key: ENV['MAILCAPTURE_API_KEY'])" if api_key.to_s.empty? unless api_key.start_with?('mc_') warn '[mailcapture] API key does not start with "mc_". Are you sure you copied the full key? ' \ 'Make sure you copied the full key from https://mailcapture.app/admin/api-keys' end @api_key = api_key @base_url = base_url.chomp('/') @timeout = timeout @username = username end |
Class Method Details
.generate_tag ⇒ String
Generate a unique, human-readable tag such as “funky-otter-a3f2b8”. Format: {adjective}-{animal}-{6 hex digits}. ~42 billion combinations — collision probability < 0.1% across 10 000 tags. No client or network call needed.
214 215 216 217 218 219 |
# File 'lib/mailcapture/client.rb', line 214 def self.generate_tag adj = ADJECTIVES.sample animal = ANIMALS.sample suffix = format('%06x', rand(0x1000000)) "#{adj}-#{animal}-#{suffix}" end |
Instance Method Details
#address(tag) ⇒ String
Return the capture email address for a tag.
Requires #ping to have been called first, or :username set in the constructor.
192 193 194 195 196 197 |
# File 'lib/mailcapture/client.rb', line 192 def address(tag) raise 'MailCapture: username is not known. Call ping first or pass username: to the constructor.' \ unless @username "#{@username}-#{tag}@mailcapture.app" end |
#delete(tag) ⇒ Object
Delete all captures for a tag. Call before each test to start with a clean inbox.
162 163 164 165 166 167 |
# File 'lib/mailcapture/client.rb', line 162 def delete(tag) raise ArgumentError, 'tag is required' if tag.to_s.empty? request(:delete, "/v1/captures/#{encode(tag)}") nil end |
#generate ⇒ GenerateResult
239 240 241 242 |
# File 'lib/mailcapture/client.rb', line 239 def generate tag = generate_tag GenerateResult.new(tag: tag, email: address(tag)) end |
#generate_tag ⇒ String
Instance-level shortcut so you can call mc.generate_tag too.
223 224 225 |
# File 'lib/mailcapture/client.rb', line 223 def generate_tag self.class.generate_tag end |
#get(capture_id) ⇒ Capture
Get a single capture by ID.
149 150 151 152 153 |
# File 'lib/mailcapture/client.rb', line 149 def get(capture_id) raise ArgumentError, 'capture_id is required' if capture_id.to_s.empty? Capture.from_hash(request(:get, "/v1/captures/#{encode(capture_id)}")) end |
#inbox(tag) ⇒ Inbox
Return a scoped Inbox for a specific tag.
179 180 181 182 183 |
# File 'lib/mailcapture/client.rb', line 179 def inbox(tag) raise ArgumentError, 'tag is required' if tag.to_s.empty? Inbox.new(self, tag) end |
#list(tag: nil, limit: nil, after: nil) ⇒ CaptureList
List recent captures (newest first).
135 136 137 138 139 140 141 142 |
# File 'lib/mailcapture/client.rb', line 135 def list(tag: nil, limit: nil, after: nil) params = {} params[:tag] = tag if tag params[:limit] = limit.to_s if limit params[:after] = after.utc.strftime('%Y-%m-%dT%H:%M:%SZ') if after CaptureList.from_hash(request(:get, '/v1/captures', params: params)) end |
#ping ⇒ PingResult
Validate your API key and return your capture address template. Also caches your username so #address works without a network call.
70 71 72 73 74 75 |
# File 'lib/mailcapture/client.rb', line 70 def ping data = request(:get, '/v1/ping') result = PingResult.from_hash(data) @username = result.username result end |
#username ⇒ String?
Your cached username, set after #ping or via the constructor.
201 202 203 |
# File 'lib/mailcapture/client.rb', line 201 def username @username end |
#wait_for(tag, timeout: 60, poll_timeout: 10, after: nil) ⇒ Capture
Wait for an email to arrive at the given tag and return it.
Long-polls the API — the server holds the connection open and responds the instant an email arrives. No busy-waiting.
The after cursor defaults to 60 seconds ago so recent emails are included but stale ones from previous runs are ignored. For maximum isolation, call delete(tag) before triggering the email.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/mailcapture/client.rb', line 97 def wait_for(tag, timeout: 60, poll_timeout: 10, after: nil) poll_timeout = [[poll_timeout.to_i, 1].max, MAX_POLL_SECONDS].min deadline = Time.now + timeout after ||= Time.now - 60 loop do remaining = deadline - Time.now break if remaining <= 0 effective_poll = [poll_timeout, [1, remaining.ceil].max].min result = poll_latest(tag, effective_poll, after) if result return result[:items].first unless result[:items].empty? after = Time.parse(result[:next_after]) end # result nil => server-side 408, loop again end hint = if @username "Make sure you're sending to #{@username}-#{tag}@mailcapture.app." else 'Check that you\'re sending to the right address (call ping first to get your username).' end raise TimeoutError.new(tag: tag, waited_seconds: timeout, hint: hint) end |