Reputation: 21
I am working on an application to sort my emails for me. It logs into the IMAP server, performs some searches, then copies items to folders and flags them for deletion from the Inbox.
Some of my folders have names with spaces in them.
The POC worked fine, but was not "quality" code. The rules were hard-coded into an array of tuples. Each tuple was a rule, consisting of a field to search, a string to search for, and the folder the matching emails should end up in. All of the rules work, but maintainability and code quality are . . . low.
The first post-POC version uses a SQLite database to store the rules (and some other things not really relevant to the problem). When it hits a rule with a space in the destination folder, it ends up sending the COPY command to the server truncated at the space. I'm assuming that it somehow got the impression that it wasn't supposed to quote that.
The part that is baking my noodle is this: In both cases, the rule is assigned to a variable from some source. The only difference is that in one case, the source is a database; in the other, it is a hard-coded array.
Where do I even start to unravel this?
Edited to add some example code:
This works (Assume M is an imaplib.IMAP4 instance and that it is connected and logged in):
rules = [
("FROM", "[email protected]", "Vendors/Insurance Company"),
("SUBJECT", "[CDLUG]", "Mailing lists/CDLUG")
]
. . .
for rule in rules:
field, value, target = rule
status, detail = M.search(None, field, value)
for id in result[0].split():
status, deatail = M.copy(id, target)
if (status == "OK"):
M.store(id, "+FLAGS", "\\Deleted")
M.expunge()
Now, if I put those tuples into a table in a sqlite database, and change the code to look like this, it will fail when it hits a folder name with a space:
dbi = sqlite3.connect("/home/pi/.mailsort/mailsort.db")
cursor = dbi.cursor()
cursor.execute("Select field, searchstring, destination from rule")
for result in cursor:
field, searchstring, destination = result
print field, searchstring, destination
status, result = M.search(None, field, searchstring)
for msgid in result[0].split():
print "Copying message", msgid
status, detail = M.copy(msgid, destination)
if (status == "OK"):
M.store(id, "+FLAGS", "\\Deleted")
M.expunge()
Upvotes: 2
Views: 2441
Reputation: 1330
The comment imaplib and folders with spaces from @jlh did the job for me.
Using spaces requires to quote the folder name in double quotes.
# delete a folder with a space inside
conn.delete("\"old folder\"")
The same applies also for searching messages with queries containing spaces:
# search messages with a specific subject containing spaces
conn.select(mailbox='INBOX', readonly=True)
typ, msgnums = conn.search(None, 'SUBJECT', "\"Subject with spaces\"")
Upvotes: 5