Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.6k views
in Technique[技术] by (71.8m points)

email - Python imaplib can't select() custom gmail labels

I have a bot I'm writing using imaplib in python to fetch emails from gmail and output some useful data from them. I've hit a snag on selecting the inbox, though; the existing sorting system uses custom labels to separate emails from different customers. I've partially replicated this system in my test email, but imaplib.select() throws a "imaplib.IMAP4.error: SELECT command error: BAD [b'Could not parse command']" with custom labels. Screenshot attatched My bot has no problem with the default gmail folders, fetching INBOX or [Gmail]/Spam. In that case, it hits an error later in the code that deals with completely different problem I have yet to fix. The point, though, is that imaplib.select() is succsessful with default inboxes and just not custom labels.

The way my code works is it works through all the available inboxes, compares it to a user-inputted name, and if they match, saves the name and sets a boolean to true to signal that it found a match. It then checks, if there was a match (the user-inputted inbox exists) it goes ahead, otherwise it throws an error message and resets. It then attempts to select the inbox the user entered.

I've verified that the variable the program's saving the inbox name to matches what's listed as the name in the imap.list() command. I have no idea what the issue is.

I could bypass the process by iterating through all mail to find the email's I'm looking for, but it's far more efficient to use the existing sorting system due to the sheer number of emails on the account I'll be using.

Any help is appreciated!

EDIT: Code attached after request. Thank you to the person who told me to do so.

'''
Fetches emails from the specified inbox and outputs them to a popup
'''
def fetchEmails(self):
    #create an imap object. Must be local otherwise we can only establish a single connection
    #imap states are kinda bad
    imap = imaplib.IMAP4_SSL(host="imap.gmail.com", port="993")
    #Login and fetch a list of available inboxes
    imap.login(username.get(), password.get())
    type, inboxList = imap.list()
        
    #Set a reference boolean and iterate through the list
    inboxNameExists = False
    for i in inboxList:
        #Finds the name of the inbox
        name = self.inboxNameParser(i.decode())
            
        #If the given inbox name is encountered, set its existence to true and break
        if name.casefold().__eq__(inboxName.get().casefold()):
            inboxNameExists = True
            break
        
        #If the inbox name does not exist, break and give error message
        if inboxNameExists != True:
            self.logout(imap)
            tk.messagebox.showerror("Disconnected!", "That Inbox does not exist.")
            return
        
    '''
    If/else to correctly feed the imap.select() method the inbox name
    Apparently inboxes containing spaces require quoations before and after
        
    Selects the inbox and pushes it to a variable
    two actually but the first is unnecessary(?)
    imap is weird
    '''
    if(name.count(" ") > 0):
        status, messages = imap.select(""" + name + """)
    else:
        status, messages = imap.select(name);
    
    #Int containing total number of emails in inbox
    messages = int(messages[0])
        
    #If there are no messages disconnect and show an infobox
    if messages == 0:
        self.logout(imap)
        tk.messagebox.showinfo("Disconnected!", "The inbox is empty.")
        
    self.mailboxLoop(imap, messages)

Figured the issue out after a few hours banging through it with a friend. As it turns out the problem was that imap.select() wants quotations around the mailbox name if it contains spaces. So imap.select("INBOX") is fine, but with spaces you'd need imap.select(""" + "Label Name" + """)

You can see this reflected in the code I posted with the last if/else statement.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Python imaplib requires mailbox names with spaces to be surrounded by apostrophes. So imap.select("INBOX") is fine, but with spaces you'd need imap.select(""" + "Label Name" + """).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...