Skip to content

Instantly share code, notes, and snippets.

@boronine
Created January 20, 2022 09:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save boronine/661fd24ba6671f687ff714969d961b85 to your computer and use it in GitHub Desktop.
Save boronine/661fd24ba6671f687ff714969d961b85 to your computer and use it in GitHub Desktop.
Fetch email from S3 bucket written to by SES "receive email" feature
#!/usr/bin/env python3
import os
import subprocess
import json
import glob
from pathlib import Path
RCLONE_REMOTE = 'my-s3-remote'
S3_BUCKET = 'my-ses-email-bucket'
RCLONE_REMOTE_S3 = f'{RCLONE_REMOTE}:{S3_BUCKET}'
MAILDIR = Path.home() / 'maildir'
MAILDIR_TMP = MAILDIR / 'tmp'
MAILDIR_NEW = MAILDIR / 'new'
MAILDIR_CUR = MAILDIR / 'cur'
def list_emails():
p = subprocess.run(['rclone', 'lsjson', RCLONE_REMOTE_S3], capture_output=True, encoding='utf-8')
emails = json.loads(p.stdout.strip())
print('fetched emails:', len(emails))
imported = 0
for email in emails:
if email['IsDir']:
continue
n = email['Name']
p = email['Path']
mod_raw = email['ModTime']
mod = mod_raw[:19].replace(':', '-')
ha = n[:10]
f_base = f'{mod}-{ha}'
f = f'{f_base}:2,'
g = glob.glob(f'{MAILDIR_CUR}/{f_base}*')
if len(g) == 0:
print('download from S3 ...')
os.system(f'rclone copyto {RCLONE_REMOTE_S3}/{p} {MAILDIR_TMP}/{f}')
print('atomic rename ...')
os.rename(f'{MAILDIR_TMP}/{f}', f'{MAILDIR_CUR}/{f}')
imported += 1
else:
print(f'email already imported: {f_base}')
# Delete regardless of whether the email was already imported, in case the process was interrupted last time
print('delete email from S3 ...')
shell(f'{RCLONE_BIN} --config {RCLONE_CONF} delete {RCLONE_REMOTE_S3}/{p}')
print('emails imported:', imported)
print(f'open using command: mutt -f {MAILDIR}')
if __name__ == '__main__':
list_emails()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment