How to read emails from gmail?

Question:

I am trying to connect my gmail to python, but show me this error:

I already checked my password, any idea what can be?

b'[AUTHENTICATIONFAILED] Invalid credentials (Failure)'
Traceback (most recent call last):
  File "/Users/myuser/Documents/migrations/untitled3.py", line 29, in read_email_from_gmail
    mail.login(FROM_EMAIL,FROM_PWD)
  File "/Users/myuser/opt/anaconda3/lib/python3.9/imaplib.py", line 612, in login
    raise self.error(dat[-1])
imaplib.IMAP4.error: b'[AUTHENTICATIONFAILED] Invalid credentials (Failure)'

Here my code:
Also i want to know which port I can use?

import smtplib
import time
import imaplib
import email
import traceback 

ORG_EMAIL = "@gmail.com" 
FROM_EMAIL = "myemail" + ORG_EMAIL 
FROM_PWD = "mypassword" 
SMTP_SERVER = "smtp.gmail.com" 
SMTP_PORT = ??

def read_email_from_gmail():
    try:
        mail = imaplib.IMAP4_SSL(SMTP_SERVER)
        mail.login(FROM_EMAIL,FROM_PWD)
        mail.select('inbox')

        data = mail.search(None, 'ALL')
        mail_ids = data[1]
        id_list = mail_ids[0].split()   
        first_email_id = int(id_list[0])
        latest_email_id = int(id_list[-1])

        for i in range(latest_email_id,first_email_id, -1):
            data = mail.fetch(str(i), '(RFC822)' )
            for response_part in data:
                arr = response_part[0]
                if isinstance(arr, tuple):
                    msg = email.message_from_string(str(arr[1],'utf-8'))
                    email_subject = msg['subject']
                    email_from = msg['from']
                    print('From : ' + email_from + 'n')
                    print('Subject : ' + email_subject + 'n')

    except Exception as e:
        traceback.print_exc() 
        print(str(e))

read_email_from_gmail()

My main goal is be able to get the CSV file from each email, but for now I just want to read messages.

Asked By: gwc

||

Answers:

  1. You need to enable ‘Less secure apps’ in your Gmail account if you’re going to check it this way. For that reason, it would be better to use the Gmail API.

  2. SMTP port is not set – ensure you are using the correct port (993)

Answered By: Joel

Here’s the problem, Gmail has a new politic who doesn’t allow to use insecure apps.

To help keep your account secure, from May 30, 2022, ​​Google no longer supports the use of third-party apps or devices which ask you to sign in to your Google Account using only your username and password.

Answered By: Carlos

As Carlos pointed out, Google no longer allows insecure apps to access GMail. The ‘Less secure apps’ option is no longer available. I encountered the same Gmail login issue but I was glad to find the article below and have solved the issue.

https://towardsdatascience.com/how-to-easily-automate-emails-with-python-8b476045c151

Answered By: David

Best way to read email is using GMAIL API. Google has stopped accessing gmail account using username and password via any outside app from 30 the May 2022.
So this is how you read gmail from python.

What this app does:

  • Read gmail message (Unread)
  • Make the message as Read after reading the message
import os.path
import base64
import json
import re
import time
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
import logging
import requests

SCOPES = ['https://www.googleapis.com/auth/gmail.readonly','https://www.googleapis.com/auth/gmail.modify']

def readEmails():
    """Shows basic usage of the Gmail API.
    Lists the user's Gmail labels.
    """
    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('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    # 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(               
                # your creds file here. Please create json file as here https://cloud.google.com/docs/authentication/getting-started
                'my_cred_file.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.json', 'w') as token:
            token.write(creds.to_json())
    try:
        # Call the Gmail API
        service = build('gmail', 'v1', credentials=creds)
        results = service.users().messages().list(userId='me', labelIds=['INBOX'], q="is:unread").execute()
        messages = results.get('messages',[]);
        if not messages:
            print('No new messages.')
        else:
            message_count = 0
            for message in messages:
                msg = service.users().messages().get(userId='me', id=message['id']).execute()                
                email_data = msg['payload']['headers']
                for values in email_data:
                    name = values['name']
                    if name == 'From':
                        from_name= values['value']                
                        for part in msg['payload']['parts']:
                            try:
                                data = part['body']["data"]
                                byte_code = base64.urlsafe_b64decode(data)

                                text = byte_code.decode("utf-8")
                                print ("This is the message: "+ str(text))

                                # mark the message as read (optional)
                                msg  = service.users().messages().modify(userId='me', id=message['id'], body={'removeLabelIds': ['UNREAD']}).execute()                                                       
                            except BaseException as error:
                                pass                            
    except Exception as error:
        print(f'An error occurred: {error}')

You need to create credential file in Google account
How to create credential file here https://cloud.google.com/docs/authentication/getting-started

Answered By: Mark P

smtp.gmail.com is for sending emails, to read the emails you want to connect to imap.gmail.com. It works for me with an App password. I wrote a short application to sync multiple email servers, which is tested with Google mail. Still as mentioned above, it is recommended to use the Google API. On my Github account I have an example application for using the Google API and sorting emails with machine learning, if that is interesting for you.

Answered By: Jan
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.