Вывод библиотеки сообщений электронной почты Python не принимается Outlook 365, когда у меня есть именованные вложения от - PullRequest
0 голосов
/ 14 сентября 2018

Я создал образец функции для проверки отправки электронных писем с приложенным html-файлом, который я намерен использовать для составления отчетов об автоматических тестовых прогонах в будущем (заменив существующий внешний скрипт powershell).Обратите внимание, что я прикрепляю html-файл, а не использую html в качестве встроенного текста в теле.Я использую службу учетной записи mailgun smtp нашей компании для отправки электронной почты.

У меня, похоже, проблема с Outlook 365 (размещен в Интернете - используется домен outlook.office.com), который либо отклоняет, либо блокирует отправленную электронную почту., но интересно то же самое письмо получено и принято моим личным адресом горячей почты (домен outlook.live.com).Я обнаружил блоки Outlook 365 или не принимает электронную почту, когда я пытаюсь назвать файл в объекте сообщения электронной почты.Но если я не назову его, он пройдет (с именем по умолчанию "ATT00001.htm").

Мой код для этого ниже, но ключевая строка, кажется,

msg.add_attachment(open_file.read(), maintype='text', subtype='html', filename=filename)

Если я опускаю ключ имени файла, он работает (но с назначенным по умолчанию именем файла), например,

msg.add_attachment(open_file.read(), maintype='text', subtype='html')

У меня есть подозрение, что-то взаголовок вложения или расположение содержимого, с которым Outlook 365 не согласен, но я не уверен, что это такое или как обойти.

Я использую следующее (Python 3.6.5, наМашина Windows 10, smtplib и email.message, кажется, встроены)

Вот код:

import smtplib
from email.message import EmailMessage
import os


def send_mail():
    MAILGUN_SMTP_LOGIN = "<my company's mailgun login>"
    MAILGUN_SMTP_PASSWORD = "<my company's mailgun password>"

    fromaddr = "muppet@sharklasers.com" # the from address seems to be inconsequential 
    toaddr = ['me@mycompanysdomainusingoffice365.com.au', 'me@hotmail.com']

    msg = EmailMessage()
    msg.preamble = 'This is preamble. Not sure where it should show in the email'

    msg['From'] = fromaddr
    msg['To'] = ', '.join(toaddr)
    msg['Subject'] = 'Testing attached html results send'
    msg.set_content(""" This is a test of attached html """)


    filename = 'api_automatedtests_20180903_1341.html'
    filepath = os.path.abspath('D:/work/temp/api_automatedtests_20180903_1341.html')
    open_file = open(filepath, "rb")
    # msg.make_mixed()
    msg.add_attachment(open_file.read(), maintype='text', subtype='html', filename=filename)
    # msg.add_attachment(open_file.read(), maintype='text', subtype='html')


    server = smtplib.SMTP(host="smtp.mailgun.org", port=587)
    server.ehlo()
    server.starttls()
    server.login(MAILGUN_SMTP_LOGIN, MAILGUN_SMTP_PASSWORD)
    server.set_debuglevel(1)
    server.send_message(msg)
    server.quit()


if __name__ == "__main__":
    send_mail()

Что я пробовал

  1. Пробная отправка с тем же кодом с использованием текстового файла (с соответствующими типами).например,
    msg.add_attachment(open_file.read(), maintype='text', subtype='plain', filename=filename)
    Результат: Это работает как ожидалось (приходит с заданным именем - имя файла является строковой переменной, например, testfile.txt)

  2. с добавлением сообщения.make_mixed (), чтобы убедиться, что оно идентифицируется как составное сообщение.Результат: без эффекта

  3. Включение отладки smtp 1-го уровня, Результат: Mailgun говорит, что все работает нормально (и сообщения отображаются в моей учетной записи hotmail, как и ожидалось)

  4. Не используется ключ имени файла в вызове msg.add_attachment.Результат: это работает, вложение приходит на ATT00001.htm Интересно, что имя по умолчанию - * .htm, а имя файла, которое я пытаюсь использовать, - * .html

    .
  5. Пробовал использовать имя файла с * .htm и подтипом 'htm' (вместо html). Результат: То же, что и для html (получено в hotmail, но не в outlook 365)

  6. Попытка с использованием универсальных типов maintype = '' application ', subtype =' octet-stream '.
    например, msg.add_attachment(open_file.read(), maintype='application', subtype='octet-stream', filename=filename)
    Результат: То же, что и для html (получено в hotmail, но не в outlook 365)

  7. Пробовал с помощью mimetypes.guess, как показано в этой ссылке
    https://docs.python.org/3.6/library/email.examples.html

