Git Product home page Git Product logo

larch's Introduction

Larch

Note: I no longer actively develop or use Larch, so it is effectively unmaintained. Many people claim it still works well for them, so feel free to use it, but please don’t expect support, bug fixes, or new features.

Larch is a tool to copy messages from one IMAP server to another quickly and safely. It’s smart enough not to copy messages that already exist on the destination and robust enough to deal with interruptions caused by flaky connections or misbehaving servers.

Larch is particularly well-suited for copying email to, from, or between Gmail accounts.

Author

Ryan Grove ([email protected])

Version

1.1.2 (2013-01-24)

Copyright

Copyright © 2013 Ryan Grove. All rights reserved.

License

GPL 2.0 (opensource.org/licenses/gpl-2.0.php)

Website

github.com/rgrove/larch

Installation

Latest stable release:

gem install larch

Latest development version:

gem install larch --pre

Usage

larch [config section] [options]
larch --from <uri> --to <uri> [options]

Server Options:
         --from, -f <s>:   URI of the source IMAP server
  --from-folder, -F <s>:   Source folder to copy from (default: INBOX)
    --from-pass, -p <s>:   Source server password (default: prompt)
    --from-user, -u <s>:   Source server username (default: prompt)
           --to, -t <s>:   URI of the destination IMAP server
    --to-folder, -T <s>:   Destination folder to copy to (default: INBOX)
      --to-pass, -P <s>:   Destination server password (default: prompt)
      --to-user, -U <s>:   Destination server username (default: prompt)

Copy Options:
              --all, -a:   Copy all folders recursively
   --all-subscribed, -s:   Copy all subscribed folders recursively
           --delete, -d:   Delete messages from the source after copying
                           them, or if they already exist at the destination
         --exclude <s+>:   List of mailbox names/patterns that shouldn't be
                           copied
     --exclude-file <s>:   Filename containing mailbox names/patterns that
                           shouldn't be copied
          --expunge, -x:   Expunge deleted messages from the source
       --sync-flags, -S:   Sync message flags from the source to the
                           destination for messages that already exist at the
                           destination

General Options:
       --config, -c <s>:   Specify a non-default config file to use (default:
                           ~/.larch/config.yaml)
         --database <s>:   Specify a non-default message database to use
                           (default: ~/.larch/larch.db)
          --dry-run, -n:   Don't actually make any changes
      --max-retries <i>:   Maximum number of times to retry after a
                           recoverable error (default: 3)
     --no-create-folder:   Don't create destination folders that don't
                           already exist
        --ssl-certs <s>:   Path to a trusted certificate bundle to use to
                           verify server SSL certificates
           --ssl-verify:   Verify server SSL certificates
    --verbosity, -V <s>:   Output verbosity: debug, info, warn, error, or
                           fatal (default: info)
          --version, -v:   Print version and exit
             --help, -h:   Show this message

Usage Examples

Larch is run from the command line. The following examples demonstrate how to run Larch using only command line arguments, but you may also place these options in a config file and run Larch without any arguments if you prefer. See the “Configuration” section below for more details.

For an overview of all available options, run:

larch -h

At a minimum, you must specify a source server and a destination server in the form of IMAP URIs:

larch --from imap://mail.example.com --to imap://imap.gmail.com

Larch will prompt you for the necessary usernames and passwords, then sync the contents of the source’s INBOX folder to the destination’s INBOX folder.

To connect using SSL, specify a URI beginning with imaps://:

larch --from imaps://mail.example.com --to imaps://imap.gmail.com

If you’d like to sync a specific folder other than INBOX, specify the source and destination folders using --from-folder and --to-folder. Folder names containing spaces must be enclosed in quotes:

larch --from imaps://mail.example.com --to imaps://imap.gmail.com \
  --from-folder 'Sent Mail' --to-folder 'Sent Mail'

To sync all folders, use the --all option (or --all-subscribed if you only want to sync subscribed folders):

larch --from imaps://mail.example.com --to imaps://imap.gmail.com --all

By default Larch will create folders on the destination server if they don’t already exist. To prevent this, add the --no-create-folder option:

larch --from imaps://mail.example.com --to imaps://imap.gmail.com --all \
  --no-create-folder

You can prevent Larch from syncing one or more folders by using the --exclude option, which accepts multiple arguments:

larch --from imaps://mail.example.com --to imaps://imap.gmail.com --all \
  --exclude Spam Trash Drafts "[Gmail]/*"

If your exclusion list is long or complex, create a text file with one exclusion pattern per line and tell Larch to load it with the --exclude-file option:

