Python kullanarak Gmail ile sağlayıcı olarak e-posta nasıl gönderilir?


289

Python kullanarak e-posta (Gmail) göndermeye çalışıyorum, ancak aşağıdaki hatayı alıyorum.

Traceback (most recent call last):  
File "emailSend.py", line 14, in <module>  
server.login(username,password)  
File "/usr/lib/python2.5/smtplib.py", line 554, in login  
raise SMTPException("SMTP AUTH extension not supported by server.")  
smtplib.SMTPException: SMTP AUTH extension not supported by server.

Python betiği şöyledir.

import smtplib
fromaddr = 'user_me@gmail.com'
toaddrs  = 'user_you@gmail.com'
msg = 'Why,Oh why!'
username = 'user_me@gmail.com'
password = 'pwd'
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login(username,password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()

16
Google'ın gmail yoluyla mesaj göndermek için dahili bir API'ye doğru ilerlediği için bu sorunun kilidi açılmalıdır. Bu hamle, bu cevaplardan biri hariç hepsini güncelliğini yitirdi ve ilgili bir cevap, problemi çözme konusunda çok hafif.
Andrew

Ayrıca, VPN kullanıcıları için sorun devam ederse VPN'nizi kapatın. Bu benim için çalıştı.
Paul

Yanıtlar:


211

EHLODoğrudan doğruya koşmadan önce söylemeniz gerekir STARTTLS:

server = smtplib.SMTP('smtp.gmail.com:587')
server.ehlo()
server.starttls()

Ayrıca gerçekten oluşturmalı From:, To:ve Subject:mesaj başlıklarını, bir satır boşluk ve kullanımı ile mesaj gövdesinden ayrılmış CRLFEOL işaretler olarak.

Örneğin

msg = "\r\n".join([
  "From: user_me@gmail.com",
  "To: user_you@gmail.com",
  "Subject: Just a message",
  "",
  "Why, oh why"
  ])

2
server.sendmail'i (fromaddr, toaddrs, msg) çağırmak için ikinci parametre, toaddrs bir liste olmalı, toaddrs = ['user_me@gmail.com']
Massimo Fazzolari 20:13

14
Ağustos 2014 itibariyle bu durum smtplib'i yükseltiyor.SMTPAuthenticationError: (534, '5.7.9 Uygulamaya özel şifre gerekli.
anon58192932

7
Yine de benim için, bir python aracılığıyla e-posta göndermek için bir @google hesabı kullanarak giriş yapmak için bir 'uygulama' şifresini etkinleştirmem gerekiyordu: support.google.com/accounts/answer/…
anon58192932

1
Birden fazla kişiye nasıl posta gönderileceği ile ilgili bir bağlantı: stackoverflow.com/questions/8856117/…
anon58192932

1
Bir keresinde telnet ile bir SMTP sunucusunda oturum açtım ve EHLOyazım hatasıyla gönderdim . HELO'yu defalarca denedikten sonra cevap farklıydı. EHLO'nun aslında SMTP'nin anladığı bir komut olduğunu anlamak saatler sürdü ve yazım hatasını yaptım.
Shiplu Mokaddim

297
def send_email(user, pwd, recipient, subject, body):
    import smtplib

    FROM = user
    TO = recipient if isinstance(recipient, list) else [recipient]
    SUBJECT = subject
    TEXT = body

    # Prepare actual message
    message = """From: %s\nTo: %s\nSubject: %s\n\n%s
    """ % (FROM, ", ".join(TO), SUBJECT, TEXT)
    try:
        server = smtplib.SMTP("smtp.gmail.com", 587)
        server.ehlo()
        server.starttls()
        server.login(user, pwd)
        server.sendmail(FROM, TO, message)
        server.close()
        print 'successfully sent the mail'
    except:
        print "failed to send mail"

465 numaralı bağlantı noktasını kullanmak istiyorsanız bir SMTP_SSLnesne oluşturmanız gerekir :

# SMTP_SSL Example
server_ssl = smtplib.SMTP_SSL("smtp.gmail.com", 465)
server_ssl.ehlo() # optional, called by login()
server_ssl.login(gmail_user, gmail_pwd)  
# ssl server doesn't support or need tls, so don't call server_ssl.starttls() 
server_ssl.sendmail(FROM, TO, message)
#server_ssl.quit()
server_ssl.close()
print 'successfully sent the mail'

2
Çok güzel örnek teşekkürler. Bir SSL bağlantısı kullanmak istiyorsam server.starttls () kaldırmak zorunda kaldım
Dowlers

18
Maalesef artık çalışmıyor: smtplib.SMTPAuthenticationError: (534, '5.7.14 < accounts.google.com/… ... Lütfen web tarayıcınızdan giriş yapın ve \ n5.7.14 tekrar deneyin. \ N5.7.14 Daha fazla bilgi daha fazla \ n5.7.14 support.google.com/mail/bin/answer.py?answer=78754 ... Sonra Google'dan şüpheli bir bağlantı girişimi olduğunu belirten bir posta aldım.
royskatt

13
@royskatt - tek yapmanız gereken bir uygulama şifresi oluşturmak ve bunu hesap şifrenizin yerine kullanmaktır. Burada bir uygulama şifresi oluşturun: security.google.com/settings/security/apppasswords
Jared

15
@royskatt: Karşılaştığınız sorunla ilgili bir düzeltme aldım. Google'ın daha az güvenli uygulamalara erişime izin veren bir ayarı vardır, sadece 'Açık' konuma getirmeniz gerekir. oradan şuradan ulaşabilirsiniz: Google -> hesabım -> Oturum açma ve güvenlik -> Bağlı uygulamalar ve siteler -> aşağı kaydırın ve 'Daha az güvenli uygulamalara izin ver' bulacaksınız
shaleen mohan

2
Gmail'iniz İki Faktörlü Kimlik Doğrulama ile korunuyorsa, önce uygulamaya özel bir şifre oluşturmalısınız -> yukarıdaki örnek kodda bu uygulama şifresini kullanmalısınız (bu çok önemlidir, çünkü daha sonra şifrenizi hiçbir yere yazmıyorsunuzdur. açık metin olarak VE istediğiniz zaman uygulama şifresini iptal edebilirsiniz).
Trevor Boyd Smith

136

Benzer bir sorunla karşılaştım ve bu soru üzerine tökezledim. SMTP Kimlik Doğrulama Hatası aldım ancak kullanıcı adım / parolam doğruydu. İşte bunu düzeltti. Bunu okudum:

https://support.google.com/accounts/answer/6010255

Özetle, google smtplib yoluyla giriş yapmanıza izin vermiyor çünkü bu tür girişleri "daha az güvenli" olarak işaretlediğinden, yapmanız gereken şey google hesabınıza giriş yaparken bu bağlantıya gitmek, ve erişime izin ver:

https://www.google.com/settings/security/lesssecureapps

Bu ayarlandıktan sonra (aşağıdaki ekran görüntüme bakın), çalışması gerekir.

resim açıklamasını buraya girin

Giriş şimdi çalışıyor:

smtpserver = smtplib.SMTP("smtp.gmail.com", 587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo()
smtpserver.login('me@gmail.com', 'me_pass')

Değişiklik sonrası yanıt:

(235, '2.7.0 Accepted')

Önceki yanıt:

smtplib.SMTPAuthenticationError: (535, '5.7.8 Username and Password not accepted. Learn more at\n5.7.8 http://support.google.com/mail/bin/answer.py?answer=14257 g66sm2224117qgf.37 - gsmtp')

Hala çalışmıyor? SMTPAuthenticationError'ı hala alıyorsanız ancak şimdi kod 534 ise, konumu bilinmemektedir. Bu bağlantıyı takip et:

https://accounts.google.com/DisplayUnlockCaptcha

Devam'ı tıklayın; bu, yeni uygulamanızı kaydetmeniz için 10 dakika sürecektir. Şimdi başka bir giriş denemesi yapmaya devam edin ve çalışması gerekir.

GÜNCELLEME : Bu hemen çalışmıyor gibi görünüyor smptlib bu hatayı alırken bir süre sıkışmış olabilir:

235 == 'Authentication successful'
503 == 'Error: already authenticated'

Mesaj, oturum açmak için tarayıcıyı kullandığını söylüyor:

SMTPAuthenticationError: (534, '5.7.9 Please log in with your web browser and then try again. Learn more at\n5.7.9 https://support.google.com/mail/bin/answer.py?answer=78754 qo11sm4014232igb.17 - gsmtp')

'Lesssecureapps' özelliğini etkinleştirdikten sonra, bir kahve alın, geri dönün ve 'DisplayUnlockCaptcha' bağlantısını tekrar deneyin. Kullanıcı deneyiminden, değişikliğin devreye girmesi bir saat kadar sürebilir. Ardından oturum açma işlemini tekrar deneyin.


3
EVET TEŞEKKÜR EDERİM ! Flask posta kullanırken oldu
Giannis

1
teşekkürler adam benim için sadece sorun: accounts.google.com/DisplayUnlockCaptcha
Limitless isa

6
Ayrıca, ayarların değişmesi için lütfen yarım saat ila bir saat bırakın. Yeni bir hesap oluşturdum, eklenen tüm güvenliği devre dışı bıraktım ve hala aynı hatayı aldım. Yaklaşık bir saat sonra her şey işe yaradı.
jkgeyti

2
"2 Adımlı Doğrulama" etkinse daha az güvenli uygulamaların etkinleştirilmesi mümkün değildir. En iyi ve en güvenli seçenek, daha önce önerildiği gibi "apppassword" security.google.com/settings/security/apppasswords özelliğini etkinleştirmektir ve bir cazibe gibi çalışır
Omiod

2
Uygulama şifreleri bağlantısını izlediğimde, tüm Google hesaplarımda "Aradığınız ayar hesabınız için kullanılamıyor" hatası alır.
Suzanne

18

OOP ile aşağı mısın?

#!/usr/bin/env python


import smtplib

class Gmail(object):
    def __init__(self, email, password):
        self.email = email
        self.password = password
        self.server = 'smtp.gmail.com'
        self.port = 587
        session = smtplib.SMTP(self.server, self.port)        
        session.ehlo()
        session.starttls()
        session.ehlo
        session.login(self.email, self.password)
        self.session = session

    def send_message(self, subject, body):
        ''' This must be removed '''
        headers = [
            "From: " + self.email,
            "Subject: " + subject,
            "To: " + self.email,
            "MIME-Version: 1.0",
           "Content-Type: text/html"]
        headers = "\r\n".join(headers)
        self.session.sendmail(
            self.email,
            self.email,
            headers + "\r\n\r\n" + body)


gm = Gmail('Your Email', 'Password')

gm.send_message('Subject', 'Message')

33
Sınıfınızda yalnızca biri __init__ olan iki yöntem varsa, yalnızca bir işlev kullanın.
JoeQuery

Bu yöntemi kullanarak bir eki nasıl eklersiniz?
sgerbhctim

İstemciyi başlatmak ve bir e-posta ve parola vermek yerine onu kodun diğer bölümlerine iletmek istiyorsanız bir sınıf kullanmak iyi olur. Veya her seferinde e-posta ve şifreyi geçmeden birkaç mesaj göndermek istiyorsanız.
Sami

15

Bu çalışıyor

Gmail APP Şifresi oluşturun!

Bunu oluşturduktan sonra şu adlı bir dosya oluşturun: sendgmail.py

Ardından bu kodu ekleyin :

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# Created By  : Jeromie Kirchoff
# Created Date: Mon Aug 02 17:46:00 PDT 2018
# =============================================================================
# Imports
# =============================================================================
import smtplib

# =============================================================================
# SET EMAIL LOGIN REQUIREMENTS
# =============================================================================
gmail_user = 'THEFROM@gmail.com'
gmail_app_password = 'YOUR-GOOGLE-APPLICATION-PASSWORD!!!!'

# =============================================================================
# SET THE INFO ABOUT THE SAID EMAIL
# =============================================================================
sent_from = gmail_user
sent_to = ['THE-TO@gmail.com', 'THE-TO@gmail.com']
sent_subject = "Where are all my Robot Women at?"
sent_body = ("Hey, what's up? friend!\n\n"
             "I hope you have been well!\n"
             "\n"
             "Cheers,\n"
             "Jay\n")

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

%s
""" % (sent_from, ", ".join(sent_to), sent_subject, sent_body)

# =============================================================================
# SEND EMAIL OR DIE TRYING!!!
# Details: http://www.samlogic.net/articles/smtp-commands-reference.htm
# =============================================================================

try:
    server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
    server.ehlo()
    server.login(gmail_user, gmail_app_password)
    server.sendmail(sent_from, sent_to, email_text)
    server.close()

    print('Email sent!')
except Exception as exception:
    print("Error: %s!\n\n" % exception)

Yani, başarılı olursanız, böyle bir görüntü görürsünüz:

Kendime ve kendime bir e-posta göndererek test ettim.

Başarılı e-posta gönderildi.

Not: Hesabımda 2 Adımlı Doğrulama etkin. Uygulama Şifresi bununla çalışır! (gmail smtp kurulumu için https://support.google.com/accounts/answer/185833?hl=tr adresine gitmeli ve aşağıdaki adımları izlemelisiniz)

Bu ayar, 2 Adımlı Doğrulama'nın etkin olduğu hesaplar için kullanılamaz. Bu tür hesaplar, daha az güvenli uygulama erişimi için uygulamaya özel bir şifre gerektirir.

Daha az güvenli uygulama erişimi ... Bu ayar, 2 Adımlı Doğrulama'nın etkin olduğu hesaplar için kullanılamaz.


1
Fantastik bir çözüm ve çok iyi kod açıkladı. Teşekkür ederim Jay, çok takdir ediyorum. Aptalca soru: Günlük gönderilen e-postaların maksimum sınırının ne olduğunu (gmail ile) biliyor musunuz?
Angelo

@Angelo teşekkür ederim ama evet bir sınır var, GMail = 500 e-posta veya 500 alıcı / Gün ref: support.google.com/mail/answer/22839 G SUITE farklıdır ve 2000 mesaj / gün'dür ve burada bulunabilir: destek .google.com / a / answer / 166852 İyi Şanslar!
JayRizzo

2
Diğerleri daha eski gönderilerdir ve çalışmıyor olabilirler, ancak bu% 100 çalışıyor. Uygulama şifreleri oluşturun. Cevabınız için teşekkürler
Shubh

1
Bu çözümün daha fazla oyu olmadığına biraz şaşırdım. Ben denemedim tüm diğerlerini ama birkaç denedim ve sadece bu bir 0 müdahalesi ile, kutunun dışında çalıştı.
mcouthon

14

Burada bulabilirsiniz: http://jayrambhia.com/blog/send-emails-using-python

smtp_host = 'smtp.gmail.com'
smtp_port = 587
server = smtplib.SMTP()
server.connect(smtp_host,smtp_port)
server.ehlo()
server.starttls()
server.login(user,passw)
fromaddr = raw_input('Send mail by the name of: ')
tolist = raw_input('To: ').split()
sub = raw_input('Subject: ')

msg = email.MIMEMultipart.MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = email.Utils.COMMASPACE.join(tolist)
msg['Subject'] = sub  
msg.attach(MIMEText(raw_input('Body: ')))
msg.attach(MIMEText('\nsent via python', 'plain'))
server.sendmail(user,tolist,msg.as_string())

2
artı 1 çünkü MIME oluşturmak kendi biçim dizenizi sabit kodlamaktan daha iyidir. Basit bir kısa mesaj için MIMEMultipart gerekli mi? Veya aşağıdakiler de doğrudur: stackoverflow.com/a/6270987/895245
Ciro Santilli 12: 冠状 病 六四 事件 法轮功

E-posta değişkenini nerede somutlaştırıyorsunuz?
madcat

11

Doğrudan ilgili değil, ama yine de dikkat çekmeye değer, paketimin gmail mesajlarını gerçekten hızlı ve acısız göndermeye çalıştığı. Ayrıca hataların bir listesini tutmaya çalışır ve çözümü hemen göstermeye çalışır.

Kelimenin tam anlamıyla tam olarak yazdıklarınızı yapmak için bu koda ihtiyaç duyar:

import yagmail
yag = yagmail.SMTP('user_me@gmail.com')
yag.send('user_you@gmail.com', 'Why,Oh why!')

Veya bir astar:

yagmail.SMTP('user_me@gmail.com').send('user_you@gmail.com', 'Why,Oh why!')

Paket / kurulum için lütfen Python 2 ve 3 için mevcut olan git veya pip'e bakın .


9

İşte bir Gmail API örneği. Daha karmaşık olmasına rağmen, 2019'da çalışan bulduğum tek yöntem bu. Bu örnek alındı ​​ve değiştirildi:

https://developers.google.com/gmail/api/guides/sending

Web siteleri aracılığıyla Google'ın API arayüzleriyle bir proje oluşturmanız gerekir. Ardından, uygulamanız için GMAIL API'sını etkinleştirmeniz gerekir. Kimlik bilgileri oluşturun ve ardından bu kredileri indirin, credentials.json olarak kaydedin.

import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

from email.mime.text import MIMEText
import base64

#pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly', 'https://www.googleapis.com/auth/gmail.send']

def create_message(sender, to, subject, msg):
    message = MIMEText(msg)
    message['to'] = to
    message['from'] = sender
    message['subject'] = subject

    # Base 64 encode
    b64_bytes = base64.urlsafe_b64encode(message.as_bytes())
    b64_string = b64_bytes.decode()
    return {'raw': b64_string}
    #return {'raw': base64.urlsafe_b64encode(message.as_string())}

def send_message(service, user_id, message):
    #try:
    message = (service.users().messages().send(userId=user_id, body=message).execute())
    print( 'Message Id: %s' % message['id'] )
    return message
    #except errors.HttpError, error:print( 'An error occurred: %s' % error )

def main():
    """Shows basic usage of the Gmail API.
    Lists the user's Gmail labels.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('gmail', 'v1', credentials=creds)

    # Example read operation
    results = service.users().labels().list(userId='me').execute()
    labels = results.get('labels', [])

    if not labels:
        print('No labels found.')
    else:
        print('Labels:')
    for label in labels:
        print(label['name'])

    # Example write
    msg = create_message("from@gmail.com", "to@gmail.com", "Subject", "Msg")
    send_message( service, 'me', msg)

if __name__ == '__main__':
    main()

smtplib tamamen iş parçacığı için güvenli değildir, bu nedenle eşzamanlı mesaj gönderme sorunları olacaktır. Bu doğru yaklaşım.
dsbajna

2

Artık, e-posta göndermenizi, e-postalarınızı okumanızı ve REST yoluyla taslaklar oluşturmanızı sağlayan bir gmail API'si var. SMTP çağrılarının aksine, istek iş parçacığında (python web sunucuları gibi) e-posta gönderen iş parçacığı tabanlı web sunucuları için iyi bir şey olabilir. API da oldukça güçlü.

  • Tabii ki, e-posta web sunucusu olmayan bir kuyruğa dağıtılmalıdır, ancak seçeneklere sahip olmak güzel.

Alan adında Google Apps yönetici haklarına sahip olup olmadığınızı ayarlamak en kolay yoldur, çünkü o zaman istemcinize battaniye izni verebilirsiniz. Aksi takdirde OAuth kimlik doğrulaması ve izniyle uğraşmak zorundasınız.

İşte bunu gösteren bir öz:

https://gist.github.com/timrichardson/1154e29174926e462b7a


2

@David'den harika yanıt, burada genel deneme olmadan Python 3 için:

def send_email(user, password, recipient, subject, body):

    gmail_user = user
    gmail_pwd = password
    FROM = user
    TO = recipient if type(recipient) is list else [recipient]
    SUBJECT = subject
    TEXT = body

    # Prepare actual message
    message = """From: %s\nTo: %s\nSubject: %s\n\n%s
    """ % (FROM, ", ".join(TO), SUBJECT, TEXT)

    server = smtplib.SMTP("smtp.gmail.com", 587)
    server.ehlo()
    server.starttls()
    server.login(gmail_user, gmail_pwd)
    server.sendmail(FROM, TO, message)
    server.close()

2

Gmail hesabınızda daha az güvenli uygulamaları etkinleştirin ve (Python> = 3.6) kullanın:

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

gmailUser = 'XXXXX@gmail.com'
gmailPassword = 'XXXXX'
recipient = 'XXXXX@gmail.com'

message = f"""
Type your message here...
"""

msg = MIMEMultipart()
msg['From'] = f'"Your Name" <{gmailUser}>'
msg['To'] = recipient
msg['Subject'] = "Subject here..."
msg.attach(MIMEText(message))

try:
    mailServer = smtplib.SMTP('smtp.gmail.com', 587)
    mailServer.ehlo()
    mailServer.starttls()
    mailServer.ehlo()
    mailServer.login(gmailUser, gmailPassword)
    mailServer.sendmail(gmailUser, recipient, msg.as_string())
    mailServer.close()
    print ('Email sent!')
except:
    print ('Something went wrong...')

1
Gerçekten harika bir cevap. Demet en iyi biri, süper özlü. Teşekkür ederim.
Bruce Dean

Teşekkürler Pedro, cevabını çözdü. Çoklu takma adlarla Gsuite kullanan herkes için Btw; Sadece aşağıdaki gmail hesabına takma adı ekleyin support.google.com/mail/answer/22370?hl=en ve değiştirerek takma adını kullanarak gönderebilirsiniz <{gmailUser}>ile <YourAlias>.
LucSpan

1

Eski sorun gibi görünüyor smtplib. Her python2.7şeyde iyi çalışıyor.

Güncelleme : Evet, server.ehlo()ayrıca yardımcı olabilir.


-1
    import smtplib

    fromadd='from@gmail.com'
    toadd='send@gmail.com'

    msg='''hi,how r u'''
    username='abc@gmail.com'
    passwd='password'

    try:
        server = smtplib.SMTP('smtp.gmail.com:587')
        server.ehlo()
        server.starttls()
        server.login(username,passwd)

        server.sendmail(fromadd,toadd,msg)
        print("Mail Send Successfully")
        server.quit()

   except:
        print("Error:unable to send mail")

   NOTE:https://www.google.com/settings/security/lesssecureapps that                                                         should be enabled

Gmail hesabından nasıl posta gönderileceğini basit kod yayınlıyorum. Herhangi bir bilgiye ihtiyacınız varsa bana bildirin. Umarım kod tüm kullanıcılara yardımcı olur.
Shyam Gupta

-2
import smtplib
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.login("fromaddress", "password")
msg = "HI!"
server.sendmail("fromaddress", "receiveraddress", msg)
server.quit()

basit bir kod python kodu kullanarak gmail yoluyla posta göndermek için. adres, gmailID'nizdir ve receraddress, posta gönderen posta kimliğidir.
Sam Divya Kumar
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.