# Gmail API Email Sender

This guide demonstrates how to send emails programmatically using the Gmail API. This approach uses OAuth 2.0 for authentication, which is more secure and reliable than using `smtplib` with "Less Secure Apps" enabled (which Google has largely deprecated).

**Modules Used:**
*   `google-api-python-client`: To interact with Google APIs.
*   `google-auth-oauthlib`: For handling the OAuth 2.0 authentication flow.
*   `email`: To construct the email message content.
*   `base64`: To encode the message for the API.

## Prerequisites

1.  **Google Cloud Console**: Go to the Google Cloud Console.
2.  **Create Project**: Create a new project.
3.  **Enable API**: Search for "Gmail API" and enable it.
4.  **Credentials**:
    *   Go to "Credentials" -> "Create Credentials" -> "OAuth client ID".
    *   Configure the Consent Screen (External, Test User = your email).
    *   Application type: Desktop App.
    *   Download the JSON file and rename it to `credentials.json`.
    *   Place `credentials.json` in the same directory as your script.

## Installation

```bash
pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
```

## The Code

Save this as `gmail_sender.py`.

```python
import os.path
import base64
import argparse
from email.message import EmailMessage
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
from googleapiclient.errors import HttpError

# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/gmail.send']

def authenticate():
    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:
            if not os.path.exists('credentials.json'):
                print("Error: credentials.json not found.")
                return None
            
            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.json', 'w') as token:
            token.write(creds.to_json())
            
    return creds

def send_email(to_email, subject, body):
    creds = authenticate()
    if not creds:
        return

    try:
        service = build('gmail', 'v1', credentials=creds)

        message = EmailMessage()
        message.set_content(body)
        message['To'] = to_email
        message['From'] = 'me' # 'me' is a special value indicating the authenticated user
        message['Subject'] = subject

        # Encode the message
        encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
        create_message = {'raw': encoded_message}

        # Send
        send_message = (service.users().messages().send(userId="me", body=create_message).execute())
        print(f'Message Id: {send_message["id"]}')
        print(f"Email sent successfully to {to_email}")

    except HttpError as error:
        print(f'An error occurred: {error}')

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Gmail API Email Sender")
    parser.add_argument("to", help="Recipient email address")
    parser.add_argument("subject", help="Email subject")
    parser.add_argument("body", help="Email body text")
    
    args = parser.parse_args()
    
    send_email(args.to, args.subject, args.body)
```

## Usage

1.  **First Run**:
    ```bash
    python gmail_sender.py recipient@example.com "Hello" "This is a test email from Python."
    ```
    A browser window will open asking you to log in and authorize the app.

2.  **Subsequent Runs**:
    The script will use the saved `token.json` to send emails instantly without user interaction.

[[programming/python/python]]