Skip to main content

Table-Based Email Automation

Outline

📥️ Pull Emails (IMAP)

A good practice is to read inputs that are coming from Envirnoment Variables. This will help passing down configurations from (Docker) Containers and/or Kubernetes to my actual running code.

Here are the Environment Variables needed:

USERNAME=email@gmail.com
APP_PASSWORD=app-password
IMAP_SERVER=imap.gmail.com
IMAP_PORT=993
IMAP_OUTPUT_DIR=./data #Optional; flags for inbox process
IMAP_FROM_EMAIL=email<+filter>@gmail.com
IMAP_TO_EMAIL=email<+filter>@gmail.com
######################
# OPTIONAL VARIABLES #
######################
IMAP_N_COUNT=1
IMAP_MAILBOX=INBOX
IMAP_CSV_COL_MESSAGE_ID=msgId
IMAP_CSV_COL_MESSAGE_REF=msgRef
IMAP_CSV_COL_DATE=date
IMAP_CSV_COL_FROM=email
IMAP_CSV_COL_SUBJECT=subject
IMAP_CSV_COL_ATTACHMENT_PATH=attachment
!source .env # load ENV variables from file; if needed
!pip install yoga1290.emailtable

from yoga1290.emailtable import processIMAPToCSV
processIMAPToCSV(
    # USERNAME= os.getenv('USERNAME', 'USERNAME-REQUIRED@gmail.com'),
    # APP_PASSWORD= os.getenv('APP_PASSWORD', 'APP-PASSWORD'),
    # IMAP_SERVER= os.getenv('IMAP_SERVER', 'imap.gmail.com'),
    # IMAP_PORT= int(os.getenv('IMAP_PORT', 993)),
    # IMAP_MAILBOX= os.getenv('IMAP_MAILBOX', 'INBOX'),
    # IMAP_N_COUNT= os.getenv('IMAP_N_COUNT', '5'),

    # IMAP_FROM_EMAIL=os.getenv('IMAP_FROM_EMAIL', None), # example: '<username>+<filter>@gmail.com'
    # IMAP_TO_EMAIL=os.getenv('IMAP_TO_EMAIL', None), # example: '<username>+<filter>@gmail.com'
    # IMAP_OUTPUT_DIR=os.getenv('IMAP_OUTPUT_DIR', './data'),
    # IMAP_CSV_COL_MESSAGE_ID=os.getenv('IMAP_CSV_COL_MESSAGE_ID', 'msgId'),
    # IMAP_CSV_COL_MESSAGE_REF=os.getenv('IMAP_CSV_COL_MESSAGE_REF', 'msgRef'),
    # IMAP_CSV_COL_DATE=os.getenv('IMAP_CSV_COL_DATE', 'date'),
    # IMAP_CSV_COL_FROM=os.getenv('IMAP_CSV_COL_FROM', 'from'),
    # IMAP_CSV_COL_SUBJECT=os.getenv('IMAP_CSV_COL_SUBJECT', 'subject'),
    # IMAP_CSV_COL_ATTACHMENT_PATH=os.getenv('IMAP_CSV_COL_ATTACHMENT_PATH', 'attachment'),
)
import pandas as pd
import os

IMAP_OUTPUT_DIR=os.getenv("IMAP_OUTPUT_DIR", None)
outboxDF = pd.read_csv(f'{IMAP_OUTPUT_DIR}/output.csv')
outboxDF.head(5)
msgId msgRef date email subject content_path

📝️ Draft emails

The Environment Variables passed as parameters:

USERNAME=email@gmail.com
APP_PASSWORD=app-password
IMAP_SERVER=imap.gmail.com
IMAP_PORT=993
DRAFT_CSV_PATH=./data/output.csv
DRAFT_CSV_EMAIL_COLUMN=email
DRAFT_CSV_MESSAGE_ID_COLUMN=msgId
DRAFT_CSV_REFERENCES_COLUMN=msgRef
DRAFT_CSV_SUBJECT_COLUMN=subject
DRAFT_CSV_FILE_COLUMN=content_path
DRAFTS_FOLDER="[Gmail]/Drafts"
!source .env # load ENV variables from file; if needed
!pip install yoga1290.emailtable

