You are not logged in.

#1 2017-09-10 09:46:51

ap
Member
Registered: 2017-08-09
Posts: 47

[SOLVED] Mutt, receive notification on new email

Hi,

Using mutt (not neomutt), how do you get notifications for a new email? I know one can set a beep for a new email, but I am looking for a proper notification rather than just the beep...

Thanks!

Ps, without using offlineimap

Last edited by ap (2017-09-12 01:24:08)

Offline

#2 2017-09-10 09:48:18

Head_on_a_Stick
Member
From: London
Registered: 2015-09-29
Posts: 9,068
Website

Re: [SOLVED] Mutt, receive notification on new email

Does this help:

https://askubuntu.com/questions/701565/ … using-mutt

This reply was brought to you by https://www.startpage.com/

EDIT: link changed.

Last edited by Head_on_a_Stick (2017-09-10 09:49:13)

Offline

#3 2017-09-10 10:00:46

ap
Member
Registered: 2017-08-09
Posts: 47

Re: [SOLVED] Mutt, receive notification on new email

Hi,thanks
There it is suggested to use Mail Notification, while I was wondering whether one can do it in mutt... Maybe using some custom script someone is willing to share.

Is the startpage thing s way of saying 'do your research first'? I did but couldn't find anything useful...

Last edited by ap (2017-09-10 10:01:15)

Offline

#4 2017-09-10 10:06:29

Head_on_a_Stick
Member
From: London
Registered: 2015-09-29
Posts: 9,068
Website

Re: [SOLVED] Mutt, receive notification on new email

ap wrote:

Is the startpage thing s way of saying 'do your research first'?

Yes  big_smile

I did but couldn't find anything useful...

My link was top of the second in the list when I highlighted the title of your thread then right-clicked and selected "Search startpage.com for..." — did you not also see it?

Last edited by Head_on_a_Stick (2017-09-10 10:07:25)

Offline

#5 2017-09-10 10:21:02

ap
Member
Registered: 2017-08-09
Posts: 47

Re: [SOLVED] Mutt, receive notification on new email

I did see that link plus a bunch of other links before asking here... However they do not answer my question smile

Update: Mail-notification requires so many dependencies, I am not really willing to install it

Last edited by ap (2017-09-10 11:28:38)

Offline

#6 2017-09-10 14:01:08

iMBeCil
WAAAT?
From: Edrychwch o'ch cwmpas
Registered: 2015-09-29
Posts: 767

Re: [SOLVED] Mutt, receive notification on new email

^IMHO, the simplest solution would be to write your own script. Note that solution depends on how your email (mutt) is configured. (Mutt is MUA!) Do you use POP, IMAP, local folder?

Furthermore, what exactly do you meen by 'notification'? Pop-up window? Item in conky?

For example, I'm using sylpheed (in POP mode, but this irrelevant for sylpheed, since it is much more than MUA), And for conky (pre 1.10!), I have had following in .conkyrc:

${execi 10 [ ! -z `pgrep sylpheed` ] && echo \| e-mails: `expr "\`sylpheed --status inbox\`" : '[0-9]* \([0-9]*\)'`    }

(it would check if 'sylpheed' is running, and if it is - it would display number of messages in INBOX).
For i3bar, similar functionality can be achieved with simple bash script.

For pop-up window, you can use cron or even better, systemd timer, to regularly run the script which will check if new mail has arrived.

Perhaps, this might be interesting to red.


Postpone all your duties; if you die, you won't have to do them ..

Offline

#7 2017-09-10 21:00:36

tknomanzr
BL Die Hard
From: Around the Bend
Registered: 2015-09-29
Posts: 1,057

Re: [SOLVED] Mutt, receive notification on new email

Here is a really simple notifier I wrote against sylpheed. Man mutt may get you the exact command you need to provide to subprocess.check_output.

#!/usr/bin/env python
import gi
import subprocess
gi.require_version('Notify', '0.7')
from gi.repository import Notify
Notify.init("Mail Notification")
try:
	num_messages = subprocess.check_output(['sylpheed', '--status', 'inbox'], stderr=subprocess.STDOUT, shell=False)
	num_messages = num_messages.split()
	print "Number of Messages:", num_messages[0]
except subprocess.CalledProcessError:
	print cmd, output, returncode
