通过 python 处理 email - Email via Python

时间:2023-03-10 07:19:14
通过 python 处理 email - Email via Python
   Email via Python

1 MIME - Multipurpose Internet Mail Extensions
SMTP - Simple Message Transport Protocol 邮件的发送,
例子 - send email
import smtplib
from email.mime.text import MIMEText
from email.utils import formatdate, make_msgid
mess = 'hello there'
mesgobj = MIMEText(mess)
mesgobj['To'] = 'testrecevier@example.com'
mesgobj['From'] = 'testsender@example.com'
mesgobj['Subject'] = 'Greeting'
mesgobj['Date'] = formatdate(localtime=1) # Date header, formatdate() 生成 email 专门日期格式
mesgobj['Message-ID'] = make_msgid() # make_msgid() 方法生成唯一的 Message-ID,
print(mesgobj.as_string())
print(mesgobj.as_bytes()) s = smtplib.SMTP('SMTP-SERVER-ADDR')
s.send_message(mesgobj)
s.quit() 邮件的解析,
例子 - parsing email,
from email.parser import Parser
headers = Parser().parsestr(mesgobj.as_string()) # mesgobj 为上例中对象.
for h,v in headers.items():
print("Header[%s] - " % h,v)
print('Emial content - ', mesgobj.get_payload()) # 打印邮件正文. 带有附件的邮件发送处理 - Packing MIME,
邮件的附件有 音频, 图像, 压缩文件等等, 通过 python doc 的上的例子看一下儿
对邮件的附件的处理方式,
例子 - send email with attachments,
* an example of how to send the entire contents of a directory as an email message import os
import sys
import smtplib
# For guessing MIME type based on file name extension
import mimetypes
from optparse import OptionParser
from email import encoders
from email.message import Message
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText COMMASPACE = ', ' def main():
parser = OptionParser(usage='''\
Send the contents of a directory as a MIME message. Usage: %prog [options] Unless the -o option is given, the email is sent by forwarding to your local
SMTP server, which then does the normal delivery process. Your local machine
must be running an SMTP server.
''')
parser.add_option('-d', '--directory',
type='string', action='store',
help='''Mail the contents of the specified directory,
otherwise use the current directory. Only the regular
files in the directory are sent, and we don't recurse to
subdirectories.''')
parser.add_option('-o', '--output',
type='string', action='store', metavar='FILE',
help='''Print the composed message to FILE instead of
sending the message to the SMTP server.''')
parser.add_option('-s', '--sender',
type='string', action='store', metavar='SENDER',
help='The value of the From: header (required)')
parser.add_option('-r', '--recipient',
type='string', action='append', metavar='RECIPIENT',
default=[], dest='recipients',
help='A To: header value (at least one required)')
opts, args = parser.parse_args()
if not opts.sender or not opts.recipients:
parser.print_help() # SMTP server 只处理地址有效的 sender 跟 recipients
sys.exit(1)
directory = opts.directory
if not directory:
directory = '.' # 之前的代码的功能是通过 OptionParser 没款完成对命令行参数的解析
# Create the enclosing (outer) message
outer = MIMEMultipart() # 构建一个带附件的 email 对象
outer['Subject'] = 'Contents of directory %s' % os.path.abspath(directory)
outer['To'] = COMMASPACE.join(opts.recipients)
outer['From'] = opts.sender
outer.preamble = 'You will not see this in a MIME-aware mail reader.\n' for filename in os.listdir(directory): # 按附件类型做相应的处理
path = os.path.join(directory, filename)
if not os.path.isfile(path):
continue
# Guess the content type based on the file's extension. Encoding
# will be ignored, although we should check for simple things like
# gzip'd or compressed files.
ctype, encoding = mimetypes.guess_type(path) # 附件类型的判断
if ctype is None or encoding is not None:
# No guess could be made, or the file is encoded (compressed), so
# use a generic bag-of-bits type.
ctype = 'application/octet-stream' # zip, pdf 等附件的类型
maintype, subtype = ctype.split('/', 1)
if maintype == 'text': # 处理的 文本text 类型的附件
fp = open(path)
# Note: we should handle calculating the charset
msg = MIMEText(fp.read(), _subtype=subtype)
fp.close()
elif maintype == 'image': # 处理的 图像image 类型的附件
fp = open(path, 'rb')
msg = MIMEImage(fp.read(), _subtype=subtype)
fp.close()
elif maintype == 'audio': # 处理的 音频audio 类型的附件
fp = open(path, 'rb')
msg = MIMEAudio(fp.read(), _subtype=subtype)
fp.close()
else:
fp = open(path, 'rb') # 处理的其他类型的附件:如 zip, pdf 等
msg = MIMEBase(maintype, subtype)
msg.set_payload(fp.read())
fp.close()
# Encode the payload using Base64
encoders.encode_base64(msg)
# Set the filename parameter
msg.add_header('Content-Disposition', 'attachment', filename=filename)
outer.attach(msg)
# Now send or store the message
composed = outer.as_string()
if opts.output: # 保存到文件 store
fp = open(opts.output, 'w')
fp.write(composed)
fp.close()
else:
s = smtplib.SMTP('localhost') # SMTP server 发送处理
s.sendmail(opts.sender, opts.recipients, composed)
s.quit() if __name__ == '__main__':
main() MIME 的解包 - Unpacking MIME 接收方对收到的 MIMEMultipart 的处理,
'''Unpack a MIME message into a directory of files.''' import os
import sys
import email
import errno
import mimetypes
from optparse import OptionParser
def main():
parser = OptionParser(usage='''\
Unpack a MIME message into a directory of files. Usage: %prog [options] msgfile
''')
parser.add_option('-d', '--directory',
type='string', action='store',
help='''Unpack the MIME message into the named
directory, which will be created if it doesn't already
exist.''')
opts, args = parser.parse_args()
if not opts.directory:
parser.print_help()
sys.exit(1) try:
msgfile = args[0]
except IndexError:
parser.print_help()
sys.exit(1) try:
os.mkdir(opts.directory)
except OSError as e:
# Ignore directory exists error
if e.errno != errno.EEXIST:
raise fp = open(msgfile)
msg = email.message_from_file(fp)
fp.close() counter = 1
for part in msg.walk():
# multipart/* are just containers
if part.get_content_maintype() == 'multipart':
continue
# Applications should really sanitize the given filename so that an
# email message can't be used to overwrite important files
filename = part.get_filename()
if not filename:
ext = mimetypes.guess_extension(part.get_content_type())
if not ext:
# Use a generic bag-of-bits extension
ext = '.bin'
filename = 'part-%03d%s' % (counter, ext)
counter += 1
fp = open(os.path.join(opts.directory, filename), 'wb')
fp.write(part.get_payload(decode=True))
fp.close() if __name__ == '__main__':
main() Reference,
https://docs.python.org/3/library/email.html