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 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