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

发布于 2024-12-03 05:54:27 字数 2311 浏览 3 评论 0原文

我正在使用 pythons imaplib 连接到我的 Gmail 帐户。我想检索前 15 条邮件(未读或已读,没关系)并仅显示主题和发件人姓名(或地址),但不知道如何显示收件箱的内容。

这是到目前为止我的代码(成功连接)

import imaplib

mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('[email protected]', 'somecrazypassword')
mail.list()
mail.select('inbox')

#need to add some stuff in here

mail.logout()

我相信这应该足够简单,我只是对 imaplib 库的命令不够熟悉。任何帮助将不胜感激...

更新 感谢 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()

但我只想要主题和发件人。是否有针对这些项目的 imaplib 命令,或者我必须解析 data[0][1] 的全部内容以获取文本:主题和发件人?

更新 好的,主题和发件人部分正常工作,但迭代 (1, 15) 是按 desc 顺序完成的,显然首先向我显示最旧的消息。我怎样才能改变这个?我尝试这样做:

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

但这只是给了我所有 15 次迭代的 None...有什么想法吗?我也尝试过 mail.sort('REVERSE DATE', 'UTF-8', 'ALL') 但 gmail 不支持 .sort() 函数

UPDATE 找到了一种方法:

#....^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

这给了我最新的 15 条消息主题和发件人地址,按要求的降序排列!感谢所有提供帮助的人!

I'm using pythons imaplib to connect to my gmail account. 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.

Here is my code so far (successful connection)

import imaplib

mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('[email protected]', '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. Any help would be must appreciated...

UPDATE
thanks to Julian I can iterate through each message and retrieve the entire contents with:

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?

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. 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? I've also tried mail.sort('REVERSE DATE', 'UTF-8', 'ALL') but gmail doesnt support the .sort() function

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! Thanks to all who helped!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

默嘫て 2024-12-10 05:54:27
import email

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].decode())
            for header in [ 'subject', 'to', 'from' ]:
                print('%-8s: %s' % (header.upper(), msg[header]))

这应该会让您了解如何检索主题以及从哪里检索主题?

import email

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].decode())
            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?

月下伊人醉 2024-12-10 05:54:27

这是我从电子邮件中获取有用信息的解决方案:

import datetime
import email
import imaplib
import mailbox


EMAIL_ACCOUNT = "[email protected]"
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

This was my solution to get the useful bits of information from emails:

import datetime
import email
import imaplib
import mailbox


EMAIL_ACCOUNT = "[email protected]"
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
2024-12-10 05:54:27

对于那些寻找如何检查邮件和解析标头的人,这就是我使用的:

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

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
独自唱情﹋歌 2024-12-10 05:54:27

我正在寻找一个现成的简单脚本来通过 IMAP 列出最后一个收件箱,而无需对所有邮件进行排序。这里的信息很有用,尽管 DIY 并遗漏了一些方面。首先, IMAP4.select 返回消息计数。其次,主题标头解码并不简单。

#! /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('[email protected]', '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)

I was looking for a ready made simple script to list last inbox via IMAP without sorting through all messages. The information here is useful, though DIY and misses some aspects. First, IMAP4.select returns message count. 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('[email protected]', '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)
絕版丫頭 2024-12-10 05:54:27

BODY 获取几乎所有内容并将消息标记为已读。
BODY[] 仅获取这些部分。
BODY.PEEK[] 获取相同的部件,但不标记消息已读。
可以是 HEADERTEXTHEADER.FIELDS(<字段列表>)
HEADER.FIELDS.NOT (<字段列表>)

这就是我使用的: 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
`

您将其放入代码示例中:通过将对 'mail.fetch()' 的调用替换为 fetch_fields(mail, i, 'SUBJECT FROM')fetch_fields(mail, i, ('SUBJECT' 'FROM'))

BODY gets almost everything and marks the message as read.
BODY[<parts>] gets just those parts.
BODY.PEEK[<parts>] gets the same parts, but doesn't mark the message read.
<parts> can be HEADER or TEXT or HEADER.FIELDS (<list of fields>) or
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)])')

`

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'))

白云悠悠 2024-12-10 05:54:27

添加到上述所有答案。

import imaplib
import base64
import os
import email

if __name__ == '__main__':
    email_user = "[email protected]"
    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'])

这将为您提供电子邮件的发件人和主题名称。

Adding to all the above answers.

import imaplib
import base64
import os
import email

if __name__ == '__main__':
    email_user = "[email protected]"
    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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文