Skip to content

Commit 682c245

Browse files
committed
Move templates API into Client
1 parent fee2a44 commit 682c245

File tree

8 files changed

+170
-3
lines changed

8 files changed

+170
-3
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## [2.4.0] - 2025-05-12
2+
3+
- Added Email Templates API support
4+
- Introduced template management methods on `Mailtrap::Client`
5+
16
## [2.3.0] - 2025-03-06
27

38
- Drop Ruby 3.0 support

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
mailtrap (2.3.0)
4+
mailtrap (2.4.0)
55

66
GEM
77
remote: https://rubygems.org/

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,16 @@ Refer to the [`examples`](examples) folder for more examples.
6666

6767
- [Full](examples/full.rb)
6868
- [Email template](examples/email_template.rb)
69+
- [Email templates management](examples/email_templates.rb)
6970
- [ActionMailer](examples/action_mailer.rb)
7071

72+
### Email Templates management
73+
74+
```ruby
75+
client = Mailtrap::Client.new(api_key: 'your-api-key')
76+
templates = client.list_templates(account_id: 1)
77+
```
78+
7179
### Content-Transfer-Encoding
7280

7381
`mailtrap` gem uses Mailtrap API to send emails. Mailtrap API does not try to

examples/email_templates.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
require 'mailtrap'
2+
3+
client = Mailtrap::Client.new(api_key: 'your-api-key')
4+
account_id = 1
5+
6+
# list templates
7+
client.list_templates(account_id:)
8+
9+
# create template
10+
created = client.create_template(
11+
account_id:,
12+
name: 'Newsletter Template',
13+
subject: 'Subject',
14+
category: 'Newsletter',
15+
body_html: '<div>Hello</div>'
16+
)
17+
18+
# update template
19+
client.update_template(
20+
account_id:,
21+
email_template_id: created[:id],
22+
name: 'Updated Template'
23+
)
24+
25+
# delete template
26+
client.destroy_template(account_id:, email_template_id: created[:id])

lib/mailtrap.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
require_relative 'mailtrap/mail'
55
require_relative 'mailtrap/errors'
66
require_relative 'mailtrap/version'
7+
require_relative 'mailtrap/client'
78

89
module Mailtrap; end

lib/mailtrap/client.rb

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
require 'uri'
66

77
module Mailtrap
8-
class Client
8+
class Client # rubocop:disable Metrics/ClassLength
99
SENDING_API_HOST = 'send.api.mailtrap.io'
1010
BULK_SENDING_API_HOST = 'bulk.api.mailtrap.io'
1111
SANDBOX_API_HOST = 'sandbox.api.mailtrap.io'
12+
TEMPLATES_API_HOST = 'mailtrap.io'
1213
API_PORT = 443
1314

1415
attr_reader :api_key, :api_host, :api_port, :bulk, :sandbox, :inbox_id
@@ -55,6 +56,27 @@ def send(mail)
5556
handle_response(response)
5657
end
5758

59+
def list_templates(account_id:)
60+
template_request(:get, "/api/accounts/#{account_id}/email_templates")
61+
end
62+
63+
def create_template(account_id:, **params)
64+
template_request(:post, "/api/accounts/#{account_id}/email_templates", params)
65+
end
66+
67+
def update_template(account_id:, email_template_id:, **params)
68+
template_request(
69+
:patch,
70+
"/api/accounts/#{account_id}/email_templates/#{email_template_id}",
71+
params
72+
)
73+
end
74+
75+
def destroy_template(account_id:, email_template_id:)
76+
template_request(:delete, "/api/accounts/#{account_id}/email_templates/#{email_template_id}")
77+
true
78+
end
79+
5880
private
5981

6082
def select_api_host(bulk:, sandbox:)
@@ -77,6 +99,10 @@ def http_client
7799
@http_client ||= Net::HTTP.new(api_host, api_port).tap { |client| client.use_ssl = true }
78100
end
79101

