def __init__(self, router, endpoint):
        self.router = router
        self.endpoint = endpoint

        self.keys = router.keys
        self.maildir = 'spool/' + encode(endpoint.public.bytes)
        self.addressBook = YamlMap('config/dustmail-addressbook.yaml')
        self.done = Event()
        self.commandDone = Event()

        self.book = YamlMap('config/dustmail-addressbook.yaml')

        dustmailConfig = YamlMap('config/dustmail-config.yaml')

        try:
            destAddress = dustmailConfig['tracker']
        except:
            entry = self.addInvite()
            destAddress = entry['tracker']
            dustmailConfig['tracker'] = destAddress

        dest, outport, v6 = decodeAddress(destAddress)

        host = getPublicIP(v6)
        inport = dustmailConfig['port']

        invite = self.keys.generateInvite(inport, v6=v6)
Пример #2
0
class TrackbackHandler:
    def __init__(self, router):
        self.state = YamlMap('config/trackback.yaml')

    def putPeerForEndpoint(self, key, value):
        try:
            map = self.state['endpoints']
            map[key] = value
            self.state.save()
        except:
            pass
Пример #3
0
class TrackbackHandler:
  def __init__(self, router):
    self.state=YamlMap('config/trackback.yaml')

  def putPeerForEndpoint(self, key, value):
    try:
      map=self.state['endpoints']
      map[key]=value
      self.state.save()
    except:
      pass
Пример #4
0
class TrackerHandler:
    def __init__(self, router, addr):
        print('new TrackerHandler ' + str(addr))
        self.router = router
        self.addr = addr
        self.state = YamlMap('config/tracker.yaml')

    def getPeerForEndpoint(self, key):
        print('getPeerForEndpoint(' + str(key) + ')')
        try:
            map = self.state['endpoints']
            value = map[key]
            trackback = TrackbackClient(self.router, self.addr)
            trackback.putPeerForEndpoint(key, value)
        except Exception as e:
            print('exception: ' + str(e))
            pass

    def putPeerForEndpoint(self, key, value):
        print('putPeerForEndpoint(' + str(key) + ',' + str(value) + ')')
        try:
            map = self.state['endpoints']
            map[key] = value
            self.state.save()
        except Exception as e:
            map = {key: value}
            self.state['endpoints'] = map

    def getInviteForPeer(self, key):
        print('getInviteForPeer(' + str(key) + ')')
        try:
            map = self.state['invites']
            value = map[key]
            trackback = TrackbackClient(self.router, self.addr)
            trackback.putInviteForPeer(key, value)
        except Exception as e:
            print('exception: ' + str(e))
            pass

    def putInviteForPeer(self, key, value):
        print('putInviteForPeer(' + str(key) + ',' + str(value) + ')')
        try:
            map = self.state['invites']
            map[key] = value
            self.state.save()
        except Exception as e:
            map = {key: value}
            self.state['invites'] = map

    def getTrackerInvite(self):
        invite = self.router.generateInvite()
        trackback = TrackbackClient(self.router, self.addr)
        trackback.putTrackerInvite(encode(invite.message))
Пример #5
0
class TrackerHandler:
  def __init__(self, router, addr):
    print('new TrackerHandler '+str(addr))
    self.router=router
    self.addr=addr
    self.state=YamlMap('config/tracker.yaml')

  def getPeerForEndpoint(self, key):
    print('getPeerForEndpoint('+str(key)+')')
    try:
      map=self.state['endpoints']
      value=map[key]
      trackback=TrackbackClient(self.router, self.addr)
      trackback.putPeerForEndpoint(key, value)
    except Exception as e:
      print('exception: '+str(e))
      pass

  def putPeerForEndpoint(self, key, value):
    print('putPeerForEndpoint('+str(key)+','+str(value)+')')
    try:
      map=self.state['endpoints']
      map[key]=value
      self.state.save()
    except Exception as e:
      map={key: value}
      self.state['endpoints']=map

  def getInviteForPeer(self, key):
    print('getInviteForPeer('+str(key)+')')
    try:
      map=self.state['invites']
      value=map[key]
      trackback=TrackbackClient(self.router, self.addr)
      trackback.putInviteForPeer(key, value)
    except Exception as e:
      print('exception: '+str(e))
      pass

  def putInviteForPeer(self, key, value):
    print('putInviteForPeer('+str(key)+','+str(value)+')')
    try:
      map=self.state['invites']
      map[key]=value
      self.state.save()
    except Exception as e:
      map={key: value}
      self.state['invites']=map

  def getTrackerInvite(self):
    invite=self.router.generateInvite()
    trackback=TrackbackClient(self.router, self.addr)
    trackback.putTrackerInvite(encode(invite.message))
