oauth2.0 如何在不启用2-fa的情况下使用Python发送电子邮件,并在发件人Gmail帐户中允许不太安全的应用程序选项?

k10s72fa  于 2023-06-21  发布在  Python
关注(0)|答案(1)|浏览(152)

我正试图开发一个功能,从一个Gmail帐户发送电子邮件与自己的域。例如:person1@companyname.com
要求是我不能在谷歌帐户中启用2因素身份验证,也不允许不太安全的应用程序。
那么,什么是最好的方法呢?我在Youtube上看过一个教程,但是他们使用credential.json或client.json文件进行身份验证,而没有解释获取这些文件或其内容的正确方法。
这是我到目前为止的代码:

# Sending email
           try:
               password = 'appPasswordIsSupposedtoBePlacedHereButIAmNotAllowedToUseit'
               sender_email = 'person1@companyname.com'
               recipient_email = ['person2@companyname.com', 'testemail@gmail.com'] 
               subject = 'blablba'
               body = 'blabla'
               em= EmailMessage()
               em['From']= sender_email
               em['To'] = ", ".join(recipient_email)
               em['subject'] = subject
               em.set_content(body)

               context = ssl.create_default_context()

               with smtplib.SMTP_SSL('smtp.gmail.com', 465, context=context) as smtp:
                   smtp.login(sender_email, password)
                   smtp.sendmail(sender_email, recipient_email, em.as_string())

           except Exception as e:
               errors = errores + ' Error while sending the email: ' + str(e)
               logging.warning(errors)
bf1o4zei

bf1o4zei1#

你其实有两个选择。
1.为你的域创建一个google workspace帐户,然后你可以使用服务帐户和域宽deligation来用gmail API做这件事。
1.使用Xoauth2授权用户并存储刷新令牌。
2023: How I access GMail SMTP without enabling 2fa. (Python oauth2)
样本Xoauth2

from __future__ import print_function

import base64
import os.path
import smtplib

from email.mime.text import MIMEText
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow

# If modifying these scopes, delete the file token.json.
SCOPES = ['https://mail.google.com/']

# user token storage
USER_TOKENS = 'token.json'

# application credentials
CREDENTIALS = 'C:\YouTube\dev\credentials.json'

def getToken() -> str:
    creds = None

    # The file token.json 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(USER_TOKENS):
        creds = Credentials.from_authorized_user_file(USER_TOKENS, SCOPES)
        creds.refresh(Request())
    # 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, SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open(USER_TOKENS, 'w') as token:
            token.write(creds.to_json())

    return creds.token

def generate_oauth2_string(username, access_token) -> str:
    auth_string = 'user=' + username + '\1auth=Bearer ' + access_token + '\1\1'
    return base64.b64encode(auth_string.encode('ascii')).decode('ascii')

def send_email(host, port, subject, msg, sender, recipients):
    access_token = getToken()
    auth_string = generate_oauth2_string(sender, access_token)

    msg = MIMEText(msg)
    msg['Subject'] = subject
    msg['From'] = sender
    msg['To'] = ', '.join(recipients)

    server = smtplib.SMTP(host, port)
    server.starttls()
    server.docmd('AUTH', 'XOAUTH2 ' + auth_string)
    server.sendmail(sender, recipients, msg.as_string())
    server.quit()

def main():
    host = "smtp.gmail.com"
    port = 587

    user = "xxx@gmail.com"
    recipient = "xxx@gmail.com"
    subject = "Test email Oauth2"
    msg = "Hello world"
    sender = user
    recipients = [recipient]
    send_email(host, port, subject, msg, sender, recipients)

if __name__ == '__main__':
    main()

访问令牌和刷新令牌将存储在'token.json'中。只需在谷歌开发者控制台上创建安装的应用程序凭据,并将应用程序设置为生产,如果它的单个用户,你不需要验证它。

相关问题