Gửi email HTML bằng Python


260

Làm cách nào tôi có thể gửi nội dung HTML trong email bằng Python? Tôi có thể gửi văn bản đơn giản.


Chỉ là một cảnh báo lớn chất béo. Nếu bạn đang gửi email không phải ASCII bằng Python <3.0, hãy xem xét sử dụng email trong Django . Nó bao bọc các chuỗi UTF-8 một cách chính xác và cũng đơn giản hơn nhiều để sử dụng. Bạn đã được cảnh báo :-)
Anders Rune Jensen

1
Nếu bạn muốn gửi một HTML với unicode, hãy xem tại đây: stackoverflow.com/questions/36397827/iêu
guettli

Câu trả lời:


419

Từ tài liệu Python v2.7.14 - 18.1.11. email: Ví dụ :

Dưới đây là ví dụ về cách tạo thông báo HTML bằng phiên bản văn bản thuần túy thay thế:

#! /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()

1
Có thể đính kèm phần thứ ba và phần thứ tư, cả hai đều là phần đính kèm (một ASCII, một nhị phân)? Làm thế nào một người sẽ làm điều đó? Cảm ơn.
Hamish Grubijan

1
Hi, tôi nhận thấy rằng cuối cùng bạn quitcác sđối tượng. Nếu tôi muốn gửi nhiều tin nhắn thì sao? Tôi có nên bỏ việc mỗi khi tôi gửi tin nhắn hoặc gửi tất cả chúng (trong một vòng lặp for) và sau đó thoát một lần và mãi mãi?
xpanta

Đảm bảo đính kèm html cuối cùng, vì phần ưa thích (hiển thị) sẽ là phần được đính kèm cuối cùng. # According to RFC 2046, the last part of a multipart message, in this case # the HTML message, is best and preferred. Tôi ước tôi đọc được điều này 2 giờ trước
dwkd 04/07/2015

1
Cảnh báo: điều này không thành công nếu bạn có các ký tự không phải là ascii trong văn bản.
guettli

2
Hmm, tôi nhận được lỗi cho Trình tin.as_opes (): list không có mã hóa thuộc tính
JohnAndrews

61

Bạn có thể thử sử dụng mô-đun gửi thư của tôi .

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)

Mô-đun Mailer rất tuyệt tuy nhiên nó tuyên bố sẽ hoạt động với Gmail, nhưng không và không có tài liệu.
MFB

1
@MFB - Bạn đã thử repo Bitbucket chưa? bitbucket.org/ginstrom/mailer
Ryan Ginstrom

2
Đối với gmail người ta nên cung cấp use_tls=True, usr='email'pwd='password'khi khởi tạo Mailervà nó sẽ hoạt động.
ToonAlfrink

Tôi khuyên bạn nên thêm vào mã của mình dòng sau ngay sau tin nhắn. Dòng message.Body = """Some text to show when the client cannot show HTML emails"""
tml

tuyệt vời nhưng làm thế nào để thêm các giá trị biến vào liên kết tôi có nghĩa là tạo một liên kết như thế này <a href=" python.org/somevalues"> liên kết </ a > để tôi có thể truy cập các giá trị đó từ các tuyến đường mà nó đi tới. Cảm ơn
TaraGurung

49

Đây là một triển khai Gmail của câu trả lời được chấp nhận:

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()

2
Mã tuyệt vời, nó hoạt động với tôi, nếu tôi bật bảo mật thấp trong google
Tovask

15
Tôi sử dụng mật khẩu dành riêng cho ứng dụng google với pyt smtplib, đã thực hiện thủ thuật mà không cần phải bảo mật thấp.
yoyo

2
cho bất kỳ ai đọc các nhận xét trên: Bạn chỉ yêu cầu "Mật khẩu ứng dụng" nếu trước đó bạn đã bật xác minh 2 bước trong tài khoản Gmail của mình.
Mugen

Có cách nào để thêm một cái gì đó linh hoạt vào phần HTML của tin nhắn không?
magma

40

Đây là một cách đơn giản để gửi email HTML, chỉ bằng cách chỉ định tiêu đề Kiểu nội dung là '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()

2
Đây là một câu trả lời đơn giản tốt đẹp, tiện dụng cho các kịch bản nhanh và bẩn, cảm ơn. BTW người ta có thể tham khảo câu trả lời được chấp nhận cho một smtplib.SMTP()ví dụ đơn giản , không sử dụng tls. Tôi đã sử dụng điều này cho một kịch bản nội bộ tại nơi làm việc, nơi chúng tôi sử dụng ssmtp và một mailhub cục bộ. Ngoài ra, ví dụ này là mất tích s.quit().
Mike S

1
"mailmerge_conf.smtp_server" không được xác định ... ít nhất là những gì Python 3.6 nói ...
ZEE

Tôi đã gặp lỗi khi sử dụng người nhận dựa trên danh sách AttributionError: đối tượng 'list' không có thuộc tính 'lstrip' nào?
navotera

10

Đây là mã mẫu. Điều này được lấy cảm hứng từ mã được tìm thấy trên trang web Python Cookbook (không thể tìm thấy liên kết chính xác)

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()


5

đối với python3, hãy cải thiện câu trả lời của @taltman :

  • sử dụng email.message.EmailMessagethay vì email.message.Messagexây dựng email.
  • sử dụng email.set_contentfunc, gán subtype='html'đối số. thay vì func cấp thấp set_payloadvà thêm tiêu đề bằng tay.
  • sử dụng SMTP.send_messagefunc thay vì SMTP.sendmailfunc để gửi email.
  • sử dụng withkhối để tự động đóng kết nối.
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)

4

Trên thực tế, yagmail có một cách tiếp cận khác.

Theo mặc định, nó sẽ gửi HTML, với dự phòng tự động cho những người đọc email không có khả năng. Nó không phải là thế kỷ 17 nữa.

Tất nhiên, nó có thể bị ghi đè, nhưng ở đây đi:

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)

Để biết hướng dẫn cài đặt và nhiều tính năng tuyệt vời hơn, hãy xem github .


3

Đây là một ví dụ hoạt động để gửi email văn bản và email HTML từ Python bằng cách sử dụng smtplibcùng với các tùy chọn CC và BCC.

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)

Hãy nghĩ rằng câu trả lời này bao gồm tất cả mọi thứ. Liên kết tuyệt vời
stingMantis

1

Đây là câu trả lời của tôi cho AWS bằng boto3

    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}
        }
    }

0

Giải pháp đơn giản nhất để gửi email từ tài khoản tổ chức trong 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()

ở đây df là một khung dữ liệu được chuyển đổi thành Bảng html, được thêm vào html_template


Câu hỏi không đề cập bất cứ điều gì về việc sử dụng Office hoặc tài khoản tổ chức. Đóng góp tốt nhưng không hữu ích cho người hỏi
Mwikala Kangwa
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.