Python을 사용하여 공급자로서 Gmail로 이메일을 보내는 방법은 무엇입니까?


289

파이썬을 사용하여 이메일 (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.

파이썬 스크립트는 다음과 같습니다.

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
구글이 Gmail을 통해 메시지를 보내기위한 내부 API로 이동하고 있기 때문에이 질문의 잠금을 해제해야합니다. 이 조치는 이러한 답변 중 하나를 제외한 모든 답변을 구식으로 만들고 관련 답변 중 하나는 실제로 문제를 해결하는 데 매우 가볍습니다.
Andrew

또한 VPN 사용자의 경우 여전히 문제가 지속되면 VPN을 끄십시오. 그것은 나를 위해 일했다.
Paul

답변:


211

EHLO똑바로 뛰어 들기 전에 말해야합니다 STARTTLS.

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

또한 메시지 본문과 빈 줄로 구분 된 From:, To:Subject:메시지 헤더를 작성 CRLF하고 EOL 표시 자로 사용해야 합니다.

예 :

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)을 호출하면 두 번째 매개 변수 인 toaddrs는 목록이어야합니다. toaddrs = [ 'user_me@gmail.com']
Massimo Fazzolari

14
년 8 월 2014 년이 이제 smtplib.SMTPAuthenticationError을 제기 : (534, '5.7.9 응용 프로그램 별 암호이 필요합니다.
anon58192932

7
그래도 저는 @google 계정으로 로그인하여 python을 통해 이메일을 보내려면 'app'비밀번호를 활성화해야합니다. support.google.com/accounts/answer/…
anon58192932

1
여러 사람에게 메일을 보내는 방법에 대한 링크는 다음과 같습니다. stackoverflow.com/questions/8856117/…
anon58192932

1
한 번은 텔넷으로 SMTP 서버에 로그인 EHLO하여 오타로 보냈습니다 . HELO를 여러 번 시도했지만 응답이 다릅니다. EHLO가 실제로 SMTP가 이해하고 오타를 수행하는 명령임을 알아내는 데 몇 시간이 걸렸습니다.
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를 사용하려면 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/… ... 웹 브라우저를 통해 로그인 한 다음 \ n5.7.14 다음에 다시 시도하십시오. \ n5.7.14 이상에서 \ n5.7.14 support.google.com/mail/bin/answer.py?answer=78754 ... 그리고 난 의심스러운 연결 시도가되었다는, 구글의 메일을 받았습니다.
royskatt

13
@royskatt-앱 비밀번호를 만들고 계정 비밀번호 대신 사용하면됩니다. 여기에 앱 비밀번호를 만드십시오. security.google.com/settings/security/apppasswords
Jared

15
@royskatt : 방금 직면 한 문제에 대한 수정 사항이 있습니다. Google은 보안이 취약한 앱에 대한 액세스를 허용하도록 설정했습니다. '켜기'만하면됩니다. 당신은에서가 얻을 수 있습니다 : -> 내 계정 -> 로그인 및 보안 -> 연결된 앱과 사이트 - 구글> 아래로 스크롤하면 찾을 것입니다 '허용 보안 수준이 낮은 앱'
shaleen 모한

2
Gmail이 2 단계 인증으로 보호되는 경우 먼저 애플리케이션 비밀번호를 생성 한 다음 위의 예제 코드에서 해당 애플리케이션 비밀번호를 사용해야합니다 (이는 비밀번호를 어디에도 기록하지 않기 때문에 매우 중요합니다) 일반 텍스트로 언제든지 앱 비밀번호를 취소 할 수 있습니다).
Trevor Boyd Smith

136

비슷한 문제가 발생 하여이 질문에 걸려 들었습니다. SMTP 인증 오류가 발생했지만 사용자 이름 / 통과가 정확했습니다. 여기에 그 문제가 해결되었습니다. 나는 이것을 읽었다 :

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

