imap-backup 4.0.0 → 4.0.4
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/README.md +17 -49
 - data/docs/development.md +53 -0
 - data/docs/restore.md +17 -0
 - data/imap-backup.gemspec +4 -7
 - data/lib/email/mboxrd/message.rb +6 -2
 - data/lib/email/provider/apple_mail.rb +7 -0
 - data/lib/email/provider/default.rb +12 -0
 - data/lib/email/provider/fastmail.rb +7 -0
 - data/lib/email/provider/gmail.rb +7 -0
 - data/lib/email/provider.rb +16 -26
 - data/lib/imap/backup/account/connection.rb +19 -29
 - data/lib/imap/backup/account/folder.rb +9 -10
 - data/lib/imap/backup/cli/helpers.rb +14 -1
 - data/lib/imap/backup/cli/local.rb +22 -28
 - data/lib/imap/backup/cli/setup.rb +1 -1
 - data/lib/imap/backup/cli/utils.rb +98 -0
 - data/lib/imap/backup/cli.rb +5 -1
 - data/lib/imap/backup/client/apple_mail.rb +11 -0
 - data/lib/imap/backup/client/default.rb +51 -0
 - data/lib/imap/backup/configuration/account.rb +3 -1
 - data/lib/imap/backup/configuration/connection_tester.rb +1 -1
 - data/lib/imap/backup/configuration/store.rb +10 -5
 - data/lib/imap/backup/downloader.rb +3 -4
 - data/lib/imap/backup/serializer/mbox.rb +5 -0
 - data/lib/imap/backup/serializer/mbox_store.rb +8 -8
 - data/lib/imap/backup/thunderbird/mailbox_exporter.rb +58 -0
 - data/lib/imap/backup/version.rb +1 -1
 - data/lib/imap/backup.rb +1 -0
 - data/lib/thunderbird/install.rb +16 -0
 - data/lib/thunderbird/local_folder.rb +65 -0
 - data/lib/thunderbird/profile.rb +30 -0
 - data/lib/thunderbird/profiles.rb +71 -0
 - data/lib/thunderbird/subdirectory.rb +96 -0
 - data/lib/thunderbird/subdirectory_placeholder.rb +21 -0
 - data/lib/thunderbird.rb +14 -0
 - data/spec/features/restore_spec.rb +1 -1
 - data/spec/features/support/email_server.rb +2 -2
 - data/spec/spec_helper.rb +1 -0
 - data/spec/unit/email/provider/apple_mail_spec.rb +7 -0
 - data/spec/unit/email/provider/default_spec.rb +17 -0
 - data/spec/unit/email/provider/fastmail_spec.rb +7 -0
 - data/spec/unit/email/provider/gmail_spec.rb +7 -0
 - data/spec/unit/email/provider_spec.rb +12 -25
 - data/spec/unit/imap/backup/account/connection_spec.rb +26 -51
 - data/spec/unit/imap/backup/account/folder_spec.rb +22 -22
 - data/spec/unit/imap/backup/cli/local_spec.rb +70 -0
 - data/spec/unit/imap/backup/cli/utils_spec.rb +50 -0
 - data/spec/unit/imap/backup/client/default_spec.rb +22 -0
 - data/spec/unit/imap/backup/configuration/connection_tester_spec.rb +3 -3
 - data/spec/unit/imap/backup/configuration/store_spec.rb +25 -12
 - data/spec/unit/imap/backup/downloader_spec.rb +1 -2
 - metadata +71 -28
 - data/docs/docker-imap.md +0 -18
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 69ed28d85dda7c3d30cd6c8d4a9888e9f477eedd6f8ff08741fcc7d27cf087f8
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 1a99e7143052a1d0b1b2d58381c5f9da0db2b1e0e3882c24e56036cebead043f
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: deb80ed5d629c81253574d96a7da0dcc6382eb6d5216c1f317b8083ca0f4dac80a3188cbc0b7f46ffbc01229dad9ab913858649558ca7b3a29bf7b81395bcce3
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 2e6b2b8d2c67c6bc1e3ff5dcbb91c4eec92d0edb87ff33ad6e8a360b6635895c72cc7eb4cc68a7ff24bcfbad5a3533bda0a916e3c4d0c40ee67de70a010d4b2b
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -16,10 +16,6 @@ 
     | 
|
| 
       16 
16 
     | 
    
         
             
            [Rubygem]: http://rubygems.org/gems/imap-backup "Ruby gem at rubygems.org"
         
     | 
| 
       17 
17 
     | 
    
         
             
            [Continuous Integration]: https://circleci.com/gh/joeyates/imap-backup "Build status by CirceCI"
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
            # GMail
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
            To use imap-backup with GMail, you will need to enable 'App passwords' on your account.
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
19 
     | 
    
         
             
            # Installation
         
     | 
| 
       24 
20 
     | 
    
         | 
| 
       25 
21 
     | 
    
         
             
            ```shell
         
     | 
| 
         @@ -51,6 +47,10 @@ Run: 
     | 
|
| 
       51 
47 
     | 
    
         
             
            $ imap-backup setup
         
     | 
| 
       52 
48 
     | 
    
         
             
            ```
         
     | 
| 
       53 
49 
     | 
    
         | 
| 
      
 50 
     | 
    
         
            +
            ## GMail
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            To use imap-backup with GMail, you will need to enable 'App passwords' on your account.
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
       54 
54 
     | 
    
         
             
            ## Folders
         
     | 
| 
       55 
55 
     | 
    
         | 
| 
       56 
56 
     | 
    
         
             
            By default, all folders are backed-up. You can override this by choosing
         
     | 
| 
         @@ -134,7 +134,15 @@ in the configuration file. 
     | 
|
| 
       134 
134 
     | 
    
         | 
| 
       135 
135 
     | 
    
         
             
            The directory ~/.imap-backup, the configuration file and all backup
         
     | 
| 
       136 
136 
     | 
    
         
             
            directories have their access permissions set to only allow access
         
     | 
| 
       137 
     | 
    
         
            -
            by your user.
         
     | 
| 
      
 137 
     | 
    
         
            +
            by your user. This is not done on Windows - see below.
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
            ## Windows
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
            Due to the complexity of managing permissions on Windows,
         
     | 
| 
      
 142 
     | 
    
         
            +
            directory and file access permissions are not set explicity.
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
            A pull request that implements permissions management on Windows
         
     | 
| 
      
 145 
     | 
    
         
            +
            would be welcome!
         
     | 
| 
       138 
146 
     | 
    
         | 
| 
       139 
147 
     | 
    
         
             
            # Run Backup
         
     | 
| 
       140 
148 
     | 
    
         | 
| 
         @@ -178,6 +186,7 @@ If you have problems: 
     | 
|
| 
       178 
186 
     | 
    
         
             
              "debug": true
         
     | 
| 
       179 
187 
     | 
    
         
             
            }
         
     | 
| 
       180 
188 
     | 
    
         
             
            ```
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
       181 
190 
     | 
    
         
             
            # Restore
         
     | 
| 
       182 
191 
     | 
    
         | 
| 
       183 
192 
     | 
    
         
             
            All missing messages are pushed to the IMAP server.
         
     | 
| 
         @@ -206,48 +215,7 @@ $ imap-backup status 
     | 
|
| 
       206 
215 
     | 
    
         
             
            * Restartable - calculate start point based on already downloaded messages
         
     | 
| 
       207 
216 
     | 
    
         
             
            * Standalone - do not rely on an email client or MTA
         
     | 
| 
       208 
217 
     | 
    
         | 
| 
       209 
     | 
    
         
            -
            #  
     | 
| 
       210 
     | 
    
         
            -
             
     | 
| 
       211 
     | 
    
         
            -
            * https://github.com/OfflineIMAP/offlineimap
         
     | 
| 
       212 
     | 
    
         
            -
             
     | 
| 
       213 
     | 
    
         
            -
            # Testing
         
     | 
| 
       214 
     | 
    
         
            -
             
     | 
| 
       215 
     | 
    
         
            -
            ## Integration Tests
         
     | 
| 
       216 
     | 
    
         
            -
             
     | 
| 
       217 
     | 
    
         
            -
            Integration tests (feature specs) are run against a Docker image
         
     | 
| 
       218 
     | 
    
         
            -
            (antespi/docker-imap-devel:latest).
         
     | 
| 
       219 
     | 
    
         
            -
             
     | 
| 
       220 
     | 
    
         
            -
            In one shell, run the Docker image:
         
     | 
| 
       221 
     | 
    
         
            -
             
     | 
| 
       222 
     | 
    
         
            -
            ```sh
         
     | 
| 
       223 
     | 
    
         
            -
            $ docker run \
         
     | 
| 
       224 
     | 
    
         
            -
              --env MAIL_ADDRESS=address@example.org \
         
     | 
| 
       225 
     | 
    
         
            -
              --env MAIL_PASS=pass \
         
     | 
| 
       226 
     | 
    
         
            -
              --env MAILNAME=example.org \
         
     | 
| 
       227 
     | 
    
         
            -
              --publish 8993:993 \
         
     | 
| 
       228 
     | 
    
         
            -
              antespi/docker-imap-devel:latest
         
     | 
| 
       229 
     | 
    
         
            -
            ```
         
     | 
| 
       230 
     | 
    
         
            -
             
     | 
| 
       231 
     | 
    
         
            -
            ```sh
         
     | 
| 
       232 
     | 
    
         
            -
            $ rake
         
     | 
| 
       233 
     | 
    
         
            -
            ```
         
     | 
| 
       234 
     | 
    
         
            -
             
     | 
| 
       235 
     | 
    
         
            -
            To exclude Docker-based tests:
         
     | 
| 
       236 
     | 
    
         
            -
             
     | 
| 
       237 
     | 
    
         
            -
            ```sh
         
     | 
| 
       238 
     | 
    
         
            -
            rake no-docker
         
     | 
| 
       239 
     | 
    
         
            -
            ```
         
     | 
| 
       240 
     | 
    
         
            -
             
     | 
| 
       241 
     | 
    
         
            -
            or
         
     | 
| 
       242 
     | 
    
         
            -
             
     | 
| 
       243 
     | 
    
         
            -
            ```sh
         
     | 
| 
       244 
     | 
    
         
            -
            $ rspec --tag ~docker
         
     | 
| 
       245 
     | 
    
         
            -
            ```
         
     | 
| 
       246 
     | 
    
         
            -
             
     | 
| 
       247 
     | 
    
         
            -
            ## Contributing
         
     | 
| 
      
 218 
     | 
    
         
            +
            # Documentation
         
     | 
| 
       248 
219 
     | 
    
         | 
| 
       249 
     | 
    
         
            -
             
     | 
| 
       250 
     | 
    
         
            -
             
     | 
| 
       251 
     | 
    
         
            -
            3. Commit your changes (`git commit -am 'Added some feature'`)
         
     | 
| 
       252 
     | 
    
         
            -
            4. Push to the branch (`git push origin my-new-feature`)
         
     | 
| 
       253 
     | 
    
         
            -
            5. Create new Pull Request
         
     | 
| 
      
 220 
     | 
    
         
            +
            * [Development](./docs/development.md)
         
     | 
| 
      
 221 
     | 
    
         
            +
            * [Restore](./docs/restore.md)
         
     | 
    
        data/docs/development.md
    ADDED
    
    | 
         @@ -0,0 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Testing
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            ## Integration Tests
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Integration tests (feature specs) are run against a local IMAP server
         
     | 
| 
      
 6 
     | 
    
         
            +
            controlled by Docker Compose, which needs to be started
         
     | 
| 
      
 7 
     | 
    
         
            +
            before running the test suite.
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 10 
     | 
    
         
            +
            $ docker-compose up -d
         
     | 
| 
      
 11 
     | 
    
         
            +
            ```
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 14 
     | 
    
         
            +
            $ rake
         
     | 
| 
      
 15 
     | 
    
         
            +
            ```
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            To exclude Docker-based tests:
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 20 
     | 
    
         
            +
            rake no-docker
         
     | 
| 
      
 21 
     | 
    
         
            +
            ```
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            or
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 26 
     | 
    
         
            +
            $ rspec --tag ~docker
         
     | 
