airmail 0.6.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/airmail/airmail.rb +12 -1
- data/lib/airmail/mail_processor.rb +1 -1
- data/lib/airmail/mail_router.rb +1 -2
- data/lib/airmail/sentiment.rb +15 -12
- data/lib/airmail/version.rb +3 -0
- data/spec/airmail/airmail_spec.rb +21 -0
- data/spec/airmail_spec.rb +0 -27
- data/spec/fixtures/email.eml +63 -0
- data/spec/fixtures/mail_controllers.rb +26 -0
- data/spec/sentiment_controller_spec.rb +54 -0
- data/spec/sentiment_spec.rb +12 -71
- data/spec/spec_helper.rb +1 -0
- metadata +23 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cdd792430f9a00732079cd493f2a36f91b0a7ac6
|
4
|
+
data.tar.gz: cff786668cbd05ed53cdfe821e7a8c0e8d88c45e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6340064f2424c696cf68b90ed3ddcf5caeca80f7c68899bc78340a6105b06aaee70e88b058be1d94a7bc0f0395efafa4ba5e0eabb126bf50115ac01b9caddafe
|
7
|
+
data.tar.gz: 5c192b71365b16237938421e5081f547636ec77ac30045ddd3b567dd3e3cd0961fbee5e11ee2db561fde4cf7d5af59dc52b984baf3060a3698cf1af455a5c262
|
data/lib/airmail/airmail.rb
CHANGED
@@ -1,20 +1,31 @@
|
|
1
|
+
require 'active_support'
|
1
2
|
require 'mail'
|
3
|
+
require 'action_mailer'
|
4
|
+
|
2
5
|
|
3
6
|
module Airmail
|
4
7
|
class << self
|
5
8
|
def receive( original )
|
6
9
|
raise RoutesNotDefined unless defined? @@route
|
7
10
|
|
8
|
-
mail =
|
11
|
+
mail = self.parse( original )
|
9
12
|
MailProcessor.new(mail, @@route, original).receive
|
10
13
|
|
11
14
|
mail
|
12
15
|
end
|
13
16
|
|
17
|
+
def parse(msg)
|
18
|
+
Mail.new(msg)
|
19
|
+
end
|
20
|
+
|
14
21
|
def route(&route)
|
15
22
|
@@route = route
|
16
23
|
end
|
17
24
|
|
25
|
+
def get_route
|
26
|
+
@@route
|
27
|
+
end
|
28
|
+
|
18
29
|
def logger= logr
|
19
30
|
@@logger = logr
|
20
31
|
end
|
data/lib/airmail/mail_router.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'mail'
|
2
1
|
class MailRouter
|
3
2
|
|
4
3
|
def initialize(mail)
|
@@ -43,7 +42,7 @@ class MailRouter
|
|
43
42
|
class << self
|
44
43
|
|
45
44
|
def receive( original )
|
46
|
-
mail = Mail.new( original )
|
45
|
+
mail = Mail::Message.new( original )
|
47
46
|
|
48
47
|
record(mail, original)
|
49
48
|
self.new(mail).route
|
data/lib/airmail/sentiment.rb
CHANGED
@@ -1,18 +1,21 @@
|
|
1
|
-
|
2
|
-
def initialize(*pattern)
|
3
|
-
@pattern = /#{"(" + pattern.map{|a| or_regex(a) }.join(').*(') + ")"}/
|
4
|
-
end
|
1
|
+
module Airmail
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
class Sentiment
|
4
|
+
def initialize(*pattern)
|
5
|
+
@pattern = /#{"(" + pattern.map{|a| or_regex(a) }.join(').*?(') + ")"}/
|
6
|
+
end
|
7
|
+
|
8
|
+
def analyze(phrase)
|
9
|
+
sentiments = @pattern.match phrase
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
10
13
|
|
11
|
-
|
14
|
+
def or_regex(phrase)
|
15
|
+
return "#{phrase.join("|")}" if phrase.is_a? Array
|
16
|
+
phrase
|
17
|
+
end
|
12
18
|
|
13
|
-
def or_regex(phrase)
|
14
|
-
return "#{phrase.join("|")}" if phrase.is_a? Array
|
15
|
-
phrase
|
16
19
|
end
|
17
20
|
|
18
21
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Airmail do
|
4
|
+
|
5
|
+
let(:mail) { :garbage }
|
6
|
+
|
7
|
+
it 'gets TO address' do
|
8
|
+
msg = Airmail.parse( email_fixture() )
|
9
|
+
|
10
|
+
expect(msg.to).to eql(['trevor@trevorgrayson.com'])
|
11
|
+
expect(msg.from).to eql(['service@paypal.com'])
|
12
|
+
expect(msg.subject).to eql('Receipt for Your Payment to Yukaholics, Inc.')
|
13
|
+
expect(msg.body).to be_a(Mail::Body)
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def email_fixture()
|
18
|
+
File.read('spec/fixtures/email.eml')
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/spec/airmail_spec.rb
CHANGED
@@ -76,30 +76,3 @@ describe Airmail do
|
|
76
76
|
end
|
77
77
|
|
78
78
|
end
|
79
|
-
|
80
|
-
class CountController < Airmail::Controller
|
81
|
-
def receive
|
82
|
-
Counter.inc
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
class BlankController < Airmail::Controller
|
87
|
-
def receive
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
class Counter
|
92
|
-
@@val = 0
|
93
|
-
|
94
|
-
def self.reset
|
95
|
-
@@val = 0
|
96
|
-
end
|
97
|
-
|
98
|
-
def self.inc
|
99
|
-
@@val += 1
|
100
|
-
end
|
101
|
-
|
102
|
-
def self.count
|
103
|
-
@@val
|
104
|
-
end
|
105
|
-
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
Delivered-To: rovertus@gmail.com
|
2
|
+
Received: by 10.79.138.196 with SMTP id m187csp883915ivd;
|
3
|
+
Sat, 1 Oct 2016 09:53:24 -0700 (PDT)
|
4
|
+
X-Received: by 10.28.92.71 with SMTP id q68mr2644068wmb.85.1475340804141;
|
5
|
+
Sat, 01 Oct 2016 09:53:24 -0700 (PDT)
|
6
|
+
Return-Path: <trevor+caf_=rovertus=gmail.com@trevorgrayson.com>
|
7
|
+
Received: from mail-wm0-x233.google.com (mail-wm0-x233.google.com. [2a00:1450:400c:c09::233])
|
8
|
+
by mx.google.com with ESMTPS id h88si4915435wmi.137.2016.10.01.09.53.23
|
9
|
+
for <rovertus@gmail.com>
|
10
|
+
(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
|
11
|
+
Sat, 01 Oct 2016 09:53:24 -0700 (PDT)
|
12
|
+
Received-SPF: neutral (google.com: 2a00:1450:400c:c09::233 is neither permitted nor denied by best guess record for domain of trevor+caf_=rovertus=gmail.com@trevorgrayson.com) client-ip=2a00:1450:400c:c09::233;
|
13
|
+
Authentication-Results: mx.google.com;
|
14
|
+
dkim=pass header.i=@paypal.com;
|
15
|
+
spf=neutral (google.com: 2a00:1450:400c:c09::233 is neither permitted nor denied by best guess record for domain of trevor+caf_=rovertus=gmail.com@trevorgrayson.com) smtp.mailfrom=trevor+caf_=rovertus=gmail.com@trevorgrayson.com;
|
16
|
+
dmarc=pass (p=REJECT dis=NONE) header.from=paypal.com
|
17
|
+
Received: by mail-wm0-x233.google.com with SMTP id p138so28291501wmb.1
|
18
|
+
for <rovertus@gmail.com>; Sat, 01 Oct 2016 09:53:23 -0700 (PDT)
|
19
|
+
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
20
|
+
d=1e100.net; s=20130820;
|
21
|
+
h=x-gm-message-state:delivered-to:dkim-signature:date:message-id
|
22
|
+
:amq-delivery-message-id:pp-correlation-id:subject:to:from
|
23
|
+
:mime-version;
|
24
|
+
bh=QUauXO7cvk7J90sDu+23Mepq6ifLLZjUj+cFpZqh6OM=;
|
25
|
+
b=EbPbYORqek10ksH5k4SJgnpUayiocTVDryXpSB4U6Eg1P+KbUjwhp+4Nvb+04cQC8h
|
26
|
+
XpkfOhwxJIDiGstJ0/HqdjBUuGzyEPgOth1tPgV6iwbKEPsop+JXZyPeuAPPf5gsmvCl
|
27
|
+
wSnbBy2NcogaXLzbrr9diKgdTe1aDRKBRYwMb0IyrEst89xzegk1O2BW2ep2nC8LQ3fv
|
28
|
+
K/i/VSaw/EuVVh0e8isnDjJIkUAryPwg5PU1ESlCUpTPjeeWau0o/DNdKemeW2s+FCXd
|
29
|
+
2T53ttuz4t95SK/yHi4H4KxFkJ4D3Gg/9rEegTIVMIzbkTMdJDyUbSIvepZvGUDFqPOn
|
30
|
+
Secg==
|
31
|
+
X-Gm-Message-State: AA6/9RmQTlbDNSr35QjSBG0PDscVZFGairlfizu2xmOQFP4eGv4oyktVSgNlnudxtpFyyHbrskFzSOhYIWpyD49HX0OGft8=
|
32
|
+
X-Received: by 10.28.23.18 with SMTP id 18mr2680718wmx.100.1475340803642;
|
33
|
+
Sat, 01 Oct 2016 09:53:23 -0700 (PDT)
|
34
|
+
X-Forwarded-To: rovertus@gmail.com
|
35
|
+
X-Forwarded-For: trevor@trevorgrayson.com rovertus@gmail.com
|
36
|
+
Delivered-To: trevor@trevorgrayson.com
|
37
|
+
Received: by 10.28.221.70 with SMTP id u67csp715650wmg;
|
38
|
+
Sat, 1 Oct 2016 09:53:22 -0700 (PDT)
|
39
|
+
X-Received: by 10.66.49.39 with SMTP id r7mr22504256pan.100.1475340802526;
|
40
|
+
Sat, 01 Oct 2016 09:53:22 -0700 (PDT)
|
41
|
+
Return-Path: <service@paypal.com>
|
42
|
+
Received: from mx0.slc.paypal.com (mx2.slc.paypal.com. [173.0.84.227])
|
43
|
+
by mx.google.com with ESMTPS id 4si16734948paj.264.2016.10.01.09.53.21
|
44
|
+
for <trevor@trevorgrayson.com>
|
45
|
+
(version=TLS1 cipher=AES128-SHA bits=128/128);
|
46
|
+
Sat, 01 Oct 2016 09:53:22 -0700 (PDT)
|
47
|
+
Received-SPF: pass (google.com: domain of service@paypal.com designates 173.0.84.227 as permitted sender) client-ip=173.0.84.227;
|
48
|
+
DKIM-Signature: v=1; a=rsa-sha256; d=paypal.com; s=pp-dkim1; c=relaxed/relaxed; q=dns/txt; i=@paypal.com; t=1475340801; h=From:From:Subject:Date:To:MIME-Version:Content-Type; bh=QUauXO7cvk7J90sDu+23Mepq6ifLLZjUj+cFpZqh6OM=; b=J31r2YJbKsHGQQzt3sFvqELSsue/qlvwPLqxEXl96VC7ohLISxXzv2pShqC5qClc 9+S8rMEqAs7nt8mRAx4ru4jbOoy7ChM55lw1KvuobL3cHdKKJWPlSu5xQv0I9S5d h+feRsMrI6lfQ+G64VE7GRij/djwYo31pvydj+IBQ8Xfc5K13YOIK0Qm7f3eNmR8 JcAuZqhGvEr7a8P7RNMakc3qyruZ0924iLzt6Mlh4lPd6BiQoifIe2sYYk1UNV74 pW7pDmIq6gbK3TksF/QtmOqp0xUhfrchgYF567oouO0ts/mvxlxUwo9ZIo4qrEbj vgbKGosdgzKcjOKygtmYfg==;
|
49
|
+
Received: (qmail 27756 invoked by uid 993); 1 Oct 2016 16:53:21 -0000
|
50
|
+
Date: Sat, 01 Oct 2016 09:53:21 -0700
|
51
|
+
Message-Id: <1475340801.27756@paypal.com>
|
52
|
+
AMQ-Delivery-Message-Id: EMAILDELIVERY-Notification_EmailDeliveryEvent-15-1475340795802-3489539719
|
53
|
+
X-PP-Email-transmission-Id: 8bef3ede-87f7-11e6-8d07-8cdcd4b6ee30
|
54
|
+
PP-Correlation-Id: ee84b5202279c
|
55
|
+
Subject: Receipt for Your Payment to Yukaholics, Inc.
|
56
|
+
X-MaxCode-Template: xpt/xclick/ReceiptXClickPayment
|
57
|
+
To: Trevor Grayson <trevor@trevorgrayson.com>
|
58
|
+
From: "service@paypal.com" <service@paypal.com>
|
59
|
+
X-Email-Type-Id: PP120 - ee84b5202279c
|
60
|
+
X-XPT-XSL-Name: email_pimp/default/en_US/xclick/ReceiptXClickPayment.xsl
|
61
|
+
Content-Type: multipart/alternative; boundary=--NextPart_048F8BC8A2197DE2036A
|
62
|
+
MIME-Version: 1.0
|
63
|
+
:
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class CountController < Airmail::Controller
|
2
|
+
def receive
|
3
|
+
Counter.inc
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class BlankController < Airmail::Controller
|
8
|
+
def receive
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Counter
|
13
|
+
@@val = 0
|
14
|
+
|
15
|
+
def self.reset
|
16
|
+
@@val = 0
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.inc
|
20
|
+
@@val += 1
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.count
|
24
|
+
@@val
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Airmail do
|
4
|
+
context 'multiple controllers' do
|
5
|
+
|
6
|
+
let(:mail) { Mail.new(body: "include bob@thomas.com") }
|
7
|
+
let(:subscribe_mail) { Mail.new(body: "subscribe bob@thomas.com") }
|
8
|
+
|
9
|
+
it 'matches sentiment' do
|
10
|
+
Counter.reset
|
11
|
+
|
12
|
+
Airmail.route do
|
13
|
+
if sentiment "include", Airmail::EMAIL_PATTERN
|
14
|
+
deliver CountController
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Airmail.receive(mail)
|
19
|
+
expect(Counter.count).to eq(1)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'matches word bag sentiment' do
|
23
|
+
|
24
|
+
Counter.reset
|
25
|
+
|
26
|
+
Airmail.route do
|
27
|
+
if sentiment ["include", "subscribe"], Airmail::EMAIL_PATTERN
|
28
|
+
deliver CountController
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Airmail.receive(mail)
|
33
|
+
expect(Counter.count).to eq(1)
|
34
|
+
|
35
|
+
Airmail.receive(subscribe_mail)
|
36
|
+
expect(Counter.count).to eq(2)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'rejects mismatched sentiment' do
|
40
|
+
Counter.reset
|
41
|
+
|
42
|
+
Airmail.route do
|
43
|
+
if sentiment "alksfdlaklsdfjslf"
|
44
|
+
deliver CountController
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
Airmail.receive(mail)
|
49
|
+
expect(Counter.count).to eq(0)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/spec/sentiment_spec.rb
CHANGED
@@ -1,82 +1,23 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Airmail do
|
3
|
+
describe Airmail::Sentiment do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
let(:subscribe_mail) { Mail.new(body: "subscribe bob@thomas.com") }
|
9
|
-
|
10
|
-
it 'matches sentiment' do
|
11
|
-
Counter.reset
|
12
|
-
|
13
|
-
Airmail.route do
|
14
|
-
if sentiment "include", Airmail::EMAIL_PATTERN
|
15
|
-
deliver CountController
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
Airmail.receive(mail)
|
20
|
-
expect(Counter.count).to eq(1)
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'matches word bag sentiment' do
|
24
|
-
|
25
|
-
Counter.reset
|
26
|
-
|
27
|
-
Airmail.route do
|
28
|
-
if sentiment ["include", "subscribe"], Airmail::EMAIL_PATTERN
|
29
|
-
deliver CountController
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
Airmail.receive(mail)
|
34
|
-
expect(Counter.count).to eq(1)
|
35
|
-
|
36
|
-
Airmail.receive(subscribe_mail)
|
37
|
-
expect(Counter.count).to eq(2)
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'rejects mismatched sentiment' do
|
41
|
-
Counter.reset
|
42
|
-
|
43
|
-
Airmail.route do
|
44
|
-
if sentiment "alksfdlaklsdfjslf"
|
45
|
-
deliver CountController
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
Airmail.receive(mail)
|
50
|
-
expect(Counter.count).to eq(0)
|
51
|
-
end
|
5
|
+
let(:email) { 'bob@thomas.com' }
|
6
|
+
let(:body) { "action #{email}" }
|
7
|
+
let(:subj) { subject.class.new('action', Airmail::EMAIL_PATTERN) }
|
52
8
|
|
9
|
+
it 'responds true' do
|
10
|
+
expect( subj.analyze(body) ).to be_truthy
|
53
11
|
end
|
54
12
|
|
55
|
-
|
56
|
-
|
57
|
-
class CountController < Airmail::Controller
|
58
|
-
def receive
|
59
|
-
Counter.inc
|
13
|
+
it 'responds false' do
|
14
|
+
expect( subj.analyze('garbage') ).to be_nil #eq(falsy)
|
60
15
|
end
|
61
|
-
end
|
62
16
|
|
63
|
-
|
64
|
-
|
17
|
+
it 'returns matches' do
|
18
|
+
sentiments = subj.analyze(body)
|
19
|
+
expect(sentiments[2]).to eq(email)
|
65
20
|
end
|
66
|
-
end
|
67
|
-
|
68
|
-
class Counter
|
69
|
-
@@val = 0
|
70
21
|
|
71
|
-
def self.reset
|
72
|
-
@@val = 0
|
73
|
-
end
|
74
|
-
|
75
|
-
def self.inc
|
76
|
-
@@val += 1
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.count
|
80
|
-
@@val
|
81
|
-
end
|
82
22
|
end
|
23
|
+
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,17 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: airmail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Trevor Grayson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-10-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: actionmailer
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - ">="
|
@@ -53,7 +67,12 @@ files:
|
|
53
67
|
- lib/airmail/mail_router.rb
|
54
68
|
- lib/airmail/patterns.rb
|
55
69
|
- lib/airmail/sentiment.rb
|
70
|
+
- lib/airmail/version.rb
|
71
|
+
- spec/airmail/airmail_spec.rb
|
56
72
|
- spec/airmail_spec.rb
|
73
|
+
- spec/fixtures/email.eml
|
74
|
+
- spec/fixtures/mail_controllers.rb
|
75
|
+
- spec/sentiment_controller_spec.rb
|
57
76
|
- spec/sentiment_spec.rb
|
58
77
|
- spec/spec_helper.rb
|
59
78
|
homepage: https://rubygems.org/gems/airmail
|
@@ -76,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
95
|
version: '0'
|
77
96
|
requirements: []
|
78
97
|
rubyforge_project:
|
79
|
-
rubygems_version: 2.5.1
|
98
|
+
rubygems_version: 2.4.5.1
|
80
99
|
signing_key:
|
81
100
|
specification_version: 4
|
82
101
|
summary: Incoming Email Router
|