简体   繁体   English

python imaplib获取gmail收件箱主题标题和发件人姓名

[英]python imaplib to get gmail inbox subjects titles and sender name

I'm using pythons imaplib to connect to my gmail account.我正在使用 pythons imaplib 连接到我的 gmail 帐户。 I want to retrieve the top 15 messages (unread or read, it doesn't matter) and display just the subjects and sender name (or address) but don't know how to display the contents of the inbox.我想检索前 15 条消息(未读或已读,无关紧要)并仅显示主题和发件人姓名(或地址),但不知道如何显示收件箱的内容。

Here is my code so far (successful connection)到目前为止,这是我的代码(连接成功)

import imaplib

mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('mygmail@gmail.com', 'somecrazypassword')
mail.list()
mail.select('inbox')

#need to add some stuff in here

mail.logout()

I believe this should be simple enough, I'm just not familiar enough with the commands for the imaplib library.我相信这应该足够简单,我只是对 imaplib 库的命令不够熟悉。 Any help would be must appreciated...必须感谢任何帮助......

UPDATE thanks to Julian I can iterate through each message and retrieve the entire contents with:更新感谢 Julian 我可以遍历每条消息并检索整个内容:

typ, data = mail.search(None, 'ALL')
for num in data[0].split():
   typ, data = mail.fetch(num, '(RFC822)')
   print 'Message %s\n%s\n' % (num, data[0][1])
mail.close()

but I'm wanting just the subject and the sender.但我只想要主题和发件人。 Is there a imaplib command for these items or will I have to parse the entire contents of data[0][1] for the text: Subject, and Sender?是否有针对这些项目的 imaplib 命令,或者我是否必须为文本解析 data[0][1] 的全部内容:主题和发件人?

UPDATE OK, got the subject and sender part working but the iteration (1, 15) is done by desc order apparently showing me the oldest messages first.更新好的,让主题和发件人部分正常工作,但迭代 (1, 15) 是按 desc 顺序完成的,显然首先向我显示了最旧的消息。 How can I change this?我怎样才能改变这个? I tried doing this:我尝试这样做:

for i in range( len(data[0])-15, len(data[0]) ):
     print data

but that just gives me None for all 15 iterations... any ideas?但这只是给了我所有 15 次迭代都None ……有什么想法吗? I've also tried mail.sort('REVERSE DATE', 'UTF-8', 'ALL') but gmail doesnt support the .sort() function我也试过mail.sort('REVERSE DATE', 'UTF-8', 'ALL')但 gmail 不支持 .sort() 函数

UPDATE Figured out a way to do it:更新想出了一种方法来做到这一点:

#....^other code is the same as above except need to import email module
mail.select('inbox')
typ, data = mail.search(None, 'ALL')
ids = data[0]
id_list = ids.split()
#get the most recent email id
latest_email_id = int( id_list[-1] )

#iterate through 15 messages in decending order starting with latest_email_id
#the '-1' dictates reverse looping order
for i in range( latest_email_id, latest_email_id-15, -1 ):
   typ, data = mail.fetch( i, '(RFC822)' )

   for response_part in data:
      if isinstance(response_part, tuple):
          msg = email.message_from_string(response_part[1])
          varSubject = msg['subject']
          varFrom = msg['from']

   #remove the brackets around the sender email address
   varFrom = varFrom.replace('<', '')
   varFrom = varFrom.replace('>', '')

   #add ellipsis (...) if subject length is greater than 35 characters
   if len( varSubject ) > 35:
      varSubject = varSubject[0:32] + '...'

   print '[' + varFrom.split()[-1] + '] ' + varSubject

this gives me the most recent 15 message subject and sender address in decending order as requested!这给了我最近的 15 个消息主题和发件人地址,按要求按降序排列! Thanks to all who helped!感谢所有帮助过的人!

    c.select('INBOX', readonly=True)

    for i in range(1, 30):
        typ, msg_data = c.fetch(str(i), '(RFC822)')
        for response_part in msg_data:
            if isinstance(response_part, tuple):
                msg = email.message_from_string(response_part[1])
                for header in [ 'subject', 'to', 'from' ]:
                    print '%-8s: %s' % (header.upper(), msg[header])

