chronicle-email 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/Gemfile +2 -2
- data/README.md +3 -3
- data/Rakefile +2 -6
- data/bin/console +4 -11
- data/chronicle-email.gemspec +29 -26
- data/lib/chronicle/email/email_transformer.rb +59 -60
- data/lib/chronicle/email/imap_extractor.rb +25 -16
- data/lib/chronicle/email/mbox_extractor.rb +17 -10
- data/lib/chronicle/email/version.rb +1 -1
- data/lib/chronicle/email.rb +4 -4
- metadata +45 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0d66a6d2109f4f46f23fdf0c157085aed6f757f962339a422e4e38ca86ed129
|
4
|
+
data.tar.gz: e4136e05cf2827f64a07657e9442f9a8cdcac1ab88ed589c52ea76f62fd0d315
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d58d42a6db25951b46a08ad44302dab836fc3063fae2b9074e5156b4db59ab147b8401b60860665a0a27394ddca98a48c58a6abdf87ce474439e4d7b179604f
|
7
|
+
data.tar.gz: b11bea8171510544c35742cb7ab72c162b7774d0bd5603a7453f065d270a230fa8b2a17d77d5bfc1205a60710f1b7d076ec4f6521630754006a5efe4e6b18fcc
|
data/.rubocop.yml
ADDED
data/Gemfile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
3
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
4
4
|
|
5
5
|
# Specify your gem's dependencies in chronicle-email.gemspec
|
6
6
|
gemspec
|
data/README.md
CHANGED
@@ -21,11 +21,11 @@ $ chronicle-etl secrets:set imap username foo@gmail.com
|
|
21
21
|
$ chronicle-etl secrets:set imap password APPPASSWORD
|
22
22
|
|
23
23
|
# Then, retrieve your email from the last five days
|
24
|
-
$ chronicle-etl --extractor email:imap --
|
24
|
+
$ chronicle-etl --extractor email:imap --schema chronicle --since 5d
|
25
25
|
|
26
26
|
# If you don't want to save your credentials as a secret, you can just pass
|
27
27
|
# them to the extractor directly
|
28
|
-
$ chronicle-etl --extractor email:imap --
|
28
|
+
$ chronicle-etl --extractor email:imap --schema chronicle --since 5d --loader json \
|
29
29
|
--extractor-opts username:foo@gmail.com --password:APPPASSWORD
|
30
30
|
```
|
31
31
|
|
@@ -34,7 +34,7 @@ The MBOX format is used to archive an email mailbox. [Google Takeout](https://ta
|
|
34
34
|
|
35
35
|
```sh
|
36
36
|
# Retrieve the subject lines of all emails in test.mbox
|
37
|
-
$ chronicle-etl --extractor email:mbox --input inbox.mbox --
|
37
|
+
$ chronicle-etl --extractor email:mbox --input ~/Downloads/inbox.mbox --fields subject
|
38
38
|
```
|
39
39
|
|
40
40
|
## Available Connectors
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -1,14 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'chronicle/email'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|
6
|
+
require 'pry'
|
7
|
+
Pry.start
|
data/chronicle-email.gemspec
CHANGED
@@ -1,51 +1,54 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
3
|
+
require 'chronicle/email/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
6
|
+
spec.name = 'chronicle-email'
|
8
7
|
spec.version = Chronicle::Email::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
8
|
+
spec.authors = ['Andrew Louis']
|
9
|
+
spec.email = ['andrew@hyfen.net']
|
11
10
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
11
|
+
spec.summary = 'Email importer for Chronicle'
|
12
|
+
spec.description = 'Various email importers for chronicle-etl'
|
13
|
+
spec.homepage = 'https://github.com/chronicle-app/chronicle-email'
|
14
|
+
spec.license = 'MIT'
|
16
15
|
|
17
16
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
17
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
18
|
if spec.respond_to?(:metadata)
|
20
19
|
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
21
20
|
|
22
|
-
spec.metadata[
|
23
|
-
spec.metadata[
|
24
|
-
spec.metadata[
|
21
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
22
|
+
spec.metadata['source_code_uri'] = 'https://github.com/chronicle-app/chronicle-email'
|
23
|
+
spec.metadata['changelog_uri'] = 'https://github.com/chronicle-app/chronicle-email'
|
25
24
|
else
|
26
|
-
raise
|
27
|
-
|
25
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
26
|
+
'public gem pushes.'
|
28
27
|
end
|
29
28
|
|
30
29
|
# Specify which files should be added to the gem when it is released.
|
31
30
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
32
|
-
spec.files
|
31
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
33
32
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
34
33
|
end
|
35
|
-
spec.bindir =
|
34
|
+
spec.bindir = 'exe'
|
36
35
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
37
|
-
spec.require_paths = [
|
36
|
+
spec.require_paths = ['lib']
|
37
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
38
|
+
spec.required_ruby_version = '>= 3.1'
|
38
39
|
|
39
40
|
spec.add_dependency 'email_reply_parser', '~> 0.5'
|
41
|
+
spec.add_dependency 'mail', '~> 2.7'
|
40
42
|
spec.add_dependency 'reverse_markdown', '~> 2.0'
|
41
|
-
spec.add_dependency "chronicle-etl", "~> 0.5"
|
42
|
-
spec.add_dependency "mail", "~> 2.7"
|
43
43
|
# Needed for Ruby 3.1 compatibility (https://github.com/mikel/mail/pull/1439#issuecomment-1002801221)
|
44
44
|
# TODO: check back for new version of `mail`
|
45
|
-
spec.add_dependency
|
46
|
-
spec.add_dependency
|
47
|
-
|
48
|
-
spec.
|
49
|
-
|
50
|
-
spec.add_development_dependency
|
45
|
+
spec.add_dependency 'chronicle-core', '~> 0.3'
|
46
|
+
spec.add_dependency 'chronicle-etl', '~> 0.6'
|
47
|
+
spec.add_dependency 'net-imap'
|
48
|
+
spec.add_dependency 'net-smtp'
|
49
|
+
|
50
|
+
spec.add_development_dependency 'bundler', '~> 2.3'
|
51
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.10'
|
52
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
53
|
+
spec.add_development_dependency 'rubocop', '~> 1.63'
|
51
54
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'chronicle/etl'
|
2
|
-
require '
|
2
|
+
require 'chronicle/models'
|
3
3
|
require 'timeout'
|
4
4
|
require 'email_reply_parser'
|
5
5
|
require 'reverse_markdown'
|
@@ -8,98 +8,97 @@ module Chronicle
|
|
8
8
|
module Email
|
9
9
|
class EmailTransformer < Chronicle::ETL::Transformer
|
10
10
|
register_connector do |r|
|
11
|
+
r.source = :email
|
12
|
+
r.type = :message
|
11
13
|
r.description = 'an email object'
|
12
|
-
r.
|
13
|
-
r.
|
14
|
+
r.from_schema = :extraction
|
15
|
+
r.to_schema = :chronicle
|
14
16
|
end
|
15
17
|
|
16
18
|
setting :body_as_markdown, default: false
|
17
19
|
setting :remove_signature, default: true
|
18
20
|
|
19
|
-
def transform
|
20
|
-
build_messaged
|
21
|
+
def transform(record)
|
22
|
+
build_messaged(record.data[:raw])
|
21
23
|
end
|
22
24
|
|
23
|
-
|
24
|
-
message.message_id || raise(Chronicle::ETL::UntransformableRecordError, "Email doesn't have an ID")
|
25
|
-
end
|
25
|
+
private
|
26
26
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
27
|
+
def build_messaged(email)
|
28
|
+
timestamp = email.date&.to_time || raise(Chronicle::ETL::UntransformableRecordError,
|
29
|
+
"Email doesn't have a timestamp")
|
30
30
|
|
31
|
-
|
31
|
+
email.message_id || raise(Chronicle::ETL::UntransformableRecordError, "Email doesn't have an ID")
|
32
32
|
|
33
|
-
|
34
|
-
|
33
|
+
Chronicle::Models::CommunicateAction.new do |r|
|
34
|
+
r.end_time = timestamp
|
35
|
+
r.agent = build_agent(email[:from])
|
36
|
+
r.source = 'email'
|
37
|
+
r.source_id = email.message_id
|
38
|
+
r.object = build_message(email)
|
39
|
+
end
|
35
40
|
end
|
36
41
|
|
37
|
-
def
|
38
|
-
|
39
|
-
record.verb = 'messaged'
|
40
|
-
record.provider = 'email'
|
41
|
-
record.provider_id = id
|
42
|
-
record.end_at = timestamp
|
42
|
+
def build_agent(from)
|
43
|
+
raise(Chronicle::ETL::UntransformableRecordError, "Can't determine email sender") unless from&.addrs&.any?
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
record.actor = build_actor
|
47
|
-
record.involved = build_message
|
48
|
-
record
|
45
|
+
build_person(from.addrs.first)
|
49
46
|
end
|
50
47
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
48
|
+
def build_message(email)
|
49
|
+
Chronicle::Models::Message.new do |r|
|
50
|
+
r.name = clean_subject(email.subject)
|
51
|
+
r.text = clean_body(email)
|
52
|
+
r.source = 'email'
|
53
|
+
r.source_id = email.message_id
|
55
54
|
|
56
|
-
|
57
|
-
record.represents = 'identity'
|
58
|
-
record.provider = 'email'
|
59
|
-
record.slug = message[:from].addrs.first.address
|
60
|
-
record.title = message[:from].addrs.first.display_name
|
55
|
+
r.recipient = email[:to]&.addrs&.map { |addr| build_person(addr) }
|
61
56
|
|
62
|
-
|
57
|
+
# TODO: handle email references
|
58
|
+
# TODO: handle email account owner
|
59
|
+
# TODO: handle attachments
|
63
60
|
|
64
|
-
|
61
|
+
r.dedupe_on << %i[source source_id type]
|
62
|
+
end
|
65
63
|
end
|
66
64
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
# TODO: handle consumer
|
76
|
-
# TODO: handle email references
|
77
|
-
# TODO: handle email account owner
|
78
|
-
# TODO: handle attachments
|
79
|
-
|
80
|
-
record
|
65
|
+
def build_person(addr)
|
66
|
+
Chronicle::Models::Person.new do |r|
|
67
|
+
r.source = 'email'
|
68
|
+
r.slug = addr.address
|
69
|
+
r.name = addr.display_name
|
70
|
+
r.dedupe_on << %i[represents provider slug]
|
71
|
+
end
|
81
72
|
end
|
82
73
|
|
83
74
|
def clean_subject(subject)
|
84
|
-
subject&.encode(
|
75
|
+
subject&.encode('UTF-8', invalid: :replace, undef: :replace)
|
85
76
|
end
|
86
77
|
|
87
|
-
def clean_body
|
88
|
-
# FIXME: this all needs to be refactored
|
78
|
+
def clean_body(message)
|
79
|
+
# FIXME: this all needs to be refactored
|
89
80
|
if message.multipart?
|
90
|
-
body =
|
81
|
+
body = begin
|
82
|
+
message.text_part&.decoded
|
83
|
+
rescue StandardError
|
84
|
+
Mail::UnknownEncodingType
|
85
|
+
end
|
91
86
|
else
|
92
|
-
body =
|
87
|
+
body = begin
|
88
|
+
message.body&.decoded
|
89
|
+
rescue StandardError
|
90
|
+
Mail::UnknownEncodingType
|
91
|
+
end
|
93
92
|
body = body_to_markdown if @config.body_as_markdown
|
94
93
|
end
|
95
94
|
|
96
95
|
return if body == Mail::UnknownEncodingType
|
97
|
-
return unless body && body !=
|
96
|
+
return unless body && body != ''
|
98
97
|
|
99
98
|
body = body_without_signature(body) if @config.remove_signature
|
100
99
|
|
101
100
|
# Force UTF-8 encoding
|
102
|
-
body.encode(
|
101
|
+
body.encode('UTF-8', invalid: :replace, undef: :replace)
|
103
102
|
end
|
104
103
|
|
105
104
|
def body_to_markdown(body)
|
@@ -111,11 +110,11 @@ module Chronicle
|
|
111
110
|
def body_without_signature(body)
|
112
111
|
# FIXME: regex in EmailReplyParse gem seems to get into infinite loops
|
113
112
|
# with certain long bodies that have binary data
|
114
|
-
|
113
|
+
Timeout.timeout(5) do
|
115
114
|
EmailReplyParser.parse_reply(body)
|
116
115
|
end
|
117
|
-
rescue Timeout::Error, StandardError
|
118
|
-
|
116
|
+
rescue Timeout::Error, StandardError
|
117
|
+
body
|
119
118
|
end
|
120
119
|
end
|
121
120
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
require 'net/imap'
|
2
|
+
require 'mail'
|
2
3
|
|
3
4
|
module Chronicle
|
4
5
|
module Email
|
5
6
|
class IMAPExtractor < Chronicle::ETL::Extractor
|
6
7
|
register_connector do |r|
|
7
|
-
r.
|
8
|
-
r.
|
9
|
-
r.
|
8
|
+
r.source = :email
|
9
|
+
r.type = :message
|
10
|
+
r.strategy = :imap
|
11
|
+
r.description = 'IMAP server'
|
10
12
|
end
|
11
13
|
|
12
14
|
setting :host, required: true, default: 'imap.gmail.com'
|
@@ -28,7 +30,15 @@ module Chronicle
|
|
28
30
|
def extract
|
29
31
|
@message_ids.each do |message_id|
|
30
32
|
message = fetch_message(message_id)
|
31
|
-
|
33
|
+
email = Mail.new(message.attr['BODY[]'])
|
34
|
+
data = {
|
35
|
+
raw: email,
|
36
|
+
time: email.date&.to_time,
|
37
|
+
subject: email.subject,
|
38
|
+
from: email&.from&.join(', '),
|
39
|
+
to: email&.to&.join(', ')
|
40
|
+
}
|
41
|
+
yield build_extraction(data:)
|
32
42
|
end
|
33
43
|
end
|
34
44
|
|
@@ -39,8 +49,8 @@ module Chronicle
|
|
39
49
|
connection.login(@config.username, @config.password)
|
40
50
|
connection.select(@config.mailbox)
|
41
51
|
connection
|
42
|
-
rescue Net::IMAP::NoResponseError
|
43
|
-
raise(Chronicle::ETL::ExtractionError,
|
52
|
+
rescue Net::IMAP::NoResponseError
|
53
|
+
raise(Chronicle::ETL::ExtractionError, 'Error connecting to IMAP server. Please check username and password')
|
44
54
|
end
|
45
55
|
|
46
56
|
def fetch_message_ids
|
@@ -48,24 +58,23 @@ module Chronicle
|
|
48
58
|
message_ids = @connection.search(keys)
|
49
59
|
message_ids = message_ids.first(@config.limit) if @config.limit
|
50
60
|
message_ids
|
51
|
-
rescue Net::IMAP::BadResponseError
|
52
|
-
raise(Chronicle::ETL::ExtractionError,
|
61
|
+
rescue Net::IMAP::BadResponseError
|
62
|
+
raise(Chronicle::ETL::ExtractionError, 'Error searching IMAP server for messages')
|
53
63
|
end
|
54
64
|
|
55
65
|
def fetch_message(message_id)
|
56
|
-
response = @connection.fetch(message_id,
|
57
|
-
raise(Chronicle::ETL::ExtractionError,
|
66
|
+
response = @connection.fetch(message_id, 'BODY.PEEK[]')
|
67
|
+
raise(Chronicle::ETL::ExtractionError, 'Error loading message') unless response
|
58
68
|
|
59
|
-
|
69
|
+
response[0]
|
60
70
|
end
|
61
71
|
|
62
72
|
def search_keys_gmail
|
63
73
|
# Gmail offers an extension to IMAP that lets us use gmail queries
|
64
|
-
q = ""
|
65
74
|
|
66
75
|
# First, we ignore drafts beacuse they break a lot of assumptions we
|
67
76
|
# make when when processing emails (lack of timestamps, ids, etc)
|
68
|
-
q =
|
77
|
+
q = '-label:draft'
|
69
78
|
|
70
79
|
# We use UNIX timestamps in gmail filters which let us do more precise
|
71
80
|
# since/until compared with date-based imap filters
|
@@ -73,14 +82,14 @@ module Chronicle
|
|
73
82
|
q += " before:#{@config.until.to_i}" if @config.until
|
74
83
|
q += " #{@config.search_query}" if @config.search_query
|
75
84
|
|
76
|
-
[
|
85
|
+
['X-GM-RAW', q]
|
77
86
|
end
|
78
87
|
|
79
88
|
def search_keys_default
|
80
89
|
keys = []
|
81
90
|
# TODO: test out non-gmail IMAP searching (for @config.search_query)
|
82
91
|
keys += ['SINCE', Net::IMAP.format_date(@config.since)] if @config.since
|
83
|
-
keys
|
92
|
+
keys + ['BEFORE', Net::IMAP.format_date(@config.until)] if @config.until
|
84
93
|
end
|
85
94
|
|
86
95
|
def gmail_mode?
|
@@ -88,4 +97,4 @@ module Chronicle
|
|
88
97
|
end
|
89
98
|
end
|
90
99
|
end
|
91
|
-
end
|
100
|
+
end
|
@@ -6,9 +6,10 @@ module Chronicle
|
|
6
6
|
module Email
|
7
7
|
class MboxExtractor < Chronicle::ETL::Extractor
|
8
8
|
register_connector do |r|
|
9
|
-
r.
|
9
|
+
r.source = :email
|
10
|
+
r.type = :message
|
11
|
+
r.strategy = :mbox
|
10
12
|
r.description = 'an .mbox file'
|
11
|
-
r.identifier = 'mbox'
|
12
13
|
end
|
13
14
|
|
14
15
|
setting :input, required: true
|
@@ -40,14 +41,20 @@ module Chronicle
|
|
40
41
|
#
|
41
42
|
# TODO: make this thread-safe (one tmp file per email?)
|
42
43
|
file.each do |line|
|
43
|
-
if line =~ NEW_EMAIL_REGEX
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
if line =~ (NEW_EMAIL_REGEX) && File.size(tmp).positive?
|
45
|
+
tmp.rewind
|
46
|
+
|
47
|
+
email = Mail.new(tmp.read)
|
48
|
+
data = {
|
49
|
+
raw: email,
|
50
|
+
time: email.date&.to_time,
|
51
|
+
subject: email.subject,
|
52
|
+
from: email&.from&.join(', '),
|
53
|
+
to: email&.to&.join(', ')
|
54
|
+
}
|
55
|
+
yield build_extraction(data:)
|
56
|
+
tmp.truncate(0)
|
57
|
+
tmp.rewind
|
51
58
|
end
|
52
59
|
tmp.write(line)
|
53
60
|
end
|
data/lib/chronicle/email.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require 'chronicle/email/version'
|
2
|
+
require 'chronicle/email/email_transformer'
|
3
|
+
require 'chronicle/email/mbox_extractor'
|
4
|
+
require 'chronicle/email/imap_extractor'
|
5
5
|
|
6
6
|
module Chronicle
|
7
7
|
module Email
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chronicle-email
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Louis
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: email_reply_parser
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: mail
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.7'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.7'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: reverse_markdown
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,33 +53,33 @@ dependencies:
|
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '2.0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: chronicle-
|
56
|
+
name: chronicle-core
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0.
|
61
|
+
version: '0.3'
|
48
62
|
type: :runtime
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0.
|
68
|
+
version: '0.3'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
70
|
+
name: chronicle-etl
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
73
|
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
75
|
+
version: '0.6'
|
62
76
|
type: :runtime
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
82
|
+
version: '0.6'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: net-imap
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,14 +114,28 @@ dependencies:
|
|
100
114
|
requirements:
|
101
115
|
- - "~>"
|
102
116
|
- !ruby/object:Gem::Version
|
103
|
-
version: '2.
|
117
|
+
version: '2.3'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '2.3'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: pry-byebug
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '3.10'
|
104
132
|
type: :development
|
105
133
|
prerelease: false
|
106
134
|
version_requirements: !ruby/object:Gem::Requirement
|
107
135
|
requirements:
|
108
136
|
- - "~>"
|
109
137
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
138
|
+
version: '3.10'
|
111
139
|
- !ruby/object:Gem::Dependency
|
112
140
|
name: rake
|
113
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,19 +151,19 @@ dependencies:
|
|
123
151
|
- !ruby/object:Gem::Version
|
124
152
|
version: '13.0'
|
125
153
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
154
|
+
name: rubocop
|
127
155
|
requirement: !ruby/object:Gem::Requirement
|
128
156
|
requirements:
|
129
157
|
- - "~>"
|
130
158
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
159
|
+
version: '1.63'
|
132
160
|
type: :development
|
133
161
|
prerelease: false
|
134
162
|
version_requirements: !ruby/object:Gem::Requirement
|
135
163
|
requirements:
|
136
164
|
- - "~>"
|
137
165
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
166
|
+
version: '1.63'
|
139
167
|
description: Various email importers for chronicle-etl
|
140
168
|
email:
|
141
169
|
- andrew@hyfen.net
|
@@ -145,6 +173,7 @@ extra_rdoc_files: []
|
|
145
173
|
files:
|
146
174
|
- ".gitignore"
|
147
175
|
- ".rspec"
|
176
|
+
- ".rubocop.yml"
|
148
177
|
- ".travis.yml"
|
149
178
|
- CODE_OF_CONDUCT.md
|
150
179
|
- Gemfile
|
@@ -166,6 +195,7 @@ metadata:
|
|
166
195
|
homepage_uri: https://github.com/chronicle-app/chronicle-email
|
167
196
|
source_code_uri: https://github.com/chronicle-app/chronicle-email
|
168
197
|
changelog_uri: https://github.com/chronicle-app/chronicle-email
|
198
|
+
rubygems_mfa_required: 'true'
|
169
199
|
post_install_message:
|
170
200
|
rdoc_options: []
|
171
201
|
require_paths:
|
@@ -174,14 +204,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
174
204
|
requirements:
|
175
205
|
- - ">="
|
176
206
|
- !ruby/object:Gem::Version
|
177
|
-
version: '
|
207
|
+
version: '3.1'
|
178
208
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
209
|
requirements:
|
180
210
|
- - ">="
|
181
211
|
- !ruby/object:Gem::Version
|
182
212
|
version: '0'
|
183
213
|
requirements: []
|
184
|
-
rubygems_version: 3.
|
214
|
+
rubygems_version: 3.4.10
|
185
215
|
signing_key:
|
186
216
|
specification_version: 4
|
187
217
|
summary: Email importer for Chronicle
|