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'
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))
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
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
def display_name_(self, fp, config): return FilePath(fp).display_basename()
def Handles(self, path): path = FilePath(path) return (self.root == path or path.raw_fp.startswith(self.root.raw_fp))
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)
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))
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))
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))
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