Bagaimana cara mengirim email dengan Gmail sebagai penyedia menggunakan Python?

289

Saya mencoba mengirim email (Gmail) menggunakan python, tetapi saya menerima kesalahan berikut.

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.

Skrip Python adalah sebagai berikut.

import smtplib
fromaddr = '[email protected]'
toaddrs  = '[email protected]'
msg = 'Why,Oh why!'
username = '[email protected]'
password = 'pwd'
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login(username,password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
Mahori
sumber
16
Pertanyaan ini harus dibuka sekarang karena Google bergerak menuju API internal untuk mengirim pesan melalui gmail. Langkah ini membuat semua kecuali satu dari jawaban ini sudah ketinggalan zaman, dan satu jawaban yang relevan sangat ringan untuk benar-benar menyelesaikan masalah.
Andrew
Juga, untuk pengguna VPN, jika masalah ini masih ada, matikan VPN Anda. Itu berhasil bagi saya.
Paul

Jawaban:

211

Anda perlu mengatakan EHLOsebelum berlari langsung ke STARTTLS:

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

Anda juga harus benar-benar membuat From:, To:dan Subject:header pesan, dipisahkan dari badan pesan oleh baris kosong dan digunakan CRLFsebagai penanda EOL.

Misalnya

msg = "\r\n".join([
  "From: [email protected]",
  "To: [email protected]",
  "Subject: Just a message",
  "",
  "Why, oh why"
  ])
MattH
sumber
2
memanggil server.sendmail (fromaddr, toaddrs, msg) parameter kedua, toaddrs harus berupa daftar, toaddrs = ['[email protected]']
Massimo Fazzolari
14
Pada Agustus 2014 ini sekarang meningkatkan smtplib.SMTPAuthenticationError: (534, '5.7.9 Diperlukan sandi khusus aplikasi.
anon58192932
7
Bagi saya, saya harus mengaktifkan kata sandi 'aplikasi' untuk masuk menggunakan akun @google untuk mengirim email melalui python: support.google.com/accounts/answer/…
anon58192932
1
Berikut tautan tentang cara mengirim banyak orang: stackoverflow.com/questions/8856117/…
anon58192932
1
Saya pernah masuk ke server SMTP melalui telnet dan dikirim EHLOdengan salah ketik. Setelah saya mencoba HELO berkali-kali tetapi responnya berbeda. Butuh berjam-jam untuk mengetahui bahwa EHLO sebenarnya adalah perintah yang dimengerti SMTP dan saya melakukan kesalahan ketik.
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"

jika Anda ingin menggunakan Port 465 Anda harus membuat SMTP_SSLobjek:

# 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'
David Okwii
sumber
2
Sampel yang sangat bagus, terima kasih. Satu hal yang saya perhatikan adalah jika saya ingin menggunakan koneksi SSL, saya harus menghapus server.starttls ()
Dowlers
18
Sayangnya, tidak berfungsi lagi: smtplib.SMTPAuthenticationError: (534, '5.7.14 < accounts.google.com/ ... ... Harap masuk melalui peramban web Anda dan \ n5.7.14 lalu coba lagi. \ N5.7.14 Pelajari lebih lanjut di \ n5.7.14 support.google.com/mail/bin/answer.py?answer=78754 ... Lalu saya mendapat email dari google, bahwa ada upaya koneksi yang mencurigakan.
royskatt
13
@royskatt - yang perlu Anda lakukan hanyalah membuat kata sandi aplikasi dan menggunakannya sebagai pengganti kata sandi akun Anda. Buat kata sandi aplikasi di sini: security.google.com/settings/security/apppasswords
Jared
15
@royskatt: Saya baru saja memperbaiki untuk masalah yang Anda hadapi. Google memiliki pengaturan untuk memungkinkan akses untuk aplikasi yang kurang aman Anda hanya perlu mengaktifkannya 'Aktif'. Anda dapat sampai di sana dari: Google -> akun saya -> Masuk & keamanan -> Aplikasi & situs yang terhubung -> gulir ke bawah dan Anda akan menemukan 'Izinkan aplikasi yang kurang aman'
shaleen mohan
2
Jika gmail Anda dijamin oleh Otentikasi Dua Faktor, Anda harus terlebih dahulu membuat kata sandi khusus aplikasi -> kemudian gunakan kata sandi aplikasi untuk dalam contoh kode di atas (ini sangat penting karena Anda tidak menuliskan kata sandi di mana pun) di cleartext DAN Anda dapat mencabut kata sandi aplikasi kapan saja).
Trevor Boyd Smith
136

Saya mengalami masalah yang sama dan menemukan pertanyaan ini. Saya mendapat Kesalahan Otentikasi SMTP tetapi nama pengguna / pass saya benar. Inilah yang diperbaiki. Saya membaca ini:

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

Singkatnya, google tidak mengizinkan Anda untuk masuk melalui smtplib karena telah menandai jenis login ini sebagai "kurang aman", jadi yang harus Anda lakukan adalah pergi ke tautan ini saat Anda masuk ke akun google Anda, dan memungkinkan akses:

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

Setelah diatur (lihat tangkapan layar saya di bawah), itu akan berfungsi.

masukkan deskripsi gambar di sini

Login sekarang berfungsi:

smtpserver = smtplib.SMTP("smtp.gmail.com", 587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo()
smtpserver.login('[email protected]', 'me_pass')

Respon setelah perubahan:

(235, '2.7.0 Accepted')

Tanggapan sebelumnya:

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

Masih tidak bekerja? Jika Anda masih mendapatkan SMTPAuthenticationError tetapi sekarang kodenya 534, karena lokasinya tidak diketahui. Ikuti tautan ini:

https://accounts.google.com/DisplayUnlockCaptcha

Klik lanjutkan dan ini akan memberi Anda 10 menit untuk mendaftarkan aplikasi baru Anda. Jadi lanjutkan untuk melakukan upaya login lain sekarang dan itu akan berhasil.

UPDATE : Tampaknya ini tidak berfungsi segera Anda mungkin akan buntu untuk sementara mendapatkan kesalahan ini di smptlib:

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

Pesan mengatakan untuk menggunakan browser untuk masuk:

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

Setelah mengaktifkan 'lesssecureapps', cari kopi, kembali, dan coba tautan 'DisplayUnlockCaptcha' lagi. Dari pengalaman pengguna, mungkin diperlukan waktu hingga satu jam agar perubahan dimulai. Kemudian coba proses masuk kembali.

radtek
sumber
3
YA TERIMA KASIH ! Terjadi saat menggunakan flask-mail
Giannis
1
terima kasih satu-satunya masalah bagi saya: accounts.google.com/DisplayUnlockCaptcha
Limitless isa
6
Selain itu, biarkan setengah jam hingga satu jam agar pengaturan berubah. Saya membuat akun baru, menonaktifkan semua keamanan yang ditambahkan, dan masih mendapat kesalahan yang sama. Sekitar satu jam kemudian, semuanya bekerja.
jkgeyti
2
Mengaktifkan aplikasi yang kurang aman tidak dimungkinkan jika Anda mengaktifkan "Verifikasi 2 Langkah". Opsi terbaik dan paling aman adalah mengaktifkan "apppassword" security.google.com/settings/security/apppasswords seperti yang disarankan, dan berfungsi seperti pesona
Omiod
2
Ketika saya mengikuti tautan kata sandi aplikasi, semua akun Google saya mendapatkan kesalahan "Pengaturan yang Anda cari tidak tersedia untuk akun Anda".
Suzanne
18

Anda jatuh sakit dengan OOP?

#!/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')
Ricky Wilson
sumber
33
Jika kelas Anda hanya memiliki dua metode, salah satunya adalah __init__, cukup gunakan fungsi.
JoeQuery
Bagaimana Anda menambahkan lampiran menggunakan metode ini?
sgerbhctim
Menggunakan kelas akan baik jika Anda ingin init klien dan menyebarkannya ke bagian lain dari kode, alih-alih membagikan email dan kata sandi. Atau jika Anda ingin mengirim beberapa pesan tanpa harus memasukkan email dan kata sandi setiap kali.
Sami Mulai
15

Ini bekerja

Buat Kata Sandi APP Gmail!

Setelah Anda membuat itu lalu buat file bernama sendgmail.py

Kemudian tambahkan kode ini :

#!/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 = '[email protected]'
gmail_app_password = 'YOUR-GOOGLE-APPLICATION-PASSWORD!!!!'

# =============================================================================
# SET THE INFO ABOUT THE SAID EMAIL
# =============================================================================
sent_from = gmail_user
sent_to = ['[email protected]', '[email protected]']
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)

Jadi, jika Anda berhasil, akan melihat gambar seperti ini:

Saya menguji dengan mengirim email dari dan ke diri saya sendiri.

Email berhasil terkirim.

Catatan: Saya mengaktifkan Verifikasi 2 Langkah di akun saya. Sandi Aplikasi berfungsi dengan ini! (untuk pengaturan smtp gmail, Anda harus membuka https://support.google.com/accounts/answer/185833?hl=id dan ikuti langkah-langkah di bawah ini)

Pengaturan ini tidak tersedia untuk akun dengan Verifikasi 2 Langkah diaktifkan. Akun semacam itu memerlukan kata sandi khusus aplikasi untuk akses aplikasi yang kurang aman.

Akses aplikasi kurang aman ... Pengaturan ini tidak tersedia untuk akun dengan Verifikasi 2 Langkah diaktifkan.

JayRizzo
sumber
1
Solusi fantastis dan dijelaskan dengan sangat baik dalam kode. Terima kasih Jay, sangat kami hargai. Pertanyaan bodoh: apakah Anda tahu batas maksimum email per hari dapat dikirim (dengan gmail)?
Angelo
Terima kasih @ Angelo tetapi ya ada batasnya, GMail = 500 email atau 500 penerima / Hari ref: support.google.com/mail/answer/22839 G SUITE berbeda dan 2000 pesan / hari dan dapat ditemukan di sini: dukungan .google.com / a / answer / 166852 Semoga Sukses!
JayRizzo
2
Semua yang lain adalah posting yang lebih lama dan mungkin tidak berfungsi, tetapi ini 100% berfungsi. Buat kata sandi aplikasi. Terima kasih atas jawabannya
Shubh
1
Saya sedikit terkejut bahwa solusi ini tidak memiliki lebih banyak upvotes. Saya belum mencoba semua yang lain, tapi saya sudah mencoba beberapa, dan hanya satu ini bekerja di luar kotak, dengan 0 bermain-main.
mcouthon
14

Anda dapat menemukannya di sini: 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())
Froyo
sumber
2
ditambah 1 karena lebih baik membangun MIME daripada mem-hardcode string format Anda sendiri. Apakah MIMEMultipart diperlukan untuk pesan teks sederhana? Atau apakah yang berikut ini juga benar: stackoverflow.com/a/6270987/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Di mana Anda instantiate variabel email?
madcat
11

Tidak terkait langsung tetapi masih layak untuk ditunjukkan adalah bahwa paket saya mencoba membuat pengiriman pesan gmail benar-benar cepat dan tidak menyakitkan. Itu juga mencoba untuk memelihara daftar kesalahan dan mencoba untuk menunjuk ke solusi segera.

Ini benar-benar hanya membutuhkan kode ini untuk melakukan apa yang Anda tulis:

import yagmail
yag = yagmail.SMTP('[email protected]')
yag.send('[email protected]', 'Why,Oh why!')

Atau satu liner:

yagmail.SMTP('[email protected]').send('[email protected]', 'Why,Oh why!')

Untuk paket / instalasi silakan lihat git atau pip , tersedia untuk Python 2 dan 3.

PascalVKooten
sumber
9

Ini adalah contoh API Gmail. Meskipun lebih rumit, ini adalah satu-satunya metode yang saya temukan yang berfungsi pada 2019. Contoh ini diambil dan dimodifikasi dari:

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

Anda harus membuat proyek dengan antarmuka API Google melalui situs web mereka. Selanjutnya Anda harus mengaktifkan API GMAIL untuk aplikasi Anda. Buat kredensial dan kemudian unduh kredibilitas tersebut, simpan sebagai kredensial.json.

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("[email protected]", "[email protected]", "Subject", "Msg")
    send_message( service, 'me', msg)

if __name__ == '__main__':
    main()
Luke Dupin
sumber
smtplib tidak sepenuhnya thread-safe, sehingga akan mengalami masalah dalam mengirim pesan bersamaan. Ini adalah pendekatan yang tepat.
dsbajna
2

Ada API gmail sekarang, yang memungkinkan Anda mengirim email, membaca email dan membuat konsep melalui REST. Berbeda dengan panggilan SMTP, ini bukan pemblokiran yang bisa menjadi hal yang baik untuk webservers berbasis utas yang mengirim email di utas permintaan (seperti python webservers). API juga cukup kuat.

  • Tentu saja, email harus diserahkan ke antrian non-server, tetapi senang memiliki opsi.

Lebih mudah untuk menyiapkan jika Anda memiliki hak administrator Google Apps di domain, karena Anda dapat memberikan izin kepada klien Anda. Kalau tidak, Anda harus mengutak-atik otentikasi dan izin OAuth.

Inilah intisari yang menunjukkannya:

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

Tim Richardson
sumber
2

jawaban bagus dari @David, ini untuk Python 3 tanpa try-generic kecuali:

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()
juan Isaza
sumber
2

Aktifkan aplikasi yang kurang aman di akun gmail Anda dan gunakan (Python> = 3.6):

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

gmailUser = '[email protected]'
gmailPassword = 'XXXXX'
recipient = '[email protected]'

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...')
HUBUNGI19
sumber
1
Jawaban yang sangat fantastis. Salah satu yang terbaik, super ringkas. Terima kasih.
Bruce Dean
Terima kasih Pedro, jawaban Anda menyelesaikannya. Btw untuk siapa saja yang menggunakan Gsuite dengan banyak alias; cukup tambahkan alias ke akun gmail Anda setelah support.google.com/mail/answer/22370?hl=id dan Anda dapat mengirim menggunakan alias dengan menggantinya <{gmailUser}>dengan <YourAlias>.
LucSpan
1

Sepertinya masalah yang lama smtplib. Dipython2.7 semuanya berfungsi dengan baik.

Perbarui : Yap, server.ehlo()juga bisa membantu.

mega.venik
sumber
-1
    import smtplib

    fromadd='[email protected]'
    toadd='[email protected]'

    msg='''hi,how r u'''
    username='[email protected]'
    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
Shyam Gupta
sumber
Saya memposting kode sederhana yang akan melakukan cara mengirim email dari akun Gmail. Jika Anda memerlukan informasi, beri tahu saya. Saya harap kode itu akan membantu semua pengguna.
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()
Sam Divya Kumar
sumber
kode sederhana untuk mengirim email melalui gmail menggunakan kode python. dari alamat adalah gmailID Anda dan alamat penerima adalah id surat yang Anda kirimi surat.
Sam Divya Kumar