Script to mark Gmail as read

1,005 views
Skip to first unread message

bdanders

unread,
Mar 27, 2013, 9:37:44 AM3/27/13
to tas...@googlegroups.com
With the recent update to the Gmail app you are now able to reply and delete a message directly from the expanded notification. Many of the messages I get are short and easily read from the notification itself, so I would like to be able to mark the message as read from the notification without having to go into the app. Hopefully the big G can add this functionality to a future iteration of the app, but until then, I've come up with my own solution using Tasker and SL4A scripts

I have Tasker create a notification whenever I get an email that simply says "Mark as read". When I click that notification it runs the following python script in SL4A. You must pass the variables %gm_user, %gm_pw, and %gm_subject to the script as your gmail username (user...@gmail.com), password, and the subject of the message you are marking. The subject can be retrieved through a sqlite database search using Tasker shell commands. There's a thread in here on that process already. One thing to note is that the gmail imap service uses the same search rules as the regular gmail search, so certain characters have to be removed from the subject line. For example I use a regex search and replace to get rid of 's in the subjects.

For most of my SL4A scripts I have some code to set the Tasker variable "%SL4A_Response" to some kind of useful message for the purpose of troubleshooting.

Several bits of what follows are surely borrowed from other people's work, but I've forgotten who and what now. Sorry if I'm using your code without proper credit.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
import imaplib
import android
droid=android.Android()
import time
import datetime

class Task():
    SET_VARIABLE = 547
    def new_task(self):
        self.action_cnt = 0
        self.extras = {'version_number': '1.0', 'task_name': 'task' + str(time.time()), 'task_priority': 9 }
    def set_var(self, varname, value):
        self.action_cnt += 1
        self.extras['action' + str(self.action_cnt)] = {'action': self.SET_VARIABLE, 'arg:1': varname, 'arg:2': value, 'arg:3': False, 'arg:4': False, 'arg:5': False}
    def run_task(self):
        taskIntent = droid.makeIntent('net.dinglisch.android.tasker.ACTION_TASK', None, None, self.extras).result
        droid.sendBroadcastIntent(taskIntent)
    def set_var_now(self, varname, value):
        self.new_task()
        self.set_var(varname, value)
        self.run_task()

try:
  gm_user = droid.getIntent().result[u'extras'][u'%gm_user']
  gm_pw = droid.getIntent().result[u'extras'][u'%gm_pw']
  gm_subject = droid.getIntent().result[u'extras'][u'%gm_subject']
  mail = imaplib.IMAP4_SSL('imap.gmail.com')
  mail.login(gm_user, gm_pw)
  mail.select("inbox")
  date = (datetime.date.today() - datetime.timedelta(1)).strftime("%d-%b-%Y")
  search_string = '(SENTSINCE {date} HEADER Subject "' + gm_subject + '")'
  typ, data = mail.search(None, search_string.format(date=date))
  if len(data[0])>0:
    mail.store(data[0].replace(' ',','),'+FLAGS','\Seen')
    droid.makeToast('Mail Marked as Read: ' + gm_subject)
    t = Task()
    t.set_var_now("%SL4A_Response", 'SL4A GMail: Message Marked as Read (' + gm_subject + ')')
  else:
    droid.makeToast('Mail Not Found')
    t = Task()
    t.set_var_now("%SL4A_Response", 'SL4A GMail: Mail Not Found (' + gm_subject + ')')
except Exception, e:
  t = Task()
  t.set_var_now("%SL4A_Response", 'SL4A GMail Message Error: ' + str(e)) 

bdanders

unread,
Apr 12, 2013, 4:01:44 PM4/12/13
to tas...@googlegroups.com
Gmail's imap search seems to have trouble handling ampersands, so I use the following regex search to get rid of any words that contain one. It also removes leading/trailing whitespace as well as "'s" and exclamations, which I read somewhere can also cause problems.

^[\t]+|[\t]+$|[^\s\\]*[&][^\s\\]*|!|'s|