larch --from imaps://mail.example.com --to imaps://imap.gmail.com --all \
  --exclude-file exclude.txt

The wildcard characters * and ? are supported in exclusion lists. You may also use a regular expression by enclosing a pattern in forward slashes, so the previous example could be achieved with the pattern /(Spam|Trash|Drafts|\[Gmail\]\/.*)/

Configuration

While it’s possible to control Larch entirely from the command line, this can be inconvenient if you need to specify a lot of options or if you run Larch frequently and can’t always remember which options to use. Using a configuration file can simplify things.

By default, Larch looks for a config file at ~/.larch/config.yaml and uses it if found. You may specify a custom config file using the --config command line option.

The Larch configuration file is a simple YAML file that may contain multiple sections, each with a different set of options, as well as a special default section. The options in the default section will be used unless they’re overridden either in another config section or on the command line.

Example

Here’s a sample Larch config file:

default:
  all-subscribed: true # Copy all subscribed folders by default

# Copy mail from Gmail to my server, excluding stuff I don't want.
gmail to my server:
  from: imaps://imap.gmail.com
  from-user: example
  from-pass: secret

  to: imaps://mail.example.com
  to-user: example
  to-pass: secret

  exclude:
    - "[Gmail]/Sent Mail"
    - "[Gmail]/Spam"
    - "[Gmail]/Trash"

# Copy mail from my INBOX to Gmail's INBOX
my inbox to gmail inbox:
  all-subscribed: false

  from: imaps://mail.example.com
  from-folder: INBOX
  from-user: example
  from-pass: secret

  to: imaps://imap.gmail.com
  to-folder: INBOX
  to-user: example
  to-pass: secret

This file contains three sections. The options from default will be used in all other sections as well unless they’re overridden.

To specify which config section you want Larch to use, just pass its name on the command line (use quotes if the name contains spaces):

larch 'gmail to my server'

If you specify additional command line options, they’ll override options in the config file:

larch 'gmail to my server' --from-user anotheruser

Running Larch with no command line arguments will cause the default section to be used. With the example above, this will result in an error since the default section doesn’t contain the required from and to options, but if you only need to use Larch with a single configuration, you could use the default section for everything and save yourself some typing on the command line.

Server Compatibility

Larch should work well with any server that properly supports IMAP4rev1, and does its best to get along with servers that have buggy, unreliable, or incomplete IMAP implementations.

Larch has been tested on and is known to work well with the following IMAP servers:

  • Dovecot

  • Gmail

  • Microsoft Exchange 2003

The following servers are known to work, but with caveats:

  • Yahoo! Mail

The following servers do not work well with Larch:

  • BlitzMail - Buggy server implementation; fails to properly quote or escape some IMAP responses, which can cause Net::IMAP to hang waiting for a terminating character that will never arrive.

Gmail Quirks

Gmail’s IMAP implementation is quirky. Larch does its best to work around these quirks whenever possible, but here are a few things to watch out for:

“Some messages could not be FETCHed” error

This error indicates that a message on Gmail is corrupt, and Gmail itself is unable to read it. The message will continue to show up in the mailbox, but all attempts to access it via IMAP, POP, or the Gmail web interface will result in errors. Larch will try to skip these messages and continue processing others if possible.

It’s not clear how this corruption occurs or exactly what kind of corruption causes these errors, although in every case I’m aware of, the corrupt message has originated outside of Gmail (Gmail itself does not corrupt the message). There is currently no known solution for this problem apart from deleting the corrupted messages.

Folder names cannot contain leading or trailing whitespace

Most IMAP servers allow folder names to contain leading and trailing whitespace, such as “ folder ”. Gmail does not. When copying folders to Gmail, Larch will automatically remove leading and trailing whitespace in folder names to prevent errors.

Yahoo! Mail Quirks

Yahoo! doesn’t officially support IMAP access for general usage, but Larch is able to connect to imap.mail.yahoo.com and imap-ssl.mail.yahoo.com by using a fairly well-known trick. That said, as with anything tricky, there are caveats.

No hierarchical folders

Similar to Gmail, Yahoo! Mail doesn’t allow hierarchical (nested) folders. If you try to copy a folder hierarchy to Yahoo!, it will work, but you’ll end up with a set of folders named “folder” and “folder.subfolder” rather than seeing “subfolder” as an actual subfolder of “folder”.

No custom flags

Yahoo! Mail IMAP doesn’t support custom message flags, such as the tags and junk/not junk flags used by Thunderbird. When transferring messages with custom flags to a Yahoo! Mail IMAP account, the custom flags will be lost.

