How to send an email through gmail without enabling 'insecure access'?

后端 未结 6 694
你的背包
你的背包 2020-12-12 17:35

Google are pushing us to improve the security of script access to their gmail smtp servers. I have no problem with that. In fact I\'m happy to help.

But they\'re n

6条回答
  •  情深已故
    2020-12-12 18:03

    Updated sample for Python 3, and GMail's current API, below.

    Note that to get the credentials.json file below, you'll need to create an Oauth client ID credential here, after selecting the relevant GCP project. Once you've created it you'll be shown the client key and client secret. Close that prompt, and click the down arrow next to the account. This is the file you'll need.

    import base64
    import logging
    import mimetypes
    import os
    import os.path
    import pickle
    from email.mime.text import MIMEText
    from google_auth_oauthlib.flow import InstalledAppFlow
    from google.auth.transport.requests import Request
    from googleapiclient import errors
    from googleapiclient.discovery import build
    
    def get_service():
        """Gets an authorized Gmail API service instance.
    
        Returns:
            An authorized Gmail API service instance..
        """    
    
        # If modifying these scopes, delete the file token.pickle.
        SCOPES = [
            'https://www.googleapis.com/auth/gmail.readonly',
            'https://www.googleapis.com/auth/gmail.send',
        ]
    
        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)
        return service
    
    def send_message(service, sender, message):
      """Send an email message.
    
      Args:
        service: Authorized Gmail API service instance.
        user_id: User's email address. The special value "me"
        can be used to indicate the authenticated user.
        message: Message to be sent.
    
      Returns:
        Sent Message.
      """
      try:
        sent_message = (service.users().messages().send(userId=sender, body=message)
                   .execute())
        logging.info('Message Id: %s', sent_message['id'])
        return sent_message
      except errors.HttpError as error:
        logging.error('An HTTP error occurred: %s', error)
    
    def create_message(sender, to, subject, message_text):
      """Create a message for an email.
    
      Args:
        sender: Email address of the sender.
        to: Email address of the receiver.
        subject: The subject of the email message.
        message_text: The text of the email message.
    
      Returns:
        An object containing a base64url encoded email object.
      """
      message = MIMEText(message_text)
      message['to'] = to
      message['from'] = sender
      message['subject'] = subject
      s = message.as_string()
      b = base64.urlsafe_b64encode(s.encode('utf-8'))
      return {'raw': b.decode('utf-8')}
    
    if __name__ == '__main__':
        logging.basicConfig(
            format="[%(levelname)s] %(message)s",
            level=logging.INFO
        )
    
        try:
            service = get_service()
            message = create_message("from@gmail.com", "to@gmail.com", "Test subject", "Test body")
            send_message(service, "from@gmail.com", message)
    
        except Exception as e:
            logging.error(e)
            raise
    

提交回复
热议问题