Пример #6
0
  def __init__(self, router, endpoint):
    self.router=router
    self.endpoint=endpoint

    self.keys=router.keys
    self.maildir='spool/'+encode(endpoint.public.bytes)
    self.addressBook=YamlMap('config/dustmail-addressbook.yaml')
    self.done=Event()
    self.commandDone=Event()

    self.book=YamlMap('config/dustmail-addressbook.yaml')

    dustmailConfig=YamlMap('config/dustmail-config.yaml')

    try:
      destAddress=dustmailConfig['tracker']
    except:
      entry=self.addInvite()
      destAddress=entry['tracker']
      dustmailConfig['tracker']=destAddress

    dest, outport, v6=decodeAddress(destAddress)

    print('Registering with tracker...')
    self.tracker=TrackerClient(self.router, addr=(dest, outport))

    host=getPublicIP(v6)
    inport=dustmailConfig['port']
    self.tracker.putPeerForEndpoint(encode(self.endpoint.public.bytes), [encode(self.endpoint.public.bytes), encodeAddress((host,inport))])

    invite=self.keys.generateInvite(inport, v6=v6)
    self.tracker.putInviteForPeer(encodeAddress((host, inport)), encode(invite.message))

    self.trackback=self.router.getService('trackback')
Пример #7
0
class TrackbackHandler:
    def __init__(self, keys):
        self.keys = keys
        self.state = YamlMap("config/trackback.yaml")
        self.callbacks = {}

    def setPutPeerForEndpointCallback(self, key, callback):
        self.callbacks[key] = callback

    def putPeerForEndpoint(self, key, value):
        print("putPeerForEndpoint!!! " + str(key) + " " + str(value))
        try:
            map = self.state["endpoints"]
            map[key] = value
            self.state.save()
        except:
            map = {key: value}
            self.state["endpoints"] = map
        print("callbacks: " + str(self.callbacks))
        callback = self.callbacks[key]
        callback(key, value)

    def setPutInviteForPeer(self, key, callback):
        self.callbacks[key] = callback

    def putInviteForPeer(self, addr, invite):
        print("putInviteForPeer!!! " + str(addr) + " " + str(invite))
        i = InviteMessage()
        i.decodeInviteMessage(decode(invite))
        self.keys.outgoingInvites.addInvite(i)
        if self.keys.outgoingFilename:
            self.keys.saveOutgoingInvites(self.keys.outgoingFilename, self.keys.invitePassword)

        callback = self.callbacks[addr]
        callback(addr, i)

    def setPutTrackerInvite(self, callback):
        self.callbacks["tracker"] = callback

    def putTrackerInvite(self, invite):
        print("putTrackerInvite: " + str(invite))

        callback = self.callbacks["tracker"]
        print("callback: " + str(callback))
        callback(decode(invite))