Here there be dragons

Larch’s support for Yahoo! Mail is very new and very lightly tested. Given its newness and the fact that Yahoo!‘s IMAP gateway isn’t official, there are likely to be other quirks we’re not yet aware of. There’s also no guarantee that Yahoo! won’t shut down its IMAP gateway, deprecate the trick Larch uses to connect, or just outright block Larch. Use at your own risk.

Known Issues

  • Larch uses Ruby’s Net::IMAP standard library for all IMAP operations. While Net::IMAP is generally a very solid library, it contains a bug that can cause a deadlock to occur if a connection drops unexpectedly (either due to network issues or because the server closed the connection without warning) when the server has already begun sending a response and Net::IMAP is waiting to receive more data. If this happens, Net::IMAP will continue waiting forever without passing control back to Larch, and you will need to manually kill and restart Larch.

    Net::IMAP in Ruby 1.8 has also been known to hang when it can’t parse a server response, either because the response itself is malformed or because of a bug in Net::IMAP’s parser. This is rare, but it happens. Unfortunately there’s nothing Larch can do about this.

  • The Ruby package on Debian, Ubuntu, and some other Debian-based Linux distributions doesn’t include the OpenSSL standard library. If you see an error like uninitialized constant Larch::IMAP::OpenSSL (NameError) when running Larch, you may need to install the libopenssl-ruby package. Please feel free to complain to the maintainer of your distribution’s Ruby packages.

Support

The Larch mailing list is the best place for questions, comments, and discussion about Larch. You can join the list or view the archives at groups.google.com/group/larch

First-time senders to the list are moderated to prevent spam, so there may be a delay before your first message shows up.

Contributors

Larch was created and is maintained by Ryan Grove <[email protected]>.

The following lovely people have also contributed to Larch:

Credit

The Larch::IMAP class borrows heavily from Sup by William Morgan, the source code of which should be required reading if you’re doing anything with IMAP in Ruby.

Larch uses the excellent Trollop command-line option parser (also by William Morgan) and the HighLine command-line IO library (by James Edward Gray II).

License

Copyright © 2013 Ryan Grove <[email protected]>

Licensed under the GNU General Public License version 2.0.

This program is free software; you can redistribute it and/or modify it under the terms of version 2.0 of the GNU General Public License as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, visit www.gnu.org/licenses/old-licenses/gpl-2.0.txt or write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

larch's People

Contributors

ehames avatar rgrove avatar toreyheinz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

larch's Issues

Gmail doesn't allow folder names longer than 40 characters (including delimiters)

Reported on the Larch mailing list at http://groups.google.com/group/larch/browse_thread/thread/2f8e8dbc2fab0af5

/var/lib/gems/1.8/bin/larch --from imap://server1 --from-user user1@domain1 --from-pass password1 --to imaps://imap.gmail.com --to-user [email protected] --to-pass password2 --all

[Sep 01 17:30:01] [info] [email protected]@imap.gmail.com: creating mailbox: INBOX/blabla/blablabla/blabla blabla 2008
[Sep 01 17:30:02] [info] [email protected]@imap.gmail.com: Net::IMAP::NoResponseError: Folder name is not allowed. (Failure) (will retry)
[Sep 01 17:30:03] [info] [email protected]@imap.gmail.com: Net::IMAP::NoResponseError: Folder name is not allowed. (Failure) (will retry)
[Sep 01 17:30:05] [info] [email protected]@imap.gmail.com: Net::IMAP::NoResponseError: Folder name is not allowed. (Failure) (will retry)
[Sep 01 17:30:09] [fatal] Net::IMAP::NoResponseError: Folder name is not allowed. (Failure) (giving up)
[Sep 01 17:30:09] [info] 0 message(s) copied, 0 failed, 1 untouched out of 1 total

problem creating folder names that contains space

I have attached the output from a run. The first time it complained about 'Sent Messages' so I tried excluding it, but it keeps complaining. I tried renaming the folder on the source server (removed the space) and it works. But I have hundreds of folders containing space in the name. Am I missing something, or could it maybe be the server that cannot handle spaces?

