Пример 13.18. PP4E\Internet\Email\popmail.py
#!/usr/local/bin/python """
############################################################################ использует модуль POP3 почтового интерфейса Python для просмотра сообщений почтовой учетной записи pop; это простой листинг — смотрите реализацию клиента с большим количеством функций взаимодействий с пользователем в pymail.py и сценарий отправки почты в smtpmail.py; протокол POP используется для получения почты и на сервере выполняется на сокете с портом номер 110, но модуль Python poplib скрывает все детали протокола; для отправки почты используйте модуль smtplib (или os.popen(‘mail…’)). Смотрите также модуль imaplib, реализующий альтернативный протокол IMAP, и программы PyMailGUI/PyMailCGI, реализующие дополнительные особенности;
############################################################################
import poplib, getpass, sys, mailconfig
mailserver = mailconfig.popservername # например: ‘pop.rmi.net’ mailuser = mailconfig.popusername # например: ‘lutz’ mailpasswd = getpass.getpass(‘Password for %s?’ % mailserver)
print(‘Connecting…’)
server = poplib.POP3(mailserver) server.user(mailuser) # соединение, регистрация на сервере
server.pass_(mailpasswd) # pass — зарезервированное слово
try:
print(server.getwelcome()) # вывод приветствия
msgCount, msgBytes = server.stat()
print(‘There are’, msgCount, ‘mail messages in’, msgBytes, ‘bytes’) print(server.list()) print(‘-‘ * 80)
input(‘[Press Enter key]’)
for i in range(msgCount):
hdr, message, octets = server.retr(i+1) # octets — счетчик байтов for line in message: print(line.decode()) # читает, выводит
# все письма
print(‘-‘ * 80) # в 3.X сообщения — bytes
if i < msgCount — 1: # почтовый ящик блокируется
input(‘[Press Enter key]’) # до вызова quit
finally: # снять блокировку с ящика
server.quit() # иначе будет разблокирован
print(‘Bye.’) # по тайм-ауту
server = poplib.POP3(mailserver)
Если этот вызов не возбудил исключение, значит, мы соединились (через сокет) с POP-сервером, который слушает запросы на порту POP с номером 110 на сервере, где у нас имеется учетная запись электронной почты.
Следующее, что необходимо сделать перед получением сообщений, — это сообщить серверу имя пользователя и пароль. Обратите внимание, что метод передачи пароля называется pass_ — без символа подчеркивания в конце идентификатор pass оказался бы зарезервированным словом и вызвал бы синтаксическую ошибку:
server.user(mailuser) # соединение, регистрация на сервере
server.pass_(mailpasswd) # pass — зарезервированное слово
Для простоты и относительной безопасности этот сценарий всегда запрашивает пароль в интерактивном режиме. Чтобы ввести, но не отображать на экране строку пароля при вводе пользователем, используется модуль getpass, знакомый по разделу этой главы, посвященному FTP.
Сообщив серверу имя пользователя и пароль, мы можем с помощью метода stat получить информацию о почтовом ящике (количество сообщений, суммарное количество байтов в сообщениях) и извлечь полный текст конкретного сообщения с помощью метода retr (передав номер сообщения — нумерация начинается с 1). Полный текст включает все заголовки, следующую за ними пустую строку, текст письма и все вложения. Метод retr возвращает кортеж, включающий список строк с содержимым письма:
msgCount, msgBytes = server.stat()
hdr, message, octets = server.retr(i+1) # octets — счетчик байтов
Закончив работу с почтой, закрываем соединение с почтовым сервером, вызывая метод quit объекта POP:
server.quit() # иначе будет разблокирован по тайм-ауту
Обратите внимание, что этот вызов помещен в предложение finally инструкции try, охватывающей основную часть сценария. Для борьбы со сложностями, связанными с изменениями данных, POP-серверы блокируют почтовый ящик на время между первым соединением и закрытием соединения (или до истечения устанавливаемого системой тайм-аута). Так как метод quit тоже разблокирует почтовый ящик, важно выполнить его перед завершением работы независимо от того, было ли во время обработки электронной почты возбуждено исключение. Заключив действия в инструкцию try/finally, мы гарантируем вызов метода quit при выходе, чтобы разблокировать почтовый ящик и сделать его доступным другим процессам (например, для доставки входящей почты).
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, II том, 2011