ctype, encoding = mimetypes.guess_type (path), если ctype равен None или кодировка не равна None: # Невозможно угадать, или файл закодирован (сжат), поэтому # используйте общий тип bag-of-bit.ctype = 'application / octet-stream' maintype, subtype = ctype.split ('/', 1) с открытым (path, 'rb') в виде fp: msg.add_attachment (fp.read (), maintype = maintype, subtype= подтип, имя файла = имя файла)
Результат: определяется как maintype = 'text', subtype = 'html', и я получаю тот же результат, что и с моим исходным кодом (то есть приходит в hotmail, но блокируется 365).

Проверка моих папок спама и беспорядка - там не было

Есть какие-либо предложения о том, почему использование имени файла будет нарушать его?

Обновление После отправки на другие адреса электронной почты различных поставщиков я обнаружил:

1) muppet@sharklasers.com не был доверенным отправителем (может изменить это)

2) Я обнаружил, что вложение помечено как небезопасное. Html-файл взят из html-отчета pytest с опцией «один файл». Он содержит JavaScript для расширителей строк. Gmail предупреждает, что вложение может быть небезопасным (Office 365 просто блокирует электронную почту вообще).

Не уверен, как обойти 2). Я могу отправить один и тот же файл себе между outlook 365 и gmail, и наоборот, и файл не будет заблокирован. Он блокируется только тогда, когда я использую вышеуказанный скрипт с использованием библиотек python и Mailgun SMTP. Я подозреваю, что мне нужно что-то изменить в заголовке письма, чтобы обойти это. Но я не знаю что.

Кажется, существует некоторая связь между попыткой добавить имя файла и вложение, помеченное как небезопасное

1 Ответ

0 голосов
/ 14 сентября 2018

Хорошо, я понял это. Проблема заключалась в том, что тип содержимого должен был включать «name = filename» в его значение. Также мне нужно было использовать maintype = 'multipart', subtype = 'mixed'.

У меня есть 2 решения.

раствор 1

import smtplib
from email.message import EmailMessage
import os

def send_mail(body_text, fromaddr, recipient_list, smtp_login, smtp_pass, file_path):
    msg = EmailMessage()
    msg.preamble = 'This is preamble. Not sure where it should show'

    msg['From'] = fromaddr
    msg['To'] = ', '.join(recipient_list)
    msg['Subject'] = 'API Testing results'
    msg.set_content(body_text)

    filename = os.path.basename(file_path)
    open_file = open(file_path, "rb")
    msg.add_attachment(open_file.read(), maintype='multipart', subtype='mixed; name=%s' % filename, filename=filename)

    server = smtplib.SMTP(host="smtp.mailgun.org", port=587)
    server.ehlo()
    server.starttls()
    server.login(smtp_login, smtp_pass)
    server.send_message(msg)
    server.quit()


if __name__ == "__main__":
    smtp_login = "<my smtp login>"
    smtp_pass = "<my smtp password>"
    recipient_list = ['user1@mycompany.com.au', 'user2@mycompany.com.au']
    file_path = os.path.abspath('D:/work/temp/api_automatedtests_20180903_1341.html')
    body_text = "test results for 03/09/2018 "
    fromaddr = 'autotesting@mycompany.com.au'
    send_mail(body_text=body_text, recipient_list=recipient_list, smtp_login=smtp_login, smtp_pass=smtp_pass,
              file_path=file_path)

решение 2 (согласно документации использование библиотек email.mime является устаревшим решением, и метод EmailMessage предполагается использовать в предпочтении.

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import os

def send_mail(body_text, fromaddr, recipient_list, smtp_login, smtp_pass, file_path):

    msg = MIMEMultipart()
    msg['From'] = fromaddr
    msg['To'] = ', '.join(recipient_list)
    msg['Subject'] = "Sending API test results"
    msg.attach(MIMEText(body_text, 'plain'))

    filename = os.path.basename(file_path)
    attachment = open(file_path, "rb")

    part = MIMEBase('multipart', 'mixed; name=%s' % filename)
    part.set_payload(attachment.read())
    encoders.encode_base64(part)
    part.add_header('Content-Disposition', "attachment; filename= %s" % filename)

    msg.attach(part)

    server = smtplib.SMTP(host="smtp.mailgun.org", port=587)
    server.starttls()
    server.login(smtp_login, smtp_pass)
    text = msg.as_string()
    server.set_debuglevel(1)
    server.sendmail(fromaddr, recipient_list, text)
    server.quit()

if __name__ == '__main__':
    smtp_login = "<my smtp login>"
    smtp_pass = "<my smtp password>"
    recipient_list = ['user1@mycompany.com.au', 'user2@mycompany.com.au']
    file_path = os.path.abspath('D:/work/temp/api_automatedtests_20180903_1341.html')
    body_text = " Api test results for 03/09/2018 "
    fromaddr = "autotest@mycompany.com.au"
    send_mail(body_text=body_text, fromaddr=fromaddr, recipient_list=recipient_list, smtp_login=smtp_login, smtp_pass=smtp_pass,
              file_path=file_path)
...