【问题标题】:Send HTML emails with Python使用 Python 发送 HTML 电子邮件
【发布时间】:2010-10-27 07:57:19
【问题描述】:

如何使用 Python 在电子邮件中发送 HTML 内容?我可以发送简单的文本。

【问题讨论】:

  • 只是一个大警告。如果您使用 Python ASCII 电子邮件,请考虑使用Django 中的电子邮件。它正确地包装了UTF-8 字符串,并且使用起来也更简单。您已被警告 :-)
  • 如果您想发送带有 unicode 的 HTML,请参见此处:stackoverflow.com/questions/36397827/…

标签: python email html-email


【解决方案1】:

来自Python v2.7.14 documentation - 18.1.11. email: Examples

下面是一个如何使用替代纯文本版本创建 HTML 消息的示例:

#! /usr/bin/python

import smtplib

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

# me == my email address
# you == recipient's email address
me = "my@email.com"
you = "your@email.com"

# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('alternative')
msg['Subject'] = "Link"
msg['From'] = me
msg['To'] = you

# Create the body of the message (a plain-text and an HTML version).
text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttp://www.python.org"
html = """\
<html>
  <head></head>
  <body>
    <p>Hi!<br>
       How are you?<br>
       Here is the <a href="http://www.python.org">link</a> you wanted.
    </p>
  </body>
</html>
"""

# Record the MIME types of both parts - text/plain and text/html.
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')

# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
msg.attach(part1)
msg.attach(part2)

# Send the message via local SMTP server.
s = smtplib.SMTP('localhost')
# sendmail function takes 3 arguments: sender's address, recipient's address
# and message to send - here it is sent as one string.
s.sendmail(me, you, msg.as_string())
s.quit()

【讨论】:

  • 是否可以附加第三和第四部分,两者都是附件(一个ASCII,一个二进制)?如何做到这一点?谢谢。
  • 嗨,我注意到最后你 quit s 对象。如果我想发送多条消息怎么办?我应该在每次发送消息时退出还是将它们全部发送(在 for 循环中)然后一劳永逸地退出?
  • 确保最后附加 html,因为首选(显示)部分将是最后附加的部分。 # According to RFC 2046, the last part of a multipart message, in this case # the HTML message, is best and preferred.我希望我能在 2 小时前读到这篇文章
  • 警告:如果文本中包含非 ascii 字符,则会失败。
  • 嗯,我得到 msg.as_string() 的错误:列表对象没有属性编码
【解决方案2】:

这是已接受答案的Gmail 实现:

import smtplib

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

# me == my email address
# you == recipient's email address
me = "my@email.com"
you = "your@email.com"

# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('alternative')
msg['Subject'] = "Link"
msg['From'] = me
msg['To'] = you

# Create the body of the message (a plain-text and an HTML version).
text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttp://www.python.org"
html = """\
<html>
  <head></head>
  <body>
    <p>Hi!<br>
       How are you?<br>
       Here is the <a href="http://www.python.org">link</a> you wanted.
    </p>
  </body>
</html>
"""

# Record the MIME types of both parts - text/plain and text/html.
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')

# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
msg.attach(part1)
msg.attach(part2)
# Send the message via local SMTP server.
mail = smtplib.SMTP('smtp.gmail.com', 587)

mail.ehlo()

mail.starttls()

mail.login('userName', 'password')
mail.sendmail(me, you, msg.as_string())
mail.quit()

【讨论】:

  • 很棒的代码,如果我打开low security in google,它对我有用
  • 我使用 google application specific password 和 python smtplib,做到了这一点而不必降低安全性。
  • 对于阅读上述 cmets 的任何人:如果您之前在 Gmail 帐户中启用了两步验证,则只需要“应用程序密码”。
  • 有没有办法在邮件的 HTML 部分动态附加一些东西?
  • 不知何故,只有最后一个附加部分似乎有效。
【解决方案3】:

您可以尝试使用我的mailer 模块。

from mailer import Mailer
from mailer import Message

message = Message(From="me@example.com",
                  To="you@example.com")
message.Subject = "An HTML Email"
message.Html = """<p>Hi!<br>
   How are you?<br>
   Here is the <a href="http://www.python.org">link</a> you wanted.</p>"""

sender = Mailer('smtp.example.com')
sender.send(message)

【讨论】:

  • Mailer 模块很棒,但它声称可以与 Gmail 一起使用,但实际上并没有,也没有文档。
  • @MFB -- 你尝试过 Bitbucket 存储库吗? bitbucket.org/ginstrom/mailer
  • 对于 gmail,在初始化 Mailer 时应提供 use_tls=True,usr='email'pwd='password',它会起作用。
  • 我建议在 message.Html 行之后添加以下行:message.Body = """Some text to show when the client cannot show HTML emails"""
  • 很好,但是如何将变量值添加到链接我的意思是创建一个像这样的链接 python.org/somevalues">link</a> 这样我就可以从它去的路由中访问这些值。谢谢
【解决方案4】:

这是发送 HTML 电子邮件的简单方法,只需将 Content-Type 标头指定为“text/html”:

import email.message
import smtplib

msg = email.message.Message()
msg['Subject'] = 'foo'
msg['From'] = 'sender@test.com'
msg['To'] = 'recipient@test.com'
msg.add_header('Content-Type','text/html')
msg.set_payload('Body of <b>message</b>')

# Send the message via local SMTP server.
s = smtplib.SMTP('localhost')
s.starttls()
s.login(email_login,
        email_passwd)
s.sendmail(msg['From'], [msg['To']], msg.as_string())
s.quit()

【讨论】:

  • 这是一个很好的简单答案,对于快速和肮脏的脚本很方便,谢谢。顺便说一句,可以参考一个简单的smtplib.SMTP() 示例的公认答案,该示例不使用 tls。我在工作中将其用于内部脚本,我们使用 ssmtp 和本地 mailhub。此外,此示例缺少 s.quit()
  • "mailmerge_conf.smtp_server" 没有定义……至少 Python 3.6 是这么说的……
【解决方案5】:

对于python3,改进@taltman 's answer

  • 使用email.message.EmailMessage 而不是email.message.Message 来构建电子邮件。
  • 使用email.set_content 函数,分配subtype='html' 参数。而不是低级 func set_payload 并手动添加标题。
  • 使用SMTP.send_message func 代替SMTP.sendmail func 来发送电子邮件。
  • 使用with 块自动关闭连接。
from email.message import EmailMessage
from smtplib import SMTP

# construct email
email = EmailMessage()
email['Subject'] = 'foo'
email['From'] = 'sender@test.com'
email['To'] = 'recipient@test.com'
email.set_content('<font color="red">red color text</font>', subtype='html')

# Send the message via local SMTP server.
with smtplib.SMTP('localhost') as s:
    s.login('foo_user', 'bar_password')
    s.send_message(email)

