Suggestions on programming in Python an email simple client

MRAB python at mrabarnett.plus.com
Tue Feb 13 18:35:15 EST 2018


On 2018-02-13 22:54, Maroso Marco wrote:
> Il giorno martedì 13 febbraio 2018 21:18:37 UTC+1, Chris Angelico ha scritto:
>> On Wed, Feb 14, 2018 at 7:05 AM, Maroso Marco <androidmaroso at gmail.com> wrote:
>> > Hi,
>> >
>> > what i'm trying to do is develop my own email client, but a simple one.
>> >
>> > I just want it to connect to a specific email account and read the subject line of messages coming from a certain email address.
>> >
>> > I then want it to be able to execute the command i wrote on the subject.
>> 
>> Be aware that "from" addresses can easily be forged. I suggest
>> whitelisting a set of valid commands and executing only those. If you
>> want a REAL way to manage your home system remotely, I would recommend
>> SSH instead.
>> 
>> > It would be nice if i could specify two parameters on the subject line
>> >
>> > first : password;
>> > second : command;
>> >
>> > The first parameter is the password and the second is the command to be executed in the local pc where this program is running.
>> 
>> That's an improvement, but since the password is being transmitted in
>> clear text, it won't prevent attacks. It does mean you won't try to
>> execute the subject lines of random spam, though, so accidents will be
>> reduced (or eliminated).
>> 
>> > The program will have to show only email coming from a specific account
>> > and if the mail is unread then it should read the subject line and find parameters.
>> > The first parameter must match my hardcoded password, and the second parameter must be executed on the local pc (example ... c:\windows\notepad.exe)
>> >
>> > It must check for new emails at a given timing (example ...every 30 seconds )
>> >  (the timing can be hardcoded or specified in a separate file)
>> >
>> > This is it.
>> >
>> > Any suggestions?
>> 
>> Seems perfectly possible.
>> 
>> > I have started doing this (but i never programmed in python before):
>> >
>> >
>> > import imaplib
>> > import os
>> > import email
>> > import email.header
>> >
>> > plusmail = "emailaddresstobechecked at gmail.com"
>> > googlepass = "mypassword"
>> > owner = "validsender at gmail.com"
>> >
>> > M = imaplib.IMAP4_SSL('imap.gmail.com')
>> > M.login(plusmail, googlepass)
>> > M.select()
>> >
>> > status, response = M.search(None, '(UNSEEN)')
>> > unread_msg_nums = response[0].split()
>> >
>> > # Print the count of all unread messages
>> > print (len(unread_msg_nums))
>> >
>> > # Print all unread messages from a certain sender of interest
>> > status, response = M.search(None, '(UNSEEN)', '(FROM "%s")' % (owner))
>> > unread_msg_nums = response[0].split()
>> > da = []
>> > for e_id in unread_msg_nums:
>> >     _, response = imap.fetch(e_id, '(BODY.PEEK[HEADER.FIELDS (From Subject)] RFC822.SIZE)')
>> >     da.append(response[0][1])
>> > # print (da)
>> >
>> > # Mark them as seen
>> > for e_id in unread_msg_nums:
>> >     imap.store(e_id, '+FLAGS', '\Seen')
>> >
>> >
>> >
>> > typ, data = M.search(None, 'From',(owner))
>> > for num in data[0].split():
>> >     typ, data = M.fetch(num, '(RFC822)')
>> >     print ('Message %s\n%s\n' % (num, data[0][1]))
>> > M.close()
>> > M.logout()
>> >
>> > I know there are duplicates but i need to figure out how to build this correctly
>> 
>> Seems like a reasonable start. So what's the code doing wrong, or
>> failing to do? Is it failing with an exception? Is it running
>> successfully, but not doing something you want it to do?
>> 
>> ChrisA
> 
> Hi Chris and thanks for replying.
> 
> I came up with the following code (thanks for the security suggestions-i'm just testing) :
> 
> My code actually works fine allthough i have a couple of problems :
> 
> 1 - once parced the messages and executed the command in the subject line, it keeps looping even if i told to only execute on unread messages
> 2 - it loops continuosly instead of waiting the correct wait time
> 3 - i had to add a delete statement so that the program stops looping at least on processing the commands.
> 
> Can you help me sort out the issue? Maybe it's an indent problem!
> 
> 
> Here is the code :
> 
> import imaplib
> import os
> import email
> import email.header
> import time
> 
> def mailcontroller():
>      
>      # Set user, pass and allowed mail for giving commands
>      plusmail = "emailaddresstobechecked at gmail.com"
>      googlepass = "thesecretpassword"
>      captain = "theallowedemailaddress at gmail.com"
> 
>      # Set vars for IMAP access
>      M = imaplib.IMAP4_SSL('imap.gmail.com')
>      M.login(plusmail, googlepass)
>      M.select()
> 
>      # Set search on UNSEEN messages
>      status, response = M.search(None, '(UNSEEN)')
>      unread_msg_nums = response[0].split()
> 
> 
>      # Mark as read
>      for e_id in unread_msg_nums:
>          M.store(e_id, '+FLAGS', '\Seen')
> 
Here you iterate through all of the messages:

>      # cycle messages sent from autorized email address
>      typ, data = M.search(None, 'From',(captain))
>      for num in data[0].split():
>          typ, data = M.fetch(num, '(RFC822)')
>          msg = email.message_from_string(data[0][1])
>          decode = email.header.decode_header(msg['Subject'])[0]
>          subject = unicode(decode[0])
>          comando = subject
> 
These lines are indented the same as the 'for' loop above, so they'll 
executed only the last message. If there are no messages, 'subject' 
won't be defined.

>      if googlepass in subject:
>          print 'Message %s: %s' % (num, subject)
>          
>          # Split subject line
>          googlepass,comando = subject.split(";")
>          # Print command
>          print comando
>          # Execute command
>          os.system(comando)
> 
>          M.store(num, '+FLAGS', '\\Deleted')

There's no need to use 'expunge' here because those messages that are 
marked for deletion will be expunged anyway when the mailbox is closed:

>          M.expunge()
>          
Why not just "else:" here?

>      elif googlepass not in subject:
>          print "Nope"
> 
>          M.close()
>          M.logout()
> 
Actually, the sequence should be more like:

     login
     for each message:
         execute if necessary
     close and logout

> 
> time.sleep(10)
> 
> while True:
>      mailcontroller()
> 
It should really be sleeping between calls.

> THanks in advance  :-)
> 



More information about the Python-list mailing list