python imaplib – mark email as unread or unseen
Question:
Searching here and on the internet, there are a lot of examples to how to mark a message as SEEN, even though this is automatic with imap.
But how can I mark an email as UNSEEN
or UNREAD
.
I have a script in python which receives UNSEEN
messages, and it works great. But after reading them, imap automatically marks them as SEEN
which works fine but only if the script has no errors, because if it raises an exception, I want the email to be marked again as UNSEEN
, so next time the script will read that message again.
How can I achieved this?
I have also used mail.select(mail_label,readonly=True)
, but it doesn’t help because with that I cannot mark a message as SEEN
which I also need. I also want this to work with Gmail.
Answers:
You can easily clear the Seen
flags with this command:
tag UID STORE -FLAGS (Seen)
but your software will probably be more robost if you only set the Seen
flag in the first place after you have successfully processed a message. That way, if anything goes wrong while you are processing a message (even if the connection to the IMAP server is broken) the flag remains unset and you can retry that message the next time the script runs. You do this by avoiding the IMAP server’s automatic setting of the Seen
flag by using BODY.PEEK
instead of BODY
.
In Python, I think that STORE
command should be issued like this but I haven’t tried it.
connection.uid('STORE', '-FLAGS', '(Seen)')
In Python, the imaplib module describes STORE as:
(typ, [data]) = <instance>.store(message_set, command, flags)
so, the following line will let you set the message to READ (‘+FLAGS’) or UNREAD (‘-FLAGS’) as required.
connection.uid('STORE', MESSAGE_ID, '+FLAGS', 'SEEN')
As you see, the secrets is on the FLAGS command 😉
You may use imap_tools package:
https://pypi.org/project/imap-tools/
from imap_tools import MailBox, MailMessageFlags, A
with MailBox('imap.mail.com').login('[email protected]', 'pwd', 'INBOX') as mailbox:
# FLAG unseen messages in current folder as Answered and Flagged, *in bulk.
flags = (MailMessageFlags.ANSWERED, MailMessageFlags.FLAGGED)
mailbox.flag(mailbox.uids(A(seen=False)), flags, True)
# SEEN: mark all messages sent at 05.03.2007 in current folder as unseen, *in bulk
mailbox.flag(mailbox.uids("SENTON 05-Mar-2007"), MailMessageFlags.SEEN, False)
I am lib author.
`imap = imaplib.IMAP4_SSL(server)
imap.login(username, password)
imap.select("inbox", readonly=False)`
if readonly="True" you can’t change any flags.
But,if it is false, you can do as follow,
imap.store(id, '-FLAGS', 'Seen')
THEN EMAIL WILL MARK AS UNREAD
(-) means REMOVE flag and (+) means ADD flag.
ex:you can set imap.store(id, '+FLAGS', 'Deleted')
to delete email as well.
Like this you can set,any flag in below
Seen Message has been read
Answered Message has been answered
Flagged Message is "flagged" for urgent/special attention
Deleted Message is "deleted" for removal by later EXPUNGE
Draft Message has not completed composition (marked as a
draft).
More details :https://www.rfc-editor.org/rfc/rfc2060.html#page-9
I created an IMAP library, Red Box, which is quite intuitive to use for such cases.
Configure
First we configure the email box (read more about configuring):
from redbox import EmailBox
# Create email box instance
box = EmailBox(
host="imap.example.com",
port=993,
username="[email protected]",
password="<PASSWORD>"
)
# Select an email folder
inbox = box["INBOX"]
Search Messages
Then we search for an email (read more about querying):
from redbox.query import SUBJECT
msgs = inbox.search(SUBJECT("Example email"))
msg = msgs[0]
Set Flags
Then we set flags:
# Set Seen flag
msg.read()
# Remove Seen flag
msg.unread()
Alternatively you can use set
method:
# Set Seen flag
msg.set(seen=True)
# Remove Seen flag
msg.set(seen=False)
Read more about messages here.
Relevant links:
Searching here and on the internet, there are a lot of examples to how to mark a message as SEEN, even though this is automatic with imap.
But how can I mark an email as UNSEEN
or UNREAD
.
I have a script in python which receives UNSEEN
messages, and it works great. But after reading them, imap automatically marks them as SEEN
which works fine but only if the script has no errors, because if it raises an exception, I want the email to be marked again as UNSEEN
, so next time the script will read that message again.
How can I achieved this?
I have also used mail.select(mail_label,readonly=True)
, but it doesn’t help because with that I cannot mark a message as SEEN
which I also need. I also want this to work with Gmail.
You can easily clear the Seen
flags with this command:
tag UID STORE -FLAGS (Seen)
but your software will probably be more robost if you only set the Seen
flag in the first place after you have successfully processed a message. That way, if anything goes wrong while you are processing a message (even if the connection to the IMAP server is broken) the flag remains unset and you can retry that message the next time the script runs. You do this by avoiding the IMAP server’s automatic setting of the Seen
flag by using BODY.PEEK
instead of BODY
.
In Python, I think that STORE
command should be issued like this but I haven’t tried it.
connection.uid('STORE', '-FLAGS', '(Seen)')
In Python, the imaplib module describes STORE as:
(typ, [data]) = <instance>.store(message_set, command, flags)
so, the following line will let you set the message to READ (‘+FLAGS’) or UNREAD (‘-FLAGS’) as required.
connection.uid('STORE', MESSAGE_ID, '+FLAGS', 'SEEN')
As you see, the secrets is on the FLAGS command 😉
You may use imap_tools package:
https://pypi.org/project/imap-tools/
from imap_tools import MailBox, MailMessageFlags, A
with MailBox('imap.mail.com').login('[email protected]', 'pwd', 'INBOX') as mailbox:
# FLAG unseen messages in current folder as Answered and Flagged, *in bulk.
flags = (MailMessageFlags.ANSWERED, MailMessageFlags.FLAGGED)
mailbox.flag(mailbox.uids(A(seen=False)), flags, True)
# SEEN: mark all messages sent at 05.03.2007 in current folder as unseen, *in bulk
mailbox.flag(mailbox.uids("SENTON 05-Mar-2007"), MailMessageFlags.SEEN, False)
I am lib author.
`imap = imaplib.IMAP4_SSL(server)
imap.login(username, password)
imap.select("inbox", readonly=False)`
if readonly="True" you can’t change any flags.
But,if it is false, you can do as follow,
imap.store(id, '-FLAGS', 'Seen')
THEN EMAIL WILL MARK AS UNREAD
(-) means REMOVE flag and (+) means ADD flag.
ex:you can set imap.store(id, '+FLAGS', 'Deleted')
to delete email as well.
Like this you can set,any flag in below
Seen Message has been read
Answered Message has been answered
Flagged Message is "flagged" for urgent/special attention
Deleted Message is "deleted" for removal by later EXPUNGE
Draft Message has not completed composition (marked as a
draft).
More details :https://www.rfc-editor.org/rfc/rfc2060.html#page-9
I created an IMAP library, Red Box, which is quite intuitive to use for such cases.
Configure
First we configure the email box (read more about configuring):
from redbox import EmailBox
# Create email box instance
box = EmailBox(
host="imap.example.com",
port=993,
username="[email protected]",
password="<PASSWORD>"
)
# Select an email folder
inbox = box["INBOX"]
Search Messages
Then we search for an email (read more about querying):
from redbox.query import SUBJECT
msgs = inbox.search(SUBJECT("Example email"))
msg = msgs[0]
Set Flags
Then we set flags:
# Set Seen flag
msg.read()
# Remove Seen flag
msg.unread()
Alternatively you can use set
method:
# Set Seen flag
msg.set(seen=True)
# Remove Seen flag
msg.set(seen=False)
Read more about messages here.
Relevant links: