Mengirim email HTML menggunakan Python

260

Bagaimana saya bisa mengirim konten HTML dalam email menggunakan Python? Saya dapat mengirim teks sederhana.

Peter Mortensen
sumber
Hanya peringatan besar. Jika Anda mengirim email non- ASCII menggunakan Python <3.0, pertimbangkan untuk menggunakan email di Django . Ini membungkus string UTF-8 dengan benar, dan juga jauh lebih mudah digunakan. Anda telah diperingatkan :-)
Anders Rune Jensen
1
Jika Anda ingin mengirim HTML dengan unicode, lihat di sini: stackoverflow.com/questions/36397827/…
guettli

Jawaban:

419

Dari dokumentasi Python v2.7.14 - 18.1.11. email: Contoh :

Berikut adalah contoh cara membuat pesan HTML dengan versi teks biasa alternatif:

#! /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 = "[email protected]"
you = "[email protected]"

# 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()
Andrew Hare
sumber
1
Apakah mungkin untuk melampirkan bagian ketiga dan keempat, yang keduanya adalah lampiran (satu ASCII, satu biner)? Bagaimana caranya? Terima kasih.
Hamish Grubijan
1
Hai, saya perhatikan bahwa pada akhirnya Anda quitadalah sobjeknya. Bagaimana jika saya ingin mengirim banyak pesan? Haruskah saya berhenti setiap kali saya mengirim pesan atau mengirim semuanya (dalam for for loop) dan kemudian berhenti sekali dan untuk semua?
xpanta
Pastikan untuk melampirkan html yang terakhir, karena bagian yang disukai (menampilkan) akan menjadi yang terlampir terakhir. # According to RFC 2046, the last part of a multipart message, in this case # the HTML message, is best and preferred. Saya berharap saya membaca ini 2 jam yang lalu
dwkd
1
Peringatan: ini gagal jika Anda memiliki karakter non-ascii dalam teks.
guettli
2
Hmm, saya mendapatkan kesalahan untuk msg.as_string (): daftar objek tidak memiliki penyandian atribut
JohnAndrews
61

Anda mungkin mencoba menggunakan modul mailer saya .

from mailer import Mailer
from mailer import Message

message = Message(From="[email protected]",
                  To="[email protected]")
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)
Ryan Ginstrom
sumber
Modul mailer bagus tetapi mengklaim berfungsi dengan Gmail, tetapi tidak dan tidak ada dokumen.
MFB
1
@MFB - Sudahkah Anda mencoba repo Bitbucket? bitbucket.org/ginstrom/mailer
Ryan Ginstrom
2
Untuk gmail, seseorang harus menyediakan use_tls=True, usr='email'dan pwd='password'ketika menginisialisasi Mailerdan itu akan berhasil.
ToonAlfrink
Saya akan merekomendasikan menambahkan ke kode Anda baris berikut tepat setelah pesan. Baris HTML:message.Body = """Some text to show when the client cannot show HTML emails"""
IvanD
hebat tapi bagaimana cara menambahkan nilai variabel ke tautan yang saya maksud membuat tautan seperti ini <a href=" python.org/somevalues"> tautan </ a > Sehingga saya dapat mengakses nilai-nilai itu dari rute yang dilaluinya . Terima kasih
TaraGurung
49

Berikut ini adalah implementasi Gmail dari jawaban yang diterima:

import smtplib

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

# me == my email address
# you == recipient's email address
me = "[email protected]"
you = "[email protected]"

# 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()
DataTx
sumber
2
Kode hebat, ini berfungsi untuk saya, jika saya menyalakan keamanan rendah di google
Tovask
15
Saya menggunakan kata sandi khusus aplikasi google dengan python smtplib, melakukan trik tanpa harus mengurangi keamanan.
yoyo
2
bagi siapa pun yang membaca komentar di atas: Anda hanya memerlukan "Sandi Aplikasi" jika sebelumnya Anda telah mengaktifkan verifikasi 2 langkah di akun Gmail Anda.
Mugen
Apakah ada cara untuk menambahkan sesuatu secara dinamis di bagian HTML pesan?
magma
40

