chronicle-email 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a910606f4987580ac86be55c02a6e3003b7cab21e93476dc1bf6fa4cc4512355
4
- data.tar.gz: ef1dbfa473c66feb93c730a5bdd4e426203519a8d94da6afccf227bfa1fa084a
3
+ metadata.gz: e0d66a6d2109f4f46f23fdf0c157085aed6f757f962339a422e4e38ca86ed129
4
+ data.tar.gz: e4136e05cf2827f64a07657e9442f9a8cdcac1ab88ed589c52ea76f62fd0d315
5
5
  SHA512:
6
- metadata.gz: f1ddc8cabf1b9fbb319ad36406e9a99e585eaad8abd772aea378438f838e11be3e75a9c3fe2a1c4805ee6c84d9dfe256ba9cff3ac205406c899ee33a71d1122f
7
- data.tar.gz: 00c745bf81b65f59c7e514e735bd3319548f747503907646ca619fbfb1634dd2bb5e199753141a9c651bf210326e803dbb3d4bdc4331bdaeba0ecb70425dd265
6
+ metadata.gz: 5d58d42a6db25951b46a08ad44302dab836fc3063fae2b9074e5156b4db59ab147b8401b60860665a0a27394ddca98a48c58a6abdf87ce474439e4d7b179604f
7
+ data.tar.gz: b11bea8171510544c35742cb7ab72c162b7774d0bd5603a7453f065d270a230fa8b2a17d77d5bfc1205a60710f1b7d076ec4f6521630754006a5efe4e6b18fcc
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ inherit_gem:
2
+ chronicle-core: .rubocop-plugin.yml
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
- source "https://rubygems.org"
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 --transformer email --since 5d --loader json
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 --transformer email --since 5d --loader json \
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 --transformer email --fields subject
37
+ $ chronicle-etl --extractor email:mbox --input ~/Downloads/inbox.mbox --fields subject
38
38
  ```
39
39
 
40
40
  ## Available Connectors
data/Rakefile CHANGED
@@ -1,6 +1,2 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
- task :default => :spec
1
+ require 'bundler/gem_tasks'
2
+ task default: %i[]
data/bin/console CHANGED
@@ -1,14 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "chronicle/email"
3
+ require 'bundler/setup'
4
+ require 'chronicle/email'
5
5
 
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
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
@@ -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 "chronicle/email/version"
3
+ require 'chronicle/email/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "chronicle-email"
6
+ spec.name = 'chronicle-email'
8
7
  spec.version = Chronicle::Email::VERSION
9
- spec.authors = ["Andrew Louis"]
10
- spec.email = ["andrew@hyfen.net"]
8
+ spec.authors = ['Andrew Louis']
9
+ spec.email = ['andrew@hyfen.net']
11
10
 
12
- spec.summary = "Email importer for Chronicle"
13
- spec.description = "Various email importers for chronicle-etl"
14
- spec.homepage = "https://github.com/chronicle-app/chronicle-email"
15
- spec.license = "MIT"
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["homepage_uri"] = spec.homepage
23
- spec.metadata["source_code_uri"] = "https://github.com/chronicle-app/chronicle-email"
24
- spec.metadata["changelog_uri"] = "https://github.com/chronicle-app/chronicle-email"
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 "RubyGems 2.0 or newer is required to protect against " \
27
- "public gem pushes."
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 = Dir.chdir(File.expand_path('..', __FILE__)) do
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 = "exe"
34
+ spec.bindir = 'exe'
36
35
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
37
- spec.require_paths = ["lib"]
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 "net-imap"
46
- spec.add_dependency "net-smtp"
47
-
48
- spec.add_development_dependency "bundler", "~> 2.1"
49
- spec.add_development_dependency "rake", "~> 13.0"
50
- spec.add_development_dependency "rspec", "~> 3.9"
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 'mail'
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.provider = 'email'
13
- r.identifier = 'email'
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
- def id
24
- message.message_id || raise(Chronicle::ETL::UntransformableRecordError, "Email doesn't have an ID")
25
- end
25
+ private
26
26
 
27
- def timestamp
28
- message.date&.to_time || raise(Chronicle::ETL::UntransformableRecordError, "Email doesn't have a timestamp")
29
- end
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
- private
31
+ email.message_id || raise(Chronicle::ETL::UntransformableRecordError, "Email doesn't have an ID")
32
32
 
33
- def message
34
- @message ||= Mail.new(@extraction.data[:email])
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 build_messaged
38
- record = ::Chronicle::ETL::Models::Activity.new
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
- record.dedupe_on << [:verb, :provider, :provider_id]
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 build_actor
52
- # sometimes From: fields are malformed and we can't build an
53
- # actor out of it.
54
- raise(Chronicle::ETL::UntransformableRecordError, "Can't determine email sender") unless message[:from]&.addrs&.any?
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
- record = ::Chronicle::ETL::Models::Entity.new
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
- record.dedupe_on << [:represents, :provider, :slug]
57
+ # TODO: handle email references
58
+ # TODO: handle email account owner
59
+ # TODO: handle attachments
63
60
 
64
- record
61
+ r.dedupe_on << %i[source source_id type]
62
+ end
65
63
  end
66
64
 
67
- def build_message
68
- record = ::Chronicle::ETL::Models::Entity.new
69
- record.represents = 'message'
70
- record.title = clean_subject(message.subject)
71
- record.body = clean_body(message)
72
- record.provider = 'email'
73
- record.provider_id = id
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("UTF-8", invalid: :replace, undef: :replace)
75
+ subject&.encode('UTF-8', invalid: :replace, undef: :replace)
85
76
  end
86
77
 
87
- def clean_body message
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 = message.text_part&.decoded rescue Mail::UnknownEncodingType
81
+ body = begin
82
+ message.text_part&.decoded
83
+ rescue StandardError
84
+ Mail::UnknownEncodingType
85
+ end
91
86
  else
92
- body = message.body&.decoded rescue Mail::UnknownEncodingType
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("UTF-8", invalid: :replace, undef: :replace)
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
- parsed_body = Timeout::timeout(5) do
113
+ Timeout.timeout(5) do
115
114
  EmailReplyParser.parse_reply(body)
116
115
  end
117
- rescue Timeout::Error, StandardError => e
118
- return body
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.provider = 'email'
8
- r.description = 'imap server'
9
- r.identifier = 'imap'
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
- yield Chronicle::ETL::Extraction.new(data: { email: message.attr["BODY[]"]} )
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 => e
43
- raise(Chronicle::ETL::ExtractionError, "Error connecting to IMAP server. Please check username and password")
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 => e
52
- raise(Chronicle::ETL::ExtractionError, "Error searching IMAP server for messages")
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, "BODY.PEEK[]")
57
- raise(Chronicle::ETL::ExtractionError, "Error loading message") unless response
66
+ response = @connection.fetch(message_id, 'BODY.PEEK[]')
67
+ raise(Chronicle::ETL::ExtractionError, 'Error loading message') unless response
58
68
 
59
- return response[0]
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 = "-label:draft"
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
- ["X-GM-RAW", q]
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 += ['BEFORE', Net::IMAP.format_date(@config.until)] if @config.until
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.provider = 'email'
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
- if File.size(tmp) > 0
45
- tmp.rewind
46
- email = tmp.read
47
- yield Chronicle::ETL::Extraction.new(data: { email: email} )
48
- tmp.truncate(0)
49
- tmp.rewind
50
- end
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
@@ -1,5 +1,5 @@
1
1
  module Chronicle
2
2
  module Email
3
- VERSION = "0.2.3"
3
+ VERSION = '0.3.0'.freeze
4
4
  end
5
5
  end
@@ -1,7 +1,7 @@
1
- require "chronicle/email/version"
2
- require "chronicle/email/email_transformer"
3
- require "chronicle/email/mbox_extractor"
4
- require "chronicle/email/imap_extractor"
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.2.3
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: 2022-03-31 00:00:00.000000000 Z
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-etl
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.5'
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.5'
68
+ version: '0.3'
55
69
  - !ruby/object:Gem::Dependency
56
- name: mail
70
+ name: chronicle-etl
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '2.7'
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: '2.7'
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.1'
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: '2.1'
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: rspec
154
+ name: rubocop
127
155
  requirement: !ruby/object:Gem::Requirement
128
156
  requirements:
129
157
  - - "~>"
130
158
  - !ruby/object:Gem::Version
131
- version: '3.9'
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: '3.9'
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: '0'
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.3.3
214
+ rubygems_version: 3.4.10
185
215
  signing_key:
186
216
  specification_version: 4
187
217
  summary: Email importer for Chronicle