class TrackbackHandler:
  def __init__(self, keys):
    self.keys=keys
    self.state=YamlMap('config/trackback.yaml')
    self.callbacks={}

  def setPutPeerForEndpointCallback(self, key, callback):
    self.callbacks[key]=callback

  def putPeerForEndpoint(self, key, value):
    print('putPeerForEndpoint!!! '+str(key)+' '+str(value))
    try:
      map=self.state['endpoints']
      map[key]=value
      self.state.save()
    except:
      map={key: value}
      self.state['endpoints']=map
    print('callbacks: '+str(self.callbacks))
    callback=self.callbacks[key]
    callback(key, value)

  def setPutInviteForPeer(self, key, callback):
    self.callbacks[key]=callback

  def putInviteForPeer(self, addr, invite):
    print('putInviteForPeer!!! '+str(addr)+' '+str(invite))
    i=InviteMessage()
    i.decodeInviteMessage(decode(invite))
    self.keys.outgoingInvites.addInvite(i)
    if self.keys.outgoingFilename:
      self.keys.saveOutgoingInvites(self.keys.outgoingFilename, self.keys.invitePassword)

    callback=self.callbacks[addr]
    callback(addr, i)

  def setPutTrackerInvite(self, callback):
    self.callbacks['tracker']=callback

  def putTrackerInvite(self, invite):
    print('putTrackerInvite: '+str(invite))

    callback=self.callbacks['tracker']
    print('callback: '+str(callback))
    callback(decode(invite))
    def __init__(self, router, endpoint):
        self.router = router
        self.endpoint = endpoint

        self.keys = router.keys
        self.maildir = 'spool/' + encode(endpoint.public.bytes)
        self.addressBook = YamlMap('config/dustmail-addressbook.yaml')
        self.done = Event()
        self.commandDone = Event()

        self.book = YamlMap('config/dustmail-addressbook.yaml')

        dustmailConfig = YamlMap('config/dustmail-config.yaml')

        try:
            destAddress = dustmailConfig['tracker']
        except:
            entry = self.addInvite()
            destAddress = entry['tracker']
            dustmailConfig['tracker'] = destAddress

        dest, outport, v6 = decodeAddress(destAddress)

        print('Registering with tracker...')
        self.tracker = TrackerClient(self.router, addr=(dest, outport))

        host = getPublicIP(v6)
        inport = dustmailConfig['port']
        self.tracker.putPeerForEndpoint(encode(self.endpoint.public.bytes), [
            encode(self.endpoint.public.bytes),
            encodeAddress((host, inport))
        ])

        invite = self.keys.generateInvite(inport, v6=v6)
        self.tracker.putInviteForPeer(encodeAddress((host, inport)),
                                      encode(invite.message))

        self.trackback = self.router.getService('trackback')
    def sendMessage(self, message):
        print('sendMessage ' + str(message))

        onion = OnionPacket()
        onion.decodeOnionPacket(self.router.keys.getKeypair(), decode(message))
        frm = encode(onion.sender)
        to = encode(onion.receiver)

        print('frm: ' + str(frm))
        print('to: ' + str(to))

        if not os.path.exists(self.maildir + '/' + to):
            os.mkdir(self.maildir + '/' + to)

        filename = None
        while not filename or os.path.exists(filename):
            filename = self.makeName(frm, to)
        f = open(filename, 'w')
        f.write(message)
        f.close()

        notifyPrefs = YamlMap('config/dustmail-notify.yaml')
        try:
            mailAddr = notifyPrefs[to]

            addressBook = YamlMap('config/dustmail-addressbook.yaml')
            frmName = self.nameForPubkey(addressBook, frm)
            if not frmName:
                frmName = frm

            notifier = Notifier('*****@*****.**')
            notifier.notify(
                mailAddr, 'New DustMail Message',
                "You have a DustMail message from " + frmName + ".")
        except KeyError:
            print('No notification set')
    def gotInvite(self, invite):
        time.sleep(1)
        print()
        ps = input("Print, Save, or Email [P/s/e]? ")
        passwd = input("Encrypt invite with password: "******"Save invite to filename: ").strip()
            if filename != '':
                f = open(filename, 'wb')
                f.write(packet.packet)
                f.close()
        elif ps == 'e':
            frm = input("Your email: ")
            to = input("Recipient email: ")
            name = input("Your name on DustMail: ")

            body = """
      You have been invited to communicate with %s via DustMail.
      Use the following invite code: %s
      """ % (name, encode(packet.packet))

            emailConfig = YamlMap('config/emailServer.yaml')
            try:
                smtpHost = emailConfig['smtpHost']
            except:
                smtpHost = input("SMTP Host: ")
                emailConfig['smtpHost'] = smtpHost

            notifier = Notifier(frm)
            notifier.notify(to, 'DustMail Invite', body)
        else:
            print()
            print(encode(packet.packet))
            print()

        self.commandDone.set()
