Pythonを使用してプロバイダーとしてGmailでメールを送信する方法


289

Pythonを使用してメール(Gmail)を送信しようとしていますが、次のエラーが発生します。

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スクリプトは次のとおりです。

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がGmail経由でメッセージを送信するための内部APIに向かっているので、この質問のロックを解除する必要があります。この移動により、これらの回答の1つを除くすべてが古くなり、1つの関連する回答は、実際に問題を解決する上で非常に軽いものです。
Andrew

また、VPNユーザーの場合、問題が解決しない場合は、VPNをオフにしてください。それでうまくいきました。
ポール

回答:


211

EHLOまっすぐ走る前に言う必要がありますSTARTTLS

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

またFrom:、実際にTo:Subject:メッセージヘッダーを作成し、メッセージ本文から空白行で区切って、CRLFEOLマーカーとして使用する必要があります。

例えば

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

2
server.sendmail(fromaddr、toaddrs、msg)を呼び出す2番目のパラメーターtoaddrsはリストでなければなりませんtoaddrs = ['user_me@gmail.com']
Massimo Fazzolari

14
2014年8月のように、これは今smtplib.SMTPAuthenticationErrorが発生します(534、「5.7.9アプリケーション固有のパスワードが必要です。
anon58192932

7
しかし私にとっては、私のpythonを経由してメールを送信するために@googleアカウントを使ってログインして「アプリ」パスワードを有効にする必要がありました:support.google.com/accounts/answer/...
anon58192932

1
ここでは、複数の人を郵送する方法についてのリンクです:stackoverflow.com/questions/8856117/...
anon58192932

1
TelnetでSMTPサーバーにログインしEHLO、typo で送信したことがあります。HELOを何度も試しましたが、反応が違いました。EHLOが実際にはSMTPが理解できるコマンドであることを理解するのに数時間かかり、私はタイプミスをしました。
Shiplu Mokaddim 2017年

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を使用する場合は、SMTP_SSLオブジェクトを作成する必要があります。

# 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
とても良いサンプルありがとう。私が気付いたのは、SSL接続を使用したい場合、server.starttls()を削除しなければならなかったということです
Dowlers

18
残念ながらもう機能しません:smtplib.SMTPAuthenticationError:(534、 '5.7.14 < accounts.google.com/… ... Webブラウザーからログインしてから、\ n5.7.14で再試行してください。\ n5.7.14詳細より\ n5.7.14でsupport.google.com/mail/bin/answer.py?answer=78754。...それから私は不審な接続の試みがあったことを、Googleからのメールを得た
royskatt

13
@royskatt-必要なのは、アプリのパスワードを作成し、アカウントのパスワードの代わりに使用することだけです。ここでアプリパスワードを作成:security.google.com/settings/security/apppasswords
Jared

15
@royskatt:私はあなたが直面している問題を修正しました。Googleには、安全性の低いアプリへのアクセスを許可する設定があり、「オン」にするだけです。次の場所からアクセスできます:
Google-

2
2要素認証によってGmailが保護されている場合は、最初にアプリケーション固有のパスワードを生成する必要があります ->次に、上記のコード例でそのアプリケーションパスワードを使用します(これは、どこにもパスワードを書き留めていないので非常に重要です)クリアテキストで、いつでもapp-passwordを取り消すことができます)。
Trevor Boyd Smith

136

私は同様の問題に遭遇し、この質問に出くわしました。SMTP認証エラーが発生しましたが、ユーザー名/パスは正しいものでした。ここでそれを修正したものです。私はこれを読んだ:

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

簡単に言うと、Googleはこの種のログインに「安全性が低い」というフラグを立てているため、smtplibを介してログインすることを許可していません。アクセスを許可します:

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

これが設定されると(下のスクリーンショットを参照)、動作するはずです。

ここに画像の説明を入力してください

ログインが機能するようになりました:

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

変更後の対応:

(235, '2.7.0 Accepted')

前の応答:

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

まだ動作していません?それでもSMTPAuthenticationErrorが発生するが、コードが534である場合は、場所が不明であるためです。このリンクに従ってください:

https://accounts.google.com/DisplayUnlockCaptcha

[続行]をクリックすると、新しいアプリの登録に10分かかります。だから今すぐ別のログイン試行を行うことに進んでください、それはうまくいくはずです。

更新:これはすぐには機能しないようですが、smptlibでこのエラーが発生するまでしばらくお待ちください:

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

メッセージには、ブラウザーを使用してサインインするように指示されています。

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」を有効にした後、コーヒーを飲み、戻ってきて、「DisplayUnlockCaptcha」リンクをもう一度試してください。ユーザーエクスペリエンスから、変更が反映されるまで最大1時間かかる場合があります。その後、サインインプロセスを再試行してください。


3
はい、ありがとうございます !フラスコメールの使用中に発生
Giannis

1
おかげで私だけの問題:accounts.google.com/DisplayUnlockCaptcha
無限のisa

6
また、設定変更のために30分〜1時間程度お時間をいただきます。新しいアカウントを作成し、追加されたすべてのセキュリティを無効にしても、同じエラーが発生しました。約1時間後、すべてが機能しました。
jkgeyti 2016年

2
「2段階認証」を有効にしている場合、安全性の低いアプリを有効にすることはできません。最善かつ最も安全なオプションは、すでに提案されているように "apppassword" security.google.com/settings/security/apppasswordsを有効にすることです。これは魅力的なように機能します
Omiod

2
apppasswordsリンクをたどると、すべてのGoogleアカウントに「お探しの設定はお使いのアカウントでは利用できません」というエラーが表示されます。
スザンヌ

18

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

33
クラスに2つのメソッドしかない場合、その1つは__init__で、関数を使用します。
JoeQuery

この方法を使用してどのように添付ファイルを追加しますか?
sgerbhctim

メールとパスワードを渡すのではなく、クライアントを初期化してコードの他の部分に渡したい場合は、クラスを使用するとよいでしょう。または、毎回メールとパスワードを渡さずに複数のメッセージを送信したい場合。
サミスタート

15

この作品

Gmail APPパスワードを作成してください!

それを作成したら、次のファイルを作成します。 sendgmail.py

次に、このコードを追加します

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

したがって、成功すると、次のような画像が表示されます。

私は自分との間でメールを送信してテストしました。

成功したメールが送信されました。

注:私のアカウントでは2段階認証が有効になっています。アプリパスワードはこれで動作します!(Gmail SMTPセットアップの場合、https: //support.google.com/accounts/answer/185833?hl = jaにアクセスして、以下の手順に従う必要があります)

この設定は、2段階認証プロセスが有効になっているアカウントでは使用できません。このようなアカウントには、安全性の低いアプリへのアクセスのために、アプリケーション固有のパスワードが必要です。

安全性の低いアプリアクセス...この設定は、2段階認証が有効になっているアカウントでは使用できません。


1
素晴らしいソリューションであり、コードで非常によく説明されています。ジェイ、ありがとうございました。ばかげた質問:(Gmailで)1日に送信できるメールの最大数はいくつでしょうか。
アンジェロ

@Angeloに感謝しますが、はい制限があります。GMail= 500メールまたは500受信者/日参照:support.google.com/mail/answer/22839 G SUITEは異なり、2000メッセージ/日であり、ここで見つけることができます:support .google.com / a / answer / 166852幸運を祈ります。
JayRizzo

2
他のすべては古い投稿で機能していない可能性がありますが、これは100%機能しています。アプリのパスワードを生成します。回答をありがとう
Shubh

1
この解決策にはこれ以上の賛成票がないことに少し驚いています。私は他のすべてを試したわけではありませんが、いくつか試してみましたが、これだけですぐに機能し、いじくり回すことはありませんでした。
mcouthon

14

ここで見つけることができます: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
プラス1は、独自のフォーマット文字列をハードコードするよりもMIMEを構築する方が良いためです。単純なテキストメッセージにMIMEMultipartは必要ですか?または、次も正しい:stackoverflow.com/a/6270987/895245
Ciro Santilli郝海东冠状病六四事件法轮機能

email変数はどこでインスタンス化しますか?
madcat

11

直接関係はありませんが、指摘しておく価値がありますが、私のパッケージでは、Gmailメッセージの送信を非常に迅速かつ簡単に行えるようにしています。また、エラーのリストを維持し、解決策をすぐに指摘しようとします。

文字通りこのコードが必要なのは、あなたが書いたことを正確に実行するためだけです。

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

またはワンライナー:

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

パッケージ/インストールについては、Python 2と3の両方で使用可能なgitまたはpipを参照してください。


9

これがGmail APIの例です。より複雑ですが、これは2019年に機能することがわかった唯一の方法です。この例は、

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

ウェブサイトを通じて、GoogleのAPIインターフェースを使用してプロジェクトを作成する必要があります。次に、アプリでGMAIL APIを有効にする必要があります。資格情報を作成し、それらの資格情報をダウンロードして、credentials.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("from@gmail.com", "to@gmail.com", "Subject", "Msg")
    send_message( service, 'me', msg)

if __name__ == '__main__':
    main()

smtplibは完全にスレッドセーフではないため、同時メッセージの送信に問題があります。これは正しいアプローチです。
dsbajna

2

現在、Gmail APIがあり、RESTを介してメールを送信したり、メールを読んだり、下書きを作成したりできます。SMTP呼び出しとは異なり、これは非ブロッキングであり、リクエストスレッドでメールを送信するスレッドベースのウェブサーバー(Pythonウェブサーバーなど)に適しています。APIも非常に強力です。

  • もちろん、電子メールはWebサーバー以外のキューに渡される必要がありますが、オプションがあると便利です。

ドメインでGoogle Apps管理者権限を持っている場合は、クライアントに全面的な権限を付与できるため、セットアップが最も簡単です。それ以外の場合は、OAuth認証と許可をいじる必要があります。

ここにそれを示す要点があります:

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


2

@Davidからの素晴らしい答えは、一般的なtry-exceptのないPython 3の場合です。

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アカウントで安全性の低いアプリを有効にして使用する(Python> = 3.6):

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
本当に素晴らしい答えです。束のうちの最高のもの、超簡潔。ありがとうございました。
ブルースディーン

ペドロに感謝します、あなたの答えはそれを解決しました。ところで、複数のエイリアスでGsuiteを使用している人にとっては。ただ、次のGmailアカウントにエイリアスを追加support.google.com/mail/answer/22370?hl=en、あなたは置き換えることで、エイリアスを使用して送信することができます<{gmailUser}><YourAlias>
LucSpan

1

昔の問題のようsmtplibです。でpython2.7、すべて罰金に動作します。

更新server.ehlo()はい、また助けることができます。


-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アカウントからメールを送信する簡単なコードを投稿しています。情報が必要な場合はお知らせください。コードがすべてのユーザーに役立つことを願っています。
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()

Pythonコードを使用してGmail経由でメールを送信する簡単なコード。fromアドレスはあなたのgmailIDで、receiveraddressはメールを送信するメールIDです。
Sam Divya Kumar
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.