Skip to content

Instantly share code, notes, and snippets.

@adam12
Created September 28, 2022 18:40
Show Gist options
  • Save adam12/7bef8710d7eb76cbdfb19c638aabac93 to your computer and use it in GitHub Desktop.
Save adam12/7bef8710d7eb76cbdfb19c638aabac93 to your computer and use it in GitHub Desktop.
require 'net/smtp'
require 'minitest/autorun'
require 'time'
require 'date'
require 'securerandom'
require 'socket'
# require 'minitest/stub_any_instance'
class SendEmail
def self.build(host, port)
new.tap do |instance|
instance.smtp = Net::SMTP.new(host, port)
end
end
attr_accessor :smtp
def call(from, to, subject, body)
message = build_message(from, to, subject, body)
# Connect and send message.
smtp.start(
Socket.gethostname,
ENV.fetch('SMTP_USER', nil),
ENV.fetch('SMTP_PASSWORD', nil),
:plain
) do |ssmtp|
ssmtp.send_message(message, from, to)
end
end
def build_message(from, to, subject, body)
hostname = Socket.gethostname
message = <<~MAIL
From: #{from}
To: #{Array(to).join(', ')}
Subject: #{subject}
Date: #{Time.new.rfc2822}
Message-Id: <#{SecureRandom.uuid}@#{hostname}>
#{body}
MAIL
end
end
class SMTPTest < Minitest::Test
class MockSMTP
Delivery = Struct.new(:from, :to, :message)
attr_accessor :deliveries
def initialize
@deliveries = []
end
def start(*)
yield self
end
def send_message(message, from, to)
@deliveries.push Delivery.new(from, to, message)
end
end
def test_send_email
send_email = SendEmail.new
send_email.smtp = smtp = MockSMTP.new
mail = send_email.call("from", "to", "subject", "body")
assert smtp.deliveries.first.from == "from"
end
end
__END__
module SMTP
class << self
def send_email(to, subject, body)
# Connection setup.
smtp = Net::SMTP.new(ENV.fetch('SMTP_HOST'), ENV.fetch('SMTP_PORT', 25))
# Message setup.
from = ENV.fetch('SMTP_FROM')
hostname = Socket.gethostname
message = <<~MAIL
From: #{from}
To: #{to.instance_of?(Array) ? to.join(', ') : to}
Subject: #{subject}
Date: #{Time.new.rfc2822}
Message-Id: <#{SecureRandom.uuid}@#{hostname}>
#{body}
MAIL
# Connect and send message.
smtp.start(
hostname,
ENV.fetch('SMTP_USER', nil),
ENV.fetch('SMTP_PASSWORD', nil),
:plain
) do |ssmtp|
ssmtp.send_message(message, from, to)
end
end
end
end
class SMTPTest < Minitest::Test
def test_send_email
Net::SMTP.stub_any_instance(
:start,
lambda do |*|
def send_message(msgstr, from_addr, *to_addrs)
{ msgstr: msgstr, from_addr: from_addr, to_addrs: to_addrs }
end
yield(self)
end
) do
mail = SMTP.send_email('to', 'subject', 'body')
assert_equal('from', mail[:from_addr])
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment