python - 如何获取从gmail python接收的电子邮件?

标签 python email gmail poplib

我想用 python 获取最近 10 个收到的 gmail。

目前我有这段代码,但它只返回有限数量的电子邮件,并且它直接操作 pop3,这使得它不必要的长。

代码来源:https://www.code-learner.com/python-use-pop3-to-read-email-example/

import poplib
import smtplib, ssl
def guess_charset(msg):
    # get charset from message object.
    charset = msg.get_charset()
    # if can not get charset
    if charset is None:
       # get message header content-type value and retrieve the charset from the value.
       content_type = msg.get('Content-Type', '').lower()
       pos = content_type.find('charset=')
       if pos >= 0:
          charset = content_type[pos + 8:].strip()
    return charset

def decode_str(s):
    value, charset = decode_header(s)[0]
    if charset:
       value = value.decode(charset)
    return value
# variable indent_number is used to decide number of indent of each level in the mail multiple bory part.
def print_info(msg, indent_number=0):
    if indent_number == 0:
       # loop to retrieve from, to, subject from email header.
       for header in ['From', 'To', 'Subject']:
           # get header value
           value = msg.get(header, '')
           if value:
              # for subject header.
              if header=='Subject':
                 # decode the subject value
                 value = decode_str(value)
              # for from and to header. 
              else:
                 # parse email address
                 hdr, addr = parseaddr(value)
                 # decode the name value.
                 name = decode_str(hdr)
                 value = u'%s <%s>' % (name, addr)
           print('%s%s: %s' % (' ' * indent_number, header, value))
    # if message has multiple part. 
    if (msg.is_multipart()):
       # get multiple parts from message body.
       parts = msg.get_payload()
       # loop for each part
       for n, part in enumerate(parts):
           print('%spart %s' % (' ' * indent_number, n))
           print('%s--------------------' % (' ' * indent_number))
           # print multiple part information by invoke print_info function recursively.
           print_info(part, indent_number + 1)
    # if not multiple part. 
    else:
        # get message content mime type
        content_type = msg.get_content_type() 
        # if plain text or html content type.
        if content_type=='text/plain' or content_type=='text/html':
           # get email content
           content = msg.get_payload(decode=True)
           # get content string charset
           charset = guess_charset(msg)
           # decode the content with charset if provided.
           if charset:
              content = content.decode(charset)
           print('%sText: %s' % (' ' * indent_number, content + '...'))
        else:
           print('%sAttachment: %s' % (' ' * indent_number, content_type))

# input email address, password and pop3 server domain or ip address
email = 'yourgmail@gmail.com'
password = 'yourpassword'

# connect to pop3 server:
server = poplib.POP3_SSL('pop.gmail.com')
# open debug switch to print debug information between client and pop3 server.
server.set_debuglevel(1)
# get pop3 server welcome message.
pop3_server_welcome_msg = server.getwelcome().decode('utf-8')
# print out the pop3 server welcome message.
print(server.getwelcome().decode('utf-8'))

# user account authentication
server.user(email)
server.pass_(password)

# stat() function return email count and occupied disk size
print('Messages: %s. Size: %s' % server.stat())
# list() function return all email list
resp, mails, octets = server.list()
print(mails)

# retrieve the newest email index number
#index = len(mails)
index = 3
# server.retr function can get the contents of the email with index variable value index number.
resp, lines, octets = server.retr(index)

# lines stores each line of the original text of the message
# so that you can get the original text of the entire message use the join function and lines variable. 
msg_content = b'\r\n'.join(lines).decode('utf-8')
# now parse out the email object.

from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr

import poplib

# parse the email content to a message object.
msg = Parser().parsestr(msg_content)
print(len(msg_content))
# get email from, to, subject attribute value.
email_from = msg.get('From')
email_to = msg.get('To')
email_subject = msg.get('Subject')
print('From ' + email_from)
print('To ' + email_to)
print('Subject ' + email_subject)
for part in msg.walk():
    if part.get_content_type():
        body = part.get_payload(decode=True)
        print_info(msg, len(msg))


