Mengirim email dari Python menggunakan SMTP

118

Saya menggunakan metode berikut untuk mengirim email dari Python menggunakan SMTP. Apakah ini metode yang tepat untuk digunakan atau adakah masalah yang saya lewatkan?

from smtplib import SMTP
import datetime

debuglevel = 0

smtp = SMTP()
smtp.set_debuglevel(debuglevel)
smtp.connect('YOUR.MAIL.SERVER', 26)
smtp.login('USERNAME@DOMAIN', 'PASSWORD')

from_addr = "John Doe <[email protected]>"
to_addr = "[email protected]"

subj = "hello"
date = datetime.datetime.now().strftime( "%d/%m/%Y %H:%M" )

message_text = "Hello\nThis is a mail from your server\n\nBye\n"

msg = "From: %s\nTo: %s\nSubject: %s\nDate: %s\n\n%s" 
        % ( from_addr, to_addr, subj, date, message_text )

smtp.sendmail(from_addr, to_addr, msg)
smtp.quit()
Eli Bendersky
sumber
2
Pastikan Anda mendapatkan Tanggal / Waktu dengan benar. Saya menemukan fungsi berikut cukup berguna, yang memberi Anda nilai yang diformat sempurna untuk Date-Header: docs.python.org/py3k/library/…
BastiBen
berikut adalah contoh kode yang memungkinkan untuk mengirim email dengan teks Unicode dalam subjek dan / atau isi
jfs
berikut adalah contoh kode yang menunjukkan cara mengirim gambar sebaris (ditambah email dengan html dan bagian teks biasa) . Ini juga menunjukkan bagaimana mengkonfigurasi parameter ssl pada versi Python lama.
jfs
2
Perhatikan bahwa ada perpustakaan pembungkus yang tersedia yang membuatnya jauh lebih sedikit kode untuk mengirim email (seperti yagmail )
PascalVKooten

Jawaban:

111

Skrip yang saya gunakan sangat mirip; Saya mempostingnya di sini sebagai contoh cara menggunakan modul email. * Untuk menghasilkan pesan MIME; sehingga skrip ini dapat dengan mudah dimodifikasi untuk melampirkan gambar, dll.

Saya mengandalkan ISP saya untuk menambahkan header waktu tanggal.

