SMTP kullanarak Python'dan posta gönderme


118

SMTP kullanarak Python'dan posta göndermek için aşağıdaki yöntemi kullanıyorum. Doğru yöntem mi yoksa kaçırdığım şeyler var mı?

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 <john@doe.net>"
to_addr = "foo@bar.com"

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

2
Tarih / Saati doğru aldığınızdan emin olun. Size Tarih Başlığı için mükemmel biçimlendirilmiş bir değer veren aşağıdaki işlevi oldukça kullanışlı buldum: docs.python.org/py3k/library/…
BastiBen


Resimlerin satır içi olarak nasıl gönderileceğini gösteren bir kod örneği (artı hem html hem de düz metin bölümleri içeren e-posta) . Ayrıca eski Python sürümlerinde ssl parametrelerinin nasıl yapılandırılacağını da gösterir.
jfs

2
E-posta göndermeyi çok daha az kod haline getiren paket kitaplıkları olduğunu unutmayın ( yagmail gibi )
PascalVKooten

Yanıtlar:


111

Kullandığım komut dosyası oldukça benzer; MIME mesajları oluşturmak için e-posta. * Modüllerinin nasıl kullanılacağına dair bir örnek olarak buraya gönderiyorum; böylece bu komut dosyası, resim vb. eklemek için kolayca değiştirilebilir.

Tarih saat başlığını eklemek için ISS'ye güveniyorum.

ISS'm posta göndermek için güvenli bir smtp bağlantısı kullanmamı gerektiriyor, smtplib modülüne güveniyorum ( http://www1.cs.columbia.edu/~db2501/ssmtplib.py adresinden indirilebilir )

Komut dosyanızda olduğu gibi, SMTP sunucusunda kimlik doğrulaması için kullanılan kullanıcı adı ve parola (aşağıda kukla değerler verilmiştir), kaynakta düz metindir. Bu bir güvenlik zayıflığıdır; ancak en iyi alternatif, bunları korumak için ne kadar dikkatli olmanız gerektiğine (istediğinize?) bağlıdır.

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

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