【讨论】:

  • 作为改进,如果您想另外发送附件,请使用email.add_alternative()(与使用email.set_content() 相同的方式添加HTML,然后使用@ 添加附件987654333@(我花了很长时间才弄清楚)
  • EmailMessage API 仅从 Python 3.6 开始正式可用,尽管它已在 3.3 中作为替代方案提供。新代码绝对应该使用它而不是旧的 email.message.Message 遗留 API,不幸的是,这里的大多数答案仍然建议使用它。带有MIMETextMIMEMultipart 的任何内容都是旧API,除非您有遗留原因,否则应避免使用。
【解决方案6】:

这里是示例代码。这灵感来自Python Cookbook 网站上的代码(找不到确切的链接)

def createhtmlmail (html, text, subject, fromEmail):
    """Create a mime-message that will render HTML in popular
    MUAs, text in better ones"""
    import MimeWriter
    import mimetools
    import cStringIO

    out = cStringIO.StringIO() # output buffer for our message 
    htmlin = cStringIO.StringIO(html)
    txtin = cStringIO.StringIO(text)

    writer = MimeWriter.MimeWriter(out)
    #
    # set up some basic headers... we put subject here
    # because smtplib.sendmail expects it to be in the
    # message body
    #
    writer.addheader("From", fromEmail)
    writer.addheader("Subject", subject)
    writer.addheader("MIME-Version", "1.0")
    #
    # start the multipart section of the message
    # multipart/alternative seems to work better
    # on some MUAs than multipart/mixed
    #
    writer.startmultipartbody("alternative")
    writer.flushheaders()
    #
    # the plain text section
    #
    subpart = writer.nextpart()
    subpart.addheader("Content-Transfer-Encoding", "quoted-printable")
    pout = subpart.startbody("text/plain", [("charset", 'us-ascii')])
    mimetools.encode(txtin, pout, 'quoted-printable')
    txtin.close()
    #
    # start the html subpart of the message
    #
    subpart = writer.nextpart()
    subpart.addheader("Content-Transfer-Encoding", "quoted-printable")
    #
    # returns us a file-ish object we can write to
    #
    pout = subpart.startbody("text/html", [("charset", 'us-ascii')])
    mimetools.encode(htmlin, pout, 'quoted-printable')
    htmlin.close()
    #
    # Now that we're done, close our writer and
    # return the message body
    #
    writer.lastpart()
    msg = out.getvalue()
    out.close()
    print msg
    return msg

if __name__=="__main__":
    import smtplib
    html = 'html version'
    text = 'TEST VERSION'
    subject = "BACKUP REPORT"
    message = createhtmlmail(html, text, subject, 'From Host <sender@host.com>')
    server = smtplib.SMTP("smtp_server_address","smtp_port")
    server.login('username', 'password')
    server.sendmail('sender@host.com', 'target@otherhost.com', message)
    server.quit()

【讨论】:

【解决方案7】:

实际上,yagmail 采取了一些不同的方法。

它会默认发送 HTML,并为无能力的电子邮件阅读者自动回退。现在已经不是 17 世纪了。

当然,它可以被覆盖,但这里是:

import yagmail
yag = yagmail.SMTP("me@example.com", "mypassword")

html_msg = """<p>Hi!<br>
              How are you?<br>
              Here is the <a href="http://www.python.org">link</a> you wanted.</p>"""

yag.send("to@example.com", "the subject", html_msg)

有关安装说明和更多强大功能,请查看github

【讨论】:

  • 只对 gmail 用户有帮助
【解决方案8】:

这是一个使用 smtplib 以及 CC 和 BCC 选项从 Python 发送纯文本和 HTML 电子邮件的工作示例。

https://varunver.wordpress.com/2017/01/26/python-smtplib-send-plaintext-and-html-emails/

#!/usr/bin/env python
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

def send_mail(params, type_):
      email_subject = params['email_subject']
      email_from = "from_email@domain.com"
      email_to = params['email_to']
      email_cc = params.get('email_cc')
      email_bcc = params.get('email_bcc')
      email_body = params['email_body']

      msg = MIMEMultipart('alternative')
      msg['To'] = email_to
      msg['CC'] = email_cc
      msg['Subject'] = email_subject
      mt_html = MIMEText(email_body, type_)
      msg.attach(mt_html)

      server = smtplib.SMTP('YOUR_MAIL_SERVER.DOMAIN.COM')
      server.set_debuglevel(1)
      toaddrs = [email_to] + [email_cc] + [email_bcc]
      server.sendmail(email_from, toaddrs, msg.as_string())
      server.quit()

# Calling the mailer functions
params = {
    'email_to': 'to_email@domain.com',
    'email_cc': 'cc_email@domain.com',
    'email_bcc': 'bcc_email@domain.com',
    'email_subject': 'Test message from python library',
    'email_body': '<h1>Hello World</h1>'
}
for t in ['plain', 'html']:
    send_mail(params, t)

【讨论】:

  • 认为这个答案涵盖了一切。很好的链接
【解决方案9】:

这是我使用 boto3 对 AWS 的回答

    subject = "Hello"
    html = "<b>Hello Consumer</b>"

    client = boto3.client('ses', region_name='us-east-1', aws_access_key_id="your_key",
                      aws_secret_access_key="your_secret")

client.send_email(
    Source='ACME <do-not-reply@acme.com>',
    Destination={'ToAddresses': [email]},
    Message={
        'Subject': {'Data': subject},
        'Body': {
            'Html': {'Data': html}
        }
    }

【讨论】:

    【解决方案10】:

    从 Office 365 中的组织帐户发送电子邮件的最简单解决方案:

    from O365 import Message
    
    html_template =     """ 
                <html>
                <head>
                    <title></title>
                </head>
                <body>
                        {}
                </body>
                </html>
            """
    
    final_html_data = html_template.format(df.to_html(index=False))
    
    o365_auth = ('sender_username@company_email.com','Password')
    m = Message(auth=o365_auth)
    m.setRecipients('receiver_username@company_email.com')
    m.setSubject('Weekly report')
    m.setBodyHTML(final_html_data)
    m.sendMessage()
    

    这里的df是转换成html Table的dataframe,正在注入到html_template

    【讨论】:

    • 这个问题没有提到任何关于使用 Office 或组织帐户的内容。贡献不错,但对提问者帮助不大
    【解决方案11】:

    我可能迟到在这里提供答案,但问题询问了一种发送 HTML 电子邮件的方法。使用像“电子邮件”这样的专用模块是可以的,但我们可以在不使用任何新模块的情况下获得相同的结果。这一切都归结为 Gmail 协议。

    以下是我仅使用“smtplib”发送 HTML 邮件的简单示例代码。

    ```
    import smtplib
    
    FROM = "....@gmail.com"
    TO = "another....@gmail.com"
    SUBJECT= "Subject"
    PWD = "thesecretkey"
    
    TEXT="""
    <h1>Hello</h1>
    """ #Your Message (Even Supports HTML Directly)
    
    message = f"Subject: {SUBJECT}\nFrom: {FROM}\nTo: {TO}\nContent-Type: text/html\n\n{TEXT}" #This is where the stuff happens
    
    try:
        server=smtplib.SMTP("smtp.gmail.com",587)
        server.ehlo()
        server.starttls()
        server.login(FROM,PWD)
        server.sendmail(FROM,TO,message)
        server.close()
        print("Successfully sent the mail.")
    except Exception as e:
        print("Failed to send the mail..", e)
    ```
    

    【讨论】:

    • email 库不是一个“新模块”,它和smtplib 一样是标准库的一部分。您绝对不应该通过组合这样的字符串来创建消息;它似乎适用于非常简单的消息,但是一旦您移出仅具有 7 位 US-ASCII 内容的单个 text/plain 有效负载的舒适领域,它就会以灾难性的方式失败(即使这样,也有一些极端情况是可能会绊倒你,特别是如果你不知道自己在做什么)。
    【解决方案12】:

    如果你想要更简单的东西:

    from redmail import EmailSender
    email = EmailSender(host="smtp.myhost.com", port=1)
    
    email.send(
        subject="Example email",
        sender="me@example.com",
        receivers=["you@example.com"],
        html="<h1>Hi, this is HTML body</h1>"
    )
    

    Pip install Red Mail from PyPI:

    pip install redmail
    

    Red Mail 很可能拥有您发送电子邮件所需的一切,并且它具有许多功能,包括:

    文档:https://red-mail.readthedocs.io/en/latest/index.html

    源码:https://github.com/Miksus/red-mail

    【讨论】:

      猜你喜欢
      • 2014-09-14
      • 1970-01-01
      • 1970-01-01
      • 2019-10-18
      • 2012-06-30
      • 2013-05-26
      相关资源
      最近更新 更多