test(dolist): add some specs and remove unsupported email sent with attachments

This commit is contained in:
Colin Darie 2024-05-14 18:34:25 +02:00
parent 3c3bc4a657
commit 2b9fe12079
No known key found for this signature in database
GPG key ID: 4FB865FDBCA4BCC4
2 changed files with 186 additions and 38 deletions

View file

@ -61,61 +61,57 @@ module Dolist
end end
def send_email(mail) def send_email(mail)
if mail.attachments.any? { !_1.inline? }
return send_email_with_attachment(mail)
end
body = { "TransactionalSending": prepare_mail_body(mail) } body = { "TransactionalSending": prepare_mail_body(mail) }
url = format_url(EMAIL_SENDING_TRANSACTIONAL) url = format_url(EMAIL_SENDING_TRANSACTIONAL)
post(url, body.to_json) post(url, body.to_json)
end end
def send_email_with_attachment(mail) # def send_email_with_attachment(mail)
uri = URI(format_url(EMAIL_SENDING_TRANSACTIONAL_ATTACHMENT)) # uri = URI(format_url(EMAIL_SENDING_TRANSACTIONAL_ATTACHMENT))
request = Net::HTTP::Post.new(uri) # request = Net::HTTP::Post.new(uri)
default_headers.each do |key, value| # default_headers.each do |key, value|
next if key.to_s == "Content-Type" # next if key.to_s == "Content-Type"
request[key] = value # request[key] = value
end # end
boundary = "---011000010111000001101001" # any random string not present in the body # boundary = "---011000010111000001101001" # any random string not present in the body
request.content_type = "multipart/form-data; boundary=#{boundary}" # request.content_type = "multipart/form-data; boundary=#{boundary}"
body = "--#{boundary}\r\n" # body = "--#{boundary}\r\n"
base64_files(mail.attachments).each do |file| # base64_files(mail.attachments).each do |file|
body << "Content-Disposition: form-data; name=\"#{file.field_name}\"; filename=\"#{file.filename}\"\r\n" # body << "Content-Disposition: form-data; name=\"#{file.field_name}\"; filename=\"#{file.filename}\"\r\n"
body << "Content-Type: #{file.mime_type}\r\n" # body << "Content-Type: #{file.mime_type}\r\n"
body << "\r\n" # body << "\r\n"
body << file.content # body << file.content
body << "\r\n" # body << "\r\n"
end # end
body << "\r\n--#{boundary}\r\n" # body << "\r\n--#{boundary}\r\n"
body << "Content-Disposition: form-data; name=\"TransactionalSending\"\r\n" # body << "Content-Disposition: form-data; name=\"TransactionalSending\"\r\n"
body << "Content-Type: text/plain; charset=utf-8\r\n" # body << "Content-Type: text/plain; charset=utf-8\r\n"
body << "\r\n" # body << "\r\n"
body << prepare_mail_body(mail).to_jsv # body << prepare_mail_body(mail).to_jsv
body << "\r\n--#{boundary}--\r\n" # body << "\r\n--#{boundary}--\r\n"
body << "\r\n" # body << "\r\n"
request.body = body # request.body = body
http = Net::HTTP.new(uri.host, uri.port) # http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true # http.use_ssl = true
response = http.request(request) # response = http.request(request)
if response.body.empty? # if response.body.empty?
fail "Dolist API returned an empty response" # fail "Dolist API returned an empty response"
else # else
JSON.parse(response.body) # JSON.parse(response.body)
end # end
end # end
def sent_mails(email_address) def sent_mails(email_address)
contact_id = fetch_contact_id(email_address) contact_id = fetch_contact_id(email_address)

152
spec/lib/dolist/api_spec.rb Normal file
View file