Пример #12
0
from dust.util.ymap import YamlMap

activeServices={}

paths=YamlMap('config/activeServices.yaml')
for serviceName in paths.keys():
  modName, clsName=paths[serviceName]
  path=modName.split('.')
  mod=__import__(modName)
  for name in path[1:]:
    mod=getattr(mod, name)
  cls=getattr(mod, clsName)
  obj=cls()
  activeServices[serviceName]=obj
Пример #13
0
 def __init__(self, router):
   self.state=YamlMap('config/trackback.yaml')
Пример #14
0
try:
  keys.loadKeypair('config/id.yaml')
except:
  print('Generating server keypair...')
  keys.createKeypair()
  keys.saveKeypair('config/id.yaml')

keys.loadKnownHosts('config/knownhosts.yaml')
keys.loadIncomingInvites('config/incoming_invites.ip')
keys.loadOutgoingInvites('config/outgoing_invites.ip')

router=PacketRouter(v6, inport, keys, passwd)
router.connect(trackerAddr[0], trackerAddr[1])

tracker=TrackerClient(router)

router.start()

keypair=keys.getKeypair()
pubkey=keypair.public

invite=keys.generateInvite(inport, v6=v6)
tracker.putInviteForPeer(encodeAddress((host, inport)), encode(invite.message))

endpoints=YamlMap('config/endpoints.yaml')
for key in endpoints.values():
  tracker.putPeerForEndpoint(key, [encode(pubkey.bytes), encodeAddress((host,inport))])

wait()
 def __init__(self, keys):
   self.keys=keys
   self.state=YamlMap('config/trackback.yaml')
   self.callbacks={}
    keys.loadKeypair('config/id.yaml')
except:
    print('Generating server keypair...')
    keys.createKeypair()
    keys.saveKeypair('config/id.yaml')

keys.loadKnownHosts('config/knownhosts.yaml')
keys.loadIncomingInvites('config/incoming_invites.ip')
keys.loadOutgoingInvites('config/outgoing_invites.ip')

router = PacketRouter(v6, inport, keys, passwd)
router.connect(trackerAddr[0], trackerAddr[1])

tracker = TrackerClient(router)

router.start()

keypair = keys.getKeypair()
pubkey = keypair.public

invite = keys.generateInvite(inport, v6=v6)
tracker.putInviteForPeer(encodeAddress((host, inport)), encode(invite.message))

endpoints = YamlMap('config/endpoints.yaml')
for key in endpoints.values():
    tracker.putPeerForEndpoint(
        key, [encode(pubkey.bytes),
              encodeAddress((host, inport))])

wait()
keys.loadOutgoingInvites('config/outgoing_invites.ip')
endpoint = keys.loadEndpoint(os.path.expanduser('~/.dust/endpoint.yaml'))

pf = input("Load invite from Paste or File [P/f]? ")
if pf == 'f':
    filename = input("Load invite from filename: ").strip()
    f = open(filename, 'rb')
    data = f.read()
    f.close()
else:
    data = decode(input("Past invite: "))

passwd = input("Decrypt invite with password: "******"pubkey: " + encode(packet.pubkey))
print("invite: " + encode(packet.invite))
invite = InviteMessage()
invite.decodeInviteMessage(packet.invite)
keys.addInvite(invite)

name = input("Name for this endpoint: ")
book = YamlMap('config/dustmail-addressbook.yaml')
try:
    entry = book[name]
except:
    entry = {}