This should give you an idea on how to retrieve the subject and from?这应该让您了解如何检索主题?

For those looking for how to check mail and parse the headers, this is what I used:对于那些正在寻找如何检查邮件和解析标题的人,这就是我使用的:

def parse_header(str_after, checkli_name, mailbox) :
    #typ, data = m.search(None,'SENTON', str_after)
    print mailbox
    m.SELECT(mailbox)
    date = (datetime.date.today() - datetime.timedelta(1)).strftime("%d-%b-%Y")
    #date = (datetime.date.today().strftime("%d-%b-%Y"))
    #date = "23-Jul-2012"

    print date
    result, data = m.uid('search', None, '(SENTON %s)' % date)
    print data

    doneli = []
    for latest_email_uid in data[0].split():
        print latest_email_uid
        result, data = m.uid('fetch', latest_email_uid, '(RFC822)')
        raw_email = data[0][1]

        import email
        email_message = email.message_from_string(raw_email)
        print email_message['To']
        print email_message['Subject']
        print email.utils.parseaddr(email_message['From'])
        print email_message.items() # print all headers

This was my solution to get the useful bits of information from emails:这是我从电子邮件中获取有用信息的解决方案:

import datetime
import email
import imaplib
import mailbox


EMAIL_ACCOUNT = "your@gmail.com"
PASSWORD = "your password"

mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login(EMAIL_ACCOUNT, PASSWORD)
mail.list()
mail.select('inbox')
result, data = mail.uid('search', None, "UNSEEN") # (ALL/UNSEEN)
i = len(data[0].split())

for x in range(i):
    latest_email_uid = data[0].split()[x]
    result, email_data = mail.uid('fetch', latest_email_uid, '(RFC822)')
    # result, email_data = conn.store(num,'-FLAGS','\\Seen') 
    # this might work to set flag to seen, if it doesn't already
    raw_email = email_data[0][1]
    raw_email_string = raw_email.decode('utf-8')
    email_message = email.message_from_string(raw_email_string)

    # Header Details
    date_tuple = email.utils.parsedate_tz(email_message['Date'])
    if date_tuple:
        local_date = datetime.datetime.fromtimestamp(email.utils.mktime_tz(date_tuple))
        local_message_date = "%s" %(str(local_date.strftime("%a, %d %b %Y %H:%M:%S")))
    email_from = str(email.header.make_header(email.header.decode_header(email_message['From'])))
    email_to = str(email.header.make_header(email.header.decode_header(email_message['To'])))
    subject = str(email.header.make_header(email.header.decode_header(email_message['Subject'])))

    # Body details
    for part in email_message.walk():
        if part.get_content_type() == "text/plain":
            body = part.get_payload(decode=True)
            file_name = "email_" + str(x) + ".txt"
            output_file = open(file_name, 'w')
            output_file.write("From: %s\nTo: %s\nDate: %s\nSubject: %s\n\nBody: \n\n%s" %(email_from, email_to,local_message_date, subject, body.decode('utf-8')))
            output_file.close()
        else:
            continue

I was looking for a ready made simple script to list last inbox via IMAP without sorting through all messages.我正在寻找一个现成的简单脚本来通过 IMAP 列出最后一个收件箱,而无需对所有邮件进行排序。 The information here is useful, though DIY and misses some aspects.这里的信息很有用,虽然 DIY 并错过了一些方面。 First, IMAP4.select returns message count.首先, IMAP4.select返回消息计数。 Second, subject header decoding isn't straightforward.其次,主题标头解码并不简单。

#! /usr/bin/env python
# -*- coding: utf-8 -*-


import imaplib
import email
from email.header import decode_header
import HTMLParser


# to unescape xml entities
_parser = HTMLParser.HTMLParser()

def decodeHeader(value):
  if value.startswith('"=?'):
    value = value.replace('"', '')

  value, encoding = decode_header(value)[0]
  if encoding:
    value = value.decode(encoding)

  return _parser.unescape(value)