| 
      
 27 
     | 
    
         
            +
            ```
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            ## Access Docker imap server
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 32 
     | 
    
         
            +
            require "net/imap"
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            imap = Net::IMAP.new("localhost", {port: 8993, ssl: {verify_mode: 0}})
         
     | 
| 
      
 35 
     | 
    
         
            +
            username = "address@example.org"
         
     | 
| 
      
 36 
     | 
    
         
            +
            imap.login(username, "pass")
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            message = "From: #{username}\nSubject: Some Subject\n\nHello!\n"
         
     | 
| 
      
 39 
     | 
    
         
            +
            response = imap.append("INBOX", message, nil, nil)
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            imap.examine("INBOX")
         
     | 
| 
      
 42 
     | 
    
         
            +
            uids = imap.uid_search(["ALL"]).sort
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            fetch_data_items = imap.uid_fetch(uids, ["BODY[]"])
         
     | 
| 
      
 45 
     | 
    
         
            +
            ```
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            # Contributing
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            1. Fork it
         
     | 
| 
      
 50 
     | 
    
         
            +
            2. Create your feature branch (`git checkout -b my-new-feature`)
         
     | 
| 
      
 51 
     | 
    
         
            +
            3. Commit your changes (`git commit -am 'Added some feature'`)
         
     | 
| 
      
 52 
     | 
    
         
            +
            4. Push to the branch (`git push origin my-new-feature`)
         
     | 
| 
      
 53 
     | 
    
         
            +
            5. Create new Pull Request
         
     | 
    
        data/docs/restore.md
    CHANGED
    
    | 
         @@ -2,10 +2,27 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            # How does restore work?
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
      
 5 
     | 
    
         
            +
            Backed-up emails are pushed to the IMAP server.
         
     | 
| 
      
 6 
     | 
    
         
            +
            If there are clashes, folders are renamed.
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
       5 
8 
     | 
    
         
             
            # What are all these 'INBOX.12345' files?
         
     | 
| 
       6 
9 
     | 
    
         | 
| 
      
 10 
     | 
    
         
            +
            If, when the backup is launched, the IMAP server contains a folder with
         
     | 
| 
      
 11 
     | 
    
         
            +
            the same name, but different history to the local backup, the local
         
     | 
| 
      
 12 
     | 
    
         
            +
            emails cannot simply be added to the existing folder.
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            In this case, a numeric suffix is added to the **local** folder,
         
     | 
| 
      
 15 
     | 
    
         
            +
            before it is restored.
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            In this way, old and new emails are kept separate.
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
       7 
19 
     | 
    
         
             
            # Will my email get overwritten?
         
     | 
| 
       8 
20 
     | 
    
         | 
| 
      
 21 
     | 
    
         
            +
            No.
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            Emails are identified by folder and a specific email id. Any email that
         
     | 
| 
      
 24 
     | 
    
         
            +
            is already on the server is skipped.
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
       9 
26 
     | 
    
         
             
            ## How do I restore to a different service?
         
     | 
| 
       10 
27 
     | 
    
         | 
| 
       11 