# delete the email from pop3 server directly by email index.
# server.dele(index)
# close pop3 server connection.
server.quit()

我也试过这段代码,但没有用:

import imaplib, email, base64


def fetch_messages(username, password):
    messages = []
    conn = imaplib.IMAP4_SSL("imap.gmail.com", 993)
    conn.login(username, password)
    conn.select()
    typ, data = conn.uid('search', None, 'ALL')

    for num in data[0].split():
        typ, msg_data = conn.uid('fetch', num, '(RFC822)')
        for response_part in msg_data:
            if isinstance(response_part, tuple):
                messages.append(email.message_from_string(response_part[1]))
        typ, response = conn.store(num, '+FLAGS', r'(\Seen)')
    return messages

这对我也不起作用......

import poplib
from email import parser
pop_conn = poplib.POP3_SSL('pop.gmail.com')
pop_conn.user('@gmail.com')
pop_conn.pass_('password')

messages = [pop_conn.retr(i) for i in range(1, len(pop_conn.list()[1]) + 1)]
# Concat message pieces:
messages = ["\n".join(mssg[1]) for mssg in messages]
#Parse message intom an email object:
messages = [parser.Parser().parsestr(mssg) for mssg in messages]
for message in messages:
    print(message['subject'])
    print(message['body'])

最佳答案

我设法解决了它,唯一的问题是它会将每封未读电子邮件标记为已读,here is the code I used:

import imaplib

mail = imaplib.IMAP4_SSL('imap.gmail.com')
email = input('Email: ')
password = input('Password: ')
mail.login(email+'@gmail.com', password)
mail.list()
# Out: list of "folders" aka labels in gmail.
mail.select("inbox") # connect to inbox.
result, data = mail.search(None, "ALL")

ids = data[0] # data is a list.
id_list = ids.split() # ids is a space separated string
latest_email_id = id_list[-1] # get the latest

# fetch the email body (RFC822) for the given ID
result, data = mail.fetch(latest_email_id, "(RFC822)") 

raw_email = data[0][1] # here's the body, which is raw text of the whole email
# including headers and alternate payloads

import email
email_message = email.message_from_string(str(raw_email))
 
print (email_message['To'])
 
print (email.utils.parseaddr(email_message['From'])) # for parsing "Yuji Tomita" <yuji@grovemade.com>
 
print (email_message.items()) # print all headers
 
# note that if you want to get text content (body) and the email contains
# multiple payloads (plaintext/ html), you must parse each message separately.
# use something like the following: (taken from a stackoverflow post)
def get_first_text_block(self, email_message_instance):
    maintype = email_message_instance.get_content_maintype()
    if maintype == 'multipart':
        for part in email_message_instance.get_payload():
            if part.get_content_maintype() == 'text':
                return part.get_payload()
    elif maintype == 'text':
        return email_message_instance.get_payload()

关于python - 如何获取从gmail python接收的电子邮件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58417462/

相关文章:

python - 我的 Python 尝试通过 Gmail 通过 SMTP 发送邮件有什么问题? SSL 包装器似乎不起作用

python - 如何使用 Python 在 Gmail 中使用 IMAP 创建草稿

python - 为什么 Python 在 Class 命名空间中对列表和整数的处理方式不同?

python - 打印列表列表,不带括号

email - 如果在PowerShell中检测到字符/字符串,则发送电子邮件

email - centos 7 同时在本地和远程保存 rsyslog

python - 如何关闭 showEvent 中的模态对话框?

python - 如何使用Python图像库(PIL)突出显示图像的一部分?

php - 尝试抛出自定义异常来验证电子邮件

google-apps-script - 谷歌应用程序脚本 - gmail - 通过过滤器返回消息(不是线程)