Berikut adalah cara sederhana untuk mengirim email HTML, hanya dengan menentukan header Tipe Konten sebagai 'teks / html':

import email.message
import smtplib

msg = email.message.Message()
msg['Subject'] = 'foo'
msg['From'] = '[email protected]'
msg['To'] = '[email protected]'
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()
taltman
sumber
2
Ini adalah jawaban sederhana yang bagus, berguna untuk skrip cepat dan kotor, terima kasih. BTW orang dapat merujuk pada jawaban yang diterima untuk smtplib.SMTP()contoh sederhana , yang tidak menggunakan tl. Saya menggunakan ini untuk skrip internal di tempat kerja di mana kami menggunakan ssmtp dan mailhub lokal. Juga, contoh ini tidak ada s.quit().
Mike S
1
"mailmerge_conf.smtp_server" tidak didefinisikan ... setidaknya adalah apa yang Python 3.6 katakan ...
ZEE
saya mendapat kesalahan saat menggunakan penerima berbasis daftar AttributeError: objek 'daftar' tidak memiliki atribut 'lstrip' solusi apa pun?
navotera
10

Ini kode contoh. Ini terinspirasi dari kode yang ditemukan di situs Python Cookbook (tidak dapat menemukan tautan yang tepat)

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 <[email protected]>')
    server = smtplib.SMTP("smtp_server_address","smtp_port")
    server.login('username', 'password')
    server.sendmail('[email protected]', '[email protected]', message)
    server.quit()
Nathan
sumber
5

untuk python3, perbaiki jawaban @taltman :

  • gunakan email.message.EmailMessagealih-alih email.message.Messageuntuk membangun email.
  • gunakan email.set_contentfunc, tentukan subtype='html'argumen. alih-alih fungsi tingkat rendah set_payloaddan tambahkan tajuk secara manual.
  • gunakan SMTP.send_messagefunc alih-alih SMTP.sendmailfunc untuk mengirim email.
  • gunakan withblokir untuk menutup koneksi secara otomatis.
from email.message import EmailMessage
from smtplib import SMTP

# construct email
email = EmailMessage()
email['Subject'] = 'foo'
email['From'] = '[email protected]'
email['To'] = '[email protected]'
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)
valleygtc
sumber
4

Sebenarnya, yagmail mengambil pendekatan yang sedikit berbeda.

Secara default akan mengirim HTML, dengan fallback otomatis untuk pembaca email yang tidak mampu. Ini bukan abad ke-17 lagi.

Tentu saja, itu bisa diganti, tetapi begini:

import yagmail
yag = yagmail.SMTP("[email protected]", "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("[email protected]", "the subject", html_msg)

Untuk instruksi penginstalan dan banyak fitur hebat lainnya, lihat github .

PascalVKooten
sumber
3

Berikut adalah contoh yang berfungsi untuk mengirim teks biasa dan email HTML dari Python menggunakan smtplibbersama dengan opsi CC dan 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 = "[email protected]"
      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': '[email protected]',
    'email_cc': '[email protected]',
    'email_bcc': '[email protected]',
    'email_subject': 'Test message from python library',
    'email_body': '<h1>Hello World</h1>'
}
for t in ['plain', 'html']:
    send_mail(params, t)
Varun Verma
sumber
Pikirkan jawaban ini mencakup segalanya. Tautan bagus
stingMantis
1

Inilah jawaban saya untuk AWS menggunakan 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 <[email protected]>',
    Destination={'ToAddresses': [email]},
    Message={
        'Subject': {'Data': subject},
        'Body': {
            'Html': {'Data': html}
        }
    }
Trent
sumber
0

Solusi paling sederhana untuk mengirim email dari akun Organisasi di 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()

di sini df adalah kerangka data yang dikonversi ke Tabel html, yang sedang disuntikkan ke html_template

Gil Baggio
sumber
Pertanyaannya tidak menyebutkan apa pun tentang penggunaan Office atau akun organisasi. Kontribusi yang baik tetapi tidak sangat membantu bagi penanya
Mwikala Kangwa