102+
def template_http_client
103+
@template_http_client ||= Net::HTTP.new(TEMPLATES_API_HOST, api_port).tap { |client| client.use_ssl = true }
104+
end
105+
80106
def post_request(path, body)
81107
request = Net::HTTP::Post.new(path)
82108
request.body = body
@@ -113,5 +139,42 @@ def handle_response(response) # rubocop:disable Metrics/AbcSize, Metrics/Cycloma
113139
def json_response(body)
114140
JSON.parse(body, symbolize_names: true)
115141
end
142+
143+
def template_request(http_method, path, body = nil) # rubocop:disable Metrics/MethodLength
144+
request_class = {
145+
get: Net::HTTP::Get,
146+
post: Net::HTTP::Post,
147+
patch: Net::HTTP::Patch,
148+
delete: Net::HTTP::Delete
149+
}.fetch(http_method)
150+
151+
request = request_class.new(path)
152+
request['Authorization'] = "Bearer #{api_key}"
153+
request['User-Agent'] = 'mailtrap-ruby (https://github.com/railsware/mailtrap-ruby)'
154+
if body
155+
request['Content-Type'] = 'application/json'
156+
request.body = JSON.generate(body)
157+
end
158+
159+
response = template_http_client.request(request)
160+
handle_template_response(response)
161+
end # rubocop:enable Metrics/MethodLength
162+
163+
def handle_template_response(response) # rubocop:disable Metrics/MethodLength
164+
case response
165+
when Net::HTTPNoContent
166+
true
167+
when Net::HTTPSuccess
168+
json_response(response.body)
169+
when Net::HTTPUnauthorized
170+
raise Mailtrap::AuthorizationError, json_response(response.body)[:errors]
171+
when Net::HTTPForbidden
172+
raise Mailtrap::RejectionError, json_response(response.body)[:errors]
173+
when Net::HTTPClientError, Net::HTTPServerError
174+
raise Mailtrap::Error, json_response(response.body)[:errors]
175+
else
176+
raise Mailtrap::Error, ["unexpected status code=#{response.code}"]
177+
end
178+
end # rubocop:enable Metrics/MethodLength
116179
end
117180
end

lib/mailtrap/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module Mailtrap
4-
VERSION = '2.3.0'
4+
VERSION = '2.4.0'
55
end
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe Mailtrap::Client do
4+
subject(:client) { described_class.new(api_key:) }
5+
6+
let(:api_key) { 'correct-api-key' }
7+
let(:account_id) { 123 }
8+
let(:template_id) { 456 }
9+
10+
def stub_api(method, path, status:, body: nil)
11+
stub = stub_request(method, "https://mailtrap.io#{path}")
12+
.to_return(status:, body:)
13+
yield
14+
expect(stub).to have_been_requested
15+
end
16+
17+
describe '#list_templates' do
18+
it 'returns templates list' do
19+
stub_api(:get, "/api/accounts/#{account_id}/email_templates", status: 200, body: '[{"id":1}]') do
20+
expect(client.list_templates(account_id:)).to eq([{ id: 1 }])
21+
end
22+
end
23+
end
24+
25+
describe '#create_template' do
26+
let(:params) { { name: 'Test', subject: 'Subj', category: 'Promotion', body_html: '<div>body</div>' } }
27+
28+
it 'sends POST request with JSON body' do
29+
stub = stub_request(:post, "https://mailtrap.io/api/accounts/#{account_id}/email_templates")
30+
.with(body: params.to_json)
31+
.to_return(status: 201, body: '{"id":2}')
32+
expect(client.create_template(account_id:, **params)).to eq({ id: 2 })
33+
expect(stub).to have_been_requested
34+
end
35+
end
36+
37+
describe '#update_template' do
38+
it 'sends PATCH request with JSON body' do # rubocop:disable RSpec/ExampleLength
39+
stub = stub_request(:patch, "https://mailtrap.io/api/accounts/#{account_id}/email_templates/#{template_id}")
40+
.with(body: { name: 'Updated' }.to_json)
41+
.to_return(status: 200, body: '{"id":2,"name":"Updated"}')
42+
expect(
43+
client.update_template(account_id:, email_template_id: template_id, name: 'Updated')
44+
).to eq({ id: 2, name: 'Updated' })
45+
expect(stub).to have_been_requested
46+
end
47+
end
48+
49+
describe '#destroy_template' do
50+
it 'sends DELETE request' do
51+
stub_api(:delete, "/api/accounts/#{account_id}/email_templates/#{template_id}", status: 204) do
52+
expect(client.destroy_template(account_id:, email_template_id: template_id)).to be true
53+
end
54+
end
55+
end
56+
57+
describe 'error handling' do
58+
it 'raises authorization error' do
59+
stub_api(:get, "/api/accounts/#{account_id}/email_templates", status: 401, body: '{"errors":["Unauthorized"]}') do
60+
expect { client.list_templates(account_id:) }.to raise_error(Mailtrap::AuthorizationError)
61+
end
62+
end
63+
end
64+
end

0 commit comments

Comments
 (0)