finished, but buggy
This commit is contained in:
parent
ad6b6281b3
commit
757eba1c6c
132
uvgotmail.py
132
uvgotmail.py
|
@ -2,6 +2,7 @@
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import atexit
|
||||||
|
|
||||||
def parseYN(s, default = False):
|
def parseYN(s, default = False):
|
||||||
if default == False:
|
if default == False:
|
||||||
|
@ -34,7 +35,7 @@ def parseConfig(args=None,config_path=None):
|
||||||
if type(config[kv[0]]) == type(True):
|
if type(config[kv[0]]) == type(True):
|
||||||
config[kv[0]] = (kv[1] == 'True') # cast to boolean
|
config[kv[0]] = (kv[1] == 'True') # cast to boolean
|
||||||
elif type(config[kv[0]]) == type(1):
|
elif type(config[kv[0]]) == type(1):
|
||||||
config[kv[0]] = parseInt(kv[1])
|
config[kv[0]] = int(kv[1])
|
||||||
else:
|
else:
|
||||||
config[kv[0]] = kv[1]
|
config[kv[0]] = kv[1]
|
||||||
except:
|
except:
|
||||||
|
@ -88,7 +89,6 @@ def parseConfig(args=None,config_path=None):
|
||||||
# make sure at least a server and a username are set
|
# make sure at least a server and a username are set
|
||||||
if config["server"] == "" or config["user"] == "":
|
if config["server"] == "" or config["user"] == "":
|
||||||
print("uvgotmail: failed to start. no imap server or username specified.")
|
print("uvgotmail: failed to start. no imap server or username specified.")
|
||||||
print(config)
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
def createConfig(config_path, config,args):
|
def createConfig(config_path, config,args):
|
||||||
|
@ -145,12 +145,16 @@ def main():
|
||||||
parser.add_argument("--config", help="specify config file (default: ~/.uvgotmail/config)", default="~/.uvgotmail/config")
|
parser.add_argument("--config", help="specify config file (default: ~/.uvgotmail/config)", default="~/.uvgotmail/config")
|
||||||
parser.add_argument("--mutt", help="use existing mutt configuration (experimental)", action="store_true")
|
parser.add_argument("--mutt", help="use existing mutt configuration (experimental)", action="store_true")
|
||||||
parser.add_argument("--check", help="run in check mode (put this in PS1)", action="store_true")
|
parser.add_argument("--check", help="run in check mode (put this in PS1)", action="store_true")
|
||||||
parser.add_argument("--no-count", help="don't display how many unread messages there are", action="store_false")
|
parser.add_argument("--no-count", help="don't display how many unread messages there are", action="store_true")
|
||||||
parser.add_argument("--mailbox-symbol", help="specify a string instead of the mailbox emoji",default="")
|
parser.add_argument("--mailbox-symbol", help="specify a string instead of the mailbox emoji",default="")
|
||||||
|
parser.add_argument("--debug", help="print errors",action="store_true")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
config_settings = parseConfig(args);
|
global config
|
||||||
|
config = parseConfig(args);
|
||||||
|
|
||||||
|
config["debug"] = args.debug
|
||||||
|
|
||||||
if(args.daemon == args.check):
|
if(args.daemon == args.check):
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
|
@ -164,17 +168,126 @@ def check():
|
||||||
filename = os.path.expanduser('~/.uvgotmail/unread')
|
filename = os.path.expanduser('~/.uvgotmail/unread')
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
with open(filename) as f:
|
with open(filename) as f:
|
||||||
unread = int(f.read());
|
unread = f.read();
|
||||||
|
if unread != '':
|
||||||
|
unread = int(unread)
|
||||||
|
else:
|
||||||
|
unread = 0
|
||||||
if unread == 0:
|
if unread == 0:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
pre = ""
|
pre = ""
|
||||||
if(unread > 1 and countmail == True):
|
if(unread > 1 and config["no_count"] == False):
|
||||||
pre = "("+str(unread)+") "
|
pre = "("+str(unread)+") "
|
||||||
print(pre+mailchar,end=' ')
|
print(pre+config["mailbox_symbol"],end=' ')
|
||||||
# if there's no unread count file, just exit quietly
|
# if there's no unread count file, just exit quietly
|
||||||
|
|
||||||
|
def writeUnreadFile(unseen):
|
||||||
|
try:
|
||||||
|
with open(os.path.expanduser('~/.uvgotmail/unread'),'w') as f:
|
||||||
|
f.write(str(len(unseen)))
|
||||||
|
except Exception as e:
|
||||||
|
if config["debug"]: print(e)
|
||||||
|
print("uvgotmail: could not write to unread file")
|
||||||
|
|
||||||
|
# we're implementing this in a disgusting way. i'm sorry.
|
||||||
|
import time
|
||||||
|
import socket
|
||||||
|
import re
|
||||||
|
|
||||||
|
def idleFunction(s,unseen):
|
||||||
|
s._startIdle = time.time()
|
||||||
|
if 'IDLE' not in s.capabilities:
|
||||||
|
raise s.error('Server does not support IDLE')
|
||||||
|
idle_tag = s._command('IDLE') # start idling
|
||||||
|
s._get_response()
|
||||||
|
while line := s._get_line():
|
||||||
|
if b'FETCH' in line:
|
||||||
|
l = str(line)
|
||||||
|
msg = re.findall(r'\d+',l)[0]
|
||||||
|
if config["debug"]: print(msg, unseen)
|
||||||
|
if "seen" in l.lower():
|
||||||
|
unseen.remove(msg)
|
||||||
|
else:
|
||||||
|
unseen.append(msg)
|
||||||
|
print(unseen)
|
||||||
|
writeUnreadFile(unseen)
|
||||||
|
else:
|
||||||
|
# we only want to idle for ten minutes maximum. we will use the keep-alive messages to keep track in a single thread.
|
||||||
|
if(time.time() - s.start > 600):
|
||||||
|
s.send(b'DONE' + imaplib.CRLF)
|
||||||
|
return s._command_complete('IDLE', idle_tag)
|
||||||
|
|
||||||
|
|
||||||
|
# thanks to trentbuck on github for this awful idea
|
||||||
|
|
||||||
def daemon():
|
def daemon():
|
||||||
import imaplib
|
import imaplib
|
||||||
|
imaplib.Commands['IDLE'] = ('AUTH', 'SELECTED')
|
||||||
|
class IMAP4_SSL_plus_IDLE(imaplib.IMAP4_SSL):
|
||||||
|
def idle(self, unseen):
|
||||||
|
idleFunction(self,unseen)
|
||||||
|
class IMAP4_plus_IDLE(imaplib.IMAP4):
|
||||||
|
def idle(self, unseen):
|
||||||
|
idleFunction(self,unseen)
|
||||||
|
|
||||||
|
IMAP4_SSL = IMAP4_SSL_plus_IDLE
|
||||||
|
IMAP4 = IMAP4_plus_IDLE
|
||||||
|
socket.setdefaulttimeout(120)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# first check if daemon is already running
|
||||||
|
pidfile = os.path.expanduser('~/.uvgotmail/.run.pid')
|
||||||
|
if os.path.exists(pidfile):
|
||||||
|
with open(pidfile) as f:
|
||||||
|
pid = f.read()
|
||||||
|
if pid != '':
|
||||||
|
pid = int(pid)
|
||||||
|
else:
|
||||||
|
pid = 0
|
||||||
|
running_cmd = os.popen("ps -p" + str(pid) +" -o command").read()
|
||||||
|
current_cmd = os.popen("ps -p" + str(os.getpid()) +" -o command").read()
|
||||||
|
if running_cmd == current_cmd or os.path.basename(sys.argv[0]) in running_cmd:
|
||||||
|
# the process is running; we don't need to start up at all
|
||||||
|
exit(0)
|
||||||
|
try:
|
||||||
|
with open(pidfile,'w') as f:
|
||||||
|
f.write(str(os.getpid()))
|
||||||
|
def delPid(pidfile):
|
||||||
|
os.remove(pidfile)
|
||||||
|
atexit.register(delPid,pidfile)
|
||||||
|
except:
|
||||||
|
print("uvgotmail: failed to write to PID file")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# main loop
|
||||||
|
import time
|
||||||
|
start_time = time.time();
|
||||||
|
IMAP4_func = IMAP4_SSL if config["ssl"] else IMAP4
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
with IMAP4_func(config["server"],config["port"]) as conn:
|
||||||
|
conn.login(user=config["user"],password=config["password"])
|
||||||
|
conn.select(mailbox='INBOX',readonly=True)
|
||||||
|
typ,msgnums = conn.search(None, "UNSEEN");
|
||||||
|
unseen = [n.decode() for n in msgnums if n != b''][0].split(' ')
|
||||||
|
if config["debug"]: print(unseen)
|
||||||
|
writeUnreadFile(unseen)
|
||||||
|
#try:
|
||||||
|
resp = conn.idle(unseen)
|
||||||
|
#except Exception as e:
|
||||||
|
if config["debug"]: print(e)
|
||||||
|
if time.time() - start_time <= 10:
|
||||||
|
print("uvgotmail: too many imap errors. exiting.")
|
||||||
|
sys.exit(1)
|
||||||
|
start_time = time.time();
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if config["debug"]:
|
||||||
|
print(e)
|
||||||
|
print("uvgotmail: failed to log in to server. dumping config.")
|
||||||
|
print(config);
|
||||||
|
exit(1)
|
||||||
|
|
||||||
# handle ctrl+c gracefully
|
# handle ctrl+c gracefully
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -182,8 +295,5 @@ if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print('Interrupted')
|
print('Interrupted')
|
||||||
try:
|
exit(130)
|
||||||
sys.exit(130)
|
|
||||||
except SystemExit:
|
|
||||||
os._exit(130)
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue