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.
- checksums.yaml +4 -4
- data/.gitignore +11 -11
- data/.rspec +3 -3
- data/.travis.yml +6 -6
- data/CODE_OF_CONDUCT.md +74 -74
- data/Gemfile +6 -6
- data/Gemfile.lock +71 -73
- data/LICENSE +201 -201
- data/README.md +62 -58
- data/Rakefile +6 -6
- data/SPECIFICATION.md +140 -0
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/exe/mailchain_connector_imap +7 -7
- data/lib/api/mailchain.rb +50 -50
- data/lib/connection/mailchain.rb +160 -159
- data/lib/connection_configuration/imap.rb +89 -89
- data/lib/connection_configuration/mailchain.rb +139 -139
- data/lib/mailchain_connector_imap/version.rb +5 -5
- data/mailchain_connector_imap.gemspec +38 -38
- metadata +7 -6
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`.
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
##
|
57
|
-
|
58
|
-
|
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
|
data/SPECIFICATION.md
ADDED
@@ -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
|
data/bin/console
CHANGED
@@ -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
|
data/lib/api/mailchain.rb
CHANGED
@@ -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
|
data/lib/connection/mailchain.rb
CHANGED
@@ -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
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
'
|
140
|
-
'
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
#
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
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
|