entry['pubkey'] = encode(packet.pubkey)
entry['tracker'] = encodeAddress((invite.ip, invite.port))
book[name] = entry
Пример #18
0
 def __init__(self, router):
     self.state = YamlMap('config/trackback.yaml')
Пример #19
0
 def __init__(self, keys):
     self.keys = keys
     self.state = YamlMap("config/trackback.yaml")
     self.callbacks = {}
Пример #20
0
 def __init__(self, router, addr):
     print('new TrackerHandler ' + str(addr))
     self.router = router
     self.addr = addr
     self.state = YamlMap('config/tracker.yaml')
Пример #21
0
class DustmailReader:
  def __init__(self, router, endpoint):
    self.router=router
    self.endpoint=endpoint

    self.keys=router.keys
    self.maildir='spool/'+encode(endpoint.public.bytes)
    self.addressBook=YamlMap('config/dustmail-addressbook.yaml')
    self.done=Event()
    self.commandDone=Event()

    self.book=YamlMap('config/dustmail-addressbook.yaml')

    dustmailConfig=YamlMap('config/dustmail-config.yaml')

    try:
      destAddress=dustmailConfig['tracker']
    except:
      entry=self.addInvite()
      destAddress=entry['tracker']
      dustmailConfig['tracker']=destAddress

    dest, outport, v6=decodeAddress(destAddress)

    print('Registering with tracker...')
    self.tracker=TrackerClient(self.router, addr=(dest, outport))

    host=getPublicIP(v6)
    inport=dustmailConfig['port']
    self.tracker.putPeerForEndpoint(encode(self.endpoint.public.bytes), [encode(self.endpoint.public.bytes), encodeAddress((host,inport))])

    invite=self.keys.generateInvite(inport, v6=v6)
    self.tracker.putInviteForPeer(encodeAddress((host, inport)), encode(invite.message))

    self.trackback=self.router.getService('trackback')

  def start(self):
    print('-'*40)
    msgs=self.displayList()

    command=None
    while command!='x':
      command=input('> ').strip()
      try:
        num=int(command)
        self.displayMessage(msgs[num-1][1])
      except:
        if command=='l':
          msgs=self.displayList()
        else:
          self.parseCommand(command)

  def displayList(self):
    #  msgs=os.listdir(maildir)
    msgs=[]
    for file in glob.glob(self.maildir + '/*.*'):
      stats = os.stat(file)
      lastmod_date = time.localtime(stats[8])
      date_file_tuple = lastmod_date, file
      msgs.append(date_file_tuple)

    if len(msgs)==0:
      print("No messages.")
    else:
      msgs.sort()
      msgs.reverse()

      for x in range(len(msgs)):
        date, fname=msgs[x]
        frm=fname.split('/')[-1].split('-')[0]
        modtime=time.strftime("%m/%d/%Y %I:%M%p",date)
        frmName=self.nameForPubkey(frm)
        if not frmName:
          frmName=frm
        print(str(x+1)+': '+frmName+' '+modtime)
    return msgs

  def nameForPubkey(self, pubkey):
    for name in self.book.keys():
      key=self.book[name]['pubkey']
      if key==pubkey:
        return name
    return None

  def displayMessage(self, fname):
    f=open(fname, 'r')
    msg=f.read()
    f.close()

    data=decode(msg)

    onion=OnionPacket()
    #print(onion)
    try:
      onion.decodeOnionPacket(self.endpoint, data)
    except:
      traceback.print_exc()
    #print(onion)
    print(onion.data.decode('ascii'))

  def parseCommand(self, command):
    self.commandDone.clear()
    if command=='x':
      self.commandDone.set()
      self.done.set()
      sys.exit(0)
    elif command=='a':
      self.addInvite()
    elif command=='i':
      self.makeInvite()
    elif command=='s':
      self.sendMessage()
    elif command=='?':
      self.printHelp()
    waitForEvent(self.commandDone)

  def addInvite(self):
    pf=input("Load invite from Paste or File [P/f]? ")
    if pf=='f':
      filename=input("Load invite from filename: ").strip()
      f=open(filename, 'rb')
      data=f.read()
      f.close()
    else:
      data=decode(input("Past invite: "))

    passwd=input("Decrypt invite with password: "******"Name for this endpoint: ")
    try:
      entry=self.book[name]
    except:
      entry={}
    entry['pubkey']=encode(packet.pubkey)
    entry['tracker']=encodeAddress((invite.ip, invite.port))
    self.book[name]=entry

    self.commandDone.set()

    return entry

  def makeInvite(self):
    self.trackback.setPutTrackerInviteCallback(self.gotInvite)
    self.tracker.getTrackerInvite()

  def gotInvite(self, invite):
    time.sleep(1)
    print()
    ps=input("Print, Save, or Email [P/s/e]? ")
    passwd=input("Encrypt invite with password: "******"Save invite to filename: ").strip()
      if filename!='':
        f=open(filename, 'wb')
        f.write(packet.packet)
        f.close()
    elif ps=='e':
      frm=input("Your email: ")
      to=input("Recipient email: ")
      name=input("Your name on DustMail: ")

      body="""
      You have been invited to communicate with %s via DustMail.
      Use the following invite code: %s
      """ % (name, encode(packet.packet))

      emailConfig=YamlMap('config/emailServer.yaml')
      try:
        smtpHost=emailConfig['smtpHost']
      except:
        smtpHost=input("SMTP Host: ")
        emailConfig['smtpHost']=smtpHost

      notifier=Notifier(frm)
      notifier.notify(to, 'DustMail Invite', body)
    else:
      print()
      print(encode(packet.packet))
      print()

    self.commandDone.set()

  def sendMessage(self):
    name=input("To: ")
    message=input("Message: ")

    PendingMessage(reader, name, message)

  def printHelp(self):
    print('num: read message num')
    print('x: quit')
    print('l: list messages')
    print('a: add invite')
    print('i: make invite')
    print('s: send message')

    self.commandDone.set()
        print('a: add invite')
        print('i: make invite')
        print('s: send message')

        self.commandDone.set()