ISP saya mengharuskan saya menggunakan koneksi smtp yang aman untuk mengirim email, saya mengandalkan modul smtplib (dapat diunduh di http://www1.cs.columbia.edu/~db2501/ssmtplib.py )

Seperti pada skrip Anda, nama pengguna dan sandi, (diberikan nilai dummy di bawah), digunakan untuk otentikasi di server SMTP, dalam teks biasa di sumbernya. Ini adalah kelemahan keamanan; tetapi alternatif terbaik tergantung pada seberapa hati-hati Anda perlu (ingin?) untuk melindungi ini.

=======================================

#! /usr/local/bin/python


SMTPserver = 'smtp.att.yahoo.com'
sender =     'me@my_email_domain.net'
destination = ['recipient@her_email_domain.com']

USERNAME = "USER_NAME_FOR_INTERNET_SERVICE_PROVIDER"
PASSWORD = "PASSWORD_INTERNET_SERVICE_PROVIDER"

# typical values for text_subtype are plain, html, xml
text_subtype = 'plain'


content="""\
Test message
"""

subject="Sent from Python"

import sys
import os
import re

from smtplib import SMTP_SSL as SMTP       # this invokes the secure SMTP protocol (port 465, uses SSL)
# from smtplib import SMTP                  # use this for standard SMTP protocol   (port 25, no encryption)

# old version
# from email.MIMEText import MIMEText
from email.mime.text import MIMEText

try:
    msg = MIMEText(content, text_subtype)
    msg['Subject']=       subject
    msg['From']   = sender # some SMTP servers will do this automatically, not all

    conn = SMTP(SMTPserver)
    conn.set_debuglevel(False)
    conn.login(USERNAME, PASSWORD)
    try:
        conn.sendmail(sender, destination, msg.as_string())
    finally:
        conn.quit()

except:
    sys.exit( "mail failed; %s" % "CUSTOM_ERROR" ) # give an error message
Vincent Marchetti
sumber
1
@Vincent: email gagal; Objek 'module' tidak memiliki atribut 'SSLFakeSocket' - menggunakan Gmail :(
RadiantHex
Ini terdengar seperti masalah versi atau impor, untuk membantu melacaknya: Versi Python apa yang Anda jalankan? - Apakah Anda perlu terhubung ke server SMTP melalui SSL (dan jika demikian, apakah Anda mengimpor ssmtplib, seperti di atas)? Dapatkah Anda mengimpor smtplib langsung dari python interactive, jika demikian, apakah ada kelas smtplib.SSLFakeSocket yang ditentukan? Semoga saya bisa membantu
Vincent Marchetti
2
Gunakan smtplib.SMTP_SSL (standar dalam versi terbaru Python) untuk membuat koneksi alih-alih ssmtplib.STMP_SSL (modul pihak ketiga yang diisyaratkan di atas). Perhatikan modul standar dimulai dengan satu 's'. Itu berhasil untuk saya.
Julio Gorgé
2
ganti from ssmtplib import SMTP_SSL as SMTPdengan from smtplib import SMTP_SSL as SMTP, dan contoh ini akan bekerja dari pustaka Python standar.
Adam Matan
9
Tambah msg['To'] = ','.join(destination), Jika tidak, tujuan tidak dilihat di gmail
Taha Jahangir
88

Cara yang biasa saya gunakan ... tidak jauh berbeda tapi sedikit

import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText

msg = MIMEMultipart()
msg['From'] = '[email protected]'
msg['To'] = '[email protected]'
msg['Subject'] = 'simple email in python'
message = 'here is the email'
msg.attach(MIMEText(message))

mailserver = smtplib.SMTP('smtp.gmail.com',587)
# identify ourselves to smtp gmail client
mailserver.ehlo()
# secure our email with tls encryption
mailserver.starttls()
# re-identify ourselves as an encrypted connection
mailserver.ehlo()
mailserver.login('[email protected]', 'mypassword')

mailserver.sendmail('[email protected]','[email protected]',msg.as_string())

mailserver.quit()

Itu dia

orang gila 2890
sumber
Jika Anda menggunakan Verifikasi 2 Langkah, Anda harus membuat kata sandi khusus Aplikasi terlebih dahulu dan mengganti kata sandi normal Anda dengannya. Lihat Masuk menggunakan Kata Sandi Aplikasi
Suzana
2
Saya setuju, ini adalah jawaban terbaik dan harus diterima. Yang diterima sebenarnya lebih rendah.
HelloWorld
7
Untuk python3, gunakan:from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText
art
21

Juga jika Anda ingin melakukan smtp auth dengan TLS sebagai lawan dari SSL maka Anda hanya perlu mengubah port (gunakan 587) dan lakukan smtp.starttls (). Ini berhasil untuk saya:

...
smtp.connect('YOUR.MAIL.SERVER', 587)
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
smtp.login('USERNAME@DOMAIN', 'PASSWORD')
...

sumber
6

Gotcha utama yang saya lihat adalah Anda tidak menangani kesalahan apa pun: .login () dan .sendmail () keduanya telah mendokumentasikan pengecualian yang dapat mereka lempar, dan sepertinya .connect () harus memiliki beberapa cara untuk menunjukkan bahwa itu tidak dapat terhubung - mungkin pengecualian yang diberikan oleh kode soket yang mendasarinya.

pjz
sumber
6

Pastikan Anda tidak memiliki firewall yang memblokir SMTP. Pertama kali saya mencoba mengirim email, itu diblokir oleh Windows Firewall dan McAfee - butuh waktu lama untuk menemukan keduanya.

Mark Ransom
sumber
6

Bagaimana dengan ini?

import smtplib

SERVER = "localhost"

FROM = "[email protected]"
TO = ["[email protected]"] # must be a list

SUBJECT = "Hello!"

TEXT = "This message was sent with Python's smtplib."

# Prepare actual message

message = """\
From: %s
To: %s
Subject: %s

%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)

# Send the mail

server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO, message)
server.quit()
Satish
sumber
4

kode berikut berfungsi dengan baik untuk saya:

import smtplib

to = '[email protected]'
gmail_user = '[email protected]'
gmail_pwd = 'yourpassword'
smtpserver = smtplib.SMTP("smtp.gmail.com",587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo() # extra characters to permit edit
smtpserver.login(gmail_user, gmail_pwd)
header = 'To:' + to + '\n' + 'From: ' + gmail_user + '\n' + 'Subject:testing \n'
print header
msg = header + '\n this is test msg from mkyong.com \n\n'
smtpserver.sendmail(gmail_user, to, msg)
print 'done!'
smtpserver.quit()

Ref: http://www.mkyong.com/python/how-do-send-email-in-python-via-smtplib/

Abdul Majeed
sumber
1
Flask memiliki kerangka kerja untuk email: dari flask.ext.mail import Mail. Saya memecahkan masalah itu, dan berpikir saya akan kembali ke kode Python untuk melihat apakah saya bisa mendapatkan sesuatu untuk bekerja. Saya menyukai jawaban ini karena tidak memiliki tulang belulang. Oh ya, dan berhasil!
Perhatian: Versi jawaban sebelumnya menyertakan baris: smtpserver.close()Ini harus:, smtpserver.quit()karena close()tidak akan memutuskan koneksi TLS dengan benar! close()akan dipanggil selama quit().
aronadaal
Hai, Saya mengalami masalah saat menjalankan perintah di atas. ketika saya menggunakan smtpserver.starttls (), saya mendapatkan kesalahan SMTP "SMTPServerDisconnected: Sambungan tiba-tiba ditutup: [Errno 10054]" .. dilaporkan di stackoverflow.com/questions/46094175/…
fazkan
3

Anda harus memastikan Anda memformat tanggal dalam format yang benar - RFC2822 .

Douglas Leeder
sumber
3

Kode contoh yang saya lakukan untuk mengirim email menggunakan SMTP.

import smtplib, ssl

smtp_server = "smtp.gmail.com"
port = 587  # For starttls
sender_email = "sender@email"
receiver_email = "receiver@email"
password = "<your password here>"
message = """ Subject: Hi there

This message is sent from Python."""


# Create a secure SSL context
context = ssl.create_default_context()

# Try to log in to server and send email
server = smtplib.SMTP(smtp_server,port)

try:
    server.ehlo() # Can be omitted
    server.starttls(context=context) # Secure the connection
    server.ehlo() # Can be omitted
    server.login(sender_email, password)
    server.sendmail(sender_email, receiver_email, message)
except Exception as e:
    # Print any error messages to stdout
    print(e)
finally:
    server.quit()
Hariharan AR
sumber
2

Lihat semua jawaban yang panjang itu? Izinkan saya untuk mempromosikan diri sendiri dengan melakukan semuanya dalam beberapa baris.

Impor dan Hubungkan:

import yagmail
yag = yagmail.SMTP('[email protected]', host = 'YOUR.MAIL.SERVER', port = 26)

Maka itu hanya satu baris:

yag.send('[email protected]', 'hello', 'Hello\nThis is a mail from your server\n\nBye\n')

Ini benar-benar akan menutup ketika keluar dari ruang lingkup (atau dapat ditutup secara manual). Selanjutnya, ini akan memungkinkan Anda untuk mendaftarkan nama pengguna Anda di keyring Anda sehingga Anda tidak perlu menulis kata sandi Anda di skrip Anda (itu benar-benar mengganggu saya sebelum menulis yagmail!)

Untuk paket / instalasi, tips dan trik silahkan lihat di git atau pip , tersedia untuk Python 2 dan 3.

PascalVKooten
sumber
@PascalvKoolen Saya menginstal yagmail, dan mencoba menghubungkan dengan memberikan id email dan kata sandi saya. tetapi itu memberi saya kesalahan otentikasi
fazkan
0

kamu bisa melakukan seperti itu

import smtplib
from email.mime.text import MIMEText
from email.header import Header


server = smtplib.SMTP('mail.servername.com', 25)
server.ehlo()
server.starttls()

server.login('username', 'password')
from = '[email protected]'
to = '[email protected]'
body = 'That A Message For My Girl Friend For tell Him If We will go to eat Something This Nigth'
subject = 'Invite to A Diner'
msg = MIMEText(body,'plain','utf-8')
msg['Subject'] = Header(subject, 'utf-8')
msg['From'] = Header(from, 'utf-8')
msg['To'] = Header(to, 'utf-8')
message = msg.as_string()
server.sendmail(from, to, message)
Skiller Dz
sumber
0

Berikut adalah contoh kerja untuk Python 3.x

#!/usr/bin/env python3

from email.message import EmailMessage
from getpass import getpass
from smtplib import SMTP_SSL
from sys import exit

smtp_server = 'smtp.gmail.com'
username = '[email protected]'
password = getpass('Enter Gmail password: ')

sender = '[email protected]'
destination = '[email protected]'
subject = 'Sent from Python 3.x'
content = 'Hello! This was sent to you via Python 3.x!'

# Create a text/plain message
msg = EmailMessage()
msg.set_content(content)

msg['Subject'] = subject
msg['From'] = sender
msg['To'] = destination

try:
    s = SMTP_SSL(smtp_server)
    s.login(username, password)
    try:
        s.send_message(msg)
    finally:
        s.quit()

except Exception as E:
    exit('Mail failed: {}'.format(str(E)))
Menandai
sumber
0

Berdasarkan contoh ini saya membuat fungsi berikut:

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

def send_email(host, port, user, pwd, recipients, subject, body, html=None, from_=None):
    """ copied and adapted from
        /programming/10147455/how-to-send-an-email-with-gmail-as-provider-using-python#12424439
    returns None if all ok, but if problem then returns exception object
    """

    PORT_LIST = (25, 587, 465)

    FROM = from_ if from_ else user 
    TO = recipients if isinstance(recipients, (list, tuple)) else [recipients]
    SUBJECT = subject
    TEXT = body.encode("utf8") if isinstance(body, unicode) else body
    HTML = html.encode("utf8") if isinstance(html, unicode) else html

    if not html:
        # Prepare actual message
        message = """From: %s\nTo: %s\nSubject: %s\n\n%s
        """ % (FROM, ", ".join(TO), SUBJECT, TEXT)
    else:
                # /programming/882712/sending-html-email-using-python#882770
        msg = MIMEMultipart('alternative')
        msg['Subject'] = SUBJECT
        msg['From'] = FROM
        msg['To'] = ", ".join(TO)

        # Record the MIME types of both parts - text/plain and text/html.
        # utf-8 -> /programming/5910104/python-how-to-send-utf-8-e-mail#5910530
        part1 = MIMEText(TEXT, 'plain', "utf-8")
        part2 = MIMEText(HTML, 'html', "utf-8")

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

        message = msg.as_string()


    try:
        if port not in PORT_LIST: 
            raise Exception("Port %s not one of %s" % (port, PORT_LIST))

        if port in (465,):
            server = smtplib.SMTP_SSL(host, port)
        else:
            server = smtplib.SMTP(host, port)

        # optional
        server.ehlo()

        if port in (587,): 
            server.starttls()

        server.login(user, pwd)
        server.sendmail(FROM, TO, message)
        server.close()
        # logger.info("SENT_EMAIL to %s: %s" % (recipients, subject))
    except Exception, ex:
        return ex

    return None

jika Anda hanya meneruskan bodymaka surat teks biasa akan dikirim, tetapi jika Anda memberikan htmlargumen bersama dengan bodyargumen, email html akan dikirim (dengan fallback ke konten teks untuk klien email yang tidak mendukung jenis html / mime).

Contoh penggunaan:

ex = send_email(
      host        = 'smtp.gmail.com'
   #, port        = 465 # OK
    , port        = 587  #OK
    , user        = "[email protected]"
    , pwd         = "xxx"
    , from_       = '[email protected]'
    , recipients  = ['[email protected]']
    , subject     = "Test from python"
    , body        = "Test from python - body"
    )
if ex: 
    print("Mail sending failed: %s" % ex)
else:
    print("OK - mail sent"

Btw. Jika Anda ingin menggunakan gmail sebagai server SMTP pengujian atau produksi, aktifkan sementara atau akses permanen ke aplikasi yang kurang aman:

Robert Lujo
sumber