Skip to content

Instantly share code, notes, and snippets.

@sahglie
Last active August 29, 2015 14:20
Show Gist options
  • Save sahglie/98849cf08bd8974f4988 to your computer and use it in GitHub Desktop.
Save sahglie/98849cf08bd8974f4988 to your computer and use it in GitHub Desktop.
require 'net/smtp'
require 'pp'
module Net
class SMTPMailToError < ProtoServerError
attr_accessor :emails
def initialize(emails=[])
@emails = emails
end
end
class SMTP
def rcptto_list(to_addrs)
raise ArgumentError, 'mail destination not given' if to_addrs.empty?
ok_users = []
unknown_users = []
to_addrs.flatten.each do |addr|
begin
rcptto addr
rescue SMTPError => e
unknown_users << addr.dump
else
ok_users << addr
end
end
raise ArgumentError, 'No valid mail destinations were given' if ok_users.empty?
ret = yield
unless unknown_users.empty?
raise SMTPMailToError.new(unknown_users)
end
ret
end
end
end
class BulkEmail < ActiveRecord::Base
self.table_name = "incidents.bulk_emails"
validates :from_email, email: { allow_blank: false }
validates :subject, presence: { allow_blank: false }
validates :to_emails, presence: { allow_blank: false }, emails: {}
validates :body, presence: { allow_blank: false }
def to
(to_emails.try(:split, "\n") || []).map(&:strip)
end
def from
from_email
end
def delivered_to
to - rejected_emails
end
def rejected_emails
(rejected_to_emails.try(:split, "\n") || []).map(&:strip)
end
def save_rejected_to_emails(emails)
update_attributes!(rejected_to_emails: emails.join("\n"))
end
def save_and_deliver!
save! && deliver!
end
def deliver!
mailer.deliver
if mailer.rejected_to_emails.count > 0
emails = mailer.rejected_to_emails.join("\n")
update_attributes!(rejected_to_emails: emails)
end
rescue Sock::Email::Mailer::Error => e
update_attributes!(error_msg: e.message)
raise ActiveRecord::ActiveRecordError, e.message
end
private
def mailer
@mailer ||= Sock::Email::Mailer.new(self)
end
end
module Sock
module Email
class Mailer
Error = Class.new(StandardError)
attr_accessor :bulk_email, :rejected_to_emails
def initialize(ar_bulk_email)
@bulk_email = ar_bulk_email
@rejected_to_emails = []
end
def deliver
smtp_session.start(*smtp_params) do |smtp|
begin
smtp.send_message(message, from, to)
rescue Net::SMTPMailToError => e
@rejected_to_emails = e.emails.map { |e| eval(e) }
rescue StandardError => e
raise Error, e.message
end
end
end
def self.deliver(email)
instance = self.new(email)
instance.deliver && instance
end
private
def smtp_params
[config(:helo_domain), config(:user), config(:password), :plain]
end
def smtp_session
@smtp_session ||= begin
sess = Net::SMTP.new(config(:hostname), config(:port))
sess.enable_starttls(OpenSSL::SSL::SSLContext.new(:TLSv1_2))
sess
end
end
def config(sym)
Rails.application.config.smtp_email.fetch(sym)
end
def from
bulk_email.from
end
def to
[bulk_email.to]
end
def message
<<-MSGSTR
From: #{@bulk_email.from}
Subject: #{@bulk_email.subject}
Date: #{Time.now.to_s}
Message-Id: <#{rand(100_000)}@security.berkeley.edu>
#{@bulk_email.body}
MSGSTR
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment