mailchain_connector_imap 0.1.4 → 0.1.5

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.
data/README.md CHANGED
@@ -1,58 +1,62 @@
1
- # MailchainConnectorImap
2
-
3
- The Mailchain Connector for IMAP makes it possible to receive Mailchain messages in your email inbox (i.e. your webmail, desktop or phone mail application).
4
-
5
- It connects to the Mailchain API, converts messages to emails, then uploads them to your chosen IMAP mailbox.
6
-
7
- **NOTE: Further documentation can be found here: <https://docs.mailchain.xyz/mailchain-connectors/mailchain-connector-imap>**
8
-
9
- ## Prerequisites
10
-
11
- You need to have installed:
12
-
13
- 1. Ruby
14
- 1. The Mailchain API client (<https://docs.mailchain.xyz/installation>)
15
-
16
- ## Installation
17
-
18
- Install by running:
19
-
20
- ```sh
21
- gem install mailchain_connector_imap
22
- ```
23
-
24
- ## Usage
25
-
26
- ### Getting Started & Configuration
27
-
28
- When running mailchain_connector_imap for the first time, or to change the configuration, run:
29
-
30
- ```sh
31
- mailchain_connector_imap --configure
32
- ```
33
-
34
- This will walk you through the configuration options.
35
-
36
- NOTE: See [Mailchain Docs](https://docs.mailchain.xyz/mailchain-connectors/mailchain-connector-imap) for further information.
37
-
38
- ### Running the Mailchain Connector for IMAP
39
-
40
- To run the connector, once you have run the configuration:
41
-
42
- ```sh
43
- mailchain_connector_imap
44
- ```
45
-
46
- ## Development
47
-
48
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
49
-
50
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
51
-
52
- ## Contributing
53
-
54
- Bug reports and pull requests are welcome on GitHub at <https://github.com/mailchain/mailchain_connector_imap>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/mailchain/community/blob/master/code-of-conduct.md).
55
-
56
- ## Code of Conduct
57
-
58
- Everyone interacting in the MailchainConnectorImap project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/mailchain/community/blob/master/code-of-conduct.md).
1
+ # MailchainConnectorImap
2
+
3
+ The Mailchain Connector for IMAP makes it possible to receive Mailchain messages in your email inbox (i.e. your webmail, desktop or phone mail application).
4
+
5
+ It connects to the Mailchain API, converts messages to emails, then uploads them to your chosen IMAP mailbox.
6
+
7
+ **NOTE: Further documentation can be found here: <https://docs.mailchain.xyz/mailchain-connectors/mailchain-connector-imap>**
8
+
9
+ ## Prerequisites
10
+
11
+ You need to have installed:
12
+
13
+ 1. Ruby
14
+ 1. The Mailchain API client (<https://docs.mailchain.xyz/installation>)
15
+
16
+ ## Installation
17
+
18
+ Install by running:
19
+
20
+ ```sh
21
+ gem install mailchain_connector_imap
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ### Getting Started & Configuration
27
+
28
+ When running mailchain_connector_imap for the first time, or to change the configuration, run:
29
+
30
+ ```sh
31
+ mailchain_connector_imap --configure
32
+ ```
33
+
34
+ This will walk you through the configuration options.
35
+
36
+ NOTE: See [Mailchain Docs](https://docs.mailchain.xyz/mailchain-connectors/mailchain-connector-imap) for further information.
37
+
38
+ ### Running the Mailchain Connector for IMAP
39
+
40
+ To run the connector, once you have run the configuration:
41
+
42
+ ```sh
43
+ mailchain_connector_imap
44
+ ```
45
+
46
+ ## Development
47
+
48
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
49
+
50
+ To install this gem onto your local machine, run `bundle exec rake install`.
51
+
52
+ To clean up and re-install the gem locally, run `bundle exec rake clean` then `bundle exec rake install`.
53
+
54
+ To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
55
+
56
+ ## Contributing
57
+
58
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/mailchain/mailchain_connector_imap>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/mailchain/community/blob/master/code-of-conduct.md).
59
+
60
+ ## Code of Conduct
61
+
62
+ Everyone interacting in the MailchainConnectorImap project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/mailchain/community/blob/master/code-of-conduct.md).
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
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
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,140 @@
1
+ # **Mailchain Connector for IMAP Specification**
2
+
3
+ The Mailchain Connector for IMAP enables users to receive Mailchain messages in their email client inbox by using the IMAP protocol to append messages to a new or existing email account via the email server (the email provider/ server must support IMAP).
4
+
5
+ The following requirements set out how the Mailchain Connector for IMAP can be implemented:
6
+
7
+ ## **Requirements Notation**
8
+
9
+ This document occasionally uses terms that appear in capital letters. When the terms “MUST”, “SHOULD”, “RECOMMENDED”, “MUST NOT”, “SHOULD NOT”, and “MAY” appear capitalised, they are being used to indicate particular requirements of this specification. A discussion of the meanings of these terms appears in [RFC2119](https://tools.ietf.org/html/rfc2119).
10
+
11
+ ### **Definitions for the purpose of these requirements**
12
+
13
+ | Term | Definition |
14
+ | ----------- | ----------- |
15
+ | Centralized resource | A single entity or group of entities could be said to have control of the resource. Responsibility for the integrity or availability or the resource falls on entity or entities.
16
+ | Decentralized resource | No single entity or group of entities could be said to have control of the resource. Responsibility for the integrity or availability or the resource falls on the participants in the decentralized system according to the set of rules that govern the system.
17
+ | Mailbox | The email account or mailbox that 1. supports IMAP, and 2. is where the Mailchain messages will be delivered.
18
+ | Mailchain Client | The Mailchain API Client, available from [https://github.com/mailchain/mailchain]
19
+ | the Connector | The Mailchain Connector for IMAP.
20
+ | Message | A Mailchain message.
21
+ | Email | A Mailchain message converted to an email message.
22
+
23
+ ## **Message Handling**
24
+
25
+ ### Mailchain Client
26
+
27
+ The Connector SHOULD interact with the Mailchain Client for Message retrieval.
28
+
29
+ ### Message Storage & Logging
30
+
31
+ Messages SHOULD not be stored on disk by the Connector.
32
+
33
+ Message metadata SHOULD not be stored on disk unless it has been encrypted or hashed.
34
+
35
+ A hash of the Message ID MAY be stored on disk to track which messages have been appended to the Mailbox.
36
+
37
+ Credentials SHOULD not be stored on disk by the Connector unless encrypted.
38
+
39
+ The Connector MAY log connection attempts.
40
+
41
+ ### IMAP Support
42
+
43
+ The Connector MUST support HTTPS and HTTP connections to the Mailbox.
44
+
45
+ The Connector MUST support PLAIN and LOGIN Mailbox authentication types.
46
+
47
+ The Connector SHOULD prompt the user for credentials at runtime.
48
+
49
+ The Connector SHOULD not append messages that already exist in the Mailbox.
50
+
51
+ The Connector SHOULD not append messages that have been deleted from the Mailbox.
52
+
53
+ Email state MUST be handled by the Mailbox server (or IMAP server). I.e. it is out of scope.
54
+
55
+ ### Appending Messages & Folder Structure
56
+
57
+ A folder hierarchy SHOULD support either: `Protocol > Network > Address`, or `Address > Protocol > Network`.
58
+
59
+ The Connector SHOULD append each Email according to the folder hierarchy.
60
+
61
+ A user MAY indicate a preference for the folder hierarchy.
62
+
63
+ The Connector SHOULD support delivering Mainnet (or equivalent) Emails to the primary inbox folder that alerts the user of a new emails.
64
+
65
+ A user MAY indicate a preference for storing Mainnet Emails in the primary inbox or in a folder in the folder hierarchy.
66
+
67
+ The Connector MAY poll for new Messages at regular intervals.
68
+
69
+ A user MAY indicate a preference for the duration between polling for new Messages.
70
+
71
+ ### **Mailchain Addressing Format**
72
+
73
+ Addressing SHOULD follow the standard mailchain format.
74
+
75
+ For example:
76
+
77
+ `recipient_public_address`@`network`.`protocol`, where:
78
+
79
+ - `recipient_public_address` SHOULD be a public address for the recipient.
80
+ - `@` MUST be the delimiter to separate address from protocol and network details.
81
+ - `network`, an optional parameter MAY be included to specify the network the transaction is broadcast to, for example a testnet or a mainnet.
82
+ - `protocol` SHOULD specify the blockchain protocol for the message, for example, bitcoin or ethereum.
83
+ - `.` (dot) MUST be the delimiter to separate the protocol from network details.
84
+
85
+ The address MAY append a resolvable FQDN to the Mailchain address when appending to the Mailbox, e.g. `recipient_public_address`@`network.protocol.example.com`.
86
+
87
+ ## **Private Keys**
88
+
89
+ The Connector MUST not handle private keys. This SHOULD be handled by the Mailchain Client.
90
+
91
+ ## **Message Format**
92
+
93
+ The Connector MUST convert the Message to RFC5322 Internet Message Format.
94
+
95
+ The Connector MUST not alter the Message subject and body.
96
+
97
+ The Connector SHOULD support plaintext and html message content types.
98
+
99
+ The Connector MAY add a footer to the Email prior to appending it to the Mailbox.
100
+
101
+ The Connector MUST add Mailchain message headers in the format 'X-Mailchain-' + 'Dash-Separated-Capitalised-Header', e.g. Mailchain message header: 'block-id-encoding' = email header 'X-Mailchain-Block-Id-Encoding'.
102
+
103
+ The Connector SHOULD include transaction details in the Email headers.
104
+
105
+ The Email body MUST be included after the headers.
106
+
107
+ An Email body MUST follow the content-type specified in Content-Type header.
108
+
109
+ An Email body MUST be encoded with the content-transfer-encoding specified in Content-Transfer-Encoding header.
110
+
111
+ An Email body MAY be empty.
112
+
113
+ An Email MUST have the following fields:
114
+
115
+ | Field | Description |
116
+ | ----------- | ----------- |
117
+ | To: | The recipient public address formatted according to the Mailchain Addressing Format
118
+ | From: | The sender public address formatted according to the Mailchain Addressing Format
119
+ | Message-ID: | The Message header message-id field value
120
+ | Date: | The RFC5322 date format
121
+ | Content-Type: | As per RFC6532 content type for the contents of the message.
122
+ | Content-Transfer-Encoding: | How the message body SHOULD encoded
123
+ | Subject: | The message subject
124
+ | Body: | The message body
125
+
126
+ Email headers SHOULD contain the following fields:
127
+
128
+ | Field | Description |
129
+ | ----------- | ----------- |
130
+ | X-Mailchain-Block-Id | Corresponding Message header field: block-id
131
+ | X-Mailchain-Transaction-Hash | Corresponding Message header field: transaction-hash
132
+ | X-Mailchain-Transaction-Hash-Encoding | Corresponding Message header field: transaction-hash-encoding
133
+ | X-Mailchain-Block-Id-Encoding | Corresponding Message header field: block-id-encoding
134
+
135
+ An Email MAY contain the following header fields:
136
+
137
+ | Field | Description |
138
+ | ----------- | ----------- |
139
+ | Reply-To: | The public address responses should be sent to
140
+ | Reply-To-Public-Key: | The public key that should be used to encrypt a reply
@@ -1,14 +1,14 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "mailchain_connector_imap"
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__)
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "mailchain_connector_imap"
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__)
data/bin/setup CHANGED
@@ -1,8 +1,8 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -1,7 +1,7 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require File.absolute_path('../lib/mailchain_connector_imap', __dir__)
5
-
6
- connector = MailchainConnectorImap::Connector.new
7
- connector.start
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require File.absolute_path('../lib/mailchain_connector_imap', __dir__)
5
+
6
+ connector = MailchainConnectorImap::Connector.new
7
+ connector.start
@@ -1,50 +1,50 @@
1
- # frozen_string_literal: true
2
-
3
- require 'httparty'
4
-
5
- class MailchainApi
6
- include HTTParty
7
- @config = {}
8
-
9
- # Initialize the config
10
- def initialize(config)
11
- @config = config
12
- end
13
-
14
- # Return the base_uri as specified in the config
15
- def base_uri
16
- ssl = @config['ssl'] ? 'https' : 'http'
17
- uri = @config['hostname']
18
- port = @config['port']
19
- "#{ssl}://#{uri}:#{port}/api"
20
- end
21
-
22
- # Get addresses endpoint
23
- # `protocol` = the protocol
24
- # `network` = the network
25
- def addresses(protocol, network)
26
- res = self.class.get("#{base_uri}/addresses?protocol=#{protocol}&network=#{network}")
27
- { body: JSON.parse(res.body), status_code: res.code }
28
- end
29
-
30
- # Get messages from api
31
- # `address`: the address (string e.g. '0x123...')
32
- # `protocol`: the protocol (string e.g. 'ethereum)
33
- # `network`: the network (string e.g. 'ropsten')
34
- def messages(address, protocol, network)
35
- res = self.class.get("#{base_uri}/messages?address=#{address}&protocol=#{protocol}&network=#{network}")
36
- { body: JSON.parse(res.body), status_code: res.code }
37
- end
38
-
39
- # Get protocols endpoint
40
- def protocols
41
- res = self.class.get("#{base_uri}/protocols")
42
- { body: JSON.parse(res.body), status_code: res.code }
43
- end
44
-
45
- # Calls the version endpoint, returns version
46
- def version
47
- res = self.class.get("#{base_uri}/version")
48
- { body: JSON.parse(res.body), status_code: res.code }
49
- end
50
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+
5
+ class MailchainApi
6
+ include HTTParty
7
+ @config = {}
8
+
9
+ # Initialize the config
10
+ def initialize(config)
11
+ @config = config
12
+ end
13
+
14
+ # Return the base_uri as specified in the config
15
+ def base_uri
16
+ ssl = @config['ssl'] ? 'https' : 'http'
17
+ uri = @config['hostname']
18
+ port = @config['port']
19
+ "#{ssl}://#{uri}:#{port}/api"
20
+ end
21
+
22
+ # Get addresses endpoint
23
+ # `protocol` = the protocol
24
+ # `network` = the network
25
+ def addresses(protocol, network)
26
+ res = self.class.get("#{base_uri}/addresses?protocol=#{protocol}&network=#{network}")
27
+ { body: JSON.parse(res.body), status_code: res.code }
28
+ end
29
+
30
+ # Get messages from api
31
+ # `address`: the address (string e.g. '0x123...')
32
+ # `protocol`: the protocol (string e.g. 'ethereum)
33
+ # `network`: the network (string e.g. 'ropsten')
34
+ def messages(address, protocol, network)
35
+ res = self.class.get("#{base_uri}/messages?address=#{address}&protocol=#{protocol}&network=#{network}")
36
+ { body: JSON.parse(res.body), status_code: res.code }
37
+ end
38
+
39
+ # Get protocols endpoint
40
+ def protocols
41
+ res = self.class.get("#{base_uri}/protocols")
42
+ { body: JSON.parse(res.body), status_code: res.code }
43
+ end
44
+
45
+ # Calls the version endpoint, returns version
46
+ def version
47
+ res = self.class.get("#{base_uri}/version")
48
+ { body: JSON.parse(res.body), status_code: res.code }
49
+ end
50
+ end
@@ -1,159 +1,160 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../api/mailchain'
4
- require_relative '../connection/mailchain'
5
- require 'mail'
6
- # Handles the Mailchain API configuration and connection
7
- class ConnectionMailchain
8
- # Initialize configs
9
- def initialize(config, config_file)
10
- @config = config
11
- @config_file = config_file
12
- @api = MailchainApi.new(@config['mailchain'])
13
- end
14
-
15
- # Configures the Mailchain API settings then tests the connection
16
- def configure_and_connect
17
- if !configuration_wizard # TODO: - wire up to connection configuration
18
- exit
19
- else
20
- test_connection
21
- end
22
- end
23
-
24
- # # Run the Mailchain API configuration
25
- def configuration_wizard
26
- connection_configuration = ConnectionConfigurationMailchain.new(@config)
27
- result = connection_configuration.configuration_wizard
28
- if result['save']
29
- result['config']['imap'].delete('password')
30
- new_config_json = JSON.pretty_generate(result['config'])
31
- File.write(@config_file, new_config_json)
32
- end
33
- end
34
-
35
- # Tests the connection to the Mailchain API
36
- def test_connection(silent = false)
37
- puts 'Testing API connection...' unless silent
38
- result = true
39
- begin
40
- res = @api.version
41
- res[:status_code] != 200
42
- puts "Connection was successful (API version: #{res[:body]['version']})" unless silent
43
- rescue StandardError => e
44
- puts "Mailchain API failed to connect with the following error: #{e}"
45
- puts 'Check the Mailchain client is running and configured correctly'
46
- result = false
47
- end
48
- result
49
- end
50
-
51
- # Converts mailchain message to regular email
52
- def convert_message(message)
53
- footer = 'Delivered by Mailchain IMAP Connector'
54
- c_type = get_content_type(message['headers']['content-type'])
55
-
56
- mail = Mail.new do
57
- from message['headers']['from']
58
- to message['headers']['to']
59
- date message['headers']['date']
60
- message_id message['headers']['message-id']
61
- subject message['subject']
62
- if c_type == 'html'
63
- html_part do
64
- content_type message['headers']['content-type']
65
- body "#{message['body']} <br/><br/>#{footer}"
66
- end
67
- end
68
- if c_type == 'plain'
69
- text_part do
70
- content_type message['headers']['content-type']
71
- body "#{message['body']} \r\n#{footer}"
72
- end
73
- end
74
- end
75
- mail.header['X-Mailchain-Block-Id'] = message['block-id']
76
- mail.header['X-Mailchain-Block-Id-Encoding'] = message['block-id-encoding']
77
- mail.header['X-Mailchain-Transaction-Hash'] = message['transaction-hash']
78
- mail.header['X-Mailchain-Transaction-Hash-Encoding'] = message['transaction-hash-encoding']
79
- mail
80
- end
81
-
82
- # Returns `text` or `html`
83
- def get_content_type(content_type)
84
- case content_type
85
- when '"text/html; charset=\"UTF-8\""'
86
- 'html'
87
- when '"text/plain; charset=\"UTF-8\""'
88
- 'plain'
89
- else
90
- 'plain'
91
- end
92
- end
93
-
94
- # Returns addresses formatted by_network
95
- # e.g. [{
96
- # "protocol" => "ethereum",
97
- # "network" => "kovan",
98
- # "addresses"=> ["1234567890...", "d5ab4ce..."]
99
- # }]
100
- def addresses_by_network
101
- protocol_networks.map do |obj|
102
- {
103
- 'protocol' => obj['protocol'],
104
- 'network' => obj['network'],
105
- 'addresses' => @api.addresses(obj['protocol'], obj['network'])[:body]['addresses']
106
- }
107
- end
108
- end
109
-
110
- # Returns messages formatted by_network
111
- # e.g. [ address, res['messages'] ]
112
- def messages_by_network(item)
113
- protocol = item['protocol']
114
- network = item['network']
115
- addresses = item['addresses']
116
- messages = []
117
- addresses.each do |address|
118
- res = get_messages(address, protocol, network)
119
- messages << [address, res['messages']] unless res['messages'].nil?
120
- end
121
- messages
122
- end
123
-
124
- # Gets messages from api and returns `body` {"messages" => [...]}
125
- def get_messages(addr, protocol, network)
126
- address = "0x#{addr}"
127
- @api.messages(address, protocol, network)[:body]
128
- end
129
-
130
- # Convert and call the append_message for each valid message
131
- def convert_messages(messages)
132
- cmgs = []
133
- messages.each do |msg|
134
- next unless msg['status'] == 'ok'
135
-
136
- cm = convert_message(msg)
137
- cmgs << {
138
- 'message' => cm,
139
- 'message_id' => msg['headers']['message-id'],
140
- 'message_date' => cm.date.to_time
141
- }
142
- end
143
- cmgs
144
- end
145
-
146
- # Returns array of each network with parent protocol
147
- # e.g. [{'protocol' => 'ethereum', 'network' => 'ropsten'},...]
148
- def protocol_networks
149
- output = []
150
- @api.protocols[:body]['protocols'].each do |proto|
151
- output << proto['networks'].map do |n|
152
- { 'protocol' => proto['name'], 'network' => n['name'] }
153
- end
154
- end
155
- output.flatten
156
- rescue StandardError => e
157
- puts "Error: #{e}"
158
- end
159
- end
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../api/mailchain'
4
+ require_relative '../connection/mailchain'
5
+ require 'mail'
6
+ # Handles the Mailchain API configuration and connection
7
+ class ConnectionMailchain
8
+ # Initialize configs
9
+ def initialize(config, config_file)
10
+ @config = config
11
+ @config_file = config_file
12
+ @api = MailchainApi.new(@config['mailchain'])
13
+ end
14
+
15
+ # Configures the Mailchain API settings then tests the connection
16
+ def configure_and_connect
17
+ if !configuration_wizard # TODO: - wire up to connection configuration
18
+ exit
19
+ else
20
+ test_connection
21
+ end
22
+ end
23
+
24
+ # # Run the Mailchain API configuration
25
+ def configuration_wizard
26
+ connection_configuration = ConnectionConfigurationMailchain.new(@config)
27
+ result = connection_configuration.configuration_wizard
28
+ if result['save']
29
+ result['config']['imap'].delete('password')
30
+ new_config_json = JSON.pretty_generate(result['config'])
31
+ File.write(@config_file, new_config_json)
32
+ end
33
+ end
34
+
35
+ # Tests the connection to the Mailchain API
36
+ def test_connection(silent = false)
37
+ puts 'Testing API connection...' unless silent
38
+ result = true
39
+ begin
40
+ res = @api.version
41
+ res[:status_code] != 200
42
+ puts "Connection was successful (API version: #{res[:body]['version']})" unless silent
43
+ rescue StandardError => e
44
+ puts "Mailchain API failed to connect with the following error: #{e}"
45
+ puts 'Check the Mailchain client is running and configured correctly'
46
+ result = false
47
+ end
48
+ result
49
+ end
50
+
51
+ # Converts mailchain message to regular email
52
+ def convert_message(message)
53
+ footer = 'Delivered by Mailchain IMAP Connector'
54
+ c_type = get_content_type(message['headers']['content-type'])
55
+
56
+ mail = Mail.new do
57
+ from message['headers']['from']
58
+ to message['headers']['to']
59
+ date message['headers']['date']
60
+ message_id message['headers']['message-id']
61
+ subject message['subject']
62
+ if c_type == 'html'
63
+ html_part do
64
+ content_type message['headers']['content-type']
65
+ body "#{message['body']} <br/><br/>#{footer}"
66
+ end
67
+ end
68
+ if c_type == 'plain'
69
+ text_part do
70
+ content_type message['headers']['content-type']
71
+ body "#{message['body']} \r\n#{footer}"
72
+ end
73
+ end
74
+ end
75
+ mail.header['X-Mailchain-Block-Id'] = message['block-id']
76
+ mail.header['X-Mailchain-Block-Id-Encoding'] = message['block-id-encoding']
77
+ mail.header['X-Mailchain-Transaction-Hash'] = message['transaction-hash']
78
+ mail.header['X-Mailchain-Transaction-Hash-Encoding'] = message['transaction-hash-encoding']
79
+ mail
80
+ end
81
+
82
+ # Returns `text` or `html`
83
+ def get_content_type(content_type)
84
+ case content_type
85
+ when '"text/html; charset=\"UTF-8\""'
86
+ 'html'
87
+ when '"text/plain; charset=\"UTF-8\""'
88
+ 'plain'
89
+ else
90
+ 'plain'
91
+ end
92
+ end
93
+
94
+ # Returns addresses formatted by_network
95
+ # e.g. [{
96
+ # "protocol" => "ethereum",
97
+ # "network" => "kovan",
98
+ # "addresses"=> ["1234567890...", "d5ab4ce..."]
99
+ # }]
100
+ def addresses_by_network
101
+ protocol_networks.map do |obj|
102
+ {
103
+ 'protocol' => obj['protocol'],
104
+ 'network' => obj['network'],
105
+ 'addresses' => @api.addresses(obj['protocol'], obj['network'])[:body]['addresses']
106
+ }
107
+ end
108
+ end
109
+
110
+ # Returns messages formatted by_network
111
+ # e.g. [ address, res['messages'] ]
112
+ def messages_by_network(item)
113
+ protocol = item['protocol']
114
+ network = item['network']
115
+ addresses = item['addresses']
116
+ messages = []
117
+ addresses.each do |address|
118
+ address_val = address["value"]
119
+ res = get_messages(address_val, protocol, network)
120
+ messages << [address_val, res['messages']] unless res['messages'].nil?
121
+ end
122
+ messages
123
+ end
124
+
125
+ # Gets messages from api and returns `body` {"messages" => [...]}
126
+ def get_messages(addr, protocol, network)
127
+ address = "#{addr}"
128
+ @api.messages(address, protocol, network)[:body]
129
+ end
130
+
131
+ # Convert and call the append_message for each valid message
132
+ def convert_messages(messages)
133
+ cmgs = []
134
+ messages.each do |msg|
135
+ next unless msg['status'] == 'ok'
136
+
137
+ cm = convert_message(msg)
138
+ cmgs << {
139
+ 'message' => cm,
140
+ 'message_id' => msg['headers']['message-id'],
141
+ 'message_date' => cm.date.to_time
142
+ }
143
+ end
144
+ cmgs
145
+ end
146
+
147
+ # Returns array of each network with parent protocol
148
+ # e.g. [{'protocol' => 'ethereum', 'network' => 'ropsten'},...]
149
+ def protocol_networks
150
+ output = []
151
+ @api.protocols[:body]['protocols'].each do |proto|
152
+ output << proto['networks'].map do |n|
153
+ { 'protocol' => proto['name'], 'network' => n['name'] }
154
+ end
155
+ end
156
+ output.flatten
157
+ rescue StandardError => e
158
+ puts "Error: #{e}"
159
+ end
160
+ end