$ bin/larch --from imap://mail.xxxxxxxx.no --to imap://xxxxxx.inmotionhosting.com -u [email protected] -p secret -P secret -U [email protected] -a -V insane --exclude 'Sent Messages'
[21:44:21] [debug] [<] updating mailboxes
[21:44:21] [debug] [<] connecting...
S: * OK IMAP4rev1 server ready at 06/12/11 21:44:24
[21:44:21] [info] [<] connected to mail.xxxxxxxx.no on port 143
C: RUBY0001 CAPABILITY
S: * CAPABILITY IMAP4rev1 IMAP4 AUTH=LOGIN AUTH=CRAM-MD5 IDLE CHILDREN AUTH=NTLM
S: RUBY0001 OK CAPABILITY completed
.....
S: RUBY0002 OK AUTHENTICATE CRAM-MD5.
[21:44:22] [debug] [<] authenticated using CRAM-MD5
C: RUBY0003 LIST "" ""
S: * LIST (\HasChildren) "/" "DIVERSE MAPPER"
S: * LIST (\HasNoChildren) "/" "DIVERSE MAPPER/ANNE BRITH"
........
S: RUBY0003 OK LIST completed
C: RUBY0004 LSUB "" "
"
S: * LSUB () "/" "Junk E-mail"
S: * LSUB () "/" "Deleted items"
S: * LSUB () "/" "DIVERSE MAPPER"
........
S: RUBY0004 OK LSUB completed
[21:44:23] [debug] [>] connecting...
S: * OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE ACL ACL2=UNION STARTTLS] Courier-IMAP ready. Copyright 1998-2010 Double Precision, Inc. See COPYING for distribution information.
[21:44:23] [info] [>] connected to xxxxxx.inmotionhosting.com on port 143
C: RUBY0001 CAPABILITY
S: * CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE ACL ACL2=UNION STARTTLS
S: RUBY0001 OK CAPABILITY completed
....
S: RUBY0002 OK LOGIN Ok.
C: RUBY0003 LIST "" ""
S: * LIST (\Noselect) "." ""
S: RUBY0003 OK LIST completed
[21:44:24] [debug] [>] updating mailboxes
C: RUBY0004 LIST "" ""
S: * LIST (\Unmarked \HasChildren) "." "INBOX"
S: * LIST (\HasNoChildren) "." "INBOX.Deleted Messages"
S: * LIST (\HasNoChildren) "." "INBOX.Notes"
S: * LIST (\HasNoChildren) "." "INBOX.Sent"
S: * LIST (\HasNoChildren) "." "INBOX.Trash"
S: * LIST (\HasNoChildren) "." "INBOX.Drafts"
S: * LIST (\HasNoChildren) "." "INBOX.Junk"
S: RUBY0004 OK LIST completed
C: RUBY0005 LSUB "" "
"
S: * LSUB (\HasNoChildren) "." "INBOX.Notes"
S: * LSUB (\HasNoChildren) "." "INBOX.Deleted Messages"
S: * LSUB (\Noselect \HasChildren) "." "INBOX"
S: RUBY0005 OK LSUB completed
[21:44:25] [info] [>] creating mailbox: DIVERSE MAPPER.ANNE BRITH
C: RUBY0006 CREATE "DIVERSE MAPPER.ANNE BRITH"
S: RUBY0006 NO Invalid mailbox name.
[21:44:25] [warning] [>] Net::IMAP::NoResponseError: Invalid mailbox name. (will retry)
C: RUBY0007 CREATE "DIVERSE MAPPER.ANNE BRITH"
S: RUBY0007 NO Invalid mailbox name.
[21:44:26] [warning] [>] Net::IMAP::NoResponseError: Invalid mailbox name. (will retry)
C: RUBY0008 CREATE "DIVERSE MAPPER.ANNE BRITH"
S: RUBY0008 NO Invalid mailbox name.
[21:44:29] [warning] [>] Net::IMAP::NoResponseError: Invalid mailbox name. (will retry)
C: RUBY0009 CREATE "DIVERSE MAPPER.ANNE BRITH"
S: RUBY0009 NO Invalid mailbox name.
[21:44:32] [fatal] Net::IMAP::NoResponseError: Invalid mailbox name. (giving up)
[21:44:32] [info] 0 message(s) copied, 0 failed, 0 deleted out of 0 total
[21:44:32] [debug] performing database maintenance

Gmail error: 'Unable to append message to folder'

when i try to copy emails with blank subject lines to Gmail, i get an error: "Unable to append message to folder."

Any idea how to resolve this?

[Dec 07 03:06:18] [info] copying message: [email protected] - Re: 
[Dec 07 03:06:19] [info] [email protected]@imap.gmail.com: Net::IMAP::NoResponseError: Unable to append message to folder (Failure) (will retry)
[Dec 07 03:06:21] [info] [email protected]@imap.gmail.com: Net::IMAP::NoResponseError: Unable to append message to folder (Failure) (will retry)
[Dec 07 03:06:24] [info] [email protected]@imap.gmail.com: Net::IMAP::NoResponseError: Unable to append message to folder (Failure) (will retry)
[Dec 07 03:06:27] [error] Net::IMAP::NoResponseError: Unable to append message to folder (Failure) (giving up)

