-
Notifications
You must be signed in to change notification settings - Fork 5
Several improvements, if ya'll are interested #2
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
Changes from all commits
e484208
51437c3
bcb5190
3839aa6
2302174
d839461
690cfaa
e3308cc
1f55792
b40e41b
79e96f8
235dea5
c4863f5
e8fbab7
98df53c
9c5eff6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,4 @@ | ||
| .idea | ||
| Rack* | ||
| start_mailphax_server.sh | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,8 @@ | ||
| source 'https://rubygems.org' | ||
| ruby '2.0.0' | ||
| ruby '2.3.0' | ||
|
|
||
| gem 'sinatra' | ||
| gem 'phaxio' | ||
| gem 'mail' | ||
| gem 'pony' | ||
| gem 'pony' | ||
| gem 'to_regexp' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,62 +2,170 @@ | |
| require 'phaxio' | ||
| require 'mail' | ||
| require 'pony' | ||
| require 'tempfile' | ||
| require 'openssl' | ||
| require 'to_regexp' | ||
|
|
||
| if not ENV['PHAXIO_KEY'] or not ENV['PHAXIO_SECRET'] | ||
| raise "You must specify your phaxio API keys in PHAXIO_KEY and PHAXIO_SECRET" | ||
| if not ENV['PHAXIO_KEY'] or not ENV['PHAXIO_SECRET'] or not ENV['MAILGUN_KEY'] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mailgun is not necessarily required for all installations
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see now that you addressed this in your comments and removed the other mail providers. you're probably right. we don't have the man power right now to implement the other providers unless they're requested. |
||
| raise "You must specify the required environment variables" | ||
| end | ||
|
|
||
| get '/' do | ||
| "Mailfax v1.0 - Visit a mail endpoint: (/sendgrid, /mandrill, /mailgun)" | ||
| "MailPhax v1.0 - Visit a mail endpoint: (/mailgun)" | ||
| end | ||
|
|
||
| get '/mailgun' do | ||
| [400, "Mailgun supported, but callbacks must be POSTs"] | ||
| end | ||
|
|
||
| get '/mandrill' do | ||
| [501, "mandrill not implemented yet"] | ||
| $recipientWhitelist = nil | ||
|
|
||
| def getRecipientWhitelist() | ||
| if $recipientWhitelist.nil? | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should document these features in the readme (the new whitelists)
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think they are useful, and so I've added to the pull request, but I can also see it being too granular. If it is a worthwhile feature, I can add some documentation. |
||
| if ENV['RECIPIENT_WHITELIST_FILE'] | ||
| $recipientWhitelist = File.read(ENV['RECIPIENT_WHITELIST_FILE']).split | ||
| end | ||
| end | ||
| return $recipientWhitelist | ||
| end | ||
|
|
||
| post '/mandrill' do | ||
| [501, "mandrill not implemented yet"] | ||
| $senderWhitelist = nil | ||
|
|
||
| def getSenderWhitelist() | ||
| if $senderWhitelist.nil? | ||
| if ENV['SENDER_WHITELIST_FILE'] | ||
| $senderWhitelist = File.read(ENV['SENDER_WHITELIST_FILE']).split | ||
| end | ||
| end | ||
| return $senderWhitelist | ||
| end | ||
|
|
||
| get '/mailgun' do | ||
| [400, "Mailgun supported, but callbacks must be POSTs"] | ||
| $bodyRegex = nil | ||
|
|
||
| def getBodyRegex() | ||
| if $bodyRegex.nil? | ||
| if ENV['BODY_REGEX'] | ||
| $bodyRegex = ENV['BODY_REGEX'].to_regexp | ||
| end | ||
| end | ||
| return $bodyRegex | ||
| end | ||
|
|
||
| def verifyMailgun(apiKey, token, timestamp, signature) | ||
| calculatedSignature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new(), apiKey, [timestamp, token].join()) | ||
| signature == calculatedSignature | ||
| end | ||
|
|
||
| mailgunTokenCache = [] | ||
|
|
||
| post '/mailgun' do | ||
| mailgunTokenCacheMaxLength = 50 | ||
| timestampThreshold = 30.0 | ||
|
|
||
| if not params['sender'] | ||
| return [400, "Must include a sender"] | ||
| elsif not params['recipient'] | ||
| return [400, "Must include a recipient"] | ||
| sender = params['sender'] | ||
| if not sender | ||
| return logAndResponse(400, "Must include a sender", logger) | ||
| end | ||
|
|
||
| files = [] | ||
| attachmentCount = params['attachment-count'].to_i | ||
| senderWhitelist = getSenderWhitelist() | ||
| if not senderWhitelist.nil? and not senderWhitelist.include? sender | ||
| return logAndResponse(401, "sender blocked", logger) | ||
| end | ||
|
|
||
| recipient = params['recipient'] | ||
| if not recipient | ||
| return logAndResponse(400, "Must include a recipient", logger) | ||
| end | ||
|
|
||
| recipientWhitelist = getRecipientWhitelist() | ||
| if not recipientWhitelist.nil? and not recipientWhitelist.include? recipient | ||
| return logAndResponse(401, "recipient blocked", logger) | ||
| end | ||
|
|
||
| token = params['token'] | ||
| if not token | ||
| return logAndResponse(400, "Must include a token", logger) | ||
| end | ||
|
|
||
| signature = params['signature'] | ||
| if not signature | ||
| return logAndResponse(400, "Must include a signature", logger) | ||
| end | ||
|
|
||
| timestamp = params['timestamp'] | ||
| if not timestamp | ||
| return logAndResponse(400, "Must include a timestamp", logger) | ||
| end | ||
|
|
||
| if mailgunTokenCache.include?(token) | ||
| return logAndResponse(400, "duplicate token", logger) | ||
| end | ||
|
|
||
| mailgunTokenCache.push(token) | ||
| while mailgunTokenCache.length() > mailgunTokenCacheMaxLength | ||
| mailgunTokenCache.pop() | ||
| end | ||
|
|
||
| timestampSeconds = timestamp.to_f | ||
| nowSeconds = Time.now().to_f | ||
| if (timestampSeconds - nowSeconds).abs() > timestampThreshold | ||
| return logAndResponse(400, "timestamp unsafe", logger) | ||
| end | ||
|
|
||
| if not verifyMailgun(ENV['MAILGUN_KEY'], token, timestamp, signature) | ||
| return logAndResponse(400, "signature does not verify", logger) | ||
| end | ||
|
|
||
| attachmentFiles = [] | ||
|
|
||
| attachmentCount = params['attachment-count'].to_i | ||
| i = 1 | ||
| while i <= attachmentCount do | ||
| #add the file to the hash | ||
| outputFile = "/tmp/#{Time.now.to_i}-#{rand(200)}-" + params["attachment-#{i}"][:filename] | ||
| tFile = Tempfile.new(['', params["attachment-#{i}"][:filename]]) | ||
| data = params["attachment-#{i}"][:tempfile].read() | ||
| tFile.write(data) | ||
| tFile.close() | ||
|
|
||
| # use the whole file to ensure GC cannot release it yet | ||
| attachmentFiles.push(tFile) | ||
|
|
||
| File.open(outputFile, "w") do |f| | ||
| f.write(params["attachment-#{i}"][:tempfile].read) | ||
| i += 1 | ||
| end | ||
|
|
||
| if params['body-plain'] | ||
| data = params['body-plain'] | ||
| bodyRegex = getBodyRegex() | ||
| if bodyRegex.nil? or bodyRegex.match(data) | ||
| tFile = Tempfile.new(['', 'email-body.txt']) | ||
| tFile.write(data) | ||
| tFile.close() | ||
|
|
||
| # use the whole file to ensure GC cannot release it yet | ||
| attachmentFiles.push(tFile) | ||
| else | ||
| return logAndResponse(401, "body not accepted", logger) | ||
| end | ||
| end | ||
|
|
||
| files.push(outputFile) | ||
| sendFax(sender, recipient, attachmentFiles) | ||
|
|
||
| i += 1 | ||
| attachmentFiles.each do |attachmentFile| | ||
| begin | ||
| attachmentFile.unlink() | ||
| rescue | ||
| # do nothing | ||
| end | ||
| end | ||
|
|
||
| sendFax(params['sender'], params['recipient'],files) | ||
| "OK" | ||
| [200, "OK"] | ||
| end | ||
|
|
||
| get '/sendgrid' do | ||
| [501, "sendgrid not implemented yet"] | ||
| def logAndResponse(responseCode, message, logger) | ||
| logger.info(message) | ||
| return [responseCode, message] | ||
| end | ||
|
|
||
| def sendFax(fromEmail, toEmail, filenames) | ||
| def sendFax(fromEmail, toEmail, attachmentFiles) | ||
| Phaxio.config do |config| | ||
| config.api_key = ENV["PHAXIO_KEY"] | ||
| config.api_secret = ENV["PHAXIO_SECRET"] | ||
|
|
@@ -67,18 +175,18 @@ def sendFax(fromEmail, toEmail, filenames) | |
|
|
||
| options = {to: number, callback_url: "mailto:#{fromEmail}" } | ||
|
|
||
| filenames.each_index do |idx| | ||
| options["filename[#{idx}]"] = File.new(filenames[idx]) | ||
| attachmentFiles.each_index do |idx| | ||
| options["filename[#{idx}]"] = File.new(attachmentFiles[idx].path) | ||
| end | ||
|
|
||
| logger.info "#{fromEmail} is attempting to send #{filenames.length} files to #{number}..." | ||
| logger.info("#{fromEmail} is attempting to send #{attachmentFiles.length} files to #{number}...") | ||
| result = Phaxio.send_fax(options) | ||
| result = JSON.parse result.body | ||
| result = JSON.parse(result.body) | ||
|
|
||
| if result['success'] | ||
| logger.info "Fax queued up successfully: ID #" + result['data']['faxId'].to_s | ||
| logger.info("Fax queued up successfully: ID #" + result['data']['faxId'].to_s) | ||
| else | ||
| logger.warn "Problem submitting fax: " + result['message'] | ||
| logger.warn("Problem submitting fax: " + result['message']) | ||
|
|
||
| if ENV['SMTP_HOST'] | ||
| #send mail back to the user telling them there was a problem | ||
|
|
@@ -87,7 +195,7 @@ def sendFax(fromEmail, toEmail, filenames) | |
| :to => fromEmail, | ||
| :from => (ENV['SMTP_FROM'] || 'mailphax@example.com'), | ||
| :subject => 'Mailfax: There was a problem sending your fax', | ||
| :body => "There was a problem faxing your #{filenames.length} files to #{number}: " + result['message'], | ||
| :body => "There was a problem faxing your #{attachmentFiles.length} files to #{number}: " + result['message'], | ||
| :via => :smtp, | ||
| :via_options => { | ||
| :address => ENV['SMTP_HOST'], | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| #!/bin/bash | ||
|
|
||
| source /usr/local/rvm/scripts/rvm | ||
|
|
||
| PORT=8080 | ||
| HOST='0.0.0.0' | ||
| ENVIRONMENT='production' | ||
|
|
||
| export PHAXIO_KEY='##PHAXIO API KEY##' | ||
| export PHAXIO_SECRET='##PHAXIO SECRET KEY##' | ||
| export MAILGUN_KEY='##MAILGUN API KEY##' | ||
|
|
||
| # see app.json for more available environment variables | ||
|
|
||
| cd /path/to/mailphax/git/repo/ | ||
| rackup -p $PORT -o $HOST -E $ENVIRONMENT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason this is being removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Botch pull-request branch. This was intended for strictly a work-related project. Undone in #3.