@ -0,0 +1,152 @@
# frozen_string_literal: true
describe Dolist::API do
let(:headers) { { "X-Rate-Limit-Remaining" => "15", "X-Rate-Limit-Reset" => (Time.current + 3600).to_i.to_s } }
let(:mail) do
Mail.new do
to 'test@example.com'
from 'sender@example.com'
subject 'Test'
body 'Test body'
header['X-Dolist-Message-Name'] = 'Test Message'
end
end
describe ".save_rate_limit_headers" do
it "saves the rate limit headers" do
Dolist::API.save_rate_limit_headers(headers)
expect(Dolist::API.limit_remaining).to eq(15)
expect(Dolist::API.limit_reset_at).to be_within(1.second).of(Time.zone.at(headers["X-Rate-Limit-Reset"].to_i / 1_000))
end
end
describe ".near_rate_limit?" do
context "when limit_remaining is nil" do
it "returns nil" do
Dolist::API.limit_remaining = nil
expect(Dolist::API.near_rate_limit?).to be_nil
end
end
context "when limit_remaining is less than 20" do
it "returns true" do
Dolist::API.limit_remaining = 15
expect(Dolist::API.near_rate_limit?).to be true
end
end
context "when limit_remaining is 20 or more" do
it "returns false" do
Dolist::API.limit_remaining = 25
expect(Dolist::API.near_rate_limit?).to be false
end
end
end
describe ".sendable?" do
context "when mail has no recipient" do
it "returns false" do
allow(mail).to receive(:to).and_return([])
expect(Dolist::API.sendable?(mail)).to be false
end
end
context "when mail has bcc" do
it "returns false" do
allow(mail).to receive(:bcc).and_return(["bcc@example.com"])
expect(Dolist::API.sendable?(mail)).to be false
end
end
context "when mail has attachments that are not inline" do
it "returns false" do
attachment = double("Attachment", inline?: false)
allow(mail).to receive(:attachments).and_return([attachment])
expect(Dolist::API.sendable?(mail)).to be false
end
end
context "when mail is valid" do
it "returns true" do
expect(Dolist::API.sendable?(mail)).to be true
end
end
end
describe "#send_email" do
let(:api) { Dolist::API.new }
let(:url) { "https://api.dolist.com/email/send" }
let(:mail_body) do
{
"Type": "TransactionalService",
"Contact": {
"FieldList": [
{
"ID" => Dolist::API::EMAIL_KEY,
"Value" => mail.to.first
}
]
},
"Message": {
"Name": mail['X-Dolist-Message-Name'].value,
"Subject": mail.subject,
"SenderID": api.send(:sender_id, mail.from_address.domain),
"ForceHttp": false,
"Format": "html",
"DisableOpenTracking": true,
"IsTrackingValidated": true
},
"MessageContent": {
"SourceCode": mail.decoded,
"EncodingType": "UTF8",
"EnableTrackingDetection": false
}
}
end
let(:expected_body) { { "TransactionalSending": mail_body }.to_json }
it "sends an email using the API" do
stub_request(:post, "https://apiv9.dolist.net/v1/email/sendings/transactional?AccountID=#{ENV["DOLIST_ACCOUNT_ID"]}")
.with(body: expected_body)
.to_return(body: { "Result" => "success" }.to_json, headers: { "X-Rate-Limit-Remaining" => "15", "X-Rate-Limit-Reset" => "1234" })
result = api.send_email(mail)
expect(result).to eq({ "Result" => "success" })
end
end
describe "#sent_mails" do
let(:api) { Dolist::API.new }
let(:email_address) { "test@example.com" }
let(:contact_id) { "12345" }
let(:dolist_messages) { [{ "SendingName" => "Test Message", "SendDate" => Time.zone.now.to_s, "Status" => "Sent", "IsDelivered" => true }] }
before do
allow(api).to receive(:fetch_contact_id).with(email_address).and_return(contact_id)
allow(api).to receive(:fetch_dolist_messages).with(contact_id).and_return(dolist_messages)
end
it "returns a list of sent mails" do
sent_mails = api.sent_mails(email_address)
expect(sent_mails).not_to be_empty
expect(sent_mails.first.subject).to eq("Test Message")
end
context "when contact_id is nil" do
it "returns an empty list" do
allow(api).to receive(:fetch_contact_id).with(email_address).and_return(nil)
expect(api.sent_mails(email_address)).to be_empty
end
end
context "when an error occurs" do
it "returns an empty list and logs the error" do
allow(api).to receive(:fetch_contact_id).and_raise(StandardError.new("Test Error"))
expect(Rails.logger).to receive(:error).with("Test Error")
expect(api.sent_mails(email_address)).to be_empty
end
end
end
end