Display estimated sync time and message count

Feature request from @akumar via Twitter: "estimate of how long the sync is likely to take (or at least the # of objects synced/not synced)."

This would require pre-scanning all mailboxes being synced in order to gather the necessary info so it would add some time to the sync, but should be doable. Cached mailbox state info can potentially reduce the pre-scanning time.

Add search criterion

Add search criterion to be able to "filter" copies.

Specifically, I'd like to see date criterion, but you could add a bunch of others too. I wanted to move all messages older than X months old to my "archive" GMail account, which has a mirrored directory structure as my primary account.

Possible problem creating nested folders on Gmail

Excerpt from a user email to the Larch mailing list:

"I found that I couldn't transfer the entire tree in go (--all), as
larch choked on one particular folder:

From-server IMAP extract (insane logging):

S: * CAPABILITY IMAP4rev1 UIDPLUS IDLE LOGIN-REFERRALS NAMESPACE QUOTA
CHILDREN AUTH=DIGEST-MD5
S: * LIST (\HasChildren) "/" work/foo
S: * LIST (\HasNoChildren) "/" work/foo/bar
S: * LSUB (\HasChildren) "/" work/foo
S: * LSUB (\HasNoChildren) "/" work/foo/bar

Gmail IMAP extract:

S: * LIST (\HasNoChildren) "/" "work/foo"
S: * LSUB (\HasNoChildren) "/" "work/foo"

Gave this:

[Jun 15 19:40:37] [fatal] mailbox not found: work/foo/bar

I worked around the problem by pulling one folder at a time, which
worked fine, including for the folder which it had originaly choked
on."

Add --exclude option

Need to add an --exclude option to specify folder names (or regexes?) to exclude when using --all or --all-subscribed.

Should also add an --exclude-file option to allow exclusions to be specified in a text file.

--to-folder does not put messages in subfolders!

Hi,

I was expecting that the subfolders of the "from" side would be put as subfolder of "to-folder" on the "to" side.

Is it intentional or a bug? I don't see why the hierarchy would not be kept…

Thanks

Problem migrating label with unicode caracter in the name

Migrating from a dovecot imap server to google mails gives me this
'unicode related' error:

[17:01:33] [info] 192.168.1.13/KLANTEN/Andrea Acuña -> imap.gmail.com/
KLANTEN/Andrea Acuña
[17:01:33] [fatal] Attempt to update object did not result in a single
row modification (SQL: UPDATE mailboxes SET uidvalidity =
1303737107 WHERE (id = 139))

Gmail Sent Items folder

I just completed moving email from an IMAP account into Gmail. Unfortunately, I now have a folder in my Gmail account called INBOX/Sent Items while my Gmail's Sent Items is empty.

What is the proper syntax to move email into Gmail's Sent Mail?

I tried:
--from-folder 'INBOX.Sent Items' --to-folder 'Sent Mail'

but that created a new folder on Gmail called [Imap]/Sent Mail.

Problems with Gmail folder names containing accented characters

Reported on the Larch mailing list at http://groups.google.com/group/larch/browse_thread/thread/294af0368c309bd

I 'am trying to synchronize my personnal IMAP (Dovecot) with my gmail account. The gmail locals are set to french, so Sent Mail folder is written in french with an accent. The problem is i connot use --to-folder option with an accent

Log messages:
creating mailbox: [Gmail]/Messages envoyés (this is the french name of Sent Mail folder)
Net::IMAP::BadResponseError: Invalid Command (will retry)

Looks like it tries to create a folder which should already exist on gmail...

Any clue?
I've set my gmail account to english and used the "Sent Mail" name instead, but i really would like to find a better solution.

Larch doesn't recopy deleted messages to the destination until a second attempt

  1. Use Larch to copy a bunch of messages from server A to server B.
  2. Delete those messages on server B.
  3. Run Larch again. It will see that the messages have been deleted, but will not recopy them.
  4. Run Larch again. This time it will recopy the deleted messages.

Larch should recopy the deleted messages the first time it sees that they're gone.

Delete from destination if not on source?

Hi,

