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.