1
@Vincent: posta başarısız oldu; 'modül' nesnesinin 'SSLFakeSocket' özniteliği yok - Gmail kullanılıyor :(
RadiantHex

Bu, izini sürmeye yardımcı olmak için bir sürüm veya içe aktarma sorununa benziyor: Hangi Python sürümünü çalıştırıyorsunuz? - SMTP sunucunuza SSL üzerinden bağlanmanız gerekiyor mu (ve eğer öyleyse, yukarıdaki gibi ssmtplib'i içe aktarıyorsunuz)? Smtplib'i doğrudan python Interactive'den içe aktarabilir misiniz, eğer öyleyse, tanımlanmış bir smtplib.SSLFakeSocket sınıfı var mı? Umarım yardımcı olabilirim
Vincent Marchetti

2
Bağlantı oluşturmak için smtplib.STMP_SSL (yukarıda ima edilen üçüncü taraf modülü) yerine smtplib.SMTP_SSL (Python'un son sürümlerinde standart) kullanın. Standart modülün tek bir 's' ile başladığına dikkat edin. Bu benim için çalıştı.
Julio Gorgé

2
yerine from ssmtplib import SMTP_SSL as SMTPsahip from smtplib import SMTP_SSL as SMTPve bu örnek standart Python kütüphanesinden çalışacak.
Adam Matan

9
Ekle msg['To'] = ','.join(destination), Aksi takdirde hedef gmail'de görüntülenmiyor
Taha Jahangir

88

Genelde kullandığım yöntem ... çok farklı değil ama biraz

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

msg = MIMEMultipart()
msg['From'] = 'me@gmail.com'
msg['To'] = 'you@gmail.com'
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('me@gmail.com', 'mypassword')

mailserver.sendmail('me@gmail.com','you@gmail.com',msg.as_string())

mailserver.quit()

Bu kadar


2 Adımlı Doğrulama kullanıyorsanız, önce Uygulamaya özel bir şifre oluşturmanız ve normal şifrenizi bununla değiştirmeniz gerekir. Bkz . Uygulama Şifrelerini kullanarak oturum açma
Suzana

2
Katılıyorum, bu en iyi cevap ve kabul edilmelidir. Gerçekte kabul edilen, aşağılıktır.
HelloWorld

6
Python3 için kullanım:from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText
sanat

21

Ayrıca, SSL yerine TLS ile smtp kimlik doğrulaması yapmak istiyorsanız, bağlantı noktasını değiştirmeniz (587 kullanın) ve smtp.starttls () yapmanız yeterlidir. Bu benim için çalıştı:

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

6

Gördüğüm en önemli şey, herhangi bir hatayı işlemediğinizdir: .login () ve .sendmail () her ikisi de atabilecekleri istisnaları belgelemiştir ve .connect (), bağlanılamıyor - muhtemelen temel soket kodu tarafından atılan bir istisna.


6

SMTP'yi engelleyen herhangi bir güvenlik duvarınız olmadığından emin olun. İlk kez bir e-posta göndermeyi denediğimde, hem Windows Güvenlik Duvarı hem de McAfee tarafından engellendi - ikisini de bulmak sonsuza kadar sürdü.


6

Peki buna ne dersin?

import smtplib

SERVER = "localhost"

FROM = "sender@example.com"
TO = ["user@example.com"] # 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()

4

aşağıdaki kod benim için iyi çalışıyor:

import smtplib

to = 'mkyong2002@yahoo.com'
gmail_user = 'mkyong2002@gmail.com'
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()

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


1
Flask, e-posta için bir çerçeveye sahiptir: flask.ext.mail'den import Mail. Sorun gideriyorum ve çalışacak bir şey alıp alamayacağımı görmek için Python koduna geri döneceğimi düşündüm. Bu cevabı sevdim çünkü çıplak kemiklerdi. Oh evet ve işe yaradı!

Dikkat: Cevabın önceki versiyonu şu satırı içeriyordu: smtpserver.close()Olması gereken:, smtpserver.quit()çünkü close()TLS bağlantısını düzgün bir şekilde sonlandırmayacak! close()sırasında çağrılacak quit().
aronadaal

Merhaba, yukarıdaki komutları çalıştırmada sorun yaşıyorum. smtpserver.starttls () kullandığımda bir SMTP hatası alıyorum "SMTPServerDisconnected: Bağlantı beklenmedik şekilde kapandı: [Errno 10054]" .. stackoverflow.com/questions/46094175/…
adresinde


3

SMTP kullanarak posta göndermek için yaptığım örnek kod.

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

2

Tüm bu uzun cevapları görüyor musun? Lütfen hepsini birkaç satırda yaparak kendimi tanıtmama izin verin.

İçe Aktar ve Bağlan:

import yagmail
yag = yagmail.SMTP('john@doe.net', host = 'YOUR.MAIL.SERVER', port = 26)

O zaman bu sadece bir satırlık:

yag.send('foo@bar.com', 'hello', 'Hello\nThis is a mail from your server\n\nBye\n')

Kapsam dışına çıktığında aslında kapanacaktır (veya manuel olarak kapatılabilir). Ayrıca, kullanıcı adınızı anahtarlığınıza kaydetmenize olanak tanır, böylece şifrenizi komut dosyanıza yazmanıza gerek kalmaz (yazmadan önce beni gerçekten rahatsız etti yagmail!)

Paket / kurulum, ipuçları ve püf noktaları için lütfen hem Python 2 hem de 3 için mevcut olan git veya pip'e bakın .


@PascalvKoolen yagmail'i kurdum ve e-posta kimliğimi ve şifremi vererek bağlanmayı denedim. ama bana bir kimlik doğrulama hatası verdi
fazkan

0

bunu beğenebilirsin

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 = 'me@servername.com'
to = 'mygfriend@servername.com'
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)

0

İşte Python 3.x için çalışan bir örnek

#!/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 = 'your_email_address@gmail.com'
password = getpass('Enter Gmail password: ')

sender = 'your_email_address@gmail.com'
destination = 'recipient_email_address@gmail.com'
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)))

0

Bu örneğe dayanarak aşağıdaki işlevi yaptım:

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

yalnızca bodyiletirseniz, düz metin postası gönderilir, ancak htmlbağımsız değişkenle birlikte bodybağımsız değişken geçirirseniz , html e-postası gönderilir (html / mime türlerini desteklemeyen e-posta istemcileri için metin içeriğine geri dönüş ile).

Örnek kullanım:

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

Btw. Gmail'i test veya üretim SMTP sunucusu olarak kullanmak istiyorsanız, daha az güvenli uygulamalara geçici veya kalıcı erişimi etkinleştirin:

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.