간단히 말해서 Google은 smtplib를 통해 로그인 할 수 없습니다. 이런 종류의 로그인은 "안전하지 않은"것으로 표시되었으므로 Google 계정에 로그인 한 상태에서이 링크로 이동하면됩니다. 액세스를 허용하십시오.

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

2
"2 단계 인증"을 사용하도록 설정 한 경우 보안 수준이 낮은 앱을 사용하도록 설정할 수 없습니다. 가장 안전하고 안전한 옵션은 이미 제안 된대로 "apppassword" security.google.com/settings/security/apppasswords 를 활성화하는 것입니다. 매력처럼 작동합니다
Omiod

2
apppasswords 링크를 따라 가면 모든 Google 계정에 "원하는 설정을 사용할 수 없습니다"라는 오류가 표시됩니다.
Suzanne

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
클래스에 두 개의 메소드가 있는데 그 중 하나가 __init__ 인 경우 함수를 사용하십시오.
JoeQuery

이 방법을 사용하여 첨부 파일을 어떻게 추가 하시겠습니까?
sgerbhctim

클라이언트를 초기화하고 전자 메일과 암호를 전달하지 않고 코드의 다른 부분으로 전달하려면 클래스를 사용하는 것이 좋습니다. 또는 매번 이메일과 비밀번호를 전달하지 않고 여러 메시지를 보내려는 경우.
Sami는

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=ko 로 이동 하여 아래 단계를 따라야합니다)

2 단계 인증을 사용하는 계정에는이 설정을 사용할 수 없습니다. 이러한 계정에는 덜 안전한 앱 액세스를 위해 애플리케이션 비밀번호가 필요합니다.

덜 안전한 앱 액세스 ... 2 단계 인증을 사용하는 계정에는이 설정을 사용할 수 없습니다.


1
환상적인 솔루션이며 코드에서 잘 설명되어 있습니다. 고마워 제이 감사합니다. 멍청한 질문 : 하루에 이메일의 최대 한도는 무엇인지 알 수 있습니까 (gmail과 함께)?
Angelo

@Angelo에게 감사하지만 그렇습니다. GMail = 500 개의 이메일 또는 500 명의 수신자 / 일 참조 : support.google.com/mail/answer/22839 G SUITE는 다르고 하루에 2000 개의 메시지이며 여기에서 찾을 수 있습니다 : 지원 .google.com / a / answer / 166852 행운을 빈다!
JayRizzo 2016 년

2
다른 모든 게시물은 오래된 게시물이며 작동하지 않을 수 있지만 100 % 작동합니다. 앱 비밀번호를 생성하십시오. 답변 주셔서 감사합니다
Shubh

1
이 솔루션에 더 많은 투표가 없다는 것에 약간 놀랐습니다. 나는 다른 모든 것을 시도 하지는 않았지만 여러 가지를 시도했지만이 중 하나만 0 팅커와 함께 즉시 작동했습니다.
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
자체 형식 문자열을 하드 코딩하는 것보다 MIME을 작성하는 것이 더 낫기 때문에 1을 더한 값입니다. 간단한 문자 메시지에 MIMEMultipart가 필요합니까? 또는 다음 사항도 정확합니다. stackoverflow.com/a/6270987/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

이메일 변수를 어디에서 인스턴스화합니까?
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

REST API를 통해 이메일을 보내고, 이메일을 읽고, 초안을 작성할 수있는 Gmail API가 있습니다. SMTP 호출과 달리 비 블로킹은 스레드 기반 웹 서버가 요청 스레드에서 전자 메일을 보내는 데 유용합니다 (파이썬 웹 서버 등). API도 매우 강력합니다.

  • 물론 이메일은 웹 서버가 아닌 대기열로 전달해야하지만 옵션이있는 것이 좋습니다.

도메인에 대한 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를 사용하는 모든 사람을위한 Btw; 다만 다음 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 2016 년

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

파이썬 코드를 사용하여 Gmail을 통해 메일을 보내는 간단한 코드입니다. 보낸 사람 주소는 gmailID이고 수신자 주소는 메일을 보내는 메일 ID입니다.
Sam Divya Kumar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.