Skip to content

Commit ed55f55

Browse files
committed
Release version 2.4.0
1 parent fee2a44 commit ed55f55

File tree

8 files changed

+193
-2
lines changed

8 files changed

+193
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## [2.4.0] - 2025-05-12
2+
3+
- Added Email Templates API support
4+
15
## [2.3.0] - 2025-03-06
26

37
- 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::EmailTemplates.new(api_key: 'your-api-key')
76+
templates = client.all(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::EmailTemplates.new(api_key: 'your-api-key')
4+
account_id = 1
5+
6+
# list templates
7+
client.all(account_id:)
8+
9+
# create template
10+
created = client.create(
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(
20+
account_id:,
21+
email_template_id: created[:id],
22+
name: 'Updated Template'
23+
)
24+
25+
# delete template
26+
client.delete(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/email_templates'
78

89
module Mailtrap; end

lib/mailtrap/email_templates.rb

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# frozen_string_literal: true
2+
3+
module Mailtrap
4+
class EmailTemplates
5+
API_HOST = 'mailtrap.io'
6+
API_PORT = 443
7+
8+
attr_reader :api_key, :api_host, :api_port
9+
10+
def initialize(api_key:, api_host: API_HOST, api_port: API_PORT)
11+
raise ArgumentError, 'api_key is required' if api_key.nil?
12+
raise ArgumentError, 'api_port is required' if api_port.nil?
13+
14+
@api_key = api_key
15+
@api_host = api_host
16+
@api_port = api_port
17+
end
18+
19+
def all(account_id:)
20+
request(:get, "/api/accounts/#{account_id}/email_templates")
21+
end
22+
23+
def create(account_id:, **params)
24+
request(:post, "/api/accounts/#{account_id}/email_templates", params)
25+
end
26+
27+
def update(account_id:, email_template_id:, **params)
28+
request(
29+
:patch,
30+
"/api/accounts/#{account_id}/email_templates/#{email_template_id}",
31+
params
32+
)
33+
end
34+
35+
def delete(account_id:, email_template_id:)
36+
request(:delete, "/api/accounts/#{account_id}/email_templates/#{email_template_id}")
37+
true
38+
end
39+
40+
private
41+
42+
def http_client
43+
@http_client ||= Net::HTTP.new(api_host, api_port).tap { |client| client.use_ssl = true }
44+
end
45+
46+
def request(http_method, path, body = nil) # rubocop:disable Metrics/MethodLength
47+
request_class = {
48+
get: Net::HTTP::Get,
49+
post: Net::HTTP::Post,
50+
patch: Net::HTTP::Patch,
51+
delete: Net::HTTP::Delete
52+
}.fetch(http_method)
53+
54+
request = request_class.new(path)
55+
request['Authorization'] = "Bearer #{api_key}"
56+
request['User-Agent'] = 'mailtrap-ruby (https://github.com/railsware/mailtrap-ruby)'
57+
if body
58+
request['Content-Type'] = 'application/json'
59+
request.body = JSON.generate(body)
60+
end
61+
62+
response = http_client.request(request)
63+
handle_response(response)
64+
end # rubocop:enable Metrics/MethodLength
65+
66+
def handle_response(response) # rubocop:disable Metrics/MethodLength
67+
case response
68+
when Net::HTTPNoContent
69+
true
70+
when Net::HTTPSuccess
71+
json_response(response.body)
72+
when Net::HTTPUnauthorized
73+
raise Mailtrap::AuthorizationError, json_response(response.body)[:errors]
74+
when Net::HTTPForbidden
75+
raise Mailtrap::RejectionError, json_response(response.body)[:errors]
76+
when Net::HTTPClientError, Net::HTTPServerError
77+
raise Mailtrap::Error, json_response(response.body)[:errors]
78+
else
79+
raise Mailtrap::Error, ["unexpected status code=#{response.code}"]
80+
end
81+
end # rubocop:enable Metrics/MethodLength
82+
83+
def json_response(body)
84+
return {} if body.nil? || body.empty?
85+
86+
JSON.parse(body, symbolize_names: true)
87+
end
88+
end
89+
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: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe Mailtrap::EmailTemplates do
4+
subject(:templates) { 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 '#all' 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(templates.all(account_id:)).to eq([{ id: 1 }])
21+
end
22+
end
23+
end
24+
25+
describe '#create' 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(templates.create(account_id:, **params)).to eq({ id: 2 })
33+
expect(stub).to have_been_requested
34+
end
35+
end
36+
37+
describe '#update' 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(templates.update(account_id:, email_template_id: template_id,
43+
name: 'Updated')).to eq({ id: 2, name: 'Updated' })
44+
expect(stub).to have_been_requested
45+
end
46+
end
47+
48+
describe '#delete' do
49+
it 'sends DELETE request' do
50+
stub_api(:delete, "/api/accounts/#{account_id}/email_templates/#{template_id}", status: 204) do
51+
expect(templates.delete(account_id:, email_template_id: template_id)).to be true
52+
end
53+
end
54+
end
55+
56+
describe 'error handling' do
57+
it 'raises authorization error' do
58+
stub_api(:get, "/api/accounts/#{account_id}/email_templates", status: 401, body: '{"errors":["Unauthorized"]}') do
59+
expect { templates.all(account_id:) }.to raise_error(Mailtrap::AuthorizationError)
60+
end
61+
end
62+
end
63+
end

0 commit comments

Comments
 (0)