def listLastInbox(top = 4):
  mailbox = imaplib.IMAP4_SSL('imap.gmail.com')
  mailbox.login('mygmail@gmail.com', 'somecrazypassword')

  selected = mailbox.select('INBOX')
  assert selected[0] == 'OK'
  messageCount = int(selected[1][0])

  for i in range(messageCount, messageCount - top, -1):
    reponse = mailbox.fetch(str(i), '(RFC822)')[1]
    for part in reponse:
      if isinstance(part, tuple):
        message = email.message_from_string(part[1])
        yield {h: decodeHeader(message[h]) for h in ('subject', 'from', 'date')}

  mailbox.logout()


if __name__ == '__main__':
  for message in listLastInbox():
    print '-' * 40
    for h, v in message.items():
      print u'{0:8s}: {1}'.format(h.upper(), v)

Adding to all the above answers.补充以上所有答案。

import imaplib
import base64
import os
import email

if __name__ == '__main__':
    email_user = "email@domain.com"
    email_pass = "********"
    mail = imaplib.IMAP4_SSL("hostname", 993)
    mail.login(email_user, email_pass)
    mail.select()
    type, data = mail.search(None, 'ALL')
    mail_ids = data[0].decode('utf-8')
    id_list = mail_ids.split()
    mail.select('INBOX', readonly=True)
    for i in id_list:
        typ, msg_data = mail.fetch(str(i), '(RFC822)')
        for response_part in msg_data:
            if isinstance(response_part, tuple):
                msg = email.message_from_bytes(response_part[1])
                print(msg['from']+"\t"+msg['subject'])

This will give you the email's from and subject name.这将为您提供电子邮件的发件人和主题名称。

BODY gets almost everything and marks the message as read. BODY获取几乎所有内容并将消息标记为已读。 BODY[<parts>] gets just those parts. BODY[<parts>]只获取那些部分。 BODY.PEEK[<parts>] gets the same parts, but doesn't mark the message read. BODY.PEEK[<parts>]获取相同的部分,但不标记消息已读。 <parts> can be HEADER or TEXT or HEADER.FIELDS (<list of fields>) or HEADER.FIELDS.NOT (<list of fields>) <parts>可以是HEADERTEXTHEADER.FIELDS (<list of fields>)HEADER.FIELDS.NOT (<list of fields>)

This is what I use: typ, data = connection.fetch(message_num_s, b'(BODY.PEEK[HEADER.FIELDS (SUBJECT FROM)])')这是我使用的: typ, data = connection.fetch(message_num_s, b'(BODY.PEEK[HEADER.FIELDS (SUBJECT FROM)])')

` `

def safe_encode(seq):
    if seq not in (list,tuple):
        seq = [seq]
    for i in seq:
        if isinstance(i, (int,float)):
            yield str(i).encode()
        elif isinstance(i, str):
            yield i.encode()
        elif isinstance(i, bytes):
            yield i
        else:
            raise ValueError

def fetch_fields(connection, message_num, field_s):
    """Fetch just the fields we care about. Parse them into a dict"""
    if isinstance(field_s, (list,tuple)):
        field_s = b' '.join(safe_encode(field_s))
    else:
        field_s = tuple(safe_encode(field_s))[0]

    message_num = tuple(safe_encode(message_num))[0]

    typ, data = connection.fetch(message_num, b'(BODY.PEEK[HEADER.FIELDS (%s)])'%(field_s.upper()))
    if typ != 'OK':
        return typ, data  #change this to an exception if you'd rather

    items={}
    lastkey = None
    for line in data[0][1].splitlines():
        if b':' in line:
            lastkey, value = line.strip().split(b':', 1)
            lastkey = lastkey.capitalize()
            #not all servers capitalize the same, and some just leave it
            #as however it arrived from some other mail server.

            items[lastkey]=value
        else:
            #subject was so long it ran onto the next line, luckily it didn't have a ':' in it so its easy to recognize.
            items[lastkey]+=line
            #print(items[lastkey])
    return typ, items
`

You drop it into your code example: by replacing the call to 'mail.fetch()' with fetch_fields(mail, i, 'SUBJECT FROM') or fetch_fields(mail, i, ('SUBJECT' 'FROM'))你把它放到你的代码示例中:通过用fetch_fields(mail, i, 'SUBJECT FROM')fetch_fields(mail, i, ('SUBJECT' 'FROM'))替换对 'mail.fetch()' 的调用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM