Exemple #1
0
    def _adjust_paths(self, config):
        # Go through sys.mailboxes, sources.*.mailbox:
        #   - if the path is outside Workdir, does not exist, clear entry
        #   - if the path is inside Workdir, does not exist, create it
        #   - if the path is src:, source does not exist, clear entry
        def path_ok(mbx_path):
            if 'src:' in mbx_path.raw_fp[:5]:
                return True
            elif vfs.mailbox_type(mbx_path, config):
                return True
            elif unicode(mbx_path).startswith('/Mailpile$/'):
                config.create_local_mailstore(self.session,
                                              name=mbx_path.raw_fp)
                return True
            else:
                return False

        for i, mbx_path in config.sys.mailbox.iteritems():
            mbx_path = FilePath(mbx_path)
            if not path_ok(mbx_path):
                config.sys.mailbox[i] = '/dev/null'

        for i, p, src in config.get_mailboxes(with_mail_source=True,
                                              mail_source_locals=True):
            mbx_path = FilePath(p)
            if src.mailbox[i].local and not path_ok(mbx_path):
                src.mailbox[i].local = '!CREATE'
Exemple #2
0
    def _has_mailbox_changed(self, mbx, state):
        mbx_path = FilePath(self._path(mbx)).raw_fp

        # This is common to all local mailboxes, check the mtime/size
        try:
            mt = long(os.path.getmtime(mbx_path))
            sz = long(os.path.getsize(mbx_path))
        except (OSError, IOError):
            mt = sz = (int(time.time()) // 7200)  # Guarantee rescans
        mtsz = state['mtsz'] = '%s/%s' % (mt, sz)

        # Check more carefully if it's a Maildir, Mac Maildir or WERVD.
        if os.path.isdir(mbx_path):
            for sub in ('cur', 'new', 'tmp', 'Info.plist', 'wervd.ver'):
                if sub == 'Info.plist':
                    sub_path = self._get_macmaildir_data(mbx_path)
                    if not sub_path:
                        continue
                else:
                    sub_path = os.path.join(mbx_path, sub)
                try:
                    mt = long(os.path.getmtime(sub_path))
                    sz = long(os.path.getsize(sub_path))
                    sub_mtsz = '%s/%s' % (mt, sz)
                    mtsz += ',' + sub_mtsz
                    state['mtsz'] += ',' + sub_mtsz
                except (OSError, IOError):
                    pass

        return (mtsz != self.event.data.get('mailbox_state', {}).get(mbx._key))
Exemple #3
0
    def _data_paths(self, mbx):
        mbx_path = FilePath(self._path(mbx)).raw_fp
        if os.path.exists(mbx_path):
            yield mbx_path

        if os.path.isdir(mbx_path):
            # Maildir, WERVD
            for s in ('cur', 'new', 'tmp', 'wervd.ver'):
                sub_path = os.path.join(mbx_path, s)
                if os.path.exists(sub_path):
                    yield sub_path

            # Mac Maildir
            sub_path = self._get_macmaildir_data(mbx_path)
            if sub_path:
                yield sub_path
Exemple #4
0
def mailbox_search(config, idx, term, hits):
    word = term.split(':', 1)[1].lower()
    try:
        mbox_id = FormatMbxId(b36(int(word, 36)))
    except ValueError:
        mbox_id = None

    mailboxes = []
    for m in config.sys.mailbox.keys():
        fn = FilePath(config.sys.mailbox[m]).display().lower()
        if (mbox_id == m) or word in fn:
            mailboxes.append(m)

    rt = []
    for mbox_id in mailboxes:
        mbox_id = FormatMbxId(mbox_id)
        rt.extend(hits('%s:mailbox' % mbox_id))

    return rt
Exemple #5
0
 def display_name_(self, fp, config):
     return FilePath(fp).display_basename()
Exemple #6
0
 def Handles(self, path):
     path = FilePath(path)
     return (self.root == path
             or path.raw_fp.startswith(self.root.raw_fp))
Exemple #7
0
 def __init__(self, config, source, *args, **kwargs):
     MailpileVfsBase.__init__(self, *args, **kwargs)
     self.config = config
     self.source = source
     self.root = FilePath('/src:%s' % self.source.my_config._key)
Exemple #8
0
    class MailSourceVfs(MailpileVfsBase):
        """Generic VFS layer for this mail source."""
        def __init__(self, config, source, *args, **kwargs):
            MailpileVfsBase.__init__(self, *args, **kwargs)
            self.config = config
            self.source = source
            self.root = FilePath('/src:%s' % self.source.my_config._key)

        def _get_mbox_id(self, path):
            return path[len(self.root.raw_fp) + 1:]

        def Handles(self, path):
            path = FilePath(path)
            return (self.root == path
                    or path.raw_fp.startswith(self.root.raw_fp))

        def glob_(self, *args, **kwargs):
            return self.listdir_(*args, **kwargs)

        def listdir_(self, where, **kwargs):
            return [m for m in self.source.my_config.mailbox.keys()]

        def open_(self, fp, *args, **kwargs):
            raise IOError('Cannot open Mail Source entries (yet)')

        def abspath_(self, path):
            if not path.startswith(self.root.raw_fp):
                path = self.root.join(path).raw_fp
            if path == self.root:
                return path
            try:
                mbox_id = self._get_mbox_id(path)
                path = self.config.sys.mailbox[mbox_id]
                if path.startswith('src:'):
                    return '/%s' % path
                return path
            except (ValueError, KeyError, IndexError):
                raise OSError('Not found: %s' % path)

        def isdir_(self, fp):
            return (self.root == fp)

        def ismailsource_(self, fp):
            return (self.root == fp)

        def mailbox_type_(self, fp, config):
            return False if (fp == self.root) else 'source'  # Fixme

        def getsize_(self, path):
            return None

        def display_name_(self, path, config):
            if (self.root == path):
                return (self.source.my_config.name
                        or self.source.my_config._key)
            try:
                mbox_id = self._get_mbox_id(path)
                return self.source.my_config.mailbox[mbox_id].name
            except (ValueError, KeyError, IndexError):
                raise OSError('Not found: %s' % path)

        def exists_(self, fp):
            return ((self.root == fp) or
                    (fp[len(self.root) + 1:] in self.source.my_config.mailbox))
Exemple #9
0
 def is_mailbox(self, fn):
     fn = FilePath(fn).raw_fp
     return (self._is_maildir(fn) or self._is_macmaildir(fn)
             or self._is_mbox(fn))
Exemple #10
0
 def __init__(self, config, source, *args, **kwargs):
     MailpileVfsBase.__init__(self, *args, **kwargs)
     self.config = config
     self.source = source
     self.root = FilePath('/src:%s' % self.source.my_config._key)
Exemple #11
0
    class MailSourceVfs(MailpileVfsBase):
        """Generic VFS layer for this mail source."""
        def __init__(self, config, source, *args, **kwargs):
            MailpileVfsBase.__init__(self, *args, **kwargs)
            self.config = config
            self.source = source
            self.root = FilePath('/src:%s' % self.source.my_config._key)

        def _get_mbox_id(self, path):
            return path[len(self.root.raw_fp)+1:]

        def Handles(self, path):
            path = FilePath(path)
            return (self.root == path or
                    path.raw_fp.startswith(self.root.raw_fp))

        def glob_(self, *args, **kwargs):
            return self.listdir_(*args, **kwargs)

        def listdir_(self, where, **kwargs):
            return [m for m in self.source.my_config.mailbox.keys()]

        def open_(self, fp, *args, **kwargs):
            raise IOError('Cannot open Mail Source entries (yet)')

        def abspath_(self, path):
            if not path.startswith(self.root.raw_fp):
                path = self.root.join(path).raw_fp
            if path == self.root:
                return path
            try:
                mbox_id = self._get_mbox_id(path)
                return self.config.sys.mailbox[mbox_id]
            except (ValueError, KeyError, IndexError):
                raise OSError('Not found: %s' % path)

        def isdir_(self, fp):
            return (self.root == fp)

        def ismailsource_(self, fp):
            return (self.root == fp)

        def mailbox_type_(self, fp, config):
            return False if (fp == self.root) else 'source'  # Fixme

        def getsize_(self, path):
            return None

        def display_name_(self, path, config):
            if (self.root == path):
                return (self.source.my_config.name or
                        self.source.my_config._key)
            try:
                mbox_id = self._get_mbox_id(path)
                return self.source.my_config.mailbox[mbox_id].name
            except (ValueError, KeyError, IndexError):
                raise OSError('Not found: %s' % path)

        def exists_(self, fp):
            return ((self.root == fp) or
                    (fp[len(self.root)+1:] in self.source.my_config.mailbox))
Exemple #12
0
def migrate_mailboxes(session):
    config = session.config
    fpath = FilePath()

    # FIXME: Link new mail sources to a profile... any profile?

    def _common_path(paths):
        common_head, junk = fpath.split(paths[0])
        for path in paths:
            head, junk = fpath.split(path)
            while (common_head and common_head != '/' and head and head != '/'
                   and head != common_head):
                # First we try shortening the target path...
                while head and head != '/' and head != common_head:
                    head, junk = fpath.split(head)
                # If that failed, lop one off the common path and try again
                if head != common_head:
                    common_head, junk = fpath.split(common_head)
                    head, junk = fpath.split(path)
        return common_head

    mailboxes = []
    thunderbird = []

    spam_tids = [tag._key for tag in config.get_tags(type='spam')]
    trash_tids = [tag._key for tag in config.get_tags(type='trash')]
    inbox_tids = [tag._key for tag in config.get_tags(type='inbox')]

    # Iterate through config.sys.mailbox, sort mailboxes by type
    for mbx_id, path, src in config.get_mailboxes(with_mail_source=False):
        if (path.startswith('src:') or config.is_editable_mailbox(mbx_id)):
            continue
        elif 'thunderbird' in path.lower():
            thunderbird.append((mbx_id, path))
        else:
            mailboxes.append((mbx_id, path))

    if thunderbird:
        # Create basic mail source...
        if 'tbird' not in config.sources:
            config.sources['tbird'] = {
                'name': 'Thunderbird',
                'protocol': 'mbox',
            }
            config.sources.tbird.discovery.create_tag = True

        config.sources.tbird.discovery.policy = 'read'
        config.sources.tbird.discovery.process_new = True
        tbird_src = LocalMailSource(session, config.sources.tbird)

        # Configure discovery policy?
        root = _common_path([path for mbx_id, path in thunderbird])
        if 'thunderbird' in root.lower():
            # FIXME: This is wrong, we should create a mailbox entry
            #        with the policy 'watch'.
            tbird_src.my_config.discovery.path = root

        # Take over all the mailboxes
        for mbx_id, path in thunderbird:
            mbx = tbird_src.take_over_mailbox(mbx_id)
            if 'inbox' in path.lower():
                mbx.apply_tags.extend(inbox_tids)
            elif 'spam' in path.lower() or 'junk' in path.lower():
                mbx.apply_tags.extend(spam_tids)
            elif 'trash' in path.lower():
                mbx.apply_tags.extend(trash_tids)

        tbird_src.my_config.discovery.policy = 'unknown'

    for name, proto, description, cls in (('mboxes', 'local',
                                           'Local mailboxes',
                                           LocalMailSource), ):
        if mailboxes:
            # Create basic mail source...
            if name not in config.sources:
                config.sources[name] = {'name': description, 'protocol': proto}
                config.sources[name].discovery.create_tag = False
            config.sources[name].discovery.policy = 'read'
            config.sources[name].discovery.process_new = True
            config.sources[name].discovery.apply_tags = inbox_tids[:]
            src = cls(session, config.sources[name])
            for mbx_id, path in mailboxes:
                mbx = src.take_over_mailbox(mbx_id)
            config.sources[name].discovery.policy = 'unknown'

    return True