Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Message Delivery #53

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ MailCatcher runs a super simple SMTP server which catches any message sent to it
* Sendmail-analogue command, `catchmail`, makes [using mailcatcher from PHP][withphp] a lot easier.
* Written super-simply in EventMachine, easy to dig in and change.
* Keyboard navigation between messages
* Can deliver caught messages to an SMTP server

## How

Expand Down
33 changes: 33 additions & 0 deletions lib/mail_catcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ def browse url
:daemon => !windows?,
:growl => growlnotify?,
:browse => false,
:delivery_address => 'smtp.gmail.com',
:delivery_port => '587',
:delivery_domain => 'gmail.com',
:delivery_user_name => '',
:delivery_password => '',
:delivery_recipient => nil,
}

def parse! arguments=ARGV, defaults=@defaults
Expand Down Expand Up @@ -83,6 +89,30 @@ def parse! arguments=ARGV, defaults=@defaults
options[:http_port] = port
end

parser.on("--delivery-address ADDRESS", "Set the SMTP address value for message delivery") do |delivery_address|
options[:delivery_address] = delivery_address
end

parser.on("--delivery-port PORT", Integer, "Set the SMTP port for message delivery") do |delivery_port|
options[:delivery_port] = delivery_port
end

parser.on("--delivery-domain DOMAIN", "Set the SMTP domain for message delivery") do |delivery_domain|
options[:delivery_domain] = delivery_domain
end

parser.on("--delivery-user-name USERNAME", "Set the SMTP user name for message delivery") do |delivery_user_name|
options[:delivery_user_name] = delivery_user_name
end

parser.on("--delivery-password USERNAME", "Set the SMTP password for message delivery") do |delivery_password|
options[:delivery_password] = delivery_password
end

parser.on("--delivery-recipient EMAIL", "(Optional) overwrite the to field for message delivery with the provided value") do |delivery_recipient|
options[:delivery_recipient] = delivery_recipient
end

if mac?
parser.on("--[no-]growl", "Growl to the local machine when a message arrives") do |growl|
if growl and not growlnotify?
Expand Down Expand Up @@ -126,6 +156,8 @@ def run! options=nil
# Otherwise, parse them from ARGV
options ||= parse!

DeliveryService.configure(options)

puts "Starting MailCatcher"

Thin::Logging.silent = true
Expand Down Expand Up @@ -190,6 +222,7 @@ def rescue_port port
end
end

require 'mail_catcher/delivery_service'
require 'mail_catcher/events'
require 'mail_catcher/growl'
require 'mail_catcher/mail'
Expand Down
40 changes: 40 additions & 0 deletions lib/mail_catcher/delivery_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
class MailCatcher::DeliveryService
attr_reader :message

mattr_accessor :address
mattr_accessor :port
mattr_accessor :domain
mattr_accessor :user_name
mattr_accessor :password
mattr_accessor :recipient

mattr_accessor :authentication # authentication is currently hard-coded
@@authentication = 'login'

def initialize(message)
@message = message
end

def config
self.class
end

def deliver!
smtp = Net::SMTP.new config.address, config.port
smtp.enable_starttls
smtp.start(config.domain, config.user_name, config.password, config.authentication) do |smtp|
smtp.send_message message['source'], config.user_name, config.recipient || message['recipients']
end
end

class << self
def configure(options = {})
@@address = options[:delivery_address]
@@port = options[:delivery_port]
@@domain = options[:delivery_domain]
@@user_name = options[:delivery_user_name]
@@password = options[:delivery_password]
@@recipient = options[:delivery_recipient]
end
end
end
15 changes: 15 additions & 0 deletions lib/mail_catcher/web.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,21 @@ class MailCatcher::Web < Sinatra::Base
end
end

post "/messages/:id/deliver" do
id = params[:id].to_i
if message = MailCatcher::Mail.message(id)
delivery_service = MailCatcher::DeliveryService.new(message)
begin
delivery_service.deliver!
rescue => e
halt 500, e.inspect
end
"" # Return 200 with an empty body
else
not_found
end
end

not_found do
"<html><body><h1>No Dice</h1><p>The message you were looking for does not exist, or doesn't have content of this type.</p></body></html>"
end
Expand Down
15 changes: 15 additions & 0 deletions public/javascripts/application.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,21 @@ class MailCatcher
else
$('#message .metadata .attachments').hide()

$('#message .views .deliver a').click (e)->
e.preventDefault()
$deliver = $(this).parent()
deliver_html = $(this).parent().html()
$deliver.text('Delivering...')
$.ajax
url: "/messages/#{id}/deliver"
type: 'POST'
success: =>
$deliver.html(deliver_html)
alert 'Message successfully delivered'
error: =>
$deliver.html(deliver_html)
alert 'An error occurred while attempting to deliver this message'

$('#message .views .download a').attr 'href', "/messages/#{id}.eml"

if $('#message .views .tab.analysis.selected').length
Expand Down
61 changes: 51 additions & 10 deletions public/javascripts/application.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions views/index.haml
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,7 @@
%li.action.download
%a.button{:href => '#'}
%span Download
%li.action.deliver
%a.button{:href => '#'}
%span Deliver
%iframe.body