I see the feature to delete from source after copying (#22) - but is there the opposite, to delete mails on the target that weren't present on the source?

My purpose is to keep an exact sync of a gmail account on another IMAP server. If I sync and then on gmail, move some items into a folder (label + archive), on the next sync I'll have a copy in both the folder and in the inbox, on the target, which is not ideal for my purposes.

larch does not copy folders with only one message

when scanning folders with only one message in imap/mailbox.rb
variable full_range is 1...2

Since

full_range.max - full_range.min 

is zero

need_full_scan = full_range && full_range.max && full_range.min && full_range.max - full_range.min > 0

is false and nothing is done on the folder.

I suggest to change the definition of need_full_scan as

need_full_scan = full_range && full_range.max && full_range.min && full_range.max - full_range.min >= 0

Duplicated folder. Gmail isn't case sensitive.

This issue happens whenever you have a folder with the same name but different casing between source and destination (ie. "folder" - "Folder"). IMAP protocol is case sensitive, but gmail isn't and throws a fatal error that stops the migration.

I coded a simple patch that adds a new quirk, that checks a regexp for the name.

def mailbox(name, delim = '/')
    retries = 0

    name.gsub!(/^(inbox\/?)/i){ $1.upcase }
    name.gsub!(delim, self.delim)

    name.gsub!(/\s+/, ' ') if @quirks[:gmail]

    # Gmail doesn't allow folders with leading or trailing whitespace.                                                                                       \

    name.strip! if @quirks[:gmail]

    begin
      if @quirks[:gmail]
        # In Gmail folders are not case sensitive                                                                                                             
        update_mailboxes
        @mailboxes.keys.each do |key|
          if key =~ /^#{Regexp.quote(name)}$/i
            return @mailboxes[key]
          end
        end
        raise MailboxNotFoundError, "mailbox not found: #{name}"
      end

      @mailboxes.fetch(name) do
        update_mailboxes
[....]

release windows executable of larch

Hi,
this tool is great!
I used it to migrate a large imap account from googlemail to another provider.
However, I think that there are many users who would like to use the tool without needing to install ruby / gems etc. on their windows machines.
I suggest to release a .exe file created with something like http://www.erikveen.dds.nl/rubyscript2exe/
Regards,
J83

Bug in imap_uid_fetch with infinite range

Just a missing return

def imap_uid_fetch(set, fields, block_size = FETCH_BLOCK_SIZE, &block) # :yields: fetch_data
    if set.is_a?(Numeric) || (set.is_a?(Range) && set.last < 0)
      data = @imap.safely do
        imap_examine
        @imap.conn.uid_fetch(set, fields)
      end

      yield data unless data.nil?

      # Return was missing, so it continued processing afterwards   
      return
    end

Add support for proxies

Enable connecting behind proxy.
Possibly attaching to the web interface of gmail (rather than imap)

Net::IMAP thread deadlock bug

Any clues how to workaorund this ?

[19:36:41] [info] [<] INBOX/supply-infreq/di.se: fetching latest message flags...
[19:36:41] [info] [>] INBOX/supply-infreq/di.se: fetching latest message flags.../usr/lib/ruby/1.9.1/thread.rb:68:in sleep': deadlock detected (fatal) from /usr/lib/ruby/1.9.1/thread.rb:68:inwait'
from /usr/lib/ruby/1.9.1/monitor.rb:97:in wait' from /usr/lib/ruby/1.9.1/net/imap.rb:1170:insend_literal'
from /usr/lib/ruby/1.9.1/net/imap.rb:1373:in send_data' from /usr/lib/ruby/1.9.1/net/imap.rb:1145:insend_data'
from /usr/lib/ruby/1.9.1/net/imap.rb:1072:in block (2 levels) in send_command' from /usr/lib/ruby/1.9.1/net/imap.rb:1070:ineach'
from /usr/lib/ruby/1.9.1/net/imap.rb:1070:in block in send_command' from /usr/lib/ruby/1.9.1/monitor.rb:190:inmon_synchronize'
from /usr/lib/ruby/1.9.1/net/imap.rb:1064:in send_command' from /usr/lib/ruby/1.9.1/net/imap.rb:635:inappend'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap/mailbox.rb:78:in block in append' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap.rb:188:insafely'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap/mailbox.rb:72:in append' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch.rb:230:inblock in copy_messages'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap/mailbox.rb:104:in block in each_db_message' from /var/lib/gems/1.9.1/gems/sequel-3.9.0/lib/sequel/dataset/actions.rb:15:ineach'
from /var/lib/gems/1.9.1/gems/sequel-3.9.0/lib/sequel/dataset/actions.rb:15:in all' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap/mailbox.rb:104:ineach_db_message'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch.rb:188:in copy_messages' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch.rb:72:inblock in copy_all'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap.rb:126:in block in each_mailbox' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap.rb:126:ineach_value'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap.rb:126:in each_mailbox' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch.rb:60:incopy_all'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/bin/larch:118:in <module:Larch>' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/bin/larch:9:in<top (required)>'
from /var/lib/gems/1.9.1/bin/larch:19:in load' from /var/lib/gems/1.9.1/bin/larch:19:in

'

[19:36:41] [info] imap.1and1.co.uk/INBOX/supply-infreq/direktronik -> imap.gmail.com/INBOX/supply-infreq/direktronik

...

[19:36:41] [info] [<] INBOX/supply-infreq/di.se: fetching latest message flags...
[19:36:41] [info] [>] INBOX/supply-infreq/di.se: fetching latest message flags.../usr/lib/ruby/1.9.1/thread.rb:68:in sleep': deadlock detected (fatal) from /usr/lib/ruby/1.9.1/thread.rb:68:inwait'
from /usr/lib/ruby/1.9.1/monitor.rb:97:in wait' from /usr/lib/ruby/1.9.1/net/imap.rb:1170:insend_literal'
from /usr/lib/ruby/1.9.1/net/imap.rb:1373:in send_data' from /usr/lib/ruby/1.9.1/net/imap.rb:1145:insend_data'
from /usr/lib/ruby/1.9.1/net/imap.rb:1072:in block (2 levels) in send_command' from /usr/lib/ruby/1.9.1/net/imap.rb:1070:ineach'
from /usr/lib/ruby/1.9.1/net/imap.rb:1070:in block in send_command' from /usr/lib/ruby/1.9.1/monitor.rb:190:inmon_synchronize'
from /usr/lib/ruby/1.9.1/net/imap.rb:1064:in send_command' from /usr/lib/ruby/1.9.1/net/imap.rb:635:inappend'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap/mailbox.rb:78:in block in append' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap.rb:188:insafely'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap/mailbox.rb:72:in append' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch.rb:230:inblock in copy_messages'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap/mailbox.rb:104:in block in each_db_message' from /var/lib/gems/1.9.1/gems/sequel-3.9.0/lib/sequel/dataset/actions.rb:15:ineach'
from /var/lib/gems/1.9.1/gems/sequel-3.9.0/lib/sequel/dataset/actions.rb:15:in all' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap/mailbox.rb:104:ineach_db_message'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch.rb:188:in copy_messages' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch.rb:72:inblock in copy_all'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap.rb:126:in block in each_mailbox' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap.rb:126:ineach_value'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch/imap.rb:126:in each_mailbox' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch.rb:60:incopy_all'
from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/bin/larch:118:in <module:Larch>' from /var/lib/gems/1.9.1/gems/larch-1.1.0.dev.20100209/bin/larch:9:in<top (required)>'
from /var/lib/gems/1.9.1/bin/larch:19:in load' from /var/lib/gems/1.9.1/bin/larch:19:in

'

[19:36:41] [info] imap.1and1.co.uk/INBOX/supply-infreq/direktronik -> imap.gmail.com/INBOX/supply-infreq/direktronik

Larch incorrectly tries to set \Recent flag on messages

When copying messages that have the \Recent flag set on the source server, Larch tries to set the flag on the destination server as well. However, the IMAP spec prohibits clients from setting this flag. It seems many IMAP servers ignore this, but some (including Zimbra) return an error.

Configurable folder mappings and delete-if-older-than option

First: GREAT WORK!

  1. I would like to copy email from the "exchange/Inbox" to the "gmail/Inbox" only if the email is not in "gmail/All Mail". Therefor the inventory comparison should be between "exchange/Inbox" and "gmail/All Mail", but the copy should be from "exchange/Inbox" to "gmail/Inbox". This would allow to archive emails in gmail without having them put back into the inbox with the next sync.

  2. Delete-if-older-than option would be nice.

Duplicated folder. Gmail isn't case sensitive.

This issue happens whenever you have a folder with the same name but different casing between source and destination (ie. "folder" - "Folder"). IMAP protocol is case sensitive, but gmail isn't and throws a fatal error that stops the migration.

I coded a simple patch that adds a new quirk, that checks a regexp for the name.

def mailbox(name, delim = '/')
    retries = 0

    name.gsub!(/^(inbox\/?)/i){ $1.upcase }
    name.gsub!(delim, self.delim)

    name.gsub!(/\s+/, ' ') if @quirks[:gmail]

    # Gmail doesn't allow folders with leading or trailing whitespace.                                                                                       \

    name.strip! if @quirks[:gmail]

    begin
      if @quirks[:gmail]
        # In Gmail folders are not case sensitive                                                                                                             
        update_mailboxes
        @mailboxes.keys.each do |key|
          if key =~ /^#{Regexp.quote(name)}$/i
            return @mailboxes[key]
          end
        end
        raise MailboxNotFoundError, "mailbox not found: #{name}"
      end

      @mailboxes.fetch(name) do
        update_mailboxes
[....]

More than one --from-folder in config.yaml

Hi Ryan,

first of all thanks for that nice program. It's really a blast and helps me migrating from my IMAP mailbox hosted on our own server to Google.

Actually, I have a lot of old emails in old folders and a lot of subfolders. I recognized, that some folders have not been transferred to labels in gmail and the emails are not there - even though larch said so in it's output. So I decided to migrate each folder.

Well, it would be really cool, if I could define more than one sourcefolder in the config.yaml file. E.g:

gmail_migration:
verbosity: debug

  from: imap://mail.milkno.com
  from-folder: INBOX.Projekte.ruby
  from-folder: INBOX.Projekte.perl
  from-folder: INBOX.Projekte.php
  from-folder: INBOX.Projekte.java
  from-folder: INBOX.Projekte.lisp
  from-folder: INBOX.Projekte.sql 
  from-user: 'mail05'
  from-pass: 'blabla'

  to: imaps://imap.googlemail.com
  to-folder: Projekte
  to-user: '[email protected]'
  to-pass: 'fallera'

That would be helpful. Or did I miss something in the docu?

CHeers

Andy

larch is incompatible with sequel > 3.11.0

I updated my gems today and got the latest version of sequel (3.12.1 released in June 9, 2010). Now when running larch I get the following message:

/opt/local/lib/ruby/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch.rb:134:in open_db': undefined methodget_current_migration_version' for Sequel::Migrator:Class (NoMethodError)
from /opt/local/lib/ruby/gems/1.9.1/gems/larch-1.1.0.dev.20100209/lib/larch.rb:36:in init' from /opt/local/lib/ruby/gems/1.9.1/gems/larch-1.1.0.dev.20100209/bin/larch:89:inmodule:Larch'
from /opt/local/lib/ruby/gems/1.9.1/gems/larch-1.1.0.dev.20100209/bin/larch:9:in <top (required)>' from /opt/local/bin/larch:19:inload'
from /opt/local/bin/larch:19:in `

'

It also happens with 3.12.0, released June 1, 2010. It works fine however with previous versions.

SQLite chokes on certain characters

Reported on the mailing list at http://groups.google.com/group/larch/browse_thread/thread/1dd363a5be6f4ad0?hl=en:

I'm using larch to perform a large migration of a client's Google Apps
account with about 100k emails and a couple hundred labels. Everything went
well until larch started with the following Gmail label (font size increased
to notice the apostrophe): "Teddy’s Bike"

Note the apostrophe, it's not your regular ' apostrophe, it's a different
one:

I believe the problem lies in the weird apostrophe, because I had no trouble
with other labels which had the regular apostrophe. I logged larch's output
with the insane option:

S: RUBY0150 OK Success^M 
[17:19:28] [info] imap.gmail.com/Teddy<E2><80><99>s Bike -> imap.gmail.com/Denny<E2><80><99>s Hawthorne 
[17:19:28] [debug] [<] Teddy<E2><80><99>s Bike: getting mailbox status 
C: RUBY0163 STATUS "Teddy&IBk-s Bike" (MESSAGES UIDNEXT UIDVALIDITY)^M 
S: * STATUS "Teddy&IBk-s Bike" (MESSAGES 167 UIDNEXT 170 UIDVALIDITY 607519705)^M 
S: RUBY0163 OK Success^M 
[17:19:28] [fatal] Attempt to update object did not result in a single row modification (SQL: UPDATE `mailboxes` SET `uidvalidity` = 607519705 WHERE (`id` = 62)) 
[17:19:28] [info] 0 message(s) copied, 0 failed, 0 deleted out of 7507 total 
[17:19:28] [debug] performing database maintenance

Certain domain names cause invalid URI error

A user reported on the Larch mailing list that the IMAP URI imaps://mail.example.no results in an invalid URI error, whereas imaps://mail.example.com works fine. Ruby's URI lib appears to be trying (and failing) to validate actual domain names.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.