from yoga1290.emailtable import proccessCSVDrafts
proccessCSVDrafts(
    # USERNAME=os.getenv("USERNAME", "USERNAME-REQUIRED@gmail.com"),
    # APP_PASSWORD=os.getenv("APP_PASSWORD", "APP-PASSWORD"),
    # IMAP_SERVER=os.getenv("IMAP_SERVER", "imap.gmail.com"),
    # IMAP_PORT=os.getenv("IMAP_PORT", "993"),
    # FROM_EMAIL=os.getenv("FROM_EMAIL", None),
    
    # DRAFT_CSV_PATH=os.getenv("DRAFT_CSV_PATH", None),
    # DRAFT_CSV_FILE_COLUMN=os.getenv("DRAFT_CSV_FILE_COLUMN", None),
    # DRAFT_CSV_EMAIL_COLUMN=os.getenv("DRAFT_CSV_EMAIL_COLUMN", None),
    # DRAFT_CSV_MESSAGE_ID_COLUMN=os.getenv(
    #     "DRAFT_CSV_MESSAGE_ID_COLUMN", None
    # ),
    # DRAFT_CSV_REFERENCES_COLUMN=os.getenv(
    #     "DRAFT_CSV_REFERENCES_COLUMN", None
    # ),
    # DRAFT_CSV_SUBJECT_COLUMN=os.getenv("DRAFT_CSV_SUBJECT_COLUMN", None),
    # DRAFT_FOLDER=os.getenv("DRAFTS_FOLDER", "[Gmail]/Drafts"),
)
import pandas as pd
import os

DRAFT_CSV_PATH=os.getenv("DRAFT_CSV_PATH", None)
outboxDF = pd.read_csv(f'{DRAFT_CSV_PATH}')
outboxDF.head(5)
msgId msgRef date email subject content_path Status

📤️ Send Emails (SMTP)

!source .env # load ENV variables from file; if needed
!pip install yoga1290.emailtable

from yoga1290.emailtable import processSMTP
processSMTP(
    # USERNAME= os.getenv('USERNAME', 'USERNAME-REQUIRED@gmail.com'),
    # APP_PASSWORD= os.getenv('APP_PASSWORD', 'APP-PASSWORD'),
    # SMTP_SERVER= os.getenv('SMTP_SERVER', 'smtp.gmail.com'),
    # SMTP_PORT= int(os.getenv('SMTP_PORT', '587')),
    
    # SMTP_CSV_PATH=os.getenv('SMTP_CSV_PATH', None),
    # SMTP_CSV_FILE_COLUMN=os.getenv('SMTP_CSV_FILE_COLUMN', None),
    # SMTP_CSV_EMAIL_COLUMN=os.getenv('SMTP_CSV_EMAIL_COLUMN', None),
    # SMTP_CSV_SUBJECT_COLUMN=os.getenv('SMTP_CSV_SUBJECT_COLUMN', None),
)
import pandas as pd
import os

SMTP_CSV_PATH=os.getenv('SMTP_CSV_PATH', None)
pd.read_csv(SMTP_CSV_PATH).head(5)
msgId msgRef date email subject content_path

📦️ Run in Docker Containers

One way I use it, I trigger it as part of chain of jobs, each runs on seperate docker container; running one by one, example: emailtable-job2 following emailtable-job1, so my docker-compose.yml would look like the following:

# docker-compose.yml

emailtable-job2:
    env_file:
      - .env
    depends_on:
      emailtable-job1:
        condition: service_completed_successfully
    image: ghcr.io/yoga1290/python-emailtable:26.10
    # my docker image here is just based on python:3.13-alpine with my package pre-installed; saves network over time.
    working_dir: /app
    volumes:
      - .:/app
    command:
      - python
      - -c
      - |
        from yoga1290.emailtable import (
                        proccessCSVDrafts,
                        processIMAPToCSV,
                        processSMTP )
        # proccessCSVDrafts() #...
$ > docker compose up emailtable-job2

Metadata

Release files for yoga1290.emailtable 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for yoga1290.emailtable 0.1.1
File Size Uploaded Provenance
yoga1290_emailtable-0.1.1.tar.gz 10.1 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for yoga1290.emailtable 0.1.1
File Interpreter ABI Platform
yoga1290_emailtable-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 20.4 kB

Release files / yoga1290_emailtable-0.1.1.tar.gz

Download URL yoga1290_emailtable-0.1.1.tar.gz
Size 10.1 kB
Tags Source
SHA-256 checksum
How to use checksums
caf601f9bc062b6d2478ac3f3107472583391595d3ac82da2c6e46657c99870b
BLAKE2b-256 checksum
How to use checksums
54a53ab62a58d205b338f61f082057e44008ba0a61ad944a6276e6986b7710ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / yoga1290_emailtable-0.1.1-py3-none-any.whl

Download URL yoga1290_emailtable-0.1.1-py3-none-any.whl
Size 10.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
be353cd55885a33aa590f478766943af23bc3305f517f179e39941a3522d6bdf
BLAKE2b-256 checksum
How to use checksums
4e59568f161dab08de47ad921eb907b777ed6f81e09bd1197d932ade06a5b370
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Security for yoga1290.emailtable 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for yoga1290_emailtable-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page