msg = "You have " + num_messages[0] + " unread messages."
notify=Notify.Notification.new("Sylpheed", msg, "dialog-information")
notify.show()

This is the part that checks the mail client:

num_messages = subprocess.check_output(['sylpheed', '--status', 'inbox'], stderr=subprocess.STDOUT, shell=False)

The comma seperated list ['sylpheed', '--status', 'inbox'] is the actual command I executed. Man mutt may offer a similar command.
I enabled it in Sylpheed --> Configuration --> Common Preferences --> Execute command when new messages arrive --> /home/user/bin/mail-notify, where mail-notify is the name of the program I listed above.

Give me a bit of time and I'll try to work on a mutt client version.
Anyway, here's a scrot showing it in action:
Screenshot_2017-09-10_15-49-44.th.png

Offline

#8 2017-09-11 01:12:11

ap
Member
Registered: 2017-08-09
Posts: 47

Re: [SOLVED] Mutt, receive notification on new email

thanks imbecil and tknomanzr for the great feedback, that's exactly what I am looking for. I believe maidir-notification (thanks imbecil for recommending it) should do the trick. however I would like to work also on a simple script to achieve the same goal, when I find some free time...your inputs were very helpful!

tknomanzr, it would be great to see a mutt version of your script, when and if you have time smile

By the way, on neomutt one can simply use

set new_mail_command="notify-send --icon='~/neomutt.png' 'New Email' '%n new messages, %u unread.' &"

and that's it. However building neomutt on debian 8 it's a real pain and I encountered all sort of problems with dependencies...if I understand right, in debian 9 mutt has been replaced by neomutt instead and available in the repos...that's another reason I am looking forward to BL Helium, when it is officially released :-D

Offline

#9 2017-09-11 08:03:52

iMBeCil
WAAAT?
From: Edrychwch o'ch cwmpas
Registered: 2015-09-29
Posts: 767

Re: [SOLVED] Mutt, receive notification on new email

^You're welcome.

^ & ^^ As for the mutt, first thing after I saw your question I did was 'man mutt' searching for "sylpheed --status inbox" equivalent command. I couldn't find one.  hmm


Postpone all your duties; if you die, you won't have to do them ..

Offline

#10 2017-09-11 10:09:30

jmc
tint3 maintainer
Registered: 2017-05-22
Posts: 9
Website

Re: [SOLVED] Mutt, receive notification on new email

Late to the thread, but: I'm using Mailnag and it's pretty good, maybe try it out.

Offline

#11 2017-09-11 11:23:49

iMBeCil
WAAAT?
From: Edrychwch o'ch cwmpas
Registered: 2015-09-29
Posts: 767

Re: [SOLVED] Mutt, receive notification on new email

^Nice find.


Postpone all your duties; if you die, you won't have to do them ..

Offline

#12 2017-09-11 12:26:22

ap
Member
Registered: 2017-08-09
Posts: 47

Re: [SOLVED] Mutt, receive notification on new email

Thanks jmc, I'll give it a try wink

Offline

#13 2017-09-11 16:03:27

tknomanzr
BL Die Hard
From: Around the Bend
Registered: 2015-09-29
Posts: 1,057

Re: [SOLVED] Mutt, receive notification on new email

Yeah, I looked at it. I didn't realize it was an old n-curses app at first.  Even still I read the man to see if I could get the outputs I needed and no go there. It looks to me like a lot of folder recursion to get something working on it. I'd likely have to rewrite the whole thing to run as a service, though, or at least the folder monitoring part of it.

Offline

#14 2017-09-11 18:36:20

nobody
The Great
Registered: 2015-08-10
Posts: 3,655

Re: [SOLVED] Mutt, receive notification on new email

tknomanzr wrote:

Yeah, I looked at it. I didn't realize it was an old n-curses app at first.  Even still I read the man to see if I could get the outputs I needed and no go there. It looks to me like a lot of folder recursion to get something working on it. I'd likely have to rewrite the whole thing to run as a service, though, or at least the folder monitoring part of it.

A watcher for local folders should probably be based on inotify; you'd need to enumerate all directories and create an inotify for each of them, and react to removals. But monitoring of writes/creates/deletes of files (mbox = single file, maildir = many files) should be fairly easy.

Offline

#15 2017-09-12 01:23:55

ap
Member
Registered: 2017-08-09
Posts: 47