if __name__ == '__main__':
    if len(sys.argv) > 1 and sys.argv[1] == '-d':
        passwd = sys.argv[2]
        headless = True
    else:
        passwd = input("Password: ")
        headless = False

    dustmailConfig = YamlMap('config/dustmail-config.yaml')

    try:
        inport = int(dustmailConfig['port'])
    except:
        inport = randomPort()
        dustmailConfig['port'] = inport

    print('Loading keys...')
    keys = KeyManager()
    keys.setInvitePassword(passwd)
    keys.loadKnownHosts('config/knownhosts.yaml')

    try:
        keys.loadKeypair('config/id.yaml')
    except:
Пример #23
0
 def __init__(self, router, addr):
   print('new TrackerHandler '+str(addr))
   self.router=router
   self.addr=addr
   self.state=YamlMap('config/tracker.yaml')
class DustmailReader:
    def __init__(self, router, endpoint):
        self.router = router
        self.endpoint = endpoint

        self.keys = router.keys
        self.maildir = 'spool/' + encode(endpoint.public.bytes)
        self.addressBook = YamlMap('config/dustmail-addressbook.yaml')
        self.done = Event()
        self.commandDone = Event()

        self.book = YamlMap('config/dustmail-addressbook.yaml')

        dustmailConfig = YamlMap('config/dustmail-config.yaml')

        try:
            destAddress = dustmailConfig['tracker']
        except:
            entry = self.addInvite()
            destAddress = entry['tracker']
            dustmailConfig['tracker'] = destAddress

        dest, outport, v6 = decodeAddress(destAddress)

        host = getPublicIP(v6)
        inport = dustmailConfig['port']

        invite = self.keys.generateInvite(inport, v6=v6)

    def start(self):
        print('-' * 40)
        msgs = self.displayList()

        command = None
        while command != 'x':
            command = input('> ').strip()
            try:
                num = int(command)
                self.displayMessage(msgs[num - 1][1])
            except:
                if command == 'l':
                    msgs = self.displayList()
                else:
                    self.parseCommand(command)

    def displayList(self):
        #  msgs=os.listdir(maildir)
        msgs = []
        for file in glob.glob(self.maildir + '/*.*'):
            stats = os.stat(file)
            lastmod_date = time.localtime(stats[8])
            date_file_tuple = lastmod_date, file
            msgs.append(date_file_tuple)

        if len(msgs) == 0:
            print("No messages.")
        else:
            msgs.sort()
            msgs.reverse()

            for x in range(len(msgs)):
                date, fname = msgs[x]
                frm = fname.split('/')[-1].split('-')[0]
                modtime = time.strftime("%m/%d/%Y %I:%M%p", date)
                frmName = self.nameForPubkey(frm)
                if not frmName:
                    frmName = frm
                print(str(x + 1) + ': ' + frmName + ' ' + modtime)
        return msgs

    def nameForPubkey(self, pubkey):
        for name in self.book.keys():
            key = self.book[name]['pubkey']
            if key == pubkey:
                return name
        return None

    def displayMessage(self, fname):
        f = open(fname, 'r')
        msg = f.read()
        f.close()

        data = decode(msg)

        onion = OnionPacket()
        #print(onion)
        try:
            onion.decodeOnionPacket(self.endpoint, data)
        except:
            traceback.print_exc()
        #print(onion)
        print(onion.data.decode('ascii'))

    def parseCommand(self, command):
        self.commandDone.clear()
        if command == 'x':
            self.commandDone.set()
            self.done.set()
            sys.exit(0)
        elif command == 'a':
            self.addInvite()
        elif command == 'i':
            self.makeInvite()
        elif command == 's':
            self.sendMessage()
        elif command == '?':
            self.printHelp()
        waitForEvent(self.commandDone)

    def addInvite(self):
        pf = input("Load invite from Paste or File [P/f]? ")
        if pf == 'f':
            filename = input("Load invite from filename: ").strip()
            f = open(filename, 'rb')
            data = f.read()
            f.close()
        else:
            data = decode(input("Past invite: "))

        passwd = input("Decrypt invite with password: "******"Name for this endpoint: ")
        try:
            entry = self.book[name]
        except:
            entry = {}
        entry['pubkey'] = encode(packet.pubkey)
        entry['tracker'] = encodeAddress((invite.ip, invite.port))
        self.book[name] = entry

        self.commandDone.set()

        return entry

    def makeInvite(self):
        self.trackback.setPutTrackerInviteCallback(self.gotInvite)
        self.tracker.getTrackerInvite()

    def gotInvite(self, invite):
        time.sleep(1)
        print()
        ps = input("Print, Save, or Email [P/s/e]? ")
        passwd = input("Encrypt invite with password: "******"Save invite to filename: ").strip()
            if filename != '':
                f = open(filename, 'wb')
                f.write(packet.packet)
                f.close()
        elif ps == 'e':
            frm = input("Your email: ")
            to = input("Recipient email: ")
            name = input("Your name on DustMail: ")

            body = """
      You have been invited to communicate with %s via DustMail.
      Use the following invite code: %s
      """ % (name, encode(packet.packet))

            emailConfig = YamlMap('config/emailServer.yaml')
            try:
                smtpHost = emailConfig['smtpHost']
            except:
                smtpHost = input("SMTP Host: ")
                emailConfig['smtpHost'] = smtpHost

            notifier = Notifier(frm)
            notifier.notify(to, 'DustMail Invite', body)
        else:
            print()
            print(encode(packet.packet))
            print()

        self.commandDone.set()

    def sendMessage(self):
        name = input("To: ")
        message = input("Message: ")

        PendingMessage(reader, name, message)

    def printHelp(self):
        print('num: read message num')
        print('x: quit')
        print('l: list messages')
        print('a: add invite')
        print('i: make invite')
        print('s: send message')

        self.commandDone.set()