28 
     | 
    
         
             
            1. Run setup and add the new server, (but don't run any backups),
         
     | 
    
        data/imap-backup.gemspec
    CHANGED
    
    | 
         @@ -1,6 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            $LOAD_PATH.unshift(File.expand_path("lib", __dir__))
         
     | 
| 
       2 
2 
     | 
    
         
             
            require "imap/backup/version"
         
     | 
| 
       3 
     | 
    
         
            -
            require "rake/file_list"
         
     | 
| 
       4 
3 
     | 
    
         | 
| 
       5 
4 
     | 
    
         
             
            Gem::Specification.new do |gem|
         
     | 
| 
       6 
5 
     | 
    
         
             
              gem.name          = "imap-backup"
         
     | 
| 
         @@ -10,24 +9,22 @@ Gem::Specification.new do |gem| 
     | 
|
| 
       10 
9 
     | 
    
         
             
              gem.email         = ["joe.g.yates@gmail.com"]
         
     | 
| 
       11 
10 
     | 
    
         
             
              gem.homepage      = "https://github.com/joeyates/imap-backup"
         
     | 
| 
       12 
11 
     | 
    
         
             
              gem.licenses      = ["MIT"]
         
     | 
| 
      
 12 
     | 
    
         
            +
              gem.version       = Imap::Backup::VERSION
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
              # Build list of files manually, see also
         
     | 
| 
       15 
     | 
    
         
            -
              # https://github.com/rubygems/rubygems/blob/master/bundler/bundler.gemspec#L37
         
     | 
| 
       16 
14 
     | 
    
         
             
              gem.files         = %w[bin/imap-backup]
         
     | 
| 
       17 
     | 
    
         
            -
              gem.files         += Dir.glob("docs 
     | 
| 
      
 15 
     | 
    
         
            +
              gem.files         += Dir.glob("docs/*.md")
         
     | 
| 
       18 
16 
     | 
    
         
             
              gem.files         += Dir.glob("lib/**/*.rb")
         
     | 
| 
       19 
     | 
    
         
            -
              gem.files         += Dir.glob("spec/**/*{.rb,.yml}")
         
     | 
| 
       20 
17 
     | 
    
         
             
              gem.files         += %w[imap-backup.gemspec]
         
     | 
| 
       21 
18 
     | 
    
         
             
              gem.files         += %w[LICENSE README.md]
         
     | 
| 
       22 
19 
     | 
    
         | 
| 
       23 
20 
     | 
    
         
             
              gem.executables   = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
         
     | 
| 
       24 
     | 
    
         
            -
              gem.test_files    =  
     | 
| 
      
 21 
     | 
    
         
            +
              gem.test_files    = Dir.glob("spec/**/*{.rb,.yml}")
         
     | 
| 
       25 
22 
     | 
    
         
             
              gem.require_paths = ["lib"]
         
     | 
| 
       26 
23 
     | 
    
         
             
              gem.required_ruby_version = ">= 2.5"
         
     | 
| 
       27 
     | 
    
         
            -
              gem.version = Imap::Backup::VERSION
         
     | 
| 
       28 
24 
     | 
    
         | 
| 
       29 
25 
     | 
    
         
             
              gem.add_runtime_dependency "highline"
         
     | 
| 
       30 
26 
     | 
    
         
             
              gem.add_runtime_dependency "mail"
         
     | 
| 
      
 27 
     | 
    
         
            +
              gem.add_runtime_dependency "os"
         
     | 
| 
       31 
28 
     | 
    
         
             
              gem.add_runtime_dependency "rake"
         
     | 
| 
       32 
29 
     | 
    
         
             
              gem.add_runtime_dependency "thor", "~> 1.1"
         
     | 
| 
       33 
30 
     | 
    
         | 
    
        data/lib/email/mboxrd/message.rb
    CHANGED
    
    | 
         @@ -1,9 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "forwardable"
         
     | 
| 
       1 
2 
     | 
    
         
             
            require "mail"
         
     | 
| 
       2 
3 
     | 
    
         | 
| 
       3 
4 
     | 
    
         
             
            module Email; end
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
       5 
6 
     | 
    
         
             
            module Email::Mboxrd
         
     | 
| 
       6 
7 
     | 
    
         
             
              class Message
         
     | 
| 
      
 8 
     | 
    
         
            +
                extend Forwardable
         
     | 
| 
      
 9 
     | 
    
         
            +
                def_delegators :@parsed, :subject
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
       7 
11 
     | 
    
         
             
                attr_reader :supplied_body
         
     | 
| 
       8 
12 
     | 
    
         | 
| 
       9 
13 
     | 
    
         
             
                def self.from_serialized(serialized)
         
     | 
| 
         @@ -36,12 +40,12 @@ module Email::Mboxrd 
     | 
|
| 
       36 
40 
     | 
    
         
             
                  supplied_body.gsub(/(?<!\r)\n/, "\r\n")
         
     | 
| 
       37 
41 
     | 
    
         
             
                end
         
     | 
| 
       38 
42 
     | 
    
         | 
| 
      
 43 
     | 
    
         
            +
                private
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
       39 
45 
     | 
    
         
             
                def parsed
         
     | 
| 
       40 
46 
     | 
    
         
             
                  @parsed ||= Mail.new(supplied_body)
         
     | 
| 
       41 
47 
     | 
    
         
             
                end
         
     | 
| 
       42 
48 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
                private
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
49 
     | 
    
         
             
                def from
         
     | 
| 
       46 
50 
     | 
    
         
             
                  @from ||=
         
     | 
| 
       47 
51 
     | 
    
         
             
                    begin
         
     | 
    
        data/lib/email/provider.rb
    CHANGED
    
    | 
         @@ -1,37 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "email/provider/default"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "email/provider/apple_mail"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "email/provider/fastmail"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "email/provider/gmail"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
       1 
6 
     | 
    
         
             
            module Email; end
         
     | 
| 
       2 
7 
     | 
    
         | 
| 
       3 
8 
     | 
    
         
             
            class Email::Provider
         
     | 
| 
       4 
     | 
    
         
            -
              GMAIL_IMAP_SERVER = "imap.gmail.com".freeze
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
9 
     | 
    
         
             
              def self.for_address(address)
         
     | 
| 
       7 
10 
     | 
    
         
             
                case
         
     | 
| 
       8 
11 
     | 
    
         
             
                when address.end_with?("@fastmail.com")
         
     | 
| 
       9 
     | 
    
         
            -
                  new 
     | 
| 
       10 
     | 
    
         
            -
                when address.end_with?("@gmail.com")
         
     | 
| 
       11 
     | 
    
         
            -
                  new(:gmail)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  Email::Provider::Fastmail.new
         
     | 
| 
       12 
13 
     | 
    
         
             
                when address.end_with?("@fastmail.fm")
         
     | 
| 
       13 
     | 
    
         
            -
                  new 
     | 
| 
      
 14 
     | 
    
         
            +
                  Email::Provider::Fastmail.new
         
     | 
| 
      
 15 
     | 
    
         
            +
                when address.end_with?("@gmail.com")
         
     | 
| 
      
 16 
     | 
    
         
            +
                  Email::Provider::GMail.new
         
     | 
| 
      
 17 
     | 
    
         
            +
                when address.end_with?("@icloud.com")
         
     | 
| 
      
 18 
     | 
    
         
            +
                  Email::Provider::AppleMail.new
         
     | 
| 
      
 19 
     | 
    
         
            +
                when address.end_with?("@mac.com")
         
     | 
| 
      
 20 
     | 
    
         
            +
                  Email::Provider::AppleMail.new
         
     | 
| 
      
 21 
     | 
    
         
            +
                when address.end_with?("@me.com")
         
     | 
| 
      
 22 
     | 
    
         
            +
                  Email::Provider::AppleMail.new
         
     | 
| 
       14 
23 
     | 
    
         
             
                else
         
     | 
| 
       15 
     | 
    
         
            -
                  new 
     | 
| 
       16 
     | 
    
         
            -
                end
         
     | 
| 
       17 
     | 
    
         
            -
              end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
              attr_reader :provider
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
              def initialize(provider)
         
     | 
| 
       22 
     | 
    
         
            -
                @provider = provider
         
     | 
| 
       23 
     | 
    
         
            -
              end
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
              def options
         
     | 
| 
       26 
     | 
    
         
            -
                {port: 993, ssl: {ssl_version: :TLSv1_2}}
         
     | 
| 
       27 
     | 
    
         
            -
              end
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
              def host
         
     | 
| 
       30 
     | 
    
         
            -
                case provider
         
     | 
| 
       31 
     | 
    
         
            -
                when :gmail
         
     | 
| 
       32 
     | 
    
         
            -
                  GMAIL_IMAP_SERVER
         
     | 
| 
       33 
     | 
    
         
            -
                when :fastmail
         
     | 
| 
       34 
     | 
    
         
            -
                  "imap.fastmail.com"
         
     | 
| 
      
 24 
     | 
    
         
            +
                  Email::Provider::Default.new
         
     | 
| 
       35 
25 
     | 
    
         
             
                end
         
     | 
| 
       36 
26 
     | 
    
         
             
              end
         
     | 
| 
       37 
27 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,4 +1,5 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require " 
     | 
| 
      
 1 
     | 
    
         
            +
            require "imap/backup/client/apple_mail"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "imap/backup/client/default"
         
     | 
| 
       2 
3 
     | 
    
         | 
| 
       3 
4 
     | 
    
         
             
            require "retry_on_error"
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
         @@ -29,17 +30,15 @@ module Imap::Backup 
     | 
|
| 
       29 
30 
     | 
    
         
             
                def folders
         
     | 
| 
       30 
31 
     | 
    
         
             
                  @folders ||=
         
     | 
| 
       31 
32 
     | 
    
         
             
                    begin
         
     | 
| 
       32 
     | 
    
         
            -
                       
     | 
| 
       33 
     | 
    
         
            -
                      mailbox_lists = imap.list(root, "*")
         
     | 
| 
      
 33 
     | 
    
         
            +
                      folders = client.list
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
                      if  
     | 
| 
      
 35 
     | 
    
         
            +
                      if folders.empty?
         
     | 
| 
       36 
36 
     | 
    
         
             
                        message = "Unable to get folder list for account #{username}"
         
     | 
| 
       37 
37 
     | 
    
         
             
                        Imap::Backup.logger.info message
         
     | 
| 
       38 
38 
     | 
    
         
             
                        raise message
         
     | 
| 
       39 
39 
     | 
    
         
             
                      end
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
                       
     | 
| 
       42 
     | 
    
         
            -
                      utf7_encoded.map { |n| Net::IMAP.decode_utf7(n) }
         
     | 
| 
      
 41 
     | 
    
         
            +
                      folders
         
     | 
| 
       43 
42 
     | 
    
         
             
                    end
         
     | 
| 
       44 
43 
     | 
    
         
             
                end
         
     | 
| 
       45 
44 
     | 
    
         | 
| 
         @@ -54,7 +53,7 @@ module Imap::Backup 
     | 
|
| 
       54 
53 
     | 
    
         
             
                def run_backup
         
     | 
| 
       55 
54 
     | 
    
         
             
                  Imap::Backup.logger.debug "Running backup of account: #{username}"
         
     | 
| 
       56 
55 
     | 
    
         
             
                  # start the connection so we get logging messages in the right order
         
     | 
| 
       57 
     | 
    
         
            -
                   
     | 
| 
      
 56 
     | 
    
         
            +
                  client
         
     | 
| 
       58 
57 
     | 
    
         
             
                  each_folder do |folder, serializer|
         
     | 
| 
       59 
58 
     | 
    
         
             
                    next if !folder.exist?
         
     | 
| 
       60 
59 
     | 
    
         | 
| 
         @@ -89,34 +88,36 @@ module Imap::Backup 
     | 
|
| 
       89 
88 
     | 
    
         
             
                end
         
     | 
| 
       90 
89 
     | 
    
         | 
| 
       91 
90 
     | 
    
         
             
                def disconnect
         
     | 
| 
       92 
     | 
    
         
            -
                   
     | 
| 
      
 91 
     | 
    
         
            +
                  client.disconnect if @client
         
     | 
| 
       93 
92 
     | 
    
         
             
                end
         
     | 
| 
       94 
93 
     | 
    
         | 
| 
       95 
94 
     | 
    
         
             
                def reconnect
         
     | 
| 
       96 
95 
     | 
    
         
             
                  disconnect
         
     | 
| 
       97 
     | 
    
         
            -
                  @ 
     | 
| 
      
 96 
     | 
    
         
            +
                  @client = nil
         
     | 
| 
       98 
97 
     | 
    
         
             
                end
         
     | 
| 
       99 
98 
     | 
    
         | 
| 
       100 
     | 
    
         
            -
                def  
     | 
| 
       101 
     | 
    
         
            -
                  @ 
     | 
| 
      
 99 
     | 
    
         
            +
                def client
         
     | 
| 
      
 100 
     | 
    
         
            +
                  @client ||=
         
     | 
| 
       102 
101 
     | 
    
         
             
                    retry_on_error(errors: LOGIN_RETRY_CLASSES) do
         
     | 
| 
       103 
102 
     | 
    
         
             
                      options = provider_options
         
     | 
| 
       104 
103 
     | 
    
         
             
                      Imap::Backup.logger.debug(
         
     | 
| 
       105 
104 
     | 
    
         
             
                        "Creating IMAP instance: #{server}, options: #{options.inspect}"
         
     | 
| 
       106 
105 
     | 
    
         
             
                      )
         
     | 
| 
       107 
     | 
    
         
            -
                       
     | 
| 
      
 106 
     | 
    
         
            +
                      client =
         
     | 
| 
      
 107 
     | 
    
         
            +
                        if provider.is_a?(Email::Provider::AppleMail)
         
     | 
| 
      
 108 
     | 
    
         
            +
                          Client::AppleMail.new(server, options)
         
     | 
| 
      
 109 
     | 
    
         
            +
                        else
         
     | 
| 
      
 110 
     | 
    
         
            +
                          Client::Default.new(server, options)
         
     | 
| 
      
 111 
     | 
    
         
            +
                        end
         
     | 
| 
       108 
112 
     | 
    
         
             
                      Imap::Backup.logger.debug "Logging in: #{username}/#{masked_password}"
         
     | 
| 
       109 
     | 
    
         
            -
                       
     | 
| 
      
 113 
     | 
    
         
            +
                      client.login(username, password)
         
     | 
| 
       110 
114 
     | 
    
         
             
                      Imap::Backup.logger.debug "Login complete"
         
     | 
| 
       111 
     | 
    
         
            -
                       
     | 
| 
      
 115 
     | 
    
         
            +
                      client
         
     | 
| 
       112 
116 
     | 
    
         
             
                    end
         
     | 
| 
       113 
117 
     | 
    
         
             
                end
         
     | 
| 
       114 
118 
     | 
    
         | 
| 
       115 
119 
     | 
    
         
             
                def server
         
     | 
| 
       116 
     | 
    
         
            -
                   
     | 
| 
       117 
     | 
    
         
            -
                  return nil if provider.nil?
         
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
                  @server = provider.host
         
     | 
| 
      
 120 
     | 
    
         
            +
                  @server ||= provider.host
         
     | 
| 
       120 
121 
     | 
    
         
             
                end
         
     | 
| 
       121 
122 
     | 
    
         | 
| 
       122 
123 
     | 
    
         
             
                private
         
     | 
| 
         @@ -186,16 +187,5 @@ module Imap::Backup 
     | 
|
| 
       186 
187 
     | 
    
         
             
                def provider_options
         
     | 
| 
       187 
188 
     | 
    
         
             
                  provider.options.merge(connection_options)
         
     | 
| 
       188 
189 
     | 
    
         
             
                end
         
     | 
| 
       189 
     | 
    
         
            -
             
     | 
| 
       190 
     | 
    
         
            -
                # 6.3.8. LIST Command
         
     | 
| 
       191 
     | 
    
         
            -
                # An empty ("" string) mailbox name argument is a special request to
         
     | 
| 
       192 
     | 
    
         
            -
                # return the hierarchy delimiter and the root name of the name given
         
     | 
| 
       193 
     | 
    
         
            -
                # in the reference.
         
     | 
| 
       194 
     | 
    
         
            -
                def provider_root
         
     | 
| 
       195 
     | 
    
         
            -
                  return @provider_root if @provider_root
         
     | 
| 
       196 
     | 
    
         
            -
             
     | 
| 
       197 
     | 
    
         
            -
                  root_info = imap.list("", "")[0]
         
     | 
| 
       198 
     | 
    
         
            -
                  @provider_root = root_info.name
         
     | 
| 
       199 
     | 
    
         
            -
                end
         
     | 
| 
       200 
190 
     | 
    
         
             
              end
         
     | 
| 
       201 
191 
     | 
    
         
             
            end
         
     | 
| 
         @@ -11,13 +11,13 @@ module Imap::Backup 
     | 
|
| 
       11 
11 
     | 
    
         
             
                extend Forwardable
         
     | 
| 
       12 
12 
     | 
    
         
             
                include RetryOnError
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                 
     | 
| 
      
 14 
     | 
    
         
            +
                BODY_ATTRIBUTE = "BODY[]".freeze
         
     | 
| 
       15 
15 
     | 
    
         
             
                UID_FETCH_RETRY_CLASSES = [EOFError].freeze
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
                attr_reader :connection
         
     | 
| 
       18 
18 
     | 
    
         
             
                attr_reader :name
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
                delegate  
     | 
| 
      
 20 
     | 
    
         
            +
                delegate client: :connection
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
                def initialize(connection, name)
         
     | 
| 
       23 
23 
     | 
    
         
             
                  @connection = connection
         
     | 
| 
         @@ -40,20 +40,20 @@ module Imap::Backup 
     | 
|
| 
       40 
40 
     | 
    
         
             
                def create
         
     | 
| 
       41 
41 
     | 
    
         
             
                  return if exist?
         
     | 
| 
       42 
42 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
                   
     | 
| 
      
 43 
     | 
    
         
            +
                  client.create(utf7_encoded_name)
         
     | 
| 
       44 
44 
     | 
    
         
             
                end
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
46 
     | 
    
         
             
                def uid_validity
         
     | 
| 
       47 
47 
     | 
    
         
             
                  @uid_validity ||=
         
     | 
| 
       48 
48 
     | 
    
         
             
                    begin
         
     | 
| 
       49 
49 
     | 
    
         
             
                      examine
         
     | 
| 
       50 
     | 
    
         
            -
                       
     | 
| 
      
 50 
     | 
    
         
            +
                      client.responses["UIDVALIDITY"][-1]
         
     | 
| 
       51 
51 
     | 
    
         
             
                    end
         
     | 
| 
       52 
52 
     | 
    
         
             
                end
         
     | 
| 
       53 
53 
     | 
    
         | 
| 
       54 
54 
     | 
    
         
             
                def uids
         
     | 
| 
       55 
55 
     | 
    
         
             
                  examine
         
     | 
| 
       56 
     | 
    
         
            -
                   
     | 
| 
      
 56 
     | 
    
         
            +
                  client.uid_search(["ALL"]).sort
         
     | 
| 
       57 
57 
     | 
    
         
             
                rescue FolderNotFound
         
     | 
| 
       58 
58 
     | 
    
         
             
                  []
         
     | 
| 
       59 
59 
     | 
    
         
             
                rescue NoMethodError
         
     | 
| 
         @@ -72,15 +72,14 @@ module Imap::Backup 
     | 
|
| 
       72 
72 
     | 
    
         
             
                  examine
         
     | 
| 
       73 
73 
     | 
    
         
             
                  fetch_data_items =
         
     | 
| 
       74 
74 
     | 
    
         
             
                    retry_on_error(errors: UID_FETCH_RETRY_CLASSES) do
         
     | 
| 
       75 
     | 
    
         
            -
                       
     | 
| 
      
 75 
     | 
    
         
            +
                      client.uid_fetch([uid.to_i], [BODY_ATTRIBUTE])
         
     | 
| 
       76 
76 
     | 
    
         
             
                    end
         
     | 
| 
       77 
77 
     | 
    
         
             
                  return nil if fetch_data_items.nil?
         
     | 
| 
       78 
78 
     | 
    
         | 
| 
       79 
79 
     | 
    
         
             
                  fetch_data_item = fetch_data_items[0]
         
     | 
| 
       80 
80 
     | 
    
         
             
                  attributes = fetch_data_item.attr
         
     | 
| 
       81 
     | 
    
         
            -
                  return nil if !attributes.key?("RFC822")
         
     | 
| 
       82 
81 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
                  attributes
         
     | 
| 
      
 82 
     | 
    
         
            +
                  attributes[BODY_ATTRIBUTE]
         
     | 
| 
       84 
83 
     | 
    
         
             
                rescue FolderNotFound
         
     | 
| 
       85 
84 
     | 
    
         
             
                  nil
         
     | 
| 
       86 
85 
     | 
    
         
             
                end
         
     | 
| 
         @@ -88,14 +87,14 @@ module Imap::Backup 
     | 
|
| 
       88 
87 
     | 
    
         
             
                def append(message)
         
     | 
| 
       89 
88 
     | 
    
         
             
                  body = message.imap_body
         
     | 
| 
       90 
89 
     | 
    
         
             
                  date = message.date&.to_time
         
     | 
| 
       91 
     | 
    
         
            -
                  response =  
     | 
| 
      
 90 
     | 
    
         
            +
                  response = client.append(utf7_encoded_name, body, nil, date)
         
     | 
| 
       92 
91 
     | 
    
         
             
                  extract_uid(response)
         
     | 
| 
       93 
92 
     | 
    
         
             
                end
         
     | 
| 
       94 
93 
     | 
    
         | 
| 
       95 
94 
     | 
    
         
             
                private
         
     | 
| 
       96 
95 
     | 
    
         | 
| 
       97 
96 
     | 
    
         
             
                def examine
         
     | 
| 
       98 
     | 
    
         
            -
                   
     | 
| 
      
 97 
     | 
    
         
            +
                  client.examine(utf7_encoded_name)
         
     | 
| 
       99 
98 
     | 
    
         
             
                rescue Net::IMAP::NoResponseError
         
     | 
| 
       100 
99 
     | 
    
         
             
                  Imap::Backup.logger.warn "Folder '#{name}' does not exist on server"
         
     | 
| 
       101 
100 
     | 
    
         
             
                  raise FolderNotFound, "Folder '#{name}' does not exist on server"
         
     | 
| 
         @@ -5,12 +5,25 @@ module Imap::Backup::CLI::Helpers 
     | 
|
| 
       5 
5 
     | 
    
         
             
                options.each.with_object({}) { |(k, v), acc| acc[k.intern] = v }
         
     | 
| 
       6 
6 
     | 
    
         
             
              end
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
      
 8 
     | 
    
         
            +
              def account(email)
         
     | 
| 
      
 9 
     | 
    
         
            +
                connections = Imap::Backup::Configuration::List.new
         
     | 
| 
      
 10 
     | 
    
         
            +
                account = connections.accounts.find { |a| a[:username] == email }
         
     | 
| 
      
 11 
     | 
    
         
            +
                raise "#{email} is not a configured account" if !account
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                account
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              def connection(email)
         
     | 
| 
      
 17 
     | 
    
         
            +
                account = account(email)
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                Imap::Backup::Account::Connection.new(account)
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
       8 
22 
     | 
    
         
             
              def each_connection(names)
         
     | 
| 
       9 
23 
     | 
    
         
             
                begin
         
     | 
| 
       10 
24 
     | 
    
         
             
                  connections = Imap::Backup::Configuration::List.new(names)
         
     | 
| 
       11 
25 
     | 
    
         
             
                rescue Imap::Backup::ConfigurationNotFound
         
     | 
| 
       12 
26 
     | 
    
         
             
                  raise "imap-backup is not configured. Run `imap-backup setup`"
         
     | 
| 
       13 
     | 
    
         
            -
                  return
         
     | 
| 
       14 
27 
     | 
    
         
             
                end
         
     | 
| 
       15 
28 
     | 
    
         | 
| 
       16 
29 
     | 
    
         
             
                connections.each_connection do |connection|
         
     | 
| 
         @@ -6,49 +6,46 @@ module Imap::Backup 
     | 
|
| 
       6 
6 
     | 
    
         
             
                desc "accounts", "List locally backed-up accounts"
         
     | 
| 
       7 
7 
     | 
    
         
             
                def accounts
         
     | 
| 
       8 
8 
     | 
    
         
             
                  connections = Imap::Backup::Configuration::List.new
         
     | 
| 
       9 
     | 
    
         
            -
                  connections.accounts.each { |a| puts a[:username] }
         
     | 
| 
      
 9 
     | 
    
         
            +
                  connections.accounts.each { |a| Kernel.puts a[:username] }
         
     | 
| 
       10 
10 
     | 
    
         
             
                end
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                desc "folders EMAIL", "List account folders"
         
     | 
| 
       13 
13 
     | 
    
         
             
                def folders(email)
         
     | 
| 
       14 
     | 
    
         
            -
                   
     | 
| 
       15 
     | 
    
         
            -
                  account = connections.accounts.find { |a| a[:username] == email }
         
     | 
| 
       16 
     | 
    
         
            -
                  raise "#{email} is not a configured account" if !account
         
     | 
| 
      
 14 
     | 
    
         
            +
                  connection = connection(email)
         
     | 
| 
       17 
15 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                   
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                    puts %("#{f.name}")
         
     | 
| 
      
 16 
     | 
    
         
            +
                  connection.local_folders.each do |_s, f|
         
     | 
| 
      
 17 
     | 
    
         
            +
                    Kernel.puts %("#{f.name}")
         
     | 
| 
       21 
18 
     | 
    
         
             
                  end
         
     | 
| 
       22 
19 
     | 
    
         
             
                end
         
     | 
| 
       23 
20 
     | 
    
         | 
| 
       24 
21 
     | 
    
         
             
                desc "list EMAIL FOLDER", "List emails in a folder"
         
     | 
| 
       25 
22 
     | 
    
         
             
                def list(email, folder_name)
         
     | 
| 
       26 
     | 
    
         
            -
                   
     | 
| 
       27 
     | 
    
         
            -
                  account = connections.accounts.find { |a| a[:username] == email }
         
     | 
| 
       28 
     | 
    
         
            -
                  raise "#{email} is not a configured account" if !account
         
     | 
| 
      
 23 
     | 
    
         
            +
                  connection = connection(email)
         
     | 
| 
       29 
24 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                   
     | 
| 
       31 
     | 
    
         
            -
                  folder_serializer, folder = account_connection.local_folders.find do |(_s, f)|
         
     | 
| 
      
 25 
     | 
    
         
            +
                  folder_serializer, _folder = connection.local_folders.find do |(_s, f)|
         
     | 
| 
       32 
26 
     | 
    
         
             
                    f.name == folder_name
         
     | 
| 
       33 
27 
     | 
    
         
             
                  end
         
     | 
| 
       34 
28 
     | 
    
         
             
                  raise "Folder '#{folder_name}' not found" if !folder_serializer
         
     | 
| 
       35 
29 
     | 
    
         | 
| 
       36 
30 
     | 
    
         
             
                  max_subject = 60
         
     | 
| 
       37 
     | 
    
         
            -
                  puts format( 
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
      
 31 
     | 
    
         
            +
                  Kernel.puts format(
         
     | 
| 
      
 32 
     | 
    
         
            +
                    "%-10<uid>s  %-#{max_subject}<subject>s - %<date>s",
         
     | 
| 
      
 33 
     | 
    
         
            +
                    {uid: "UID", subject: "Subject", date: "Date"}
         
     | 
| 
      
 34 
     | 
    
         
            +
                  )
         
     | 
| 
      
 35 
     | 
    
         
            +
                  Kernel.puts "-" * (12 + max_subject + 28)
         
     | 
| 
       39 
36 
     | 
    
         | 
| 
       40 
37 
     | 
    
         
             
                  uids = folder_serializer.uids
         
     | 
| 
       41 
38 
     | 
    
         | 
| 
       42 
39 
     | 
    
         
             
                  folder_serializer.each_message(uids).map do |uid, message|
         
     | 
| 
       43 
40 
     | 
    
         
             
                    m = {
         
     | 
| 
       44 
41 
     | 
    
         
             
                      uid: uid,
         
     | 
| 
       45 
     | 
    
         
            -
                      date: message. 
     | 
| 
       46 
     | 
    
         
            -
                      subject: message. 
     | 
| 
      
 42 
     | 
    
         
            +
                      date: message.date.to_s,
         
     | 
| 
      
 43 
     | 
    
         
            +
                      subject: message.subject || ""
         
     | 
| 
       47 
44 
     | 
    
         
             
                    }
         
     | 
| 
       48 
45 
     | 
    
         
             
                    if m[:subject].length > max_subject
         
     | 
| 
       49 
     | 
    
         
            -
                      puts format("% 10<uid>u: %.#{max_subject - 3}<subject>s... - %<date>s", m)
         
     | 
| 
      
 46 
     | 
    
         
            +
                      Kernel.puts format("% 10<uid>u: %.#{max_subject - 3}<subject>s... - %<date>s", m)
         
     | 
| 
       50 
47 
     | 
    
         
             
                    else
         
     | 
| 
       51 
     | 
    
         
            -
                      puts format("% 10<uid>u: %-#{max_subject}<subject>s - %<date>s", m)
         
     | 
| 
      
 48 
     | 
    
         
            +
                      Kernel.puts format("% 10<uid>u: %-#{max_subject}<subject>s - %<date>s", m)
         
     | 
| 
       52 
49 
     | 
    
         
             
                    end
         
     | 
| 
       53 
50 
     | 
    
         
             
                  end
         
     | 
| 
       54 
51 
     | 
    
         
             
                end
         
     | 
| 
         @@ -60,12 +57,9 @@ module Imap::Backup 
     | 
|
| 
       60 
57 
     | 
    
         
             
                  the UID.
         
     | 
| 
       61 
58 
     | 
    
         
             
                DESC
         
     | 
| 
       62 
59 
     | 
    
         
             
                def show(email, folder_name, uids)
         
     | 
| 
       63 
     | 
    
         
            -
                   
     | 
| 
       64 
     | 
    
         
            -
                  account = connections.accounts.find { |a| a[:username] == email }
         
     | 
| 
       65 
     | 
    
         
            -
                  raise "#{email} is not a configured account" if !account
         
     | 
| 
      
 60 
     | 
    
         
            +
                  connection = connection(email)
         
     | 
| 
       66 
61 
     | 
    
         | 
| 
       67 
     | 
    
         
            -
                   
     | 
| 
       68 
     | 
    
         
            -
                  folder_serializer, _folder = account_connection.local_folders.find do |(_s, f)|
         
     | 
| 
      
 62 
     | 
    
         
            +
                  folder_serializer, _folder = connection.local_folders.find do |(_s, f)|
         
     | 
| 
       69 
63 
     | 
    
         
             
                    f.name == folder_name
         
     | 
| 
       70 
64 
     | 
    
         
             
                  end
         
     | 
| 
       71 
65 
     | 
    
         
             
                  raise "Folder '#{folder_name}' not found" if !folder_serializer
         
     | 
| 
         @@ -73,13 +67,13 @@ module Imap::Backup 
     | 
|
| 
       73 
67 
     | 
    
         
             
                  uid_list = uids.split(",")
         
     | 
| 
       74 
68 
     | 
    
         
             
                  folder_serializer.each_message(uid_list).each do |uid, message|
         
     | 
| 
       75 
69 
     | 
    
         
             
                    if uid_list.count > 1
         
     | 
| 
       76 
     | 
    
         
            -
                      puts <<~HEADER
         
     | 
| 
       77 
     | 
    
         
            -
                        #{ 
     | 
| 
       78 
     | 
    
         
            -
                        #{format( 
     | 
| 
       79 
     | 
    
         
            -
                        #{ 
     | 
| 
      
 70 
     | 
    
         
            +
                      Kernel.puts <<~HEADER
         
     | 
| 
      
 71 
     | 
    
         
            +
                        #{'-' * 80}
         
     | 
| 
      
 72 
     | 
    
         
            +
                        #{format('| UID: %-71s |', uid)}
         
     | 
| 
      
 73 
     | 
    
         
            +
                        #{'-' * 80}
         
     | 
| 
       80 
74 
     | 
    
         
             
                      HEADER
         
     | 
| 
       81 
75 
     | 
    
         
             
                    end
         
     | 
| 
       82 
     | 
    
         
            -
                    puts message.supplied_body
         
     | 
| 
      
 76 
     | 
    
         
            +
                    Kernel.puts message.supplied_body
         
     | 
| 
       83 
77 
     | 
    
         
             
                  end
         
     | 
| 
       84 
78 
     | 
    
         
             
                end
         
     | 
| 
       85 
79 
     | 
    
         
             
              end
         
     |