114 lines
4.2 KiB
Python
114 lines
4.2 KiB
Python
import os.path
|
|
import base64
|
|
import imaplib
|
|
import email
|
|
from email.header import decode_header
|
|
import google.auth
|
|
from google.oauth2.credentials import Credentials
|
|
from google_auth_oauthlib.flow import InstalledAppFlow
|
|
from google.auth.transport.requests import Request
|
|
from bs4 import BeautifulSoup # Import BeautifulSoup for parsing HTML
|
|
from datetime import datetime
|
|
|
|
# If modifying these SCOPES, delete the file token.json.
|
|
SCOPES = ['https://mail.google.com/']
|
|
|
|
def authenticate_gmail():
|
|
"""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.
|
|
|
|
token = r'/data/token.json'
|
|
if os.path.isfile(token) is False:
|
|
token = r'x:\substack\token.json'
|
|
|
|
cred = r'/data/client_secret_396578640529-o4dsukvomuo43j5d4j0bogg17e3e8l7f.apps.googleusercontent.com.json'
|
|
if os.path.isfile(cred) is False:
|
|
cred = r'x:\substack\client_secret_396578640529-o4dsukvomuo43j5d4j0bogg17e3e8l7f.apps.googleusercontent.com.json'
|
|
|
|
if os.path.exists(token):
|
|
creds = Credentials.from_authorized_user_file(token, 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(cred, SCOPES)
|
|
creds = flow.run_local_server(port=0)
|
|
# Save the credentials for the next run
|
|
with open(token, 'w') as token:
|
|
token.write(creds.to_json())
|
|
|
|
return creds
|
|
|
|
def generate_oauth2_string(username, access_token):
|
|
return f"user={username}\1auth=Bearer {access_token}\1\1"
|
|
|
|
def decode_mime_words(s):
|
|
return ''.join(
|
|
word.decode(encoding or 'utf-8') if isinstance(word, bytes) else word
|
|
for word, encoding in decode_header(s)
|
|
)
|
|
|
|
def get_verification_link(email_user, sender_email, start_time):
|
|
creds = authenticate_gmail()
|
|
auth_string = generate_oauth2_string(email_user, creds.token)
|
|
|
|
mail = imaplib.IMAP4_SSL("imap.gmail.com")
|
|
#mail.debug = 4 # Enable IMAP debug output for more detailed logs
|
|
|
|
try:
|
|
mail.authenticate('XOAUTH2', lambda x: auth_string)
|
|
except imaplib.IMAP4.error as e:
|
|
print(f"IMAP authentication error: {e}")
|
|
return None
|
|
|
|
mail.select("inbox")
|
|
|
|
result, data = mail.search(None, f'(FROM "{sender_email}" SUBJECT "Finish signing in to Substack")')
|
|
mail_ids = data[0]
|
|
id_list = mail_ids.split()
|
|
|
|
for num in reversed(id_list): # Check the most recent emails first
|
|
result, data = mail.fetch(num, "(RFC822)")
|
|
raw_email = data[0][1]
|
|
msg = email.message_from_bytes(raw_email)
|
|
# Decode and print the email subject
|
|
subject = decode_mime_words(msg["Subject"])
|
|
# Get email date
|
|
email_date_tuple = email.utils.parsedate_tz(msg["Date"])
|
|
email_timestamp = email.utils.mktime_tz(email_date_tuple)
|
|
print(subject, start_time, email_timestamp)
|
|
|
|
if abs(email_timestamp - start_time) > 12 * 3600:
|
|
continue
|
|
|
|
if msg.is_multipart():
|
|
for part in msg.walk():
|
|
if part.get_content_type() == "text/plain":
|
|
body = part.get_payload(decode=True).decode()
|
|
for line in body.split("\n"):
|
|
if "http" in line:
|
|
return line.strip()
|
|
else:
|
|
print("-----")
|
|
body = msg.get_payload(decode=True).decode()
|
|
soup = BeautifulSoup(body, 'html.parser')
|
|
link = soup.find('a', href=True, text="Connectez-vous dès maintenant")
|
|
if link:
|
|
return link['href']
|
|
|
|
return None
|
|
|
|
if __name__ == "__main__":
|
|
email_user = "gael.honorez@gmail.com"
|
|
sender_email = "no-reply@substack.com"
|
|
verification_link = get_verification_link(email_user, sender_email)
|
|
if verification_link:
|
|
print("Verification link found:", verification_link)
|
|
else:
|
|
print("No verification link found.") |