Another thing I've added at the end of my routine is to call the Synker plugin to Sync gmail after the mail has been marked as read. This automatically clears the Gmail notification without even having to swipe it away.

bdanders

unread,
Jun 11, 2013, 9:00:56 AM6/11/13
to tas...@googlegroups.com
Another slight improvement I just added is to use a search and replace to get rid of all words that contain non-ASCII characters, as this causes problems in the script. The regex that I'm using to match that is:
([a-zA-Z]?)+[^\x00-\x7F]([a-zA-Z]?)+

I've also added '$' to the previously mentioned regex because apparently that is troublesome for gmail's search. So that regex pattern is now:
^[\t]+|[\t]+$|[^\s\\]*[&][^\s\\]*|!|'s|\$

easiuser

unread,
Jul 12, 2013, 3:29:35 PM7/12/13
to tas...@googlegroups.com
I created a task that sets the three variables and then calls the script.  For some reason it worked on one email but could not get it to work on others.  The subjects do not contain an & or non-ascii characters.

Also, where do you use the regex you mentioned in this post?

bdanders

unread,
Jul 12, 2013, 3:47:55 PM7/12/13
to tas...@googlegroups.com
Well, it's encouraging that you got it to work at least once. Are there any special characters at all in the subject line that you're searching? I use the regex in a tasker "Variable Search Replace" action on the %gm_subject variable before sending it to the script. Try flashing the %gm_subject variable to make sure that it looks right. Is the %SL4A_Response variable getting set with an error code?

Oh, and another slight improvement on the 'non-ASCII' regex: ([\x21-\x7E]?)+[^\x00-\x7F]([\x21-\x7E]?)+
I noticed that the previous version wouldn't catch words that had multiple non-ASCII characters.

One more thing, the line in there that says date = (datetime.date.today() - datetime.timedelta(1)).strftime("%d-%b-%Y") means that it will only search for messages sent within the last day, so if you're testing on older messages it won't find them. You can change the timedelta value to something larger if you want.

easiuser

unread,
Jul 12, 2013, 6:05:09 PM7/12/13
to tas...@googlegroups.com
It was the date thing. Works great. Thanks.

easiuser

unread,
Jul 19, 2013, 12:12:56 PM7/19/13
to tas...@googlegroups.com
bdanders thanks again for the script.

UPDATE:  The script works but I will sometimes I get an SL4A has stopped working popup.  I will check immediately after and the message was marked as read.  It seems to happen at least 50% of the time.  I have the latest versions of SL4a and Python.  Any Ideas?

bdanders

unread,
Jul 19, 2013, 1:21:27 PM7/19/13
to tas...@googlegroups.com
No idea. I get that sometimes too. Unfortunately I'm really not a Python programmer, I just figured out enough to make this work. I don't know if it's a problem with the script or with SL4A. I can't even really tell what conditions cause it. It's pretty intermittent for me though. I've just been living with it, although it seems to happen way less than 50% for me. I suspect it's an SL4A problem though because I've seen it happen with some other scripts too.

Matt R

unread,
Jul 19, 2013, 1:32:40 PM7/19/13
to tas...@googlegroups.com
I've experienced similar problems. It's made me avoid SL4A just because of it's unreliability, and that it doesn't run well in the background or when the screen is locked. Glad it's not just me.

Matt

easiuser

unread,
Jul 19, 2013, 3:09:56 PM7/19/13
to tas...@googlegroups.com
I am running it in the background most of the time which is probably why.  I don't know a thing about Python or Javascript.  Could this possibly be done in Javascript?  That seems to be much more stable and you don't have to install additional apps.

Side note:  I did try to manipulate gmail's sql database and it worked until I synced back up and then the messages appeared as unread again.

Chris Dock

unread,
Jun 22, 2015, 12:44:01 AM6/22/15
to tas...@googlegroups.com
This looks great - precisely what I'm looking for. However, I recently switched to the Droid Turbo which hasn't really been rooted yet. Does this require root? 

Thanks 
Reply all
Reply to author
Forward
0 new messages