1

I'm relatively new to Python (and development in general) so would appreciate any help that can be offered.

I've built a script which runs on my local machine, and I want to run it on my webserver if possible as a scheduled task.

The script checks for new emails in a dedicated email account, and if certain criteria are met against the subject, a textfile is appended with taskpaper formatted text, which I will have a workflow (iOS) setup to add these tasks into omnifocus.

I was originally getting the following error:

NameError: name 'email' is not defined

So I added 'import email', and now I get the following error:

subject = msg['subject'].split()
AttributeError
:
'NoneType' object has no attribute 'split'
End of script output before headers: omnifocus.py

I'm not sure where I'm going wrong, as it works locally but not on my server. I can set up a raspberry pi for this, but since I already pay for a webserver, would be great if it could run this for me.

My Code:

#! /bin/usr/python

import imaplib
import email

ORG_EMAIL   = "@xxx.com"
FROM_EMAIL  = "omnifocus" + ORG_EMAIL
FROM_PWD    = "xxxxxxxxxx"
SMTP_SERVER = "smtp.stackmail.com"
SMTP_PORT   = 993
IMAP_SERVER = 'imap.stackmail.com'

mail = imaplib.IMAP4_SSL(SMTP_SERVER)
mail.login(FROM_EMAIL,FROM_PWD)
mail.select('inbox')
type, data = mail.search(None, 'ALL')
mail_ids = data[0]
id_list = mail_ids.split()

result = []


for i in id_list:
    typ, data = mail.fetch(i, '(RFC822)' )
    msg = email.message_from_string(data[0][1].decode('utf-8'))
    subject = msg['subject'].split()


    if subject[-1] == 'Accepted':
        job_id = subject[-2]
        tp = 'Quote ' + job_id + ' Accepted @autodone(true)\n\t- Complete Site Report @due(5:00 pm) @tag(Work : Computer)\n\t\t' + 'http://xxxxxxx.com?ARGUMENTS=-ALITEJOBDETAIL&jobid=' + job_id
        result.append(tp)
    elif subject[-2] == 'Quote':
        job_id = subject[-1]
        tp = 'Quote ' + job_id + ' Sent @autodone(true)\n\t- 3 day follow up @due(3 days 5:00 pm) @tag(iPhone : Calls)\n\t\t' + 'http://xxxxxxx.com?ARGUMENTS=-ALITEJOBDETAIL&jobid=' + job_id + '\n\t- 7 day follow up @due(7 days 5:00 pm) @tag(iPhone : Calls)\n\t\t' + 'http://xxxxxxx.com?ARGUMENTS=-ALITEJOBDETAIL&jobid=' + job_id + '\n\t- 13 day follow up @due(13 days 5:00 pm) @tag(iPhone : Calls)\n\t\t' + 'http://xxxxxxx.com?PRGNAME=master&ARGUMENTS=-ALITEJOBDETAIL&jobid=' + job_id
        result.append(tp)

    # delete emails, deactivated during test stage
    #mail.store(i, '+FLAGS', '\\Deleted')

taskpaper = '\n'.join(result)

with open('taskpaper.txt', mode='a') as txt:
    f.write('\n' + taskpaper)
5
  • email package is probably missing on your env ... did you do pip install email or similar? Commented Jun 26, 2018 at 15:29
  • 1
    You can add a print statement to write to your console the value of the subject variable and the msg variable. This will tell you if something is getting messed up during the call to the email module and not returning you a valid msg variable. Commented Jun 26, 2018 at 15:29
  • @JozefCechovsky it is installed, or he won't get the import email statement to work. Commented Jun 26, 2018 at 15:37
  • Thanks All, unfortunately I can’t use pip to install new packages (shared hosting). @dfundako thanks for this tip, basic stuff to add to the knowledge bank, much appreciated. Commented Jun 28, 2018 at 0:32
  • Just to update, I ended up modifying the script and run it in Pythonista on my iPhone (rather than using this version on a server and parsing the text file created with Workflow). Ends up a simpler process, and most importantly, it works! I assume the issue is something is do with the locked down server missing a package, or potentially an issue with Python 2.7. I’m learning Python 3, however I realised afterwards my server is running 2.7, and as I have no experience with Python 2 I’m not confident my code is compliant with 2.7. Thanks for all your help! Commented Jun 28, 2018 at 0:39

1 Answer 1

1

Probably one of your messages had no Subject header, and thus wasn't able to get it. The Python documentation for email.message.Message states the subscription operator returns None if it's called with a non-existing header.

__getitem__(name)

Return the value of the named header field. name should not include the colon field separator. If the header is missing, None is returned; a KeyError is never raised.

Note that if the named field appears more than once in the message’s headers, exactly which of those field values will be returned is undefined. Use the get_all() method to get the values of all the extant named headers.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the response, but all emails had a subject line (three emails in the account, one for each condition in the if statement plus one that matched nothing) and the code runs fine on my Mac. I ended up modifying the script and running it in Pythonista on my phone (rather than using this in combination with workflow) simpler, and works perfectly! Thanks for your time suggestion though!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.