Re: [SOLVED] Mutt, receive notification on new email

thanks for the answers...mailnag did the trick, and I see that implementing this directly in mutt is problematic. I mark this as solved, thanks again :-D

Offline

#16 2017-09-12 04:27:31

Sector11
Mod Squid Tpyo Knig
From: Upstairs
Registered: 2015-08-20
Posts: 8,011

Re: [SOLVED] Mutt, receive notification on new email

I realize it's marked [Solved] but...

I use "conkyEmail" a python script written by Kaivalagi

 12 Sep 17 @ 01:14:57 ~
   $ conkyEmail --help
Usage: conkyEmail.py [options]

Options:
  -h, --help            show this help message and exit
  -m SERVERTYPE, --servertype=SERVERTYPE
                        servertype to check [default: POP] The server type
                        options are POP or IMAP
  -s SERVERNAME, --servername=SERVERNAME
                        server name to access [default: pop.mail.yahoo.co.uk]
                        The server name should be either a domain name or ip
                        address
  -o NUMBER, --port=NUMBER
                        Define an alternative port number to use other than
                        the default for the protocol/ssl
  -f FOLDER, --folder=FOLDER
                        [default: Inbox] IMAP folder to check, not applicable
                        for POP mail checks
  -e, --ssl             Use an SSL based connection.
  -u USERNAME, --username=USERNAME
                        username to login with
  -p PASSWORD, --password=PASSWORD
                        Password to login with
  -t FILE, --template=FILE
                        define a template file to generate output in one call.
                        A displayable item in the file is in the form
                        [--servertype=IMAP --ssl --servername=imap.gmail.com
                        --folder=Inbox --username=joebloggs
                        --password=letmein, --connectiontimeout=10]. Note that
                        the short forms of the options are not currently
                        supported! None of these options are applicable at
                        command line when used in templates.
  -i NUMBER, --mailinfo=NUMBER
                        [default: 0] The number of newest emails to output
                        'from' and 'subject' information for. Not applicable
                        at command line when using templates.
  -w NUMBER, --maxwidth=NUMBER
                        [default: 80] Define the number of characters to
                        output per line
  -l NUMBER, --linelimit=NUMBER
                        [default: 0] If above zero this limits the number of
                        lines output for mail info
  -q CHAR, --quote=CHAR
                        [default: "] The character to use for quotations
                        around the subject line
  -c NUMBER, --connectiontimeout=NUMBER
                        [default: 10] Define the number of seconds before a
                        connection timeout can occur. Not applicable at
                        command line when using templates.
  -v, --verbose         request verbose output, not a good idea when running
                        through conky!
  -V, --version         Displays the version of the script.
  --errorlogfile=FILE   If a filepath is set, the script appends errors to the
                        filepath.
  --infologfile=FILE    If a filepath is set, the script appends info to the
                        filepath.
 
 12 Sep 17 @ 01:15:24 ~
   $ 

In my conky I use it like this:

${goto 255}${font fira mono:size=14}| ${color}S${color2} \
${if_match ${execi 90 conkyEmail -t /media/5/Conky/email/S} == 0}00${else}\
${if_match ${execi 90 conkyEmail -t /media/5/Conky/email/S} < 10}0\
${execi 90 conkyEmail -t /media/5/Conky/email/S}${else}\
${execi 90 conkyEmail -t /media/5/Conky/email/S}${endif}${endif}${color}${font}

The template is so I don't need my personal data in the conky.
2017-09-12_012111_Scrot11.jpg

EDIT:
That's two accounts the " C 00 " is the account my wife uses.

${font fira mono:size=14}${color}C${color2} \
${if_match ${execi 90 conkyEmail -t /media/5/Conky/email/C} == 0}00${else}\
${if_match ${execi 90 conkyEmail -t /media/5/Conky/email/C} < 10}0\
${execi 90 conkyEmail -t /media/5/Conky/email/C}${else}\
${execi 90 conkyEmail -t /media/5/Conky/email/C}${endif}${endif}

Last edited by Sector11 (2017-09-12 04:33:40)


Debian 12 Beardog, SoxDog and still a Conky 1.9er

Offline

#17 2017-09-12 09:11:48

ap
Member
Registered: 2017-08-09
Posts: 47

Re: [SOLVED] Mutt, receive notification on new email

Wow that looks awesome, definitely something to implement in my conky too!

Offline

#18 2017-09-12 09:46:03

iMBeCil
WAAAT?
From: Edrychwch o'ch cwmpas
Registered: 2015-09-29
Posts: 767

Re: [SOLVED] Mutt, receive notification on new email

^^Excellent find, Sector, thanks.

I find it very simple and non-convoluted, perfect for learn how to do it (in python).


Postpone all your duties; if you die, you won't have to do them ..

Offline

#19 2017-09-12 14:49:07

Sector11
Mod Squid Tpyo Knig
From: Upstairs
Registered: 2015-08-20
Posts: 8,011

Re: [SOLVED] Mutt, receive notification on new email

I have been using Kaivalagi's scripts since he first wrote them (I was his Beta tester) the thing is I have ALL of his files here on my HDD, but I only use two.  conkyEmail and conkyMisc  They come as deb files via the UBU PPA (I was using Xubu at the time) but I also have:

conkyemail_2.07.tar.gz
conkyemail_2.13_all.deb
conkyemail_2.15.dsc
conkyemail_2.15.tar.gz
conkyemail_2.15_all.deb
conkymisc_1.06.dsc
conkymisc_1.06.tar.gz
conkymisc_1.06_all.deb

as well as the files for:
conkybanshee_2.10
conkyclementine_2.03
conkyexaile_2.16
conkyforecast_2.24
conkygooglecalendar_2.16
conkygooglereader_1.08
conkyguayadeque_2.09
conkykeyring_1.01
conkypidgin_2.17
conkyrhythmbox_2.17
conkytransmission_1.03
rhythmbox-desktop-art_2.00

Now with conkyMisc I know I can run the .py files from ~/bin so things like:

 12 Sep 17 @ 11:41:59 ~
   $ conkyLatLong
-34.612999 / -58.470001
 
 12 Sep 17 @ 11:42:07 ~
   $ conkyLatLong -i
34°36"46.7964'S / 58°28"12.0036'W
 
 12 Sep 17 @ 11:42:11 ~
   $ 

work quite nicely in a conky as well

I have been using the Ubuntu PPA files (for these python script) forever.  ConkyEmail and conkyMisc:

/usr/share/conkymisc/conkyDateDiff.py
/usr/share/conkymisc/conkyDatetimeDiff.py
/usr/share/conkymisc/conkyDaysDiff.py
/usr/share/conkymisc/conkyLatLong.py
/usr/share/conkymisc/conkySlideshow.py
/usr/share/conkymisc/conkyText.py

all work in Debian 9 as well.  Not sure about the MUSIC script, I don't use any of them.

conkyemail.py this is conkyemail v 2.13 since 2.15 requires conkyKeyring- This will probably work in ~/bin as well (might need a ${execi 90 python conkyemail.py ...} start I'm not sure.  I install with the .deb file ... 9 years old an still going strong!

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
###############################################################################
# conkyEmail.py is a simple python script to gather
# details of email inboxes use in conky.
#
# Author: Kaivalagi
# Created: 16/05/2008

from datetime import datetime,timedelta
from email.header import decode_header
from optparse import OptionParser
import sys
import poplib
import imaplib
import socket
import re
import textwrap
import traceback
import codecs
import os

class CommandLineParser:

    parser = None

    def __init__(self):

        self.parser = OptionParser()
        self.parser.add_option("-m","--servertype", dest="servertype", default="POP", type="string", metavar="SERVERTYPE", help=u"servertype to check [default: %default] The server type options are POP or IMAP")
        self.parser.add_option("-s","--servername", dest="servername", default="pop.mail.yahoo.co.uk", type="string", metavar="SERVERNAME", help=u"server name to access [default: %default] The server name should be either a domain name or ip address")
        self.parser.add_option("-o","--port",dest="port", type="int", metavar="NUMBER", help=u"Define an alternative port number to use other than the default for the protocol/ssl")
        self.parser.add_option("-f","--folder",dest="folder", type="string", metavar="FOLDER", default="Inbox", help=u"[default: %default] IMAP folder to check, not applicable for POP mail checks")
        self.parser.add_option("-e","--ssl", dest="ssl", default=False, action="store_true", help=u"Use an SSL based connection.")
        self.parser.add_option("-u","--username",dest="username", type="string", metavar="USERNAME", help=u"username to login with")
        self.parser.add_option("-p","--password",dest="password", type="string", metavar="PASSWORD", help=u"Password to login with")
        self.parser.add_option("-t","--template",dest="template", type="string", metavar="FILE", help=u"define a template file to generate output in one call. A displayable item in the file is in the form [--servertype=IMAP --ssl --servername=imap.gmail.com --folder=Inbox --username=joebloggs --password=letmein, --connectiontimeout=10]. Note that the short forms of the options are not currently supported! None of these options are applicable at command line when used in templates.")
        self.parser.add_option("-i","--mailinfo", dest="mailinfo", type="int", default=0, metavar="NUMBER", help=u"[default: %default] The number of newest emails to output 'from' and 'subject' information for. Not applicable at command line when using templates.")
        self.parser.add_option("-w","--maxwidth",dest="maxwidth", default=80, type="int", metavar="NUMBER", help=u"[default: %default] Define the number of characters to output per line")
        self.parser.add_option("-l","--linelimit", dest="linelimit", default=0, type="int", metavar="NUMBER", help=u"[default: %default] If above zero this limits the number of lines output for mail info")
        self.parser.add_option("-q","--quote", dest="quote", default="\"", type="string", metavar="CHAR", help=u"[default: %default] The character to use for quotations around the subject line")
        self.parser.add_option("-c","--connectiontimeout",dest="connectiontimeout", type="int", default=10, metavar="NUMBER", help=u"[default: %default] Define the number of seconds before a connection timeout can occur. Not applicable at command line when using templates.")
        self.parser.add_option("-v","--verbose", dest="verbose", default=False, action="store_true", help=u"request verbose output, not a good idea when running through conky!")
        self.parser.add_option("-V", "--version", dest="version", default=False, action="store_true", help=u"Displays the version of the script.")
        self.parser.add_option("--errorlogfile", dest="errorlogfile", type="string", metavar="FILE", help=u"If a filepath is set, the script appends errors to the filepath.")
        self.parser.add_option("--infologfile", dest="infologfile", type="string", metavar="FILE", help=u"If a filepath is set, the script appends info to the filepath.")

    def parse_args(self):
        (options, args) = self.parser.parse_args()
        return (options, args)

    def print_help(self):
        return self.parser.print_help()

class EmailData:
    def __init__(self, servername, folder, username, num, sender, subject, recvdate, messageid):
        self.servername = servername
        self.folder = folder
        self.username = username
        self.num = num
        self.sender = sender
        self.subject = subject
        self.recvdate = recvdate
        self.messageid = messageid

    def __cmp__(self, other):
        return cmp(self.getRecvDate(self.recvdate), self.getRecvDate(other.recvdate))

    def getRecvDate(self, recvdate):
        if recvdate is None:
            return datetime.now()
        else:
            return recvdate

class EmailInfo:

    IMAP_SEARCH_OPTION = "UNSEEN" # "RECENT"
    POP_FETCH_OPTION = "TOP" # "RETR"

    emaillist = []

    def __init__(self,options):

        self.options = options

    def getTemplateList(self,template):

        templatelist = []

        for template_part in template.split("{"):
            if template_part != "":
                for template_part in template_part.split("}"):
                    if template_part != "":
                        templatelist.append(u""+template_part)

        return templatelist

    def getOutputData(self,servertype,servername,port,folder,ssl,username,password,connectiontimeout,mailinfo):
        try:
            output = u""

            socket.setdefaulttimeout(connectiontimeout)

            if servertype == "POP":
                count = self.getPOPEmailData(servername,port,folder,ssl,username,password,mailinfo)
            elif servertype == "IMAP":
                count = self.getIMAPEmailData(servername,port,folder,ssl,username,password,mailinfo)
            else:
                if self.options.verbose == True:
                    self.logError("Unknown server type of %s requested"%servertype)

            if count == -1:
                output = "?"
            elif count == 0:
                output = "0"
            else:

                if mailinfo > 0:

                    output = "%s New"%count

                    counter = 0
                    self.emaillist.sort(reverse=True)
                    for emaildata in self.emaillist:
                        counter = counter + 1
                        if mailinfo >= counter:
                            bullet = "%s. "%(counter)

                            text = "%s: %s%s%s"%(emaildata.sender,self.options.quote,emaildata.subject,self.options.quote)
                            text = bullet + self.getWrappedText(text, self.options.maxwidth, len(bullet), self.options.linelimit)
                            output = output + "\n" + text

                else:
                    output = str(count)

            return output

        except Exception, e:
            self.logError("getOutputData:Unexpected error:" + traceback.format_exc())
            return "?"

    def getTemplateItemOutput(self, template_text):

        # keys to template data
        SERVERTYPE_KEY = "servertype"
        SERVERNAME_KEY = "servername"
        PORT_KEY = "port"
        FOLDER_KEY = "folder"
        SSL_KEY= "ssl"
        USERNAME_KEY = "username"
        PASSWORD_KEY = "password"
        CONNECTION_TIMEOUT_KEY = "connectiontimeout"
        MAILINFO_KEY = "mailinfo"

        servertype = self.options.servertype
        servername = None
        port = None
        folder = self.options.folder
        ssl = self.options.ssl
        username = None
        password = None
        connectiontimeout = self.options.connectiontimeout
        mailinfo = self.options.mailinfo

        for option in template_text.split('--'):
            if len(option) == 0 or option.isspace():
                continue

            # not using split here...it can't assign both key and value in one call, this should be faster
            x = option.find('=')
            if (x != -1):
                key = option[:x].strip()
                value = option[x + 1:].strip()
                if value == "":
                    value = None
            else:
                key = option.strip()
                value = None

            try:
                if key == SERVERTYPE_KEY:
                    servertype = value
                elif key == SERVERNAME_KEY:
                    servername = value
                elif key == PORT_KEY:
                    port = int(value)
                elif key == FOLDER_KEY:
                    folder = value
                elif key == SSL_KEY:
                    ssl = True
                elif key == USERNAME_KEY:
                    username = value
                elif key == PASSWORD_KEY:
                    password = value
                elif key == CONNECTION_TIMEOUT_KEY:
                    connectiontimeout = int(value)
                elif key == MAILINFO_KEY:
                    mailinfo = int(value)
                else:
                    self.logError("Unknown template option: " + option)

            except (TypeError, ValueError):
                self.logError("Cannot convert option argument to number: " + option)
                return u""

        if servername != None:
            return self.getOutputData(servertype,servername,port,folder,ssl,username,password,connectiontimeout,mailinfo)
        else:
            self.logError("Template item does not have servername defined")
            return u""


    def getOutputFromTemplate(self, template):
        output = u""
        end = False
        a = 0

        # a and b are indexes in the template string
        # moving from left to right the string is processed
        # b is index of the opening bracket and a of the closing bracket
        # everything between b and a is a template that needs to be parsed
        while not end:
            b = template.find('[', a)

            if b == -1:
                b = len(template)
                end = True

            # if there is something between a and b, append it straight to output
            if b > a:
                output += template[a : b]
                # check for the escape char (if we are not at the end)
                if template[b - 1] == '\\' and not end:
                    # if its there, replace it by the bracket
                    output = output[:-1] + '['
                    # skip the bracket in the input string and continue from the beginning
                    a = b + 1
                    continue

            if end:
                break

            a = template.find(']', b)

            if a == -1:
                self.logError("Missing terminal bracket (]) for a template item")
                return u""

            # if there is some template text...
            if a > b + 1:
                output += self.getTemplateItemOutput(template[b + 1 : a])

            a = a + 1

        return output

    def getEmailData(self,servername,folder,username,num,lines):

        try:
            self.logInfo("Processing email data to determine 'From', 'Subject' and 'Received Date'")

            sender = None
            subject = None
            recvdate = None
            messageid = None

            for line in lines:
                if sender is None and line.find("From: ") >= 0:
                    text = line.replace("From: ","").strip("\r ")
                    try:
                        text = self.decodeHeader(text)
                    except Exception, e:
                        sender = text
                        self.logError("getEmailData:Unexpected error when decoding sender:" + e.__str__())
                    sender = re.sub('<.*?@.*?>','',text).strip().lstrip('"').rstrip('"') # remove trailing email in <>
                    if sender is None:
                        sender = "Unknown"
                elif subject is None and line.find("Subject: ") >= 0:
                    text = line.replace("Subject: ","").strip("\r\" ")
                    try:
                        subject = self.decodeHeader(text)
                    except Exception, e:
                        subject = text
                        self.logError("getEmailData:Unexpected error when decoding subject:" + e.__str__())
                    if subject is None:
                        subject = "Unknown"
                elif recvdate is None and line.find("Date: ") >= 0:
                    text = line.replace("Date: ","").strip("\r ")
                    try:
                        matches = re.match(r"(.*\s)(\d{1,2}\s\w{3}\s\d{4}\s\d{1,2}:\d{1,2}:\d{1,2})(\s.*)"," "+text+" ") # intentional space at the front and back of text to allow for groups when missing
                        datetext = matches.group(2)
                        
                        #extract timezone (strptime not supported) and convert it to a timedelta and add to datetime                        
                        timezonetext = matches.group(3).strip(" ")
                        timezonediff = timedelta(hours=int(timezonetext[0:3])) + timedelta(minutes=int(timezonetext[3:5]))

                        recvdate = datetime.strptime(datetext,"%d %b %Y %H:%M:%S") + timezonediff
                       
                    except Exception, e:
                        recvdate = datetime.now()
                        self.logError("getEmailData:Unexpected error when converting receive date to datetime:" + e.__str__())
                elif messageid is None and line.find("Message-ID: ") >= 0:
                    text = line.replace("Message-ID: ","").strip("\r ")
                    messageid = text
                    if messageid is None:
                        messageid = 0

                if sender is not None and \
                   subject is not None and \
                   recvdate is not None and \
                   messageid is not None:
                    break

            if subject is None:
                subject = ""

            emaildata = EmailData(servername, folder, username, num, sender, subject, recvdate, messageid)

            return emaildata

        except Exception, e:
            self.logError("getEmailData:Unexpected error:" + traceback.format_exc())
            return None

    def getPOPEmailData(self,servername,port,folder,ssl,username,password,mailinfo):

        try:

            self.logInfo("Logging on to POP server: "+ servername)

            if port == None:
                if ssl == True:
                    pop = poplib.POP3_SSL(servername)
                else:
                    pop = poplib.POP3(servername)
            else:
                if ssl == True:
                    pop = poplib.POP3_SSL(servername, port)
                else:
                    pop = poplib.POP3(servername, port)

            pop.user(username)
            pop.pass_(password)

            self.logInfo("Getting message count from POP server: "+ servername)

            count = len(pop.list()[1])

            if count > 0 and mailinfo > 0:

                self.logInfo("Extracting message data from POP server \"%s\""%servername)

                self.emaillist = []

                for num in range(count):

                    if self.POP_FETCH_OPTION == "TOP":
                        lines = pop.top(num+1,1)[1]
                    else:
                        lines = pop.retr(num+1,1)[1] #more robust but sets message as seen!

                    emaildata = self.getEmailData(servername,folder,username,num,lines)

                    if emaildata is not None:
                        self.emaillist.append(emaildata)

            self.logInfo("Logging off from POP server: "+ servername)

            pop.quit()

            return count

        except Exception, e:
            self.logError("getPOPEmailData:Unexpected error:" + traceback.format_exc())
            return -1

    def getIMAPEmailData(self,servername,port,folder,ssl,username,password,mailinfo):

        try:

            self.logInfo("Logging on to IMAP server: "+ servername)

            if port == None:
                if ssl == True:
                    imap = imaplib.IMAP4_SSL(servername)
                else:
                    imap = imaplib.IMAP4(servername)
            else:
                if ssl == True:
                    imap = imaplib.IMAP4_SSL(servername, port)
                else:
                    imap = imaplib.IMAP4(servername, port)

            imap.login(username, password)

            self.logInfo("Searching for new mail on IMAP server \"%s\" in folder \"%s\""%(servername,folder))

            imap.select(folder)
            typ, data = imap.search(None, self.IMAP_SEARCH_OPTION)
            for item in data:
                if item == '':
                    data.remove(item)

            if data != None and len(data) > 0:
                nums = data[0].split()
                count = (len(nums))
            else:
                count = 0

            if count > 0 and mailinfo > 0:

                self.logInfo("Extracting message data for IMAP server: "+ servername)

                self.emaillist = []

                for num in nums:
                    typ, message = imap.fetch(num, '(BODY.PEEK[HEADER])')
                    lines = message[0][1].split("\n") # grab the content we want and split out lines

                    emaildata = self.getEmailData(servername,folder,username,num,lines)

                    if emaildata is not None:
                        self.emaillist.append(emaildata)

            self.logInfo("Logging of from IMAP server: "+ servername)

            imap.close()
            imap.logout()
            imap.shutdown()

            return count

        except Exception, e:
            self.logError("getIMAPEmailData:Unexpected error:" + traceback.format_exc())
            return -1

    def writeOutput(self):

        if self.options.template != None:
            #load the file
            try:
                fileinput = codecs.open(os.path.expanduser(self.options.template),encoding='utf-8')
                template = fileinput.read()
                fileinput.close()
            except Exception, e:
                self.logError("Error loading template file: " + e.__str__())
            else:
                output = self.getOutputFromTemplate(template)
        else:
            output = self.getOutputData(self.options.servertype,self.options.servername,self.options.port,self.options.folder,self.options.ssl,self.options.username,self.options.password,self.options.connectiontimeout,self.options.mailinfo)

        output = self.getMadeSafeOutput(output)

        print output.encode("utf-8")

    def decodeHeader(self,header_text):

        text,encoding = decode_header(header_text)[0]
        if encoding:
            try:
                return text.decode(encoding)
            except: # fallback on decode error to windows encoding as this may be introduced by sloppy mail clients
                return text.decode('cp1252')
        else:
            return text

    def getWrappedText(self,text,width=40,indent=0,linelimit=0):
        if len(text) > width:
            wrappedtext = ""
            indentchars = "".ljust(indent)
            linecount = 0
            lines = textwrap.wrap(text,width=width,expand_tabs=False,replace_whitespace=False,subsequent_indent=indentchars)
            for line in lines:
                linecount = linecount + 1
                if linelimit == 0 or linecount <= linelimit:
                    wrappedtext = wrappedtext + line + "\n"
                else:
                    break
            return wrappedtext.rstrip("\n ")
        else:
            return text

    def logInfo(self, text):
        if self.options.verbose == True:
            print >> sys.stdout, "INFO: " + text

        if self.options.infologfile != None:
            datetimestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            fileoutput = open(self.options.infologfile, "ab")
            fileoutput.write(datetimestamp+" INFO: "+text+"\n")
            fileoutput.close()

    def logError(self, text):
        print >> sys.stderr, "ERROR: " + text

        if self.options.errorlogfile != None:
            datetimestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            fileoutput = open(self.options.errorlogfile, "ab")
            fileoutput.write(datetimestamp+" ERROR: "+text+"\n")
            fileoutput.close()

    def getMadeSafeOutput(self, text):
        return text.replace("${exec","${!noexec!")

def main():

    parser = CommandLineParser()
    (options, args) = parser.parse_args()

    if options.version == True:

        print >> sys.stdout,"conkyEmail v.2.13"

    else:

        if options.verbose == True:
            print >> sys.stdout, "*** INITIAL OPTIONS:"
            print >> sys.stdout, "    servertype:",options.servertype
            print >> sys.stdout, "    servername:",options.servername
            print >> sys.stdout, "    port:",options.port
            print >> sys.stdout, "    folder:",options.folder
            print >> sys.stdout, "    ssl:",options.ssl
            print >> sys.stdout, "    username:",options.username
            print >> sys.stdout, "    password:",options.password
            print >> sys.stdout, "    template:",options.template
            print >> sys.stdout, "    mailinfo:",options.mailinfo
            print >> sys.stdout, "    maxwidth:",options.maxwidth
            print >> sys.stdout, "    linelimit:",options.linelimit
            print >> sys.stdout, "    quote:",options.quote
            print >> sys.stdout, "    verbose:",options.verbose
            print >> sys.stdout, "    errorlogfile:",options.errorlogfile
            print >> sys.stdout, "    infologfile:",options.infologfile

        # create new email info object
        emailinfo = EmailInfo(options)
        emailinfo.writeOutput()

if __name__ == '__main__':
    main()
    sys.exit()

Debian 12 Beardog, SoxDog and still a Conky 1.9er

Offline

#20 2017-09-13 20:25:11

tknomanzr
BL Die Hard
From: Around the Bend
Registered: 2015-09-29
Posts: 1,057

Re: [SOLVED] Mutt, receive notification on new email

^ Dang S11. That's awesome. I need to get my hands on those scripts and dissect them.

